text:
# Workflow Engine for Yii 2 Framework
[![Latest Stable Version](https://poser.pugx.org/fproject/workflowii/v/stable)](https://packagist.org/packages/fproject/workflowii)
[![Total Downloads](https://poser.pugx.org/fproject/workflowii/downloads)](https://packagist.org/packages/fproject/workflowii)
[![Latest Unstable Version](https://poser.pugx.org/fproject/workflowii/v/unstable)](https://packagist.org/packages/fproject/workflowii)
[![Build](https://travis-ci.org/fproject/workflowii.svg?branch=master)](https://travis-ci.org/fproject/workflowii)
[![License](https://poser.pugx.org/fproject/workflowii/license)](https://packagist.org/packages/fproject/workflowii)

## INSTALLATION

The preferred way to install **Workflowii** is through [composer](http://getcomposer.org/download/).

You can either run:
```
php composer.phar require fproject/workflowii "*"
```

or add this block to the *require* section of your `composer.json` file:
```javascript
"require" : {
		"php" : ">=5.4.0",
		"yiisoft/yii2" : "*",
		"fproject/workflowii": "*",
		// ...
	}
```

## REQUIREMENTS

The minimum requirement by Workflowii:
- Your Web server supports PHP 5.4 or above
- Your Web server is running on Yii 2.0.0 or above

## QUICK START

### Configuration

In this simple start guide we use default configuration settings, but note that *workflowii* is designed to be highly
flexible so to adapt to a lot of execution contexts.

### Create A WorkflowSource

A workflow source is defined as a PHP class that implements the `\fproject\workflow\core\IWorkflowSource` interface. This interface
declares the *getDefinition()* method that must return an array representing the workflow of a model object.

Let's define a very simple workflow source that will be used to manage article posts represented by `Article` model class.
This workflow source will simply return the same workflow for all model object instances of `Article`, by specifying a PHP
associative array as return value of `getDefinition()` method:

*ArticleWorkflowSource.php*
```php
class ArticleWorkflowSource implements \fproject\workflow\core\IWorkflowSource
{
	public function getDefinition($model) {
		return [
			'initialStatusId' => 'draft',
			'status' => [
				'draft' => [
					'transition' => ['published','deleted']
				],
				'published' => [
					'transition' => ['draft','deleted']
				],
				'deleted' => [
					'transition' => ['draft']
				]
			]
		];
	}
}
```

### Attach ActiveWorkflowBehavior To The Model

Now let's have a look to our `Article` model that extends from \yii\db\ActiveRecord and has a column named
`status` of type `string`.

The last step is to associate the workflow definition with articles models. All things we have to do is overriding
the `function behaviors()` method in the `Article` model class and specify the *ActiveWorkflowBehavior* behavior as
return value. That's all, the *workflowii*'s default configuration settings will do the rest for you.

*Article.php*
```php
/**
 * @property integer $id
 * @property string $title
 * @property string $body
 * @property string $status column used to store the status of the article
 */
class Article extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
    	return [
			\fproject\workflow\core\ActiveWorkflowBehavior::className()
    	];
    }
    // ...
```

By default, the `ActiveWorkflowBehavior` will search to find a workflow source class that has the same namespace with the
model class and has the class name is the model class name with suffix `WorkflowSource`. In this case, it will be `ArticleWorkflowSource`.

Thus, we are now ready to play with `ArticleWorkflowSource` workflow that dedicated for `Article` model.

### Let's Use It !

Now that we are all setup, we can use the *ActiveWorkflowBehavior* methods to set/get the status of our articles : the *ActiveWorkflowBehavior* will
take care that the article doesn't reach a status where it is not supposed to go, depending on the workflow definition that we have created.

```php
$article = new Article();
$article->status = 'draft';
$article->save();
echo 'article status now is : '. $article->workflowStatus->label;
```
This will print the following message :

	article status is : Draft

If you do the same thing but instead of *draft* set the status to *published* and try to save it, the following exception is thrown :

	Not an initial status : ArticleWorkflow/published ("ArticleWorkflow/draft" expected)

That's because in your workflow definition the **initial status** is  set to *draft* and not *published*.

Now we will go further. This time we are not going to perform the transition when the Article is saved (like we did in the previous
example), but immediately by invoking the `sendToStatus` method. Our Article is going to try to reach status *published* passing through *deleted*
which is strictly forbidden by the workflow. Will it be successful in this risky attempt of breaking workflow rules ?

```php
$article = new Article();
$article->sendToStatus('draft'); // OK
$article->sendToStatus('deleted'); // OK
$article->sendToStatus('published'); // Error!
```

There is no transition between *deleted* and *published*, and that's what *Workflow* tries to explain the problem:

	Workflow Exception – fproject\workflow\core\WorkflowException
	No transition found between status ArticleWorkflow/deleted and ArticleWorkflow/published

Yes, that's severe, but there was many ways to avoid this exception like for instance by first validating that the transition was possible.

### What's Next ?

This is just a very simple way of using the *ActiveWorkflowBehavior*. Workflowii has much more functionalities enough to assist you
in your workflow management inside your Yii 2 web app.

In the meantime you can have a look to the [Workflowii User Guide](guide) (still under dev) and send any feedback.

##ROADMAP

- At the first stage, we build a workflow engine based on Yii 2 Framework with basic functionalities.
- At the second stage, we are planning to develop a web component that allows users display/edit workflows by
interacting with a RIA GUI, using HTML5 or Flex.

##LICENSE

**Workflowii** is released under the Apache 2.0 License. See the bundled `LICENSE.md` for details.

##LINKS

- [GitHub](https://github.com/fproject/workflowii)
- [Packagist](https://packagist.org/packages/fproject/workflowii)


text:
#include "El.hpp"

namespace El {

template<typename T>
T Dot( const Matrix<T>& A, const Matrix<T>& B )
{
    DEBUG_ONLY(CallStackEntry cse("Dot"))
    return HilbertSchmidt( A, B );
}

template<typename T>
T Dot( const AbstractDistMatrix<T>& A, const AbstractDistMatrix<T>& B )
{
    DEBUG_ONLY(CallStackEntry cse("Dot"))
    return HilbertSchmidt( A, B );
}

template<typename T>
T Dot( const DistMultiVec<T>& A, const DistMultiVec<T>& B )
{
    DEBUG_ONLY(CallStackEntry cse("Dot"))
    return HilbertSchmidt( A, B );
}

#define PROTO(T) \
  template T Dot( const Matrix<T>& A, const Matrix<T>& B ); \
  template T Dot \
  ( const AbstractDistMatrix<T>& A, const AbstractDistMatrix<T>& B ); \
  template T Dot( const DistMultiVec<T>& A, const DistMultiVec<T>& B );

#include "El/macros/Instantiate.h"

} // namespace El

redpajama_set_name: RedPajamaGithub


text:
using System.Linq;

namespace OpenLibrary.Extension
{
	/// <summary>
	/// Extension for <see cref="System.DateTime"/>
	/// </summary>
	public static class DateTimeExtension
	{
		/// <summary>
		/// Convert date time to SQL DateTime
		/// </summary>
		/// <param name="dateTime"></param>
		/// <returns></returns>
		public static string ToSqlDateTime(this System.DateTime dateTime)
		{
			return string.Format("cast('{0}' as datetime)", dateTime.ToString("yyyy-MM-dd HH:mm:ss"));
		}

		/// <summary>
		/// SQL Server minimum date time
		/// </summary>
		/// <param name="dateTime"></param>
		/// <returns></returns>
		public static System.DateTime SqlMinDateTime(this System.DateTime dateTime)
		{
			return System.DateTime.ParseExact("1753-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
		}

		/// <summary>
		/// Check wether certain date is the end of the month
		/// </summary>
		/// <param name="date">tanggal yang akan dicek</param>
		/// <returns></returns>
		public static bool IsEndOfMonth(this System.DateTime date)
		{
			//untuk februari kabisat -> berakhir tanggal 29
			if (date.Year % 4 == 0 && date.Month == 2 && date.Day == 29)
				return true;
			//untuk februari non kabisat -> berakhir tanggal 28
			if (date.Year % 4 != 0 && date.Month == 2 && date.Day == 28)
				return true;
			//dari januari - juli, bulan ganjil berakhir tgl 31
			if (date.Month % 2 == 1 && date.Month <= 7 && date.Day == 31)
				return true;
			//dari januari - juli, bulan genap berakhir tgl 30
			if (date.Month % 2 == 0 && date.Month <= 7 && date.Day == 30)
				return true;
			//dari agustus - desember, bulan ganjil berakhir tgl 30
			if (date.Month % 2 != 0 && date.Month >= 8 && date.Day == 30)
				return true;
			//dari agustus - desember, bulan genap berakhir tgl 31
			if (date.Month % 2 == 0 && date.Month >= 8 && date.Day == 31)
				return true;
			return false;
		}

		/// <summary>
		/// Digunakan untuk mencari tanggal pertama kali untuk hari tertentu pada bulan yg ditentukan.
		/// </summary>
		/// <param name="month">bulang pencarian tanggal pertama</param>
		/// <param name="day">hari (senin - minggu)</param>
		/// <returns></returns>
		public static System.DateTime FirstDayWeekOfMonth(this System.DateTime month, System.DayOfWeek day)
		{
			//cari untuk pekan pertama saja
			for (int i = 1; i <= 7; i++)
			{
				var date = new System.DateTime(month.Year, month.Month, i);
				if (date.DayOfWeek == day)
					return date.Date;
			}
			return month.Date;
		}

		/// <summary>
		/// Get next week for certain day of week
		/// </summary>
		/// <param name="date"></param>
		/// <param name="weeks">how many week</param>
		/// <param name="dayTarget">day of week</param>
		/// <returns></returns>
		public static System.DateTime NextWeek(this System.DateTime date, int weeks, System.DayOfWeek? dayTarget = null)
		{
			var day = dayTarget.HasValue ? dayTarget.Value : date.DayOfWeek;
			var dayToBeSearch = date;
			//cari tanggal untuk hari
			for (int i = 0; i <= 7; i++)
			{
				var tempDay = date.AddDays(i);
				if (tempDay.DayOfWeek == day)
				{
					dayToBeSearch = tempDay;
					break;
				}
			}
			return dayToBeSearch.AddDays(7 * weeks);
		}

		/// <summary>
		/// Get previous week for certain day of week
		/// </summary>
		/// <param name="date"></param>
		/// <param name="weeks">how many week</param>
		/// <param name="dayTarget">day of week</param>
		/// <returns></returns>
		public static System.DateTime BeforeWeek(this System.DateTime date, int weeks, System.DayOfWeek? dayTarget = null)
		{
			var day = dayTarget.HasValue ? dayTarget.Value : date.DayOfWeek;
			var dayToBeSearch = date;
			//cari tanggal untuk hari
			for (int i = 0; i <= 7; i++)
			{
				var tempDay = date.AddDays(-i);
				if (tempDay.DayOfWeek == day)
				{
					dayToBeSearch = tempDay;
					break;
				}
			}
			return dayToBeSearch.AddDays(-(7 * weeks));
		}

		/// <summary>
		/// Get total day for day of week for a certain range date
		/// </summary>
		/// <param name="startDate">start range</param>
		/// <param name="endDate">end range</param>
		/// <param name="days">look for these day of week</param>
		/// <returns></returns>
		public static int TotalDays(System.DateTime startDate, System.DateTime endDate, System.DayOfWeek[] days)
		{
			int total = 0;
			var day = startDate;
			while (day <= endDate)
			{
				if (days.Contains(day.DayOfWeek))
					total++;
				day = day.AddDays(1);
			}
			return total;
		}
	}
}


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- Release notes -->
    <string name="release_127">
         Added a switch for disabling video gestures\n
         Added a switch for deleting empty folders after deleting content
    </string>
    <string name="release_125">Moved media type filter from Settings to the Action menu</string>
    <string name="release_123">Allow changing the screen brightness and volume at videos by vertically dragging the screen sides</string>
    <string name="release_122">Added slideshow at the fullscreen view</string>
    <string name="release_119">Added pattern/pin protection for showing hidden items</string>
    <string name="release_118">Added a toggle for replacing Share with Rotate at fullscreen media</string>
    <string name="release_115">
        Added an indicator of folders located on SD cards\n
        Improved the way of rotating jpg images on the internal storage by modifying the exif tags + added autosave
    </string>
    <string name="release_114">Added an option for automatically hiding the system UI at entering fullscreen mode</string>
    <string name="release_112">Added an option for enabling horizontal scrolling</string>
    <string name="release_108">Allow setting custom folder covers</string>
    <string name="release_98">
        Allow selecting multiple items by finger dragging\n
        Added an option to always use black background at fullscreen media
    </string>
    <string name="release_97">Allow hiding individual files by prepending filenames with a dot</string>
    <string name="release_94">Added horizontal and vertical image flipping in the image editor</string>
    <string name="release_93">
        Allow setting portrait wallpapers\n
        Added more fields in photo Properties dialog
    </string>
    <string name="release_89">
        Improved fullscreen image zooming\n
        Added more settings related to screen autorotating\n
        Split copy and move functions for ease of use
    </string>
    <string name="release_88">
        Added an option to temporarily show hidden folders\n
        Added a setting for preventing thumbnail croping to square\n
        Added a setting for auto-rotating the screen depending on photo aspect ratio
    </string>
    <string name="release_84">
        Added an option to use max brightness at viewing fullscreen media\n
        Added an option to manually include folders which contain media, but were not recognized by the app
    </string>
    <string name="release_83">
        Fixed some sharing and editor issues\n
        Sorry for the frequent updates lately, they should be stopped now.
    </string>
    <string name="release_77">
        Exclude the subfolders of excluded folders too\n
        Added an easy way of excluding parent folders from the exclude confirmation dialog\n
        Added draggable scrollbars\n
        Allow setting a third party video player as the default
    </string>
    <string name="release_76">Added an option to toggle gif animation at thumbnails</string>
    <string name="release_74">Allow setting different sorting per folder</string>
    <string name="release_72">
        Implement proper folder hiding via .nomedia file\n
        Allow managing excluded folders in Settings
    </string>
    <string name="release_70">Added menu items for easy image rotating in fullscreen view</string>
    <string name="release_69">Added menu buttons for changing the column count</string>
    <string name="release_66">Allow picking colors by hex codes</string>
    <string name="release_65">Allow showing the photos and videos on a map, if there are available map coordinates</string>
    <string name="release_62">Show some additional Exif data at photo properties</string>
    <string name="release_58">
        Allow zooming pngs and gifs\n
        Allow creating new folders at Copy/Move or Save as dialog destinations
    </string>
    <string name="release_54">Added an option to loop videos automatically</string>
    <string name="release_52">
        Added more color customization options\n
        Your settings have been cleared, please reset them
    </string>
    <string name="release_51">Allow changing the column count with pinch gestures</string>
    <string name="release_50">Added an option to display images or videos only</string>
    <string name="release_49">Added a Select all button at selecting media and folders</string>
    <string name="release_47">
        Added an image resizer to the editor\n
        Allow displaying images and videos from all folders together
    </string>
    <string name="release_46">Allow pinning folders at the top</string>

</resources>


text:
<?php declare(strict_types=1);

namespace Composer\Util;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Config;
use Composer\Downloader\TransportException;

/**
 * @author Paul Wenke <wenke.paul@gmail.com>
 */
class Bitbucket
{
    /** @var IOInterface */
    private $io;
    /** @var Config */
    private $config;
    /** @var ProcessExecutor */
    private $process;
    /** @var HttpDownloader */
    private $httpDownloader;
    /** @var array{access_token: string, expires_in?: int}|null */
    private $token = null;
    /** @var int|null */
    private $time;

    public const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';

    /**
     * Constructor.
     *
     * @param IOInterface     $io             The IO instance
     * @param Config          $config         The composer configuration
     * @param ProcessExecutor $process        Process instance, injectable for mocking
     * @param HttpDownloader  $httpDownloader Remote Filesystem, injectable for mocking
     * @param int             $time           Timestamp, injectable for mocking
     */
    public function __construct(IOInterface $io, Config $config, ?ProcessExecutor $process = null, ?HttpDownloader $httpDownloader = null, ?int $time = null)
    {
        $this->io = $io;
        $this->config = $config;
        $this->process = $process ?: new ProcessExecutor($io);
        $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config);
        $this->time = $time;
    }

    public function getToken(): string
    {
        if (!isset($this->token['access_token'])) {
            return '';
        }

        return $this->token['access_token'];
    }

    /**
     * Attempts to authorize a Bitbucket domain via OAuth
     *
     * @param  string $originUrl The host this Bitbucket instance is located at
     * @return bool   true on success
     */
    public function authorizeOAuth(string $originUrl): bool
    {
        if ($originUrl !== 'bitbucket.org') {
            return false;
        }

        // if available use token from git config
        if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
            $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));

            return true;
        }

        return false;
    }

    private function requestAccessToken(): bool
    {
        try {
            $response = $this->httpDownloader->get(self::OAUTH2_ACCESS_TOKEN_URL, [
                'retry-auth-failure' => false,
                'http' => [
                    'method' => 'POST',
                    'content' => 'grant_type=client_credentials',
                ],
            ]);

            $token = $response->decodeJson();
            if (!isset($token['expires_in']) || !isset($token['access_token'])) {
                throw new \LogicException('Expected a token configured with expires_in and access_token present, got '.json_encode($token));
            }

            $this->token = $token;
        } catch (TransportException $e) {
            if ($e->getCode() === 400) {
                $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
                $this->io->writeError('This can have three reasons:');
                $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
                $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
                $this->io->writeError('3. You are using an OAuth consumer, but didn\'t configure it as private consumer');

                return false;
            }
            if (in_array($e->getCode(), [403, 401])) {
                $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
                $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');

                return false;
            }

            throw $e;
        }

        return true;
    }

    /**
     * Authorizes a Bitbucket domain interactively via OAuth
     *
     * @param  string                        $originUrl The host this Bitbucket instance is located at
     * @param  string                        $message   The reason this authorization is required
     * @throws \RuntimeException
     * @throws TransportException|\Exception
     * @return bool                          true on success
     */
    public function authorizeOAuthInteractively(string $originUrl, ?string $message = null): bool
    {
        if ($message) {
            $this->io->writeError($message);
        }

        $url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/';
        $this->io->writeError(sprintf('Follow the instructions on %s', $url));
        $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
        $this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)');

        $consumerKey = trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): '));

        if (!$consumerKey) {
            $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
            $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');

            return false;
        }

        $consumerSecret = trim((string) $this->io->askAndHideAnswer('Consumer Secret (hidden): '));

        if (!$consumerSecret) {
            $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
            $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');

            return false;
        }

        $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);

        if (!$this->requestAccessToken()) {
            return false;
        }

        // store value in user config
        $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);

        // Remove conflicting basic auth credentials (if available)
        $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);

        $this->io->writeError('<info>Consumer stored successfully.</info>');

        return true;
    }

    /**
     * Retrieves an access token from Bitbucket.
     */
    public function requestToken(string $originUrl, string $consumerKey, string $consumerSecret): string
    {
        if ($this->token !== null || $this->getTokenFromConfig($originUrl)) {
            return $this->token['access_token'];
        }

        $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
        if (!$this->requestAccessToken()) {
            return '';
        }

        $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);

        if (!isset($this->token['access_token'])) {
            throw new \LogicException('Failed to initialize token above');
        }

        return $this->token['access_token'];
    }

    /**
     * Store the new/updated credentials to the configuration
     */
    private function storeInAuthConfig(string $originUrl, string $consumerKey, string $consumerSecret): void
    {
        $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);

        if (null === $this->token || !isset($this->token['expires_in'])) {
            throw new \LogicException('Expected a token configured with expires_in present, got '.json_encode($this->token));
        }

        $time = null === $this->time ? time() : $this->time;
        $consumer = [
            "consumer-key" => $consumerKey,
            "consumer-secret" => $consumerSecret,
            "access-token" => $this->token['access_token'],
            "access-token-expiration" => $time + $this->token['expires_in'],
        ];

        $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
    }

    /**
     * @phpstan-assert-if-true array{access_token: string} $this->token
     */
    private function getTokenFromConfig(string $originUrl): bool
    {
        $authConfig = $this->config->get('bitbucket-oauth');

        if (
            !isset($authConfig[$originUrl]['access-token'], $authConfig[$originUrl]['access-token-expiration'])
            || time() > $authConfig[$originUrl]['access-token-expiration']
        ) {
            return false;
        }

        $this->token = [
            'access_token' => $authConfig[$originUrl]['access-token'],
        ];

        return true;
    }
}


text:
package es.tid.cosmos.servicemanager.ambari.services

import es.tid.cosmos.servicemanager.configuration.ConfigurationKeys.MasterNode

class OozieIT extends ConfiguredServiceTest  {

  override val dynamicProperties = Map(
    MasterNode -> "aMasterNodeName"
  )

  override def configurator = AmbariOozie.configurator((), resourcesConfigDirectory)

  "An Oozie service" must "have global and service configuration contributions without core" in {
    contributions.global must be ('defined)
    contributions.core must not be 'defined
    contributions.services must have length 1
  }
}


text:
https://www.hitechnectar.com/blogs/open-source-master-data-management-tools/#Talend

- [Pimcore](https://github.com/pimcore)

- [Unidata CE](https://unidata-community.com/opensource#rec233952365)


text:
import * as KTX2Decoder from "@tools/ktx2decoder";

const globalObject = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : undefined;
if (typeof globalObject !== "undefined") {
    (<any>globalObject).KTX2DECODER = KTX2Decoder;
}

export * from "@tools/ktx2decoder";


text:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook MathML Module V1.1b1//EN"
              "http://www.oasis-open.org/docbook/xml/mathml/1.1CR1/dbmathml.dtd">
<refentry id="glHistogram">
    <refmeta>
        <refmetainfo>
            <copyright>
                <year>1991-2006</year>
                <holder>Silicon Graphics, Inc.</holder>
            </copyright>
        </refmetainfo>
        <refentrytitle>glHistogram</refentrytitle>
        <manvolnum>3G</manvolnum>
    </refmeta>
    <refnamediv>
        <refname>glHistogram</refname>
        <refpurpose>define histogram table</refpurpose>
    </refnamediv>
    <refsynopsisdiv><title>C Specification</title>
        <funcsynopsis>
            <funcprototype>
                <funcdef>void <function>glHistogram</function></funcdef>
                <paramdef>GLenum <parameter>target</parameter></paramdef>
                <paramdef>GLsizei <parameter>width</parameter></paramdef>
                <paramdef>GLenum <parameter>internalformat</parameter></paramdef>
                <paramdef>GLboolean <parameter>sink</parameter></paramdef>
            </funcprototype>
        </funcsynopsis>
    </refsynopsisdiv>

    <refsect1 id="parameters"><title>Parameters</title>
        <variablelist>
        <varlistentry>
            <term><parameter>target</parameter></term>
            <listitem>
                <para>
                    The histogram whose parameters are to be set.
                    Must be one of
                    <constant>GL_HISTOGRAM</constant> or
                    <constant>GL_PROXY_HISTOGRAM</constant>.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term><parameter>width</parameter></term>
            <listitem>
                <para>
                    The number of entries in the histogram table.  Must be a power of 2.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term><parameter>internalformat</parameter></term>
            <listitem>
                <para>
                    The format of entries in the histogram table.
                    Must be one of
                    <constant>GL_ALPHA</constant>,
                    <constant>GL_ALPHA4</constant>,
                    <constant>GL_ALPHA8</constant>,
                    <constant>GL_ALPHA12</constant>,
                    <constant>GL_ALPHA16</constant>,
                    <constant>GL_LUMINANCE</constant>,
                    <constant>GL_LUMINANCE4</constant>,
                    <constant>GL_LUMINANCE8</constant>,
                    <constant>GL_LUMINANCE12</constant>,
                    <constant>GL_LUMINANCE16</constant>,
                    <constant>GL_LUMINANCE_ALPHA</constant>,
                    <constant>GL_LUMINANCE4_ALPHA4</constant>,
                    <constant>GL_LUMINANCE6_ALPHA2</constant>,
                    <constant>GL_LUMINANCE8_ALPHA8</constant>,
                    <constant>GL_LUMINANCE12_ALPHA4</constant>,
                    <constant>GL_LUMINANCE12_ALPHA12</constant>,
                    <constant>GL_LUMINANCE16_ALPHA16</constant>,
                    <constant>GL_R3_G3_B2</constant>,
                    <constant>GL_RGB</constant>,
                    <constant>GL_RGB4</constant>,
                    <constant>GL_RGB5</constant>,
                    <constant>GL_RGB8</constant>,
                    <constant>GL_RGB10</constant>,
                    <constant>GL_RGB12</constant>,
                    <constant>GL_RGB16</constant>,
                    <constant>GL_RGBA</constant>,
                    <constant>GL_RGBA2</constant>,
                    <constant>GL_RGBA4</constant>,
                    <constant>GL_RGB5_A1</constant>,
                    <constant>GL_RGBA8</constant>,
                    <constant>GL_RGB10_A2</constant>,
                    <constant>GL_RGBA12</constant>, or
                    <constant>GL_RGBA16</constant>.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term><parameter>sink</parameter></term>
            <listitem>
                <para>
                    If <constant>GL_TRUE</constant>, pixels will be consumed by the histogramming
                    process and no drawing or texture loading will take place.
                    If <constant>GL_FALSE</constant>, pixels will proceed to the minmax process after
                    histogramming.
                </para>
            </listitem>
        </varlistentry>
        </variablelist>
    </refsect1>
    <refsect1 id="description"><title>Description</title>
        <para>
            When <constant>GL_HISTOGRAM</constant> is enabled, RGBA color components are converted to
            histogram table indices by clamping to the range [0,1], multiplying by
            the width of the histogram table, and rounding to the nearest integer.
            The table entries selected by the RGBA indices are then incremented.
            (If the internal format of the histogram table includes luminance, then
            the index derived from the R color component determines the luminance
            table entry to be incremented.)  If a histogram table entry is incremented
            beyond its maximum value, then its value becomes undefined.  (This is
            not an error.)
        </para>
        <para>
            Histogramming is performed only for RGBA pixels (though these may
            be specified originally as color indices and converted to RGBA by
            index table lookup).
            Histogramming is enabled with <citerefentry><refentrytitle>glEnable</refentrytitle></citerefentry> and disabled with <citerefentry><refentrytitle>glDisable</refentrytitle></citerefentry>.
        </para>
        <para>
            When <parameter>target</parameter> is <constant>GL_HISTOGRAM</constant>, <function>glHistogram</function> redefines the current
            histogram table to have <parameter>width</parameter> entries of the format specified by
            <parameter>internalformat</parameter>.
            The entries are indexed 0 through
            <inlineequation><mml:math>

                <mml:mrow>
                    <mml:mi mathvariant="italic">width</mml:mi>
                    <mml:mo>-</mml:mo>
                    <mml:mn>1</mml:mn>
                </mml:mrow>
            </mml:math></inlineequation>,
            and
            all entries are initialized to zero.
            The values in the previous histogram table, if any, are lost.
            If <parameter>sink</parameter> is <constant>GL_TRUE</constant>, then pixels are discarded after histogramming;
            no further processing of the pixels takes place, and no drawing,
            texture loading, or pixel readback will result.
        </para>
        <para>
            When <parameter>target</parameter> is <constant>GL_PROXY_HISTOGRAM</constant>, <function>glHistogram</function> computes all
            state information as if the histogram table were to be redefined,
            but does not actually define the new table.
            If the requested histogram table is too large to be supported, then the
            state information will be set to zero.
            This provides a way to determine if a histogram table with the given
            parameters can be supported.
        </para>
        <para>
        </para>
    </refsect1>
    <refsect1 id="notes"><title>Notes</title>
        <para>
            <function>glHistogram</function> is present only if ARB_imaging is returned when <citerefentry><refentrytitle>glGetString</refentrytitle></citerefentry>
            is called with an argument of <constant>GL_EXTENSIONS</constant>.
        </para>
    </refsect1>
    <refsect1 id="errors"><title>Errors</title>
        <para>
            <constant>GL_INVALID_ENUM</constant> is generated if <parameter>target</parameter> is not one of the allowable
            values.
        </para>
        <para>
            <constant>GL_INVALID_VALUE</constant> is generated if <parameter>width</parameter> is less than zero or is
            not a power of 2.
        </para>
        <para>
            <constant>GL_INVALID_ENUM</constant> is generated if <parameter>internalformat</parameter> is not one of the
            allowable values.
        </para>
        <para>
            <constant>GL_TABLE_TOO_LARGE</constant> is generated if <parameter>target</parameter> is <constant>GL_HISTOGRAM</constant>
            and the histogram table specified is too large for the implementation.
        </para>
        <para>
            <constant>GL_INVALID_OPERATION</constant> is generated if <function>glHistogram</function> is executed
            between the execution of <citerefentry><refentrytitle>glBegin</refentrytitle></citerefentry> and the corresponding
            execution of <citerefentry><refentrytitle>glEnd</refentrytitle></citerefentry>.
        </para>
    </refsect1>
    <refsect1 id="associatedgets"><title>Associated Gets</title>
        <para>
            <citerefentry><refentrytitle>glGetHistogramParameter</refentrytitle></citerefentry>
        </para>
    </refsect1>
    <refsect1 id="seealso"><title>See Also</title>
        <para>
            <citerefentry><refentrytitle>glGetHistogram</refentrytitle></citerefentry>,
            <citerefentry><refentrytitle>glResetHistogram</refentrytitle></citerefentry>
        </para>
    </refsect1>
    <refsect1 id="Copyright"><title>Copyright</title>
        <para>
            Copyright <trademark class="copyright"></trademark> 1991-2006
            Silicon Graphics, Inc. This document is licensed under the SGI
            Free Software B License. For details, see
            <ulink url="http://oss.sgi.com/projects/FreeB/">http://oss.sgi.com/projects/FreeB/</ulink>.
        </para>
    </refsect1>
</refentry>


text:
id: functions-worker
title: Deploy and manage functions worker
sidebar_label: "Setup: Pulsar Functions Worker"
original_id: functions-worker
---

Before using Pulsar Functions, you need to learn how to set up Pulsar Functions worker and how to [configure Functions runtime](functions-runtime).

Pulsar `functions-worker` is a logic component to run Pulsar Functions in cluster mode. Two options are available, and you can select either of the two options based on your requirements.
- [run with brokers](#run-functions-worker-with-brokers)
- [run it separately](#run-functions-worker-separately) in a different broker

:::note

The `--- Service Urls---` lines in the following diagrams represent Pulsar service URLs that Pulsar client and admin use to connect to a Pulsar cluster.

:::

## Run Functions-worker with brokers

The following diagram illustrates the deployment of functions-workers running along with brokers.

![assets/functions-worker-corun.png](/assets/functions-worker-corun.png)

To enable functions-worker running as part of a broker, you need to set `functionsWorkerEnabled` to `true` in the `broker.conf` file.

```conf

functionsWorkerEnabled=true

```

When you set `functionsWorkerEnabled` to `true`, it means that you start functions-worker as part of a broker. You need to configure the `conf/functions_worker.yml` file to customize your functions_worker.

Before you run Functions-work with broker, you have to configure Functions-worker, and then start it with brokers.

### Configure Functions-Worker to run with brokers
In this mode, since `functions-worker` is running as part of broker, most of the settings already inherit from your broker configuration (for example, configurationStore settings, authentication settings, and so on).

Pay attention to the following required settings when configuring functions-worker in this mode.

- `numFunctionPackageReplicas`: The number of replicas to store function packages. The default value is `1`, which is good for standalone deployment. For production deployment, to ensure high availability, set it to be more than `2` .
- `pulsarFunctionsCluster`: Set the value to your Pulsar cluster name (same as the `clusterName` setting in the broker configuration).

If authentication is enabled on the BookKeeper cluster, configure the following BookKeeper authentication settings.

- `bookkeeperClientAuthenticationPlugin`: the BookKeeper client authentication plugin name.
- `bookkeeperClientAuthenticationParametersName`: the BookKeeper client authentication plugin parameters name.
- `bookkeeperClientAuthenticationParameters`: the BookKeeper client authentication plugin parameters.

### Start Functions-worker with broker

Once you have configured the `functions_worker.yml` file, you can start or restart your broker.

And then you can use the following command to verify if `functions-worker` is running well.

```bash

curl <broker-ip>:8080/admin/v2/worker/cluster

```

After entering the command above, a list of active function workers in the cluster is returned. The output is something similar as follows.

```json

[{"workerId":"<worker-id>","workerHostname":"<worker-hostname>","port":8080}]

```

## Run Functions-worker separately

This section illustrates how to run `functions-worker` as a separate process in separate machines.

![assets/functions-worker-separated.png](/assets/functions-worker-separated.png)

> Note
In this mode, make sure `functionsWorkerEnabled` is set to `false`, so you won't start `functions-worker` with brokers by mistake.

### Configure Functions-worker to run separately

To run function-worker separately, you have to configure the following parameters.

#### Worker parameters

- `workerId`: The type is string. It is unique across clusters, used to identify a worker machine.
- `workerHostname`: The hostname of the worker machine.
- `workerPort`: The port that the worker server listens on. Keep it as default if you don't customize it.
- `workerPortTls`: The TLS port that the worker server listens on. Keep it as default if you don't customize it.

#### Function package parameter

- `numFunctionPackageReplicas`: The number of replicas to store function packages. The default value is `1`.

#### Function metadata parameter

- `pulsarServiceUrl`: The Pulsar service URL for your broker cluster.
- `pulsarWebServiceUrl`: The Pulsar web service URL for your broker cluster.
- `pulsarFunctionsCluster`: Set the value to your Pulsar cluster name (same as the `clusterName` setting in the broker configuration).

If authentication is enabled for your broker cluster, you *should* configure the authentication plugin and parameters for the functions worker to communicate with the brokers.

- `clientAuthenticationPlugin`
- `clientAuthenticationParameters`

#### Security settings

If you want to enable security on functions workers, you *should*:
- [Enable TLS transport encryption](#enable-tls-transport-encryption)
- [Enable Authentication Provider](#enable-authentication-provider)
- [Enable Authorization Provider](#enable-authorization-provider)

##### Enable TLS transport encryption

To enable TLS transport encryption, configure the following settings.

```

tlsEnabled: true
tlsCertificateFilePath: /path/to/functions-worker.cert.pem
tlsKeyFilePath:         /path/to/functions-worker.key-pk8.pem
tlsTrustCertsFilePath:  /path/to/ca.cert.pem

```

For details on TLS encryption, refer to [Transport Encryption using TLS](security-tls-transport).

##### Enable Authentication Provider

To enable authentication on Functions Worker, configure the following settings.
> Note
Substitute the *providers list* with the providers you want to enable.

```

authenticationEnabled: true
authenticationProviders: [ provider1, provider2 ]

```

For *SASL Authentication* provider, add `saslJaasClientAllowedIds` and `saslJaasBrokerSectionName`
under `properties` if needed.

```

properties:
  saslJaasClientAllowedIds: .*pulsar.*
  saslJaasBrokerSectionName: Broker

```

For *Token Authentication* prodivder, add necessary settings under `properties` if needed.
See [Token Authentication](security-token-admin) for more details.

```

properties:
  tokenSecretKey:       file://my/secret.key
  # If using public/private
  # tokenPublicKey:     file:///path/to/public.key

```

##### Enable Authorization Provider

To enable authorization on Functions Worker, you need to configure `authorizationEnabled` and `configurationStoreServers`. The authentication provider connects to `configurationStoreServers` to receive namespace policies.

```yaml

authorizationEnabled: true
configurationStoreServers: <configuration-store-servers>

```

You should also configure a list of superuser roles. The superuser roles are able to access any admin API. The following is a configuration example.

```yaml

superUserRoles:
  - role1
  - role2
  - role3

```

#### BookKeeper Authentication

If authentication is enabled on the BookKeeper cluster, you should configure the BookKeeper authentication settings as follows:

- `bookkeeperClientAuthenticationPlugin`: the plugin name of BookKeeper client authentication.
- `bookkeeperClientAuthenticationParametersName`: the plugin parameters name of BookKeeper client authentication.
- `bookkeeperClientAuthenticationParameters`: the plugin parameters of BookKeeper client authentication.

### Start Functions-worker

Once you have finished configuring the `functions_worker.yml` configuration file, you can use the following command to start a `functions-worker`:

```bash

bin/pulsar functions-worker

```

### Configure Proxies for Functions-workers

When you are running `functions-worker` in a separate cluster, the admin rest endpoints are split into two clusters. `functions`, `function-worker`, `source` and `sink` endpoints are now served
by the `functions-worker` cluster, while all the other remaining endpoints are served by the broker cluster.
Hence you need to configure your `pulsar-admin` to use the right service URL accordingly.

In order to address this inconvenience, you can start a proxy cluster for routing the admin rest requests accordingly. Hence you will have one central entry point for your admin service.

If you already have a proxy cluster, continue reading. If you haven't setup a proxy cluster before, you can follow the [instructions](http://pulsar.apache.org/docs/en/administration-proxy/) to
start proxies.

![assets/functions-worker-separated.png](/assets/functions-worker-separated-proxy.png)

To enable routing functions related admin requests to `functions-worker` in a proxy, you can edit the `proxy.conf` file to modify the following settings:

```conf

functionWorkerWebServiceURL=<pulsar-functions-worker-web-service-url>
functionWorkerWebServiceURLTLS=<pulsar-functions-worker-web-service-url>

```

## Compare the Run-with-Broker and Run-separately modes

As described above, you can run Function-worker with brokers, or run it separately. And it is more convenient to run functions-workers along with brokers. However, running functions-workers in a separate cluster provides better resource isolation for running functions in `Process` or `Thread` mode.

Use which mode for your cases, refer to the following guidelines to determine.

Use the `Run-with-Broker` mode in the following cases:
- a) if resource isolation is not required when running functions in `Process` or `Thread` mode;
- b) if you configure the functions-worker to run functions on Kubernetes (where the resource isolation problem is addressed by Kubernetes).

Use the `Run-separately` mode in the following cases:
-  a) you don't have a Kubernetes cluster;
-  b) if you want to run functions and brokers separately.

## Troubleshooting

**Error message: Namespace missing local cluster name in clusters list**

```

Failed to get partitioned topic metadata: org.apache.pulsar.client.api.PulsarClientException$BrokerMetadataException: Namespace missing local cluster name in clusters list: local_cluster=xyz ns=public/functions clusters=[standalone]

```

The error message prompts when either of the cases occurs:
- a) a broker is started with `functionsWorkerEnabled=true`, but the `pulsarFunctionsCluster` is not set to the correct cluster in the `conf/functions_worker.yaml` file;
- b) setting up a geo-replicated Pulsar cluster with `functionsWorkerEnabled=true`, while brokers in one cluster run well, brokers in the other cluster do not work well.

**Workaround**

If any of these cases happens, follow the instructions below to fix the problem:

1. Disable Functions Worker by setting `functionsWorkerEnabled=false`, and restart brokers.

2. Get the current clusters list of `public/functions` namespace.

```bash

bin/pulsar-admin namespaces get-clusters public/functions

```

3. Check if the cluster is in the clusters list. If the cluster is not in the list, add it to the list and update the clusters list.

```bash

bin/pulsar-admin namespaces set-clusters --clusters <existing-clusters>,<new-cluster> public/functions

```

4. After setting the cluster successfully, enable functions worker by setting `functionsWorkerEnabled=true`.

5. Set the correct cluster name in `pulsarFunctionsCluster` in the `conf/functions_worker.yml` file, and restart brokers.


text:
package com.jcwhatever.nucleus.internal;

import com.jcwhatever.nucleus.internal.managed.reflection._ReflectionTestSuite;
import com.jcwhatever.nucleus.internal.providers.bankitems._InternalBankItemsTestSuite;
import com.jcwhatever.nucleus.internal.providers.economy._InternalEconomyTestSuite;
import com.jcwhatever.nucleus.internal.providers.friends._InternalFriendsTestSuite;
import com.jcwhatever.nucleus.internal.providers.math._InternalMathTestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
        _ReflectionTestSuite.class,
        _InternalBankItemsTestSuite.class,
        _InternalEconomyTestSuite.class,
        _InternalFriendsTestSuite.class,
        _InternalMathTestSuite.class
})
public class _InternalTestSuite {
}


text:
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">

    <include file="classpath:config/liquibase/changelog/00000000000000_initial_schema.xml" relativeToChangelogFile="false"/>
</databaseChangeLog>


text:
/*************************************************************************/
/*  style_box.cpp                                                        */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "style_box.h"

#include "scene/main/canvas_item.h"

#include <limits.h>

bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const {
	return true;
}

void StyleBox::set_default_margin(Margin p_margin, float p_value) {
	ERR_FAIL_INDEX((int)p_margin, 4);

	margin[p_margin] = p_value;
	emit_changed();
}

float StyleBox::get_default_margin(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0);

	return margin[p_margin];
}

float StyleBox::get_margin(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0);

	if (margin[p_margin] < 0) {
		return get_style_margin(p_margin);
	} else {
		return margin[p_margin];
	}
}

CanvasItem *StyleBox::get_current_item_drawn() const {
	return CanvasItem::get_current_item_drawn();
}

Size2 StyleBox::get_minimum_size() const {
	return Size2(get_margin(MARGIN_LEFT) + get_margin(MARGIN_RIGHT), get_margin(MARGIN_TOP) + get_margin(MARGIN_BOTTOM));
}

Point2 StyleBox::get_offset() const {
	return Point2(get_margin(MARGIN_LEFT), get_margin(MARGIN_TOP));
}

Size2 StyleBox::get_center_size() const {
	return Size2();
}

Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const {
	return p_rect;
}

void StyleBox::_bind_methods() {
	ClassDB::bind_method(D_METHOD("test_mask", "point", "rect"), &StyleBox::test_mask);

	ClassDB::bind_method(D_METHOD("set_default_margin", "margin", "offset"), &StyleBox::set_default_margin);
	ClassDB::bind_method(D_METHOD("get_default_margin", "margin"), &StyleBox::get_default_margin);

	//ClassDB::bind_method(D_METHOD("set_default_margin"),&StyleBox::set_default_margin);
	//ClassDB::bind_method(D_METHOD("get_default_margin"),&StyleBox::get_default_margin);

	ClassDB::bind_method(D_METHOD("get_margin", "margin"), &StyleBox::get_margin);
	ClassDB::bind_method(D_METHOD("get_minimum_size"), &StyleBox::get_minimum_size);
	ClassDB::bind_method(D_METHOD("get_center_size"), &StyleBox::get_center_size);
	ClassDB::bind_method(D_METHOD("get_offset"), &StyleBox::get_offset);
	ClassDB::bind_method(D_METHOD("get_current_item_drawn"), &StyleBox::get_current_item_drawn);

	ClassDB::bind_method(D_METHOD("draw", "canvas_item", "rect"), &StyleBox::draw);

	ADD_GROUP("Content Margin", "content_margin_");
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_left", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_TOP);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_BOTTOM);
}

StyleBox::StyleBox() {
	for (int i = 0; i < 4; i++) {
		margin[i] = -1;
	}
}

void StyleBoxTexture::set_texture(Ref<Texture2D> p_texture) {
	if (texture == p_texture) {
		return;
	}
	texture = p_texture;
	if (p_texture.is_null()) {
		region_rect = Rect2(0, 0, 0, 0);
	} else {
		region_rect = Rect2(Point2(), texture->get_size());
	}
	emit_signal("texture_changed");
	emit_changed();
	_change_notify("texture");
}

Ref<Texture2D> StyleBoxTexture::get_texture() const {
	return texture;
}

void StyleBoxTexture::set_normal_map(Ref<Texture2D> p_normal_map) {
	if (normal_map == p_normal_map) {
		return;
	}
	normal_map = p_normal_map;
	emit_changed();
}

Ref<Texture2D> StyleBoxTexture::get_normal_map() const {
	return normal_map;
}

void StyleBoxTexture::set_margin_size(Margin p_margin, float p_size) {
	ERR_FAIL_INDEX((int)p_margin, 4);

	margin[p_margin] = p_size;
	emit_changed();
	static const char *margin_prop[4] = {
		"content_margin_left",
		"content_margin_top",
		"content_margin_right",
		"content_margin_bottom",
	};
	_change_notify(margin_prop[p_margin]);
}

float StyleBoxTexture::get_margin_size(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0);

	return margin[p_margin];
}

float StyleBoxTexture::get_style_margin(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0);

	return margin[p_margin];
}

Rect2 StyleBoxTexture::get_draw_rect(const Rect2 &p_rect) const {
	return p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]);
}

void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const {
	if (texture.is_null()) {
		return;
	}

	Rect2 rect = p_rect;
	Rect2 src_rect = region_rect;

	texture->get_rect_region(rect, src_rect, rect, src_rect);

	rect.position.x -= expand_margin[MARGIN_LEFT];
	rect.position.y -= expand_margin[MARGIN_TOP];
	rect.size.x += expand_margin[MARGIN_LEFT] + expand_margin[MARGIN_RIGHT];
	rect.size.y += expand_margin[MARGIN_TOP] + expand_margin[MARGIN_BOTTOM];

	RID normal_rid;
	if (normal_map.is_valid()) {
		normal_rid = normal_map->get_rid();
	}

	RenderingServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), RS::NinePatchAxisMode(axis_h), RS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid);
}

void StyleBoxTexture::set_draw_center(bool p_enabled) {
	draw_center = p_enabled;
	emit_changed();
}

bool StyleBoxTexture::is_draw_center_enabled() const {
	return draw_center;
}

Size2 StyleBoxTexture::get_center_size() const {
	if (texture.is_null()) {
		return Size2();
	}

	return region_rect.size - get_minimum_size();
}

void StyleBoxTexture::set_expand_margin_size(Margin p_expand_margin, float p_size) {
	ERR_FAIL_INDEX((int)p_expand_margin, 4);
	expand_margin[p_expand_margin] = p_size;
	emit_changed();
}

void StyleBoxTexture::set_expand_margin_size_individual(float p_left, float p_top, float p_right, float p_bottom) {
	expand_margin[MARGIN_LEFT] = p_left;
	expand_margin[MARGIN_TOP] = p_top;
	expand_margin[MARGIN_RIGHT] = p_right;
	expand_margin[MARGIN_BOTTOM] = p_bottom;
	emit_changed();
}

void StyleBoxTexture::set_expand_margin_size_all(float p_expand_margin_size) {
	for (int i = 0; i < 4; i++) {
		expand_margin[i] = p_expand_margin_size;
	}
	emit_changed();
}

float StyleBoxTexture::get_expand_margin_size(Margin p_expand_margin) const {
	ERR_FAIL_INDEX_V((int)p_expand_margin, 4, 0);
	return expand_margin[p_expand_margin];
}

void StyleBoxTexture::set_region_rect(const Rect2 &p_region_rect) {
	if (region_rect == p_region_rect) {
		return;
	}

	region_rect = p_region_rect;
	emit_changed();
	_change_notify("region");
}

Rect2 StyleBoxTexture::get_region_rect() const {
	return region_rect;
}

void StyleBoxTexture::set_h_axis_stretch_mode(AxisStretchMode p_mode) {
	ERR_FAIL_INDEX((int)p_mode, 3);
	axis_h = p_mode;
	emit_changed();
}

StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_h_axis_stretch_mode() const {
	return axis_h;
}

void StyleBoxTexture::set_v_axis_stretch_mode(AxisStretchMode p_mode) {
	ERR_FAIL_INDEX((int)p_mode, 3);
	axis_v = p_mode;
	emit_changed();
}

StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_v_axis_stretch_mode() const {
	return axis_v;
}

void StyleBoxTexture::set_modulate(const Color &p_modulate) {
	if (modulate == p_modulate) {
		return;
	}
	modulate = p_modulate;
	emit_changed();
}

Color StyleBoxTexture::get_modulate() const {
	return modulate;
}

void StyleBoxTexture::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_texture", "texture"), &StyleBoxTexture::set_texture);
	ClassDB::bind_method(D_METHOD("get_texture"), &StyleBoxTexture::get_texture);

	ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &StyleBoxTexture::set_normal_map);
	ClassDB::bind_method(D_METHOD("get_normal_map"), &StyleBoxTexture::get_normal_map);

	ClassDB::bind_method(D_METHOD("set_margin_size", "margin", "size"), &StyleBoxTexture::set_margin_size);
	ClassDB::bind_method(D_METHOD("get_margin_size", "margin"), &StyleBoxTexture::get_margin_size);

	ClassDB::bind_method(D_METHOD("set_expand_margin_size", "margin", "size"), &StyleBoxTexture::set_expand_margin_size);
	ClassDB::bind_method(D_METHOD("set_expand_margin_all", "size"), &StyleBoxTexture::set_expand_margin_size_all);
	ClassDB::bind_method(D_METHOD("set_expand_margin_individual", "size_left", "size_top", "size_right", "size_bottom"), &StyleBoxTexture::set_expand_margin_size_individual);
	ClassDB::bind_method(D_METHOD("get_expand_margin_size", "margin"), &StyleBoxTexture::get_expand_margin_size);

	ClassDB::bind_method(D_METHOD("set_region_rect", "region"), &StyleBoxTexture::set_region_rect);
	ClassDB::bind_method(D_METHOD("get_region_rect"), &StyleBoxTexture::get_region_rect);

	ClassDB::bind_method(D_METHOD("set_draw_center", "enable"), &StyleBoxTexture::set_draw_center);
	ClassDB::bind_method(D_METHOD("is_draw_center_enabled"), &StyleBoxTexture::is_draw_center_enabled);

	ClassDB::bind_method(D_METHOD("set_modulate", "color"), &StyleBoxTexture::set_modulate);
	ClassDB::bind_method(D_METHOD("get_modulate"), &StyleBoxTexture::get_modulate);

	ClassDB::bind_method(D_METHOD("set_h_axis_stretch_mode", "mode"), &StyleBoxTexture::set_h_axis_stretch_mode);
	ClassDB::bind_method(D_METHOD("get_h_axis_stretch_mode"), &StyleBoxTexture::get_h_axis_stretch_mode);

	ClassDB::bind_method(D_METHOD("set_v_axis_stretch_mode", "mode"), &StyleBoxTexture::set_v_axis_stretch_mode);
	ClassDB::bind_method(D_METHOD("get_v_axis_stretch_mode"), &StyleBoxTexture::get_v_axis_stretch_mode);

	ADD_SIGNAL(MethodInfo("texture_changed"));

	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_map", "get_normal_map");
	ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
	ADD_GROUP("Margin", "margin_");
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_TOP);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_BOTTOM);
	ADD_GROUP("Expand Margin", "expand_margin_");
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_TOP);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_BOTTOM);
	ADD_GROUP("Axis Stretch", "axis_stretch_");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode");
	ADD_GROUP("Modulate", "modulate_");
	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate_color"), "set_modulate", "get_modulate");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled");

	BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_STRETCH);
	BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_TILE);
	BIND_ENUM_CONSTANT(AXIS_STRETCH_MODE_TILE_FIT);
}

StyleBoxTexture::StyleBoxTexture() {
	for (int i = 0; i < 4; i++) {
		margin[i] = 0;
		expand_margin[i] = 0;
	}
	draw_center = true;
	modulate = Color(1, 1, 1, 1);

	axis_h = AXIS_STRETCH_MODE_STRETCH;
	axis_v = AXIS_STRETCH_MODE_STRETCH;
}

StyleBoxTexture::~StyleBoxTexture() {
}

////////////////

void StyleBoxFlat::set_bg_color(const Color &p_color) {
	bg_color = p_color;
	emit_changed();
}

Color StyleBoxFlat::get_bg_color() const {
	return bg_color;
}

void StyleBoxFlat::set_border_color(const Color &p_color) {
	border_color = p_color;
	emit_changed();
}

Color StyleBoxFlat::get_border_color() const {
	return border_color;
}

void StyleBoxFlat::set_border_width_all(int p_size) {
	border_width[0] = p_size;
	border_width[1] = p_size;
	border_width[2] = p_size;
	border_width[3] = p_size;
	emit_changed();
}

int StyleBoxFlat::get_border_width_min() const {
	return MIN(MIN(border_width[0], border_width[1]), MIN(border_width[2], border_width[3]));
}

void StyleBoxFlat::set_border_width(Margin p_margin, int p_width) {
	ERR_FAIL_INDEX((int)p_margin, 4);
	border_width[p_margin] = p_width;
	emit_changed();
}

int StyleBoxFlat::get_border_width(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0);
	return border_width[p_margin];
}

void StyleBoxFlat::set_border_blend(bool p_blend) {
	blend_border = p_blend;
	emit_changed();
}

bool StyleBoxFlat::get_border_blend() const {
	return blend_border;
}

void StyleBoxFlat::set_corner_radius_all(int radius) {
	for (int i = 0; i < 4; i++) {
		corner_radius[i] = radius;
	}

	emit_changed();
}

void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left) {
	corner_radius[0] = radius_top_left;
	corner_radius[1] = radius_top_right;
	corner_radius[2] = radius_botton_right;
	corner_radius[3] = radius_bottom_left;

	emit_changed();
}

int StyleBoxFlat::get_corner_radius_min() const {
	int smallest = corner_radius[0];
	for (int i = 1; i < 4; i++) {
		if (smallest > corner_radius[i]) {
			smallest = corner_radius[i];
		}
	}
	return smallest;
}

void StyleBoxFlat::set_corner_radius(const Corner p_corner, const int radius) {
	ERR_FAIL_INDEX((int)p_corner, 4);
	corner_radius[p_corner] = radius;
	emit_changed();
}

int StyleBoxFlat::get_corner_radius(const Corner p_corner) const {
	ERR_FAIL_INDEX_V((int)p_corner, 4, 0);
	return corner_radius[p_corner];
}

void StyleBoxFlat::set_expand_margin_size(Margin p_expand_margin, float p_size) {
	ERR_FAIL_INDEX((int)p_expand_margin, 4);
	expand_margin[p_expand_margin] = p_size;
	emit_changed();
}

void StyleBoxFlat::set_expand_margin_size_individual(float p_left, float p_top, float p_right, float p_bottom) {
	expand_margin[MARGIN_LEFT] = p_left;
	expand_margin[MARGIN_TOP] = p_top;
	expand_margin[MARGIN_RIGHT] = p_right;
	expand_margin[MARGIN_BOTTOM] = p_bottom;
	emit_changed();
}

void StyleBoxFlat::set_expand_margin_size_all(float p_expand_margin_size) {
	for (int i = 0; i < 4; i++) {
		expand_margin[i] = p_expand_margin_size;
	}
	emit_changed();
}

float StyleBoxFlat::get_expand_margin_size(Margin p_expand_margin) const {
	ERR_FAIL_INDEX_V((int)p_expand_margin, 4, 0.0);
	return expand_margin[p_expand_margin];
}

void StyleBoxFlat::set_draw_center(bool p_enabled) {
	draw_center = p_enabled;
	emit_changed();
}

bool StyleBoxFlat::is_draw_center_enabled() const {
	return draw_center;
}

void StyleBoxFlat::set_shadow_color(const Color &p_color) {
	shadow_color = p_color;
	emit_changed();
}

Color StyleBoxFlat::get_shadow_color() const {
	return shadow_color;
}

void StyleBoxFlat::set_shadow_size(const int &p_size) {
	shadow_size = p_size;
	emit_changed();
}

int StyleBoxFlat::get_shadow_size() const {
	return shadow_size;
}

void StyleBoxFlat::set_shadow_offset(const Point2 &p_offset) {
	shadow_offset = p_offset;
	emit_changed();
}

Point2 StyleBoxFlat::get_shadow_offset() const {
	return shadow_offset;
}

void StyleBoxFlat::set_anti_aliased(const bool &p_anti_aliased) {
	anti_aliased = p_anti_aliased;
	emit_changed();
}

bool StyleBoxFlat::is_anti_aliased() const {
	return anti_aliased;
}

void StyleBoxFlat::set_aa_size(const int &p_aa_size) {
	aa_size = CLAMP(p_aa_size, 1, 5);
	emit_changed();
}

int StyleBoxFlat::get_aa_size() const {
	return aa_size;
}

void StyleBoxFlat::set_corner_detail(const int &p_corner_detail) {
	corner_detail = CLAMP(p_corner_detail, 1, 20);
	emit_changed();
}

int StyleBoxFlat::get_corner_detail() const {
	return corner_detail;
}

Size2 StyleBoxFlat::get_center_size() const {
	return Size2();
}

inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_rect, const int corner_radius[4], int *inner_corner_radius) {
	int border_left = inner_rect.position.x - style_rect.position.x;
	int border_top = inner_rect.position.y - style_rect.position.y;
	int border_right = style_rect.size.width - inner_rect.size.width - border_left;
	int border_bottom = style_rect.size.height - inner_rect.size.height - border_top;

	int rad;
	//tl
	rad = MIN(border_top, border_left);
	inner_corner_radius[0] = MAX(corner_radius[0] - rad, 0);

	//tr
	rad = MIN(border_top, border_right);
	inner_corner_radius[1] = MAX(corner_radius[1] - rad, 0);

	//br
	rad = MIN(border_bottom, border_right);
	inner_corner_radius[2] = MAX(corner_radius[2] - rad, 0);

	//bl
	rad = MIN(border_bottom, border_left);
	inner_corner_radius[3] = MAX(corner_radius[3] - rad, 0);
}

inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const int corner_radius[4],
		const Rect2 &ring_rect, const Rect2 &inner_rect, const Color &inner_color, const Color &outer_color, const int corner_detail, const bool fill_center = false) {
	int vert_offset = verts.size();
	if (!vert_offset) {
		vert_offset = 0;
	}

	int adapted_corner_detail = (corner_radius[0] == 0 && corner_radius[1] == 0 && corner_radius[2] == 0 && corner_radius[3] == 0) ? 1 : corner_detail;

	int ring_corner_radius[4];
	set_inner_corner_radius(style_rect, ring_rect, corner_radius, ring_corner_radius);

	//corner radius center points
	Vector<Point2> outer_points;
	outer_points.push_back(ring_rect.position + Vector2(ring_corner_radius[0], ring_corner_radius[0])); //tl
	outer_points.push_back(Point2(ring_rect.position.x + ring_rect.size.x - ring_corner_radius[1], ring_rect.position.y + ring_corner_radius[1])); //tr
	outer_points.push_back(ring_rect.position + ring_rect.size - Vector2(ring_corner_radius[2], ring_corner_radius[2])); //br
	outer_points.push_back(Point2(ring_rect.position.x + ring_corner_radius[3], ring_rect.position.y + ring_rect.size.y - ring_corner_radius[3])); //bl

	int inner_corner_radius[4];
	set_inner_corner_radius(style_rect, inner_rect, corner_radius, inner_corner_radius);

	Vector<Point2> inner_points;
	inner_points.push_back(inner_rect.position + Vector2(inner_corner_radius[0], inner_corner_radius[0])); //tl
	inner_points.push_back(Point2(inner_rect.position.x + inner_rect.size.x - inner_corner_radius[1], inner_rect.position.y + inner_corner_radius[1])); //tr
	inner_points.push_back(inner_rect.position + inner_rect.size - Vector2(inner_corner_radius[2], inner_corner_radius[2])); //br
	inner_points.push_back(Point2(inner_rect.position.x + inner_corner_radius[3], inner_rect.position.y + inner_rect.size.y - inner_corner_radius[3])); //bl

	//calculate the vert array
	for (int corner_index = 0; corner_index < 4; corner_index++) {
		for (int detail = 0; detail <= adapted_corner_detail; detail++) {
			for (int inner_outer = 0; inner_outer < 2; inner_outer++) {
				float radius;
				Color color;
				Point2 corner_point;
				if (inner_outer == 0) {
					radius = inner_corner_radius[corner_index];
					color = inner_color;
					corner_point = inner_points[corner_index];
				} else {
					radius = ring_corner_radius[corner_index];
					color = outer_color;
					corner_point = outer_points[corner_index];
				}
				float x = radius * (float)cos((double)corner_index * Math_PI / 2.0 + (double)detail / (double)adapted_corner_detail * Math_PI / 2.0 + Math_PI) + corner_point.x;
				float y = radius * (float)sin((double)corner_index * Math_PI / 2.0 + (double)detail / (double)adapted_corner_detail * Math_PI / 2.0 + Math_PI) + corner_point.y;
				verts.push_back(Vector2(x, y));
				colors.push_back(color);
			}
		}
	}

	int ring_vert_count = verts.size() - vert_offset;

	//fill the indices and the colors for the border
	for (int i = 0; i < ring_vert_count; i++) {
		indices.push_back(vert_offset + ((i + 0) % ring_vert_count));
		indices.push_back(vert_offset + ((i + 2) % ring_vert_count));
		indices.push_back(vert_offset + ((i + 1) % ring_vert_count));
	}

	if (fill_center) {
		//fill the indices and the colors for the center
		for (int index = 0; index < ring_vert_count / 2; index += 2) {
			int i = index;
			//poly 1
			indices.push_back(vert_offset + i);
			indices.push_back(vert_offset + ring_vert_count - 4 - i);
			indices.push_back(vert_offset + i + 2);
			//poly 2
			indices.push_back(vert_offset + i);
			indices.push_back(vert_offset + ring_vert_count - 2 - i);
			indices.push_back(vert_offset + ring_vert_count - 4 - i);
		}
	}
}

inline void adapt_values(int p_index_a, int p_index_b, int *adapted_values, const int *p_values, const real_t p_width, const int p_max_a, const int p_max_b) {
	if (p_values[p_index_a] + p_values[p_index_b] > p_width) {
		float factor;
		int newValue;

		factor = (float)p_width / (float)(p_values[p_index_a] + p_values[p_index_b]);

		newValue = (int)(p_values[p_index_a] * factor);
		if (newValue < adapted_values[p_index_a]) {
			adapted_values[p_index_a] = newValue;
		}
		newValue = (int)(p_values[p_index_b] * factor);
		if (newValue < adapted_values[p_index_b]) {
			adapted_values[p_index_b] = newValue;
		}
	} else {
		adapted_values[p_index_a] = MIN(p_values[p_index_a], adapted_values[p_index_a]);
		adapted_values[p_index_b] = MIN(p_values[p_index_b], adapted_values[p_index_b]);
	}
	adapted_values[p_index_a] = MIN(p_max_a, adapted_values[p_index_a]);
	adapted_values[p_index_b] = MIN(p_max_b, adapted_values[p_index_b]);
}

Rect2 StyleBoxFlat::get_draw_rect(const Rect2 &p_rect) const {
	Rect2 draw_rect = p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]);

	if (shadow_size > 0) {
		Rect2 shadow_rect = draw_rect.grow(shadow_size);
		shadow_rect.position += shadow_offset;
		draw_rect = draw_rect.merge(shadow_rect);
	}

	return draw_rect;
}

void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
	//PREPARATIONS
	bool draw_border = (border_width[0] > 0) || (border_width[1] > 0) || (border_width[2] > 0) || (border_width[3] > 0);
	bool draw_shadow = (shadow_size > 0);
	if (!draw_border && !draw_center && !draw_shadow) {
		return;
	}

	Rect2 style_rect = p_rect.grow_individual(expand_margin[MARGIN_LEFT], expand_margin[MARGIN_TOP], expand_margin[MARGIN_RIGHT], expand_margin[MARGIN_BOTTOM]);
	if (Math::is_zero_approx(style_rect.size.width) || Math::is_zero_approx(style_rect.size.height)) {
		return;
	}

	bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0);
	bool aa_on = rounded_corners && anti_aliased;
	float aa_size_grow = 0.5 * ((float)aa_size + 1.0);

	bool blend_on = blend_border && draw_border;

	Color border_color_alpha = Color(border_color.r, border_color.g, border_color.b, 0);
	Color border_color_blend = (draw_center ? bg_color : border_color_alpha);
	Color border_color_inner = blend_on ? border_color_blend : border_color;

	//adapt borders (prevent weird overlapping/glitchy drawings)
	int width = MAX(style_rect.size.width, 0);
	int height = MAX(style_rect.size.height, 0);
	int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
	adapt_values(MARGIN_TOP, MARGIN_BOTTOM, adapted_border, border_width, height, height, height);
	adapt_values(MARGIN_LEFT, MARGIN_RIGHT, adapted_border, border_width, width, width, width);

	//adapt corners (prevent weird overlapping/glitchy drawings)
	int adapted_corner[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
	adapt_values(CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]);
	adapt_values(CORNER_TOP_LEFT, CORNER_BOTTOM_LEFT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]);
	adapt_values(CORNER_TOP_LEFT, CORNER_TOP_RIGHT, adapted_corner, corner_radius, width, width - adapted_border[MARGIN_RIGHT], width - adapted_border[MARGIN_LEFT]);
	adapt_values(CORNER_BOTTOM_LEFT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, width, width - adapted_border[MARGIN_RIGHT], width - adapted_border[MARGIN_LEFT]);

	Rect2 infill_rect = style_rect.grow_individual(-adapted_border[MARGIN_LEFT], -adapted_border[MARGIN_TOP], -adapted_border[MARGIN_RIGHT], -adapted_border[MARGIN_BOTTOM]);

	Rect2 border_style_rect = style_rect;
	if (aa_on) {
		for (int i = 0; i < 4; i++) {
			if (border_width[i] > 0) {
				border_style_rect = border_style_rect.grow_margin((Margin)i, -aa_size_grow);
			}
		}
	}

	Vector<Point2> verts;
	Vector<int> indices;
	Vector<Color> colors;
	Vector<Point2> uvs;

	//DRAW SHADOW
	if (draw_shadow) {
		Rect2 shadow_inner_rect = style_rect;
		shadow_inner_rect.position += shadow_offset;

		Rect2 shadow_rect = style_rect.grow(shadow_size);
		shadow_rect.position += shadow_offset;

		Color shadow_color_transparent = Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);

		draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner,
				shadow_rect, shadow_inner_rect, shadow_color, shadow_color_transparent, corner_detail);

		if (draw_center) {
			draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner,
					shadow_inner_rect, shadow_inner_rect, shadow_color, shadow_color, corner_detail, true);
		}
	}

	//DRAW border
	if (draw_border) {
		draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
				border_style_rect, infill_rect, border_color_inner, border_color, corner_detail);
	}

	//DRAW INFILL
	if (draw_center && (!aa_on || blend_on || !draw_border)) {
		draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
				infill_rect, infill_rect, bg_color, bg_color, corner_detail, true);
	}

	if (aa_on) {
		int aa_border_width[4];
		int aa_fill_width[4];
		if (draw_border) {
			for (int i = 0; i < 4; i++) {
				if (border_width[i] > 0) {
					aa_border_width[i] = aa_size_grow;
					aa_fill_width[i] = 0;
				} else {
					aa_border_width[i] = 0;
					aa_fill_width[i] = aa_size_grow;
				}
			}
		} else {
			for (int i = 0; i < 4; i++) {
				aa_border_width[i] = 0;
				aa_fill_width[i] = aa_size_grow;
			}
		}

		Rect2 infill_inner_rect = infill_rect.grow_individual(-aa_border_width[MARGIN_LEFT], -aa_border_width[MARGIN_TOP],
				-aa_border_width[MARGIN_RIGHT], -aa_border_width[MARGIN_BOTTOM]);

		if (draw_center) {
			if (!blend_on && draw_border) {
				//DRAW INFILL WITHIN BORDER AA
				draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
						infill_inner_rect, infill_inner_rect, bg_color, bg_color, corner_detail, true);
			}

			if (!blend_on || !draw_border) {
				Rect2 infill_aa_rect = infill_rect.grow_individual(aa_fill_width[MARGIN_LEFT], aa_fill_width[MARGIN_TOP],
						aa_fill_width[MARGIN_RIGHT], aa_fill_width[MARGIN_BOTTOM]);

				Color alpha_bg = Color(bg_color.r, bg_color.g, bg_color.b, 0);

				//INFILL AA
				draw_ring(verts, indices, colors, style_rect, adapted_corner,
						infill_aa_rect, infill_rect, bg_color, alpha_bg, corner_detail);
			}
		}

		if (draw_border) {
			if (!blend_on) {
				//DRAW INNER BORDER AA
				draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
						infill_rect, infill_inner_rect, border_color_blend, border_color, corner_detail);
			}

			//DRAW OUTER BORDER AA
			draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
					style_rect, border_style_rect, border_color, border_color_alpha, corner_detail);
		}
	}

	//COMPUTE UV COORDINATES
	Rect2 uv_rect = style_rect.grow(aa_on ? aa_size_grow : 0);
	uvs.resize(verts.size());
	for (int i = 0; i < verts.size(); i++) {
		uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width;
		uvs.write[i].y = (verts[i].y - uv_rect.position.y) / uv_rect.size.height;
	}

	//DRAWING
	RenderingServer *vs = RenderingServer::get_singleton();
	vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors, uvs);
}

float StyleBoxFlat::get_style_margin(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0);
	return border_width[p_margin];
}

void StyleBoxFlat::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &StyleBoxFlat::set_bg_color);
	ClassDB::bind_method(D_METHOD("get_bg_color"), &StyleBoxFlat::get_bg_color);

	ClassDB::bind_method(D_METHOD("set_border_color", "color"), &StyleBoxFlat::set_border_color);
	ClassDB::bind_method(D_METHOD("get_border_color"), &StyleBoxFlat::get_border_color);

	ClassDB::bind_method(D_METHOD("set_border_width_all", "width"), &StyleBoxFlat::set_border_width_all);
	ClassDB::bind_method(D_METHOD("get_border_width_min"), &StyleBoxFlat::get_border_width_min);

	ClassDB::bind_method(D_METHOD("set_border_width", "margin", "width"), &StyleBoxFlat::set_border_width);
	ClassDB::bind_method(D_METHOD("get_border_width", "margin"), &StyleBoxFlat::get_border_width);

	ClassDB::bind_method(D_METHOD("set_border_blend", "blend"), &StyleBoxFlat::set_border_blend);
	ClassDB::bind_method(D_METHOD("get_border_blend"), &StyleBoxFlat::get_border_blend);

	ClassDB::bind_method(D_METHOD("set_corner_radius_individual", "radius_top_left", "radius_top_right", "radius_bottom_right", "radius_bottom_left"), &StyleBoxFlat::set_corner_radius_individual);
	ClassDB::bind_method(D_METHOD("set_corner_radius_all", "radius"), &StyleBoxFlat::set_corner_radius_all);

	ClassDB::bind_method(D_METHOD("set_corner_radius", "corner", "radius"), &StyleBoxFlat::set_corner_radius);
	ClassDB::bind_method(D_METHOD("get_corner_radius", "corner"), &StyleBoxFlat::get_corner_radius);

	ClassDB::bind_method(D_METHOD("set_expand_margin", "margin", "size"), &StyleBoxFlat::set_expand_margin_size);
	ClassDB::bind_method(D_METHOD("set_expand_margin_all", "size"), &StyleBoxFlat::set_expand_margin_size_all);
	ClassDB::bind_method(D_METHOD("set_expand_margin_individual", "size_left", "size_top", "size_right", "size_bottom"), &StyleBoxFlat::set_expand_margin_size_individual);
	ClassDB::bind_method(D_METHOD("get_expand_margin", "margin"), &StyleBoxFlat::get_expand_margin_size);

	ClassDB::bind_method(D_METHOD("set_draw_center", "draw_center"), &StyleBoxFlat::set_draw_center);
	ClassDB::bind_method(D_METHOD("is_draw_center_enabled"), &StyleBoxFlat::is_draw_center_enabled);

	ClassDB::bind_method(D_METHOD("set_shadow_color", "color"), &StyleBoxFlat::set_shadow_color);
	ClassDB::bind_method(D_METHOD("get_shadow_color"), &StyleBoxFlat::get_shadow_color);

	ClassDB::bind_method(D_METHOD("set_shadow_size", "size"), &StyleBoxFlat::set_shadow_size);
	ClassDB::bind_method(D_METHOD("get_shadow_size"), &StyleBoxFlat::get_shadow_size);

	ClassDB::bind_method(D_METHOD("set_shadow_offset", "offset"), &StyleBoxFlat::set_shadow_offset);
	ClassDB::bind_method(D_METHOD("get_shadow_offset"), &StyleBoxFlat::get_shadow_offset);

	ClassDB::bind_method(D_METHOD("set_anti_aliased", "anti_aliased"), &StyleBoxFlat::set_anti_aliased);
	ClassDB::bind_method(D_METHOD("is_anti_aliased"), &StyleBoxFlat::is_anti_aliased);

	ClassDB::bind_method(D_METHOD("set_aa_size", "size"), &StyleBoxFlat::set_aa_size);
	ClassDB::bind_method(D_METHOD("get_aa_size"), &StyleBoxFlat::get_aa_size);

	ClassDB::bind_method(D_METHOD("set_corner_detail", "detail"), &StyleBoxFlat::set_corner_detail);
	ClassDB::bind_method(D_METHOD("get_corner_detail"), &StyleBoxFlat::get_corner_detail);

	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "bg_color"), "set_bg_color", "get_bg_color");

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_center"), "set_draw_center", "is_draw_center_enabled");

	ADD_GROUP("Border Width", "border_width_");
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_TOP);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1"), "set_border_width", "get_border_width", MARGIN_BOTTOM);

	ADD_GROUP("Border", "border_");
	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color");

	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "border_blend"), "set_border_blend", "get_border_blend");

	ADD_GROUP("Corner Radius", "corner_radius_");
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT);

	ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail");

	ADD_GROUP("Expand Margin", "expand_margin_");
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_LEFT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_RIGHT);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_TOP);
	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_BOTTOM);

	ADD_GROUP("Shadow", "shadow_");
	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size"), "set_shadow_size", "get_shadow_size");
	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset"), "set_shadow_offset", "get_shadow_offset");

	ADD_GROUP("Anti Aliasing", "anti_aliasing_");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "anti_aliasing"), "set_anti_aliased", "is_anti_aliased");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "1,5,1"), "set_aa_size", "get_aa_size");
}

StyleBoxFlat::StyleBoxFlat() {
	bg_color = Color(0.6, 0.6, 0.6);
	shadow_color = Color(0, 0, 0, 0.6);
	border_color = Color(0.8, 0.8, 0.8);

	blend_border = false;
	draw_center = true;
	anti_aliased = true;

	shadow_size = 0;
	shadow_offset = Point2(0, 0);
	corner_detail = 8;
	aa_size = 1;

	border_width[0] = 0;
	border_width[1] = 0;
	border_width[2] = 0;
	border_width[3] = 0;

	expand_margin[0] = 0;
	expand_margin[1] = 0;
	expand_margin[2] = 0;
	expand_margin[3] = 0;

	corner_radius[0] = 0;
	corner_radius[1] = 0;
	corner_radius[2] = 0;
	corner_radius[3] = 0;
}

StyleBoxFlat::~StyleBoxFlat() {
}

void StyleBoxLine::set_color(const Color &p_color) {
	color = p_color;
	emit_changed();
}

Color StyleBoxLine::get_color() const {
	return color;
}

void StyleBoxLine::set_thickness(int p_thickness) {
	thickness = p_thickness;
	emit_changed();
}

int StyleBoxLine::get_thickness() const {
	return thickness;
}

void StyleBoxLine::set_vertical(bool p_vertical) {
	vertical = p_vertical;
	emit_changed();
}

bool StyleBoxLine::is_vertical() const {
	return vertical;
}

void StyleBoxLine::set_grow_end(float p_grow_end) {
	grow_end = p_grow_end;
	emit_changed();
}

float StyleBoxLine::get_grow_end() const {
	return grow_end;
}

void StyleBoxLine::set_grow_begin(float p_grow_begin) {
	grow_begin = p_grow_begin;
	emit_changed();
}

float StyleBoxLine::get_grow_begin() const {
	return grow_begin;
}

void StyleBoxLine::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_color", "color"), &StyleBoxLine::set_color);
	ClassDB::bind_method(D_METHOD("get_color"), &StyleBoxLine::get_color);
	ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &StyleBoxLine::set_thickness);
	ClassDB::bind_method(D_METHOD("get_thickness"), &StyleBoxLine::get_thickness);
	ClassDB::bind_method(D_METHOD("set_grow_begin", "offset"), &StyleBoxLine::set_grow_begin);
	ClassDB::bind_method(D_METHOD("get_grow_begin"), &StyleBoxLine::get_grow_begin);
	ClassDB::bind_method(D_METHOD("set_grow_end", "offset"), &StyleBoxLine::set_grow_end);
	ClassDB::bind_method(D_METHOD("get_grow_end"), &StyleBoxLine::get_grow_end);
	ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &StyleBoxLine::set_vertical);
	ClassDB::bind_method(D_METHOD("is_vertical"), &StyleBoxLine::is_vertical);

	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_begin", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_begin", "get_grow_begin");
	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_end", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_end", "get_grow_end");
	ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10"), "set_thickness", "get_thickness");
	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
}

float StyleBoxLine::get_style_margin(Margin p_margin) const {
	ERR_FAIL_INDEX_V((int)p_margin, 4, thickness);
	return thickness;
}

Size2 StyleBoxLine::get_center_size() const {
	return Size2();
}

void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const {
	RenderingServer *vs = RenderingServer::get_singleton();
	Rect2i r = p_rect;

	if (vertical) {
		r.position.y -= grow_begin;
		r.size.y += (grow_begin + grow_end);
		r.size.x = thickness;
	} else {
		r.position.x -= grow_begin;
		r.size.x += (grow_begin + grow_end);
		r.size.y = thickness;
	}

	vs->canvas_item_add_rect(p_canvas_item, r, color);
}

StyleBoxLine::StyleBoxLine() {
	grow_begin = 1.0;
	grow_end = 1.0;
	thickness = 1;
	color = Color(0.0, 0.0, 0.0);
	vertical = false;
}

StyleBoxLine::~StyleBoxLine() {}


text:
//
//  OCLogObjectConsolePrinter.h
//  OCLogService
//
//  Created by Dmitry Fantastik on 11/16/13.
//  Copyright (c) 2013 fantastik. All rights reserved.
//

#import <Foundation/Foundation.h>

/*
 * OCLogObjectConsolePrinter
 *
 * if OCLogObject implements that protocol
 * than console printer will use these method
 * as object description
 */
@protocol OCLogObjectConsolePrinter <NSObject>

- (NSString *)consolePrint;

@end


text:
#include <stdexcept>

#include "AudioFile.h"
#include "FileInput.h"
#include "FileOutput.h"
#include "IOBase.h"
#include "LogMessage.h"

namespace Bavieca {

// constructor
AudioFile::AudioFile() {
}

// destructor
AudioFile::~AudioFile() {
}

// load the data
short *AudioFile::load(const char *strFile, int *iSamples) {

	short *sSamples = NULL;
	try {

		FileInput file(strFile,true);
		file.open();

		*iSamples = file.size()/2;
		assert(*iSamples > 0);
		sSamples = new short[*iSamples];
		IOBase::readBytes(file.getStream(),reinterpret_cast<char*>(sSamples),*iSamples*sizeof(short));

		file.close();

	} catch (std::runtime_error) {
		BVC_ERROR<< "unable to load the audio file: " << strFile;
	}

	return sSamples;
}

// store the data
void AudioFile::store(const char *strFile, short *sSamples, int iSamples) {

	assert((iSamples >= 0) && (sSamples));

	FileOutput file(strFile,true);
	IOBase::writeBytes(file.getStream(),reinterpret_cast<char*>(sSamples),iSamples*sizeof(short));
	file.close();
}

};	// end-of-namespace


text:
layout: default
title: Discords - Productions - Fail Better Productions
menu-item: productions
submenu-item: discords
styles:
 - /css/colours.css
 - ../production.css
 - ./styles.css
styles-ie6: ../production-ie6.css
---

Discords

after Shakespeare

Cast and Crew

Writer/Director

Jonathan Heron

Designer

Nomi Everall

Lighting Designer

Dave Thwaites

Performers (2011)

Ben Edmunds

Lucy Katz

Oliver Hayes

Soraya Nabipour

Stephanie Taylor

Thom May

Tom Syms

Zoë Walshe

About the production

       Warwick Arts Centre - 21st & 22nd January 2011 @ 7:45pm

       Presented as part of a double bill with Diary of a Madman

<q>"Hell is murky"</q>

This piece emerged from our BeckettLab (2009) and takes key theatrical ideas from the work of Samuel Beckett and applies them to a devised adaptation of Shakespeare's King Lear. A <q>'theatre machine'</q> (Brook, 1968) in every sense, this work uses an intensely restrictive shape to move through numerous iterations and performance patterns. Isolating simply the performer's heads, which emerge from a 'cabinet of curiosities' - or perhaps an archive of disembodied heads - the piece is named after the notion of the 'discord':

        When creatures like us appeared, which had bodies and conscious minds, they were, as Nietzsche called them, <q>"hybrids of plants and ghosts"</q>, the combination of a bounded, well-circumscribed, easily identifiable living object with seemingly unbounded, internal, and difficult-to-localize mental animation. He also called those creatures <q>"discords"</q>, for they did possess a strange marriage of the clearly material with the apparently insubstantial.

        [Demasio, Antonio, The Feeling of What Happens, Vintage, 2000, p.143]

The re-iteration of Shakespearean text through the theatrical device of the disembodied head, introduced a particularly Beckettian intensity. In this sense, our production recalled the corporeal abstractions of Play (1963), Not I (1973), and That Time (1976) in which Beckett reduces the human form to disembodied heads or even mouths. When his last theatrical work - What Where (1983) - was adapted for German television, Beckett replaced the bodies of stage-play with heads for the broadcast. This process of reduction was recycled for our devising process and used as a stimulus for new work.

A work-in-progress of Discords was performed at our New Work Festival (May, 2010) by Ben Edmunds, Carl Cerny, Fran Duncan, Lucy Katz, Oliver Hayes, Soraya Nabipour, Stephanie Taylor and Tom Syms, with Hari Carpenter as Assistant Director, Rima Dodd as Assistant Stage Manager and Sita Thomas as Movement Director.