1237 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1237 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * File containing the ezcGraphGdDriver class
 | 
						|
 *
 | 
						|
 * @package Graph
 | 
						|
 * @version 1.4.3
 | 
						|
 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
 | 
						|
 * @license http://ez.no/licenses/new_bsd New BSD License
 | 
						|
 */
 | 
						|
/**
 | 
						|
 * Driver using PHPs ext/gd to draw images. The GD extension is available on 
 | 
						|
 * nearly all PHP installations, but slow and produces slightly incorrect 
 | 
						|
 * results.
 | 
						|
 *
 | 
						|
 * The driver can make use of the different font extensions available with 
 | 
						|
 * ext/gd. It is possible to use Free Type 2, native TTF and PostScript Type 1 
 | 
						|
 * fonts.
 | 
						|
 *
 | 
						|
 * The options of this driver are configured in {@link ezcGraphGdDriverOptions}
 | 
						|
 * extending the basic driver options class {@link ezcGraphDriverOptions}.
 | 
						|
 *
 | 
						|
 * <code>
 | 
						|
 *   $graph = new ezcGraphPieChart();
 | 
						|
 *   $graph->palette = new ezcGraphPaletteEzGreen();
 | 
						|
 *   $graph->title = 'Access statistics';
 | 
						|
 *   $graph->legend = false;
 | 
						|
 *   
 | 
						|
 *   $graph->driver = new ezcGraphGdDriver();
 | 
						|
 *   $graph->options->font = 'tutorial_font.ttf';
 | 
						|
 *
 | 
						|
 *   // Generate a Jpeg with lower quality. The default settings result in a image
 | 
						|
 *   // with better quality.
 | 
						|
 *   // 
 | 
						|
 *   // The reduction of the supersampling to 1 will result in no anti aliasing of
 | 
						|
 *   // the image. JPEG is not the optimal format for grapics, PNG is far better for
 | 
						|
 *   // this kind of images.
 | 
						|
 *   $graph->driver->options->supersampling = 1;
 | 
						|
 *   $graph->driver->options->jpegQuality = 100;
 | 
						|
 *   $graph->driver->options->imageFormat = IMG_JPEG;
 | 
						|
 *   
 | 
						|
 *   $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
 | 
						|
 *       'Mozilla' => 19113,
 | 
						|
 *       'Explorer' => 10917,
 | 
						|
 *       'Opera' => 1464,
 | 
						|
 *       'Safari' => 652,
 | 
						|
 *       'Konqueror' => 474,
 | 
						|
 *   ) );
 | 
						|
 *   
 | 
						|
 *   $graph->render( 400, 200, 'tutorial_dirver_gd.jpg' );
 | 
						|
 * </code>
 | 
						|
 *
 | 
						|
 * @version 1.4.3
 | 
						|
 * @package Graph
 | 
						|
 * @mainclass
 | 
						|
 */
 | 
						|
class ezcGraphGdDriver extends ezcGraphDriver
 | 
						|
{
 | 
						|
 | 
						|
    /**
 | 
						|
     * Image resource
 | 
						|
     * 
 | 
						|
     * @var resource
 | 
						|
     */
 | 
						|
    protected $image;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Array with image files to draw
 | 
						|
     * 
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $preProcessImages = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * List of strings to draw
 | 
						|
     * array ( array(
 | 
						|
     *          'text' => array( 'strings' ),
 | 
						|
     *          'options' => ezcGraphFontOptions,
 | 
						|
     *      )
 | 
						|
     * 
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $strings = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Contains resources for already loaded ps fonts.
 | 
						|
     *  array(
 | 
						|
     *      path => resource
 | 
						|
     *  )
 | 
						|
     * 
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $psFontResources = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor
 | 
						|
     * 
 | 
						|
     * @param array $options Default option array
 | 
						|
     * @return void
 | 
						|
     * @ignore
 | 
						|
     */
 | 
						|
    public function __construct( array $options = array() )
 | 
						|
    {
 | 
						|
        ezcBase::checkDependency( 'Graph', ezcBase::DEP_PHP_EXTENSION, 'gd' );
 | 
						|
        $this->options = new ezcGraphGdDriverOptions( $options );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the image resource to draw on.
 | 
						|
     *
 | 
						|
     * If no resource exists the image will be created. The size of the 
 | 
						|
     * returned image depends on the supersampling factor and the size of the
 | 
						|
     * chart.
 | 
						|
     * 
 | 
						|
     * @return resource
 | 
						|
     */
 | 
						|
    protected function getImage()
 | 
						|
    {
 | 
						|
        if ( !isset( $this->image ) )
 | 
						|
        {
 | 
						|
            $this->image = imagecreatetruecolor( 
 | 
						|
                $this->supersample( $this->options->width ), 
 | 
						|
                $this->supersample( $this->options->height )
 | 
						|
            );
 | 
						|
 | 
						|
            // Default to a transparent white background
 | 
						|
            $bgColor = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 );
 | 
						|
            imagealphablending( $this->image, true );
 | 
						|
            imagesavealpha( $this->image, true );
 | 
						|
            imagefill( $this->image, 1, 1, $bgColor );
 | 
						|
 | 
						|
            imagesetthickness( 
 | 
						|
                $this->image, 
 | 
						|
                $this->options->supersampling
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        return $this->image;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Allocates a color
 | 
						|
     *
 | 
						|
     * This function tries to allocate the requested color. If the color 
 | 
						|
     * already exists in the imaga it will be reused.
 | 
						|
     * 
 | 
						|
     * @param ezcGraphColor $color 
 | 
						|
     * @return int Color index
 | 
						|
     */
 | 
						|
    protected function allocate( ezcGraphColor $color )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
 | 
						|
        if ( $color->alpha > 0 )
 | 
						|
        {
 | 
						|
            $fetched = imagecolorexactalpha( $image, $color->red, $color->green, $color->blue, $color->alpha / 2 );
 | 
						|
            if ( $fetched < 0 )
 | 
						|
            {
 | 
						|
                $fetched = imagecolorallocatealpha( $image, $color->red, $color->green, $color->blue, $color->alpha / 2 );
 | 
						|
            }
 | 
						|
            return $fetched;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            $fetched = imagecolorexact( $image, $color->red, $color->green, $color->blue );
 | 
						|
            if ( $fetched < 0 )
 | 
						|
            {
 | 
						|
                $fetched = imagecolorallocate( $image, $color->red, $color->green, $color->blue );
 | 
						|
            }
 | 
						|
            return $fetched;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates an image resource from an image file
 | 
						|
     *
 | 
						|
     * @param string $file Filename
 | 
						|
     * @return resource Image
 | 
						|
     */
 | 
						|
    protected function imageCreateFrom( $file )
 | 
						|
    {
 | 
						|
        $data = getimagesize( $file );
 | 
						|
 | 
						|
        switch ( $data[2] )
 | 
						|
        {
 | 
						|
            case 1:
 | 
						|
                return array(
 | 
						|
                    'width' => $data[0],
 | 
						|
                    'height' => $data[1],
 | 
						|
                    'image' => imagecreatefromgif( $file )
 | 
						|
                );
 | 
						|
            case 2:
 | 
						|
                return array(
 | 
						|
                    'width' => $data[0],
 | 
						|
                    'height' => $data[1],
 | 
						|
                    'image' => imagecreatefromjpeg( $file )
 | 
						|
                );
 | 
						|
            case 3:
 | 
						|
                return array(
 | 
						|
                    'width' => $data[0],
 | 
						|
                    'height' => $data[1],
 | 
						|
                    'image' => imagecreatefrompng( $file )
 | 
						|
                );
 | 
						|
            default:
 | 
						|
                throw new ezcGraphGdDriverUnsupportedImageTypeException( $data[2] );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Supersamples a single coordinate value.
 | 
						|
     *
 | 
						|
     * Applies supersampling to a single coordinate value.
 | 
						|
     * 
 | 
						|
     * @param float $value Coordinate value
 | 
						|
     * @return float Supersampled coordinate value
 | 
						|
     */
 | 
						|
    protected function supersample( $value )
 | 
						|
    {
 | 
						|
        $mod = (int) floor( $this->options->supersampling / 2 );
 | 
						|
        return $value * $this->options->supersampling - $mod;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Draws a single polygon. 
 | 
						|
     * 
 | 
						|
     * @param array $points Point array
 | 
						|
     * @param ezcGraphColor $color Polygon color
 | 
						|
     * @param mixed $filled Filled
 | 
						|
     * @param float $thickness Line thickness
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawPolygon( array $points, ezcGraphColor $color, $filled = true, $thickness = 1. )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
 | 
						|
        $drawColor = $this->allocate( $color );
 | 
						|
 | 
						|
        // Create point array
 | 
						|
        $pointCount = count( $points );
 | 
						|
        $pointArray = array();
 | 
						|
        for ( $i = 0; $i < $pointCount; ++$i )
 | 
						|
        {
 | 
						|
            $pointArray[] = $this->supersample( $points[$i]->x );
 | 
						|
            $pointArray[] = $this->supersample( $points[$i]->y );
 | 
						|
        }
 | 
						|
 | 
						|
        // Draw polygon
 | 
						|
        if ( $filled )
 | 
						|
        {
 | 
						|
            imagefilledpolygon( $image, $pointArray, $pointCount, $drawColor );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            imagepolygon( $image, $pointArray, $pointCount, $drawColor );
 | 
						|
        }
 | 
						|
 | 
						|
        return $points;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Draws a line 
 | 
						|
     * 
 | 
						|
     * @param ezcGraphCoordinate $start Start point
 | 
						|
     * @param ezcGraphCoordinate $end End point
 | 
						|
     * @param ezcGraphColor $color Line color
 | 
						|
     * @param float $thickness Line thickness
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawLine( ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphColor $color, $thickness = 1. )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
 | 
						|
        $drawColor = $this->allocate( $color );
 | 
						|
 | 
						|
        imagesetthickness( 
 | 
						|
            $this->image, 
 | 
						|
            $this->options->supersampling * $thickness
 | 
						|
        );
 | 
						|
 | 
						|
        imageline( 
 | 
						|
            $image, 
 | 
						|
            $this->supersample( $start->x ), 
 | 
						|
            $this->supersample( $start->y ), 
 | 
						|
            $this->supersample( $end->x ), 
 | 
						|
            $this->supersample( $end->y ), 
 | 
						|
            $drawColor
 | 
						|
        );
 | 
						|
 | 
						|
        imagesetthickness( 
 | 
						|
            $this->image, 
 | 
						|
            $this->options->supersampling
 | 
						|
        );
 | 
						|
 | 
						|
        return array();
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Returns boundings of text depending on the available font extension
 | 
						|
     * 
 | 
						|
     * @param float $size Textsize
 | 
						|
     * @param ezcGraphFontOptions $font Font
 | 
						|
     * @param string $text Text
 | 
						|
     * @return ezcGraphBoundings Boundings of text
 | 
						|
     */
 | 
						|
    protected function getTextBoundings( $size, ezcGraphFontOptions $font, $text )
 | 
						|
    {
 | 
						|
        switch ( $font->type )
 | 
						|
        {
 | 
						|
            case ezcGraph::PS_FONT:
 | 
						|
                if ( !isset( $this->psFontResources[$font->path] ) )
 | 
						|
                {
 | 
						|
                    $this->psFontResources[$font->path] = imagePsLoadFont( $font->path );
 | 
						|
                }
 | 
						|
 | 
						|
                $boundings = imagePsBBox( $text, $this->psFontResources[$font->path], $size );
 | 
						|
                return new ezcGraphBoundings(
 | 
						|
                    $boundings[0],
 | 
						|
                    $boundings[1],
 | 
						|
                    $boundings[2],
 | 
						|
                    $boundings[3]
 | 
						|
                );
 | 
						|
            case ezcGraph::TTF_FONT:
 | 
						|
                switch ( true )
 | 
						|
                {
 | 
						|
                    case ezcBaseFeatures::hasFunction( 'imageftbbox' ) && !$this->options->forceNativeTTF:
 | 
						|
                        $boundings = imageFtBBox( $size, 0, $font->path, $text );
 | 
						|
                        return new ezcGraphBoundings(
 | 
						|
                            $boundings[0],
 | 
						|
                            $boundings[1],
 | 
						|
                            $boundings[4],
 | 
						|
                            $boundings[5]
 | 
						|
                        );
 | 
						|
                    case ezcBaseFeatures::hasFunction( 'imagettfbbox' ):
 | 
						|
                        $boundings = imageTtfBBox( $size, 0, $font->path, $text );
 | 
						|
                        return new ezcGraphBoundings(
 | 
						|
                            $boundings[0],
 | 
						|
                            $boundings[1],
 | 
						|
                            $boundings[4],
 | 
						|
                            $boundings[5]
 | 
						|
                        );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Render text depending of font type and available font extensions
 | 
						|
     * 
 | 
						|
     * @param resource $image Image resource
 | 
						|
     * @param string $text Text
 | 
						|
     * @param int $type Font type
 | 
						|
     * @param string $path Font path
 | 
						|
     * @param ezcGraphColor $color Font color
 | 
						|
     * @param ezcGraphCoordinate $position Position
 | 
						|
     * @param float $size Textsize
 | 
						|
     * @param ezcGraphRotation $rotation
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function renderText( $image, $text, $type, $path, ezcGraphColor $color, ezcGraphCoordinate $position, $size, ezcGraphRotation $rotation = null )
 | 
						|
    {
 | 
						|
        if ( $rotation !== null )
 | 
						|
        {
 | 
						|
            // Rotation is relative to top left point of text and not relative
 | 
						|
            // to the bounding coordinate system
 | 
						|
            $rotation = new ezcGraphRotation(
 | 
						|
                $rotation->getRotation(),
 | 
						|
                new ezcGraphCoordinate(
 | 
						|
                    $rotation->getCenter()->x - $position->x,
 | 
						|
                    $rotation->getCenter()->y - $position->y
 | 
						|
                )
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        switch ( $type )
 | 
						|
        {
 | 
						|
            case ezcGraph::PS_FONT:
 | 
						|
                imagePsText( 
 | 
						|
                    $image, 
 | 
						|
                    $text, 
 | 
						|
                    $this->psFontResources[$path], 
 | 
						|
                    $size, 
 | 
						|
                    $this->allocate( $color ), 
 | 
						|
                    1, 
 | 
						|
                    $position->x + 
 | 
						|
                        ( $rotation === null ? 0 : $rotation->get( 0, 2 ) ),
 | 
						|
                    $position->y + 
 | 
						|
                        ( $rotation === null ? 0 : $rotation->get( 1, 2 ) ),
 | 
						|
                    0,
 | 
						|
                    0,
 | 
						|
                    ( $rotation === null ? 0 : -$rotation->getRotation() ),
 | 
						|
                    4
 | 
						|
                );
 | 
						|
                break;
 | 
						|
            case ezcGraph::TTF_FONT:
 | 
						|
                switch ( true )
 | 
						|
                {
 | 
						|
                    case ezcBaseFeatures::hasFunction( 'imagefttext' ) && !$this->options->forceNativeTTF:
 | 
						|
                        imageFtText(
 | 
						|
                            $image, 
 | 
						|
                            $size,
 | 
						|
                            ( $rotation === null ? 0 : -$rotation->getRotation() ),
 | 
						|
                            $position->x + 
 | 
						|
                                ( $rotation === null ? 0 : $rotation->get( 0, 2 ) ),
 | 
						|
                            $position->y + 
 | 
						|
                                ( $rotation === null ? 0 : $rotation->get( 1, 2 ) ),
 | 
						|
                            $this->allocate( $color ),
 | 
						|
                            $path,
 | 
						|
                            $text
 | 
						|
                        );
 | 
						|
                        break;
 | 
						|
                    case ezcBaseFeatures::hasFunction( 'imagettftext' ):
 | 
						|
                        imageTtfText(
 | 
						|
                            $image, 
 | 
						|
                            $size,
 | 
						|
                            ( $rotation === null ? 0 : -$rotation->getRotation() ),
 | 
						|
                            $position->x + 
 | 
						|
                                ( $rotation === null ? 0 : $rotation->get( 0, 2 ) ),
 | 
						|
                            $position->y + 
 | 
						|
                                ( $rotation === null ? 0 : $rotation->get( 1, 2 ) ),
 | 
						|
                            $this->allocate( $color ),
 | 
						|
                            $path,
 | 
						|
                            $text
 | 
						|
                        );
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Writes text in a box of desired size
 | 
						|
     * 
 | 
						|
     * @param string $string Text
 | 
						|
     * @param ezcGraphCoordinate $position Top left position
 | 
						|
     * @param float $width Width of text box
 | 
						|
     * @param float $height Height of text box
 | 
						|
     * @param int $align Alignement of text
 | 
						|
     * @param ezcGraphRotation $rotation
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawTextBox( $string, ezcGraphCoordinate $position, $width, $height, $align, ezcGraphRotation $rotation = null )
 | 
						|
    {
 | 
						|
        $padding = $this->options->font->padding + ( $this->options->font->border !== false ? $this->options->font->borderWidth : 0 );
 | 
						|
 | 
						|
        $width -= $padding * 2;
 | 
						|
        $height -= $padding * 2;
 | 
						|
        $position->x += $padding;
 | 
						|
        $position->y += $padding;
 | 
						|
 | 
						|
        // Try to get a font size for the text to fit into the box
 | 
						|
        $maxSize = min( $height, $this->options->font->maxFontSize );
 | 
						|
        $result = false;
 | 
						|
        for ( $size = $maxSize; $size >= $this->options->font->minFontSize; --$size )
 | 
						|
        {
 | 
						|
            $result = $this->testFitStringInTextBox( $string, $position, $width, $height, $size );
 | 
						|
            if ( is_array( $result ) )
 | 
						|
            {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            $size = floor( ( $newsize = $size * ( $result ) ) >= $size ? $size - 1 : $newsize );
 | 
						|
        }
 | 
						|
 | 
						|
        if ( !is_array( $result ) )
 | 
						|
        {
 | 
						|
            if ( ( $height >= $this->options->font->minFontSize ) &&
 | 
						|
                 ( $this->options->autoShortenString ) )
 | 
						|
            {
 | 
						|
                $result = $this->tryFitShortenedString( $string, $position, $width, $height, $size = $this->options->font->minFontSize );
 | 
						|
            } 
 | 
						|
            else
 | 
						|
            {
 | 
						|
                throw new ezcGraphFontRenderingException( $string, $this->options->font->minFontSize, $width, $height );
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        $this->options->font->minimalUsedFont = $size;
 | 
						|
 | 
						|
        $this->strings[] = array(
 | 
						|
            'text' => $result,
 | 
						|
            'position' => $position,
 | 
						|
            'width' => $width,
 | 
						|
            'height' => $height,
 | 
						|
            'align' => $align,
 | 
						|
            'font' => $this->options->font,
 | 
						|
            'rotation' => $rotation,
 | 
						|
        );
 | 
						|
 | 
						|
        return array(
 | 
						|
            clone $position,
 | 
						|
            new ezcGraphCoordinate( $position->x + $width, $position->y ),
 | 
						|
            new ezcGraphCoordinate( $position->x + $width, $position->y + $height ),
 | 
						|
            new ezcGraphCoordinate( $position->x, $position->y + $height ),
 | 
						|
        );
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Draw all collected texts
 | 
						|
     *
 | 
						|
     * The texts are collected and their maximum possible font size is 
 | 
						|
     * calculated. This function finally draws the texts on the image, this
 | 
						|
     * delayed drawing has two reasons:
 | 
						|
     *
 | 
						|
     * 1) This way the text strings are always on top of the image, what 
 | 
						|
     *    results in better readable texts
 | 
						|
     * 2) The maximum possible font size can be calculated for a set of texts
 | 
						|
     *    with the same font configuration. Strings belonging to one chart 
 | 
						|
     *    element normally have the same font configuration, so that all texts
 | 
						|
     *    belonging to one element will have the same font size.
 | 
						|
     * 
 | 
						|
     * @access protected
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function drawAllTexts()
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
 | 
						|
        foreach ( $this->strings as $text )
 | 
						|
        {
 | 
						|
            $size = $text['font']->minimalUsedFont;
 | 
						|
 | 
						|
            $completeHeight = count( $text['text'] ) * $size + ( count( $text['text'] ) - 1 ) * $this->options->lineSpacing;
 | 
						|
 | 
						|
            // Calculate y offset for vertical alignement
 | 
						|
            switch ( true )
 | 
						|
            {
 | 
						|
                case ( $text['align'] & ezcGraph::BOTTOM ):
 | 
						|
                    $yOffset = $text['height'] - $completeHeight;
 | 
						|
                    break;
 | 
						|
                case ( $text['align'] & ezcGraph::MIDDLE ):
 | 
						|
                    $yOffset = ( $text['height'] - $completeHeight ) / 2;
 | 
						|
                    break;
 | 
						|
                case ( $text['align'] & ezcGraph::TOP ):
 | 
						|
                default:
 | 
						|
                    $yOffset = 0;
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
 | 
						|
            $padding = $text['font']->padding + $text['font']->borderWidth / 2;
 | 
						|
            if ( $this->options->font->minimizeBorder === true )
 | 
						|
            {
 | 
						|
                // Calculate maximum width of text rows
 | 
						|
                $width = false;
 | 
						|
                foreach ( $text['text'] as $line )
 | 
						|
                {
 | 
						|
                    $string = implode( ' ', $line );
 | 
						|
                    $boundings = $this->getTextBoundings( $size, $text['font'], $string );
 | 
						|
                    if ( ( $width === false) || ( $boundings->width > $width ) )
 | 
						|
                    {
 | 
						|
                        $width = $boundings->width;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                switch ( true )
 | 
						|
                {
 | 
						|
                    case ( $text['align'] & ezcGraph::LEFT ):
 | 
						|
                        $xOffset = 0;
 | 
						|
                        break;
 | 
						|
                    case ( $text['align'] & ezcGraph::CENTER ):
 | 
						|
                        $xOffset = ( $text['width'] - $width ) / 2;
 | 
						|
                        break;
 | 
						|
                    case ( $text['align'] & ezcGraph::RIGHT ):
 | 
						|
                        $xOffset = $text['width'] - $width;
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                $borderPolygonArray = array(
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x - $padding + $xOffset,
 | 
						|
                        $text['position']->y - $padding + $yOffset
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x + $padding * 2 + $xOffset + $width,
 | 
						|
                        $text['position']->y - $padding + $yOffset
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x + $padding * 2 + $xOffset + $width,
 | 
						|
                        $text['position']->y + $padding * 2 + $yOffset + $completeHeight
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x - $padding + $xOffset,
 | 
						|
                        $text['position']->y + $padding * 2 + $yOffset + $completeHeight
 | 
						|
                    ),
 | 
						|
                );
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                $borderPolygonArray = array(
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x - $padding,
 | 
						|
                        $text['position']->y - $padding
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x + $padding * 2 + $text['width'],
 | 
						|
                        $text['position']->y - $padding
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x + $padding * 2 + $text['width'],
 | 
						|
                        $text['position']->y + $padding * 2 + $text['height']
 | 
						|
                    ),
 | 
						|
                    new ezcGraphCoordinate(
 | 
						|
                        $text['position']->x - $padding,
 | 
						|
                        $text['position']->y + $padding * 2 + $text['height']
 | 
						|
                    ),
 | 
						|
                );
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $text['rotation'] !==  null )
 | 
						|
            {
 | 
						|
                foreach ( $borderPolygonArray as $nr => $point )
 | 
						|
                {
 | 
						|
                    $borderPolygonArray[$nr] = $text['rotation']->transformCoordinate( $point );
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $text['font']->background !== false )
 | 
						|
            {
 | 
						|
                $this->drawPolygon( 
 | 
						|
                    $borderPolygonArray, 
 | 
						|
                    $text['font']->background,
 | 
						|
                    true
 | 
						|
                );
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $text['font']->border !== false )
 | 
						|
            {
 | 
						|
                $this->drawPolygon( 
 | 
						|
                    $borderPolygonArray, 
 | 
						|
                    $text['font']->border,
 | 
						|
                    false,
 | 
						|
                    $text['font']->borderWidth
 | 
						|
                );
 | 
						|
            }
 | 
						|
 | 
						|
            // Render text with evaluated font size
 | 
						|
            foreach ( $text['text'] as $line )
 | 
						|
            {
 | 
						|
                $string = implode( ' ', $line );
 | 
						|
                $boundings = $this->getTextBoundings( $size, $text['font'], $string );
 | 
						|
                $text['position']->y += $size;
 | 
						|
 | 
						|
                switch ( true )
 | 
						|
                {
 | 
						|
                    case ( $text['align'] & ezcGraph::LEFT ):
 | 
						|
                        $position = new ezcGraphCoordinate( 
 | 
						|
                            $text['position']->x, 
 | 
						|
                            $text['position']->y + $yOffset
 | 
						|
                        );
 | 
						|
                        break;
 | 
						|
                    case ( $text['align'] & ezcGraph::RIGHT ):
 | 
						|
                        $position = new ezcGraphCoordinate( 
 | 
						|
                            $text['position']->x + ( $text['width'] - $boundings->width ), 
 | 
						|
                            $text['position']->y + $yOffset
 | 
						|
                        );
 | 
						|
                        break;
 | 
						|
                    case ( $text['align'] & ezcGraph::CENTER ):
 | 
						|
                        $position = new ezcGraphCoordinate( 
 | 
						|
                            $text['position']->x + ( ( $text['width'] - $boundings->width ) / 2 ), 
 | 
						|
                            $text['position']->y + $yOffset
 | 
						|
                        );
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                // Calculate relative modification of rotation center point
 | 
						|
                if ( $text['rotation'] !== null )
 | 
						|
                {
 | 
						|
                    $rotation = new ezcGraphRotation(
 | 
						|
                        $text['rotation']->getRotation(),
 | 
						|
                        new ezcGraphCoordinate(
 | 
						|
                            $text['rotation']->getCenter()->x + 
 | 
						|
                                $position->x - $text['position']->x,
 | 
						|
                            $text['rotation']->getCenter()->y + 
 | 
						|
                                $position->y - $text['position']->y
 | 
						|
                        )
 | 
						|
                    );
 | 
						|
                    $rotation = $text['rotation'];
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    $rotation = null;
 | 
						|
                }
 | 
						|
 | 
						|
                // Optionally draw text shadow
 | 
						|
                if ( $text['font']->textShadow === true )
 | 
						|
                {
 | 
						|
                    $this->renderText( 
 | 
						|
                        $image, 
 | 
						|
                        $string,
 | 
						|
                        $text['font']->type, 
 | 
						|
                        $text['font']->path, 
 | 
						|
                        $text['font']->textShadowColor,
 | 
						|
                        new ezcGraphCoordinate(
 | 
						|
                            $position->x + $text['font']->textShadowOffset,
 | 
						|
                            $position->y + $text['font']->textShadowOffset
 | 
						|
                        ),
 | 
						|
                        $size,
 | 
						|
                        $rotation
 | 
						|
                    );
 | 
						|
                }
 | 
						|
                
 | 
						|
                // Finally draw text
 | 
						|
                $this->renderText( 
 | 
						|
                    $image, 
 | 
						|
                    $string,
 | 
						|
                    $text['font']->type, 
 | 
						|
                    $text['font']->path, 
 | 
						|
                    $text['font']->color, 
 | 
						|
                    $position,
 | 
						|
                    $size,
 | 
						|
                    $rotation
 | 
						|
                );
 | 
						|
 | 
						|
                $text['position']->y += $size * $this->options->lineSpacing;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Draws a sector of cirlce
 | 
						|
     * 
 | 
						|
     * @param ezcGraphCoordinate $center Center of circle
 | 
						|
     * @param mixed $width Width
 | 
						|
     * @param mixed $height Height
 | 
						|
     * @param mixed $startAngle Start angle of circle sector
 | 
						|
     * @param mixed $endAngle End angle of circle sector
 | 
						|
     * @param ezcGraphColor $color Color
 | 
						|
     * @param mixed $filled Filled
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawCircleSector( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
        $drawColor = $this->allocate( $color );
 | 
						|
 | 
						|
        // Normalize angles
 | 
						|
        if ( $startAngle > $endAngle )
 | 
						|
        {
 | 
						|
            $tmp = $startAngle;
 | 
						|
            $startAngle = $endAngle;
 | 
						|
            $endAngle = $tmp;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( ( $endAngle - $startAngle ) > 359.99999 )
 | 
						|
        {
 | 
						|
            return $this->drawCircle( $center, $width, $height, $color, $filled );
 | 
						|
        }
 | 
						|
 | 
						|
        // Because of bug #45552 in PHPs ext/GD we check for a minimal distance
 | 
						|
        // on the outer border of the circle sector, and skip the drawing if
 | 
						|
        // the distance is lower then 1.
 | 
						|
        //
 | 
						|
        // See also: http://bugs.php.net/45552
 | 
						|
        $startPoint = new ezcGraphVector( 
 | 
						|
            $center->x + 
 | 
						|
                ( ( cos( deg2rad( $startAngle ) ) * $width ) / 2 ),
 | 
						|
            $center->y + 
 | 
						|
                ( ( sin( deg2rad( $startAngle ) ) * $height ) / 2 )
 | 
						|
        );
 | 
						|
        if ( $startPoint->sub( new ezcGraphVector( 
 | 
						|
                $center->x + 
 | 
						|
                    ( ( cos( deg2rad( $endAngle ) ) * $width ) / 2 ),
 | 
						|
                $center->y + 
 | 
						|
                    ( ( sin( deg2rad( $endAngle ) ) * $height ) / 2 )
 | 
						|
             ) )->length() < 1 )
 | 
						|
        {
 | 
						|
            // Skip this circle sector
 | 
						|
            return array();
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $filled )
 | 
						|
        {
 | 
						|
            imagefilledarc( 
 | 
						|
                $image, 
 | 
						|
                $this->supersample( $center->x ), 
 | 
						|
                $this->supersample( $center->y ), 
 | 
						|
                $this->supersample( $width ), 
 | 
						|
                $this->supersample( $height ), 
 | 
						|
                $startAngle, 
 | 
						|
                $endAngle, 
 | 
						|
                $drawColor, 
 | 
						|
                IMG_ARC_PIE 
 | 
						|
            );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            imagefilledarc( 
 | 
						|
                $image, 
 | 
						|
                $this->supersample( $center->x ), 
 | 
						|
                $this->supersample( $center->y ), 
 | 
						|
                $this->supersample( $width ), 
 | 
						|
                $this->supersample( $height ), 
 | 
						|
                $startAngle, 
 | 
						|
                $endAngle, 
 | 
						|
                $drawColor, 
 | 
						|
                IMG_ARC_PIE | IMG_ARC_NOFILL | IMG_ARC_EDGED
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        // Create polygon array to return
 | 
						|
        $polygonArray = array( $center );
 | 
						|
        for ( $angle = $startAngle; $angle < $endAngle; $angle += $this->options->imageMapResolution )
 | 
						|
        {
 | 
						|
            $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
                $center->x + 
 | 
						|
                    ( ( cos( deg2rad( $angle ) ) * $width ) / 2 ),
 | 
						|
                $center->y + 
 | 
						|
                    ( ( sin( deg2rad( $angle ) ) * $height ) / 2 )
 | 
						|
            );
 | 
						|
        }
 | 
						|
        $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
            $center->x + 
 | 
						|
                ( ( cos( deg2rad( $endAngle ) ) * $width ) / 2 ),
 | 
						|
            $center->y + 
 | 
						|
                ( ( sin( deg2rad( $endAngle ) ) * $height ) / 2 )
 | 
						|
        );
 | 
						|
 | 
						|
        return $polygonArray;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Draws a single element of a circular arc
 | 
						|
     * 
 | 
						|
     * ext/gd itself does not support something like circular arcs, so that
 | 
						|
     * this functions draws rectangular polygons as a part of circular arcs
 | 
						|
     * to interpolate them. This way it is possible to apply a linear gradient
 | 
						|
     * to the circular arc, because we draw single steps anyway.
 | 
						|
     *
 | 
						|
     * @param ezcGraphCoordinate $center Center of ellipse
 | 
						|
     * @param integer $width Width of ellipse
 | 
						|
     * @param integer $height Height of ellipse
 | 
						|
     * @param integer $size Height of border
 | 
						|
     * @param float $startAngle Starting angle of circle sector
 | 
						|
     * @param float $endAngle Ending angle of circle sector
 | 
						|
     * @param ezcGraphColor $color Color of Border
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function drawCircularArcStep( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color )
 | 
						|
    {
 | 
						|
        $this->drawPolygon(
 | 
						|
            array(
 | 
						|
                new ezcGraphCoordinate(
 | 
						|
                    $center->x + 
 | 
						|
                        ( ( cos( deg2rad( $startAngle ) ) * $width ) / 2 ),
 | 
						|
                    $center->y + 
 | 
						|
                        ( ( sin( deg2rad( $startAngle ) ) * $height ) / 2 )
 | 
						|
                ),
 | 
						|
                new ezcGraphCoordinate(
 | 
						|
                    $center->x + 
 | 
						|
                        ( ( cos( deg2rad( $startAngle ) ) * $width ) / 2 ),
 | 
						|
                    $center->y + 
 | 
						|
                        ( ( sin( deg2rad( $startAngle ) ) * $height ) / 2 ) + $size
 | 
						|
                ),
 | 
						|
                new ezcGraphCoordinate(
 | 
						|
                    $center->x + 
 | 
						|
                        ( ( cos( deg2rad( $endAngle ) ) * $width ) / 2 ),
 | 
						|
                    $center->y + 
 | 
						|
                        ( ( sin( deg2rad( $endAngle ) ) * $height ) / 2 ) + $size
 | 
						|
                ),
 | 
						|
                new ezcGraphCoordinate(
 | 
						|
                    $center->x + 
 | 
						|
                        ( ( cos( deg2rad( $endAngle ) ) * $width ) / 2 ),
 | 
						|
                    $center->y + 
 | 
						|
                        ( ( sin( deg2rad( $endAngle ) ) * $height ) / 2 )
 | 
						|
                ),
 | 
						|
            ),
 | 
						|
            $color->darken( $this->options->shadeCircularArc * ( 1 + cos ( deg2rad( $startAngle ) ) ) / 2 ),
 | 
						|
            true
 | 
						|
        );
 | 
						|
    }
 | 
						|
 
 | 
						|
    /**
 | 
						|
     * Draws a circular arc
 | 
						|
     * 
 | 
						|
     * @param ezcGraphCoordinate $center Center of ellipse
 | 
						|
     * @param integer $width Width of ellipse
 | 
						|
     * @param integer $height Height of ellipse
 | 
						|
     * @param integer $size Height of border
 | 
						|
     * @param float $startAngle Starting angle of circle sector
 | 
						|
     * @param float $endAngle Ending angle of circle sector
 | 
						|
     * @param ezcGraphColor $color Color of Border
 | 
						|
     * @param bool $filled
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
        $drawColor = $this->allocate( $color );
 | 
						|
 | 
						|
        // Normalize angles
 | 
						|
        if ( $startAngle > $endAngle )
 | 
						|
        {
 | 
						|
            $tmp = $startAngle;
 | 
						|
            $startAngle = $endAngle;
 | 
						|
            $endAngle = $tmp;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if ( $filled === true )
 | 
						|
        {
 | 
						|
            $startIteration = ceil( $startAngle / $this->options->detail ) * $this->options->detail;
 | 
						|
            $endIteration = floor( $endAngle / $this->options->detail ) * $this->options->detail;
 | 
						|
 | 
						|
            if ( $startAngle < $startIteration )
 | 
						|
            {
 | 
						|
                // Draw initial step
 | 
						|
                $this->drawCircularArcStep( 
 | 
						|
                    $center, 
 | 
						|
                    $width, 
 | 
						|
                    $height, 
 | 
						|
                    $size, 
 | 
						|
                    $startAngle, 
 | 
						|
                    $startIteration, 
 | 
						|
                    $color
 | 
						|
                );
 | 
						|
            }
 | 
						|
 | 
						|
            // Draw all steps
 | 
						|
            for ( ; $startIteration < $endIteration; $startIteration += $this->options->detail )
 | 
						|
            {
 | 
						|
                $this->drawCircularArcStep( 
 | 
						|
                    $center, 
 | 
						|
                    $width, 
 | 
						|
                    $height, 
 | 
						|
                    $size, 
 | 
						|
                    $startIteration, 
 | 
						|
                    $startIteration + $this->options->detail, 
 | 
						|
                    $color 
 | 
						|
                );
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $endIteration < $endAngle )
 | 
						|
            {
 | 
						|
                // Draw closing step
 | 
						|
                $this->drawCircularArcStep( 
 | 
						|
                    $center, 
 | 
						|
                    $width, 
 | 
						|
                    $height, 
 | 
						|
                    $size, 
 | 
						|
                    $endIteration, 
 | 
						|
                    $endAngle, 
 | 
						|
                    $color 
 | 
						|
                );
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            imagefilledarc( 
 | 
						|
                $image, 
 | 
						|
                $this->supersample( $center->x ), 
 | 
						|
                $this->supersample( $center->y ), 
 | 
						|
                $this->supersample( $width ), 
 | 
						|
                $this->supersample( $height ), 
 | 
						|
                $startAngle, 
 | 
						|
                $endAngle, 
 | 
						|
                $drawColor, 
 | 
						|
                IMG_ARC_PIE | IMG_ARC_NOFILL
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        // Create polygon array to return
 | 
						|
        $polygonArray = array();
 | 
						|
        for ( $angle = $startAngle; $angle < $endAngle; $angle += $this->options->imageMapResolution )
 | 
						|
        {
 | 
						|
            $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
                $center->x + 
 | 
						|
                    ( ( cos( deg2rad( $angle ) ) * $width ) / 2 ),
 | 
						|
                $center->y + 
 | 
						|
                    ( ( sin( deg2rad( $angle ) ) * $height ) / 2 )
 | 
						|
            );
 | 
						|
        }
 | 
						|
        $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
            $center->x + 
 | 
						|
                ( ( cos( deg2rad( $endAngle ) ) * $width ) / 2 ),
 | 
						|
            $center->y + 
 | 
						|
                ( ( sin( deg2rad( $endAngle ) ) * $height ) / 2 )
 | 
						|
        );
 | 
						|
 | 
						|
        for ( $angle = $endAngle; $angle > $startAngle; $angle -= $this->options->imageMapResolution )
 | 
						|
        {
 | 
						|
            $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
                $center->x + 
 | 
						|
                    ( ( cos( deg2rad( $angle ) ) * $width ) / 2 ) + $size,
 | 
						|
                $center->y + 
 | 
						|
                    ( ( sin( deg2rad( $angle ) ) * $height ) / 2 )
 | 
						|
            );
 | 
						|
        }
 | 
						|
        $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
            $center->x + 
 | 
						|
                ( ( cos( deg2rad( $startAngle ) ) * $width ) / 2 ) + $size,
 | 
						|
            $center->y + 
 | 
						|
                ( ( sin( deg2rad( $startAngle ) ) * $height ) / 2 )
 | 
						|
        );
 | 
						|
 | 
						|
        return $polygonArray;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Draw circle 
 | 
						|
     * 
 | 
						|
     * @param ezcGraphCoordinate $center Center of ellipse
 | 
						|
     * @param mixed $width Width of ellipse
 | 
						|
     * @param mixed $height height of ellipse
 | 
						|
     * @param ezcGraphColor $color Color
 | 
						|
     * @param mixed $filled Filled
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawCircle( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $color, $filled = true )
 | 
						|
    {
 | 
						|
        $image = $this->getImage();
 | 
						|
 | 
						|
        $drawColor = $this->allocate( $color );
 | 
						|
 | 
						|
        if ( $filled )
 | 
						|
        {
 | 
						|
            imagefilledellipse( 
 | 
						|
                $image, 
 | 
						|
                $this->supersample( $center->x ), 
 | 
						|
                $this->supersample( $center->y ), 
 | 
						|
                $this->supersample( $width ), 
 | 
						|
                $this->supersample( $height ), 
 | 
						|
                $drawColor 
 | 
						|
            );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            imageellipse( 
 | 
						|
                $image, 
 | 
						|
                $this->supersample( $center->x ), 
 | 
						|
                $this->supersample( $center->y ), 
 | 
						|
                $this->supersample( $width ), 
 | 
						|
                $this->supersample( $height ), 
 | 
						|
                $drawColor 
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        $polygonArray = array();
 | 
						|
        for ( $angle = 0; $angle < 360; $angle += $this->options->imageMapResolution )
 | 
						|
        {
 | 
						|
            $polygonArray[] = new ezcGraphCoordinate(
 | 
						|
                $center->x + 
 | 
						|
                    ( ( cos( deg2rad( $angle ) ) * $width ) / 2 ),
 | 
						|
                $center->y + 
 | 
						|
                    ( ( sin( deg2rad( $angle ) ) * $height ) / 2 )
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        return $polygonArray;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Draw an image
 | 
						|
     *
 | 
						|
     * The actual drawing of the image is delayed, to not apply supersampling 
 | 
						|
     * to the image. The image will normally be resized using the gd function
 | 
						|
     * imagecopyresampled, which provides nice antialiased scaling, so that
 | 
						|
     * additional supersampling would make the image look blurred. The delayed
 | 
						|
     * images will be pre-processed, so that they are draw in the back of 
 | 
						|
     * everything else.
 | 
						|
     * 
 | 
						|
     * @param mixed $file Image file
 | 
						|
     * @param ezcGraphCoordinate $position Top left position
 | 
						|
     * @param mixed $width Width of image in destination image
 | 
						|
     * @param mixed $height Height of image in destination image
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function drawImage( $file, ezcGraphCoordinate $position, $width, $height )
 | 
						|
    {
 | 
						|
        $this->preProcessImages[] = array(
 | 
						|
            'file' => $file, 
 | 
						|
            'position' => clone $position,
 | 
						|
            'width' => $width,
 | 
						|
            'height' => $height,
 | 
						|
        );
 | 
						|
 | 
						|
        return array(
 | 
						|
            $position,
 | 
						|
            new ezcGraphCoordinate( $position->x + $width, $position->y ),
 | 
						|
            new ezcGraphCoordinate( $position->x + $width, $position->y + $height ),
 | 
						|
            new ezcGraphCoordinate( $position->x, $position->y + $height ),
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Draw all images to image resource handler
 | 
						|
     * 
 | 
						|
     * @param resource $image Image to draw on
 | 
						|
     * @return resource Updated image resource
 | 
						|
     */
 | 
						|
    protected function addImages( $image )
 | 
						|
    {
 | 
						|
        foreach ( $this->preProcessImages as $preImage )
 | 
						|
        {
 | 
						|
            $preImageData = $this->imageCreateFrom( $preImage['file'] );
 | 
						|
            call_user_func_array(
 | 
						|
                $this->options->resampleFunction,
 | 
						|
                array(
 | 
						|
                    $image,
 | 
						|
                    $preImageData['image'],
 | 
						|
                    $preImage['position']->x, $preImage['position']->y,
 | 
						|
                    0, 0,
 | 
						|
                    $preImage['width'], $preImage['height'],
 | 
						|
                    $preImageData['width'], $preImageData['height'],
 | 
						|
                )
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        return $image;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return mime type for current image format
 | 
						|
     * 
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getMimeType()
 | 
						|
    {
 | 
						|
        switch ( $this->options->imageFormat )
 | 
						|
        {
 | 
						|
            case IMG_PNG:
 | 
						|
                return 'image/png';
 | 
						|
            case IMG_JPEG:
 | 
						|
                return 'image/jpeg';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Render image directly to output
 | 
						|
     *
 | 
						|
     * The method renders the image directly to the standard output. You 
 | 
						|
     * normally do not want to use this function, because it makes it harder 
 | 
						|
     * to proper cache the generated graphs.
 | 
						|
     * 
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function renderToOutput()
 | 
						|
    {
 | 
						|
        header( 'Content-Type: ' . $this->getMimeType() );
 | 
						|
        $this->render( null );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Finally save image
 | 
						|
     * 
 | 
						|
     * @param string $file Destination filename
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function render( $file )
 | 
						|
    {
 | 
						|
        $destination = imagecreatetruecolor( $this->options->width, $this->options->height );
 | 
						|
 | 
						|
        // Default to a transparent white background
 | 
						|
        $bgColor = imagecolorallocatealpha( $destination, 255, 255, 255, 127 );
 | 
						|
        imagealphablending( $destination, true );
 | 
						|
        imagesavealpha( $destination, true );
 | 
						|
        imagefill( $destination, 1, 1, $bgColor );
 | 
						|
 | 
						|
        // Apply background if one is defined
 | 
						|
        if ( $this->options->background !== false )
 | 
						|
        {
 | 
						|
            $background = $this->imageCreateFrom( $this->options->background );
 | 
						|
 | 
						|
            call_user_func_array(
 | 
						|
                $this->options->resampleFunction,
 | 
						|
                array(
 | 
						|
                    $destination,
 | 
						|
                    $background['image'],
 | 
						|
                    0, 0,
 | 
						|
                    0, 0,
 | 
						|
                    $this->options->width, $this->options->height,
 | 
						|
                    $background['width'], $background['height'],
 | 
						|
                )
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        // Draw all images to exclude them from supersampling
 | 
						|
        $destination = $this->addImages( $destination );
 | 
						|
 | 
						|
        // Finally merge with graph
 | 
						|
        $image = $this->getImage();
 | 
						|
        call_user_func_array(
 | 
						|
            $this->options->resampleFunction,
 | 
						|
            array(
 | 
						|
                $destination,
 | 
						|
                $image,
 | 
						|
                0, 0,
 | 
						|
                0, 0,
 | 
						|
                $this->options->width, $this->options->height,
 | 
						|
                $this->supersample( $this->options->width ), $this->supersample( $this->options->height )
 | 
						|
            )
 | 
						|
        );
 | 
						|
 | 
						|
        $this->image = $destination;
 | 
						|
        imagedestroy( $image );
 | 
						|
 | 
						|
        // Draw all texts
 | 
						|
        // Reset supersampling during text rendering
 | 
						|
        $supersampling = $this->options->supersampling;
 | 
						|
        $this->options->supersampling = 1;
 | 
						|
        $this->drawAllTexts();
 | 
						|
        $this->options->supersampling = $supersampling;
 | 
						|
 | 
						|
        $image = $this->getImage();
 | 
						|
        switch ( $this->options->imageFormat )
 | 
						|
        {
 | 
						|
            case IMG_PNG:
 | 
						|
                if ( $file === null )
 | 
						|
                {
 | 
						|
                    imagepng( $image );
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    imagepng( $image, $file );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case IMG_JPEG:
 | 
						|
                imagejpeg( $image, $file, $this->options->jpegQuality );
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                throw new ezcGraphGdDriverUnsupportedImageTypeException( $this->options->imageFormat );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get resource of rendered result
 | 
						|
     *
 | 
						|
     * Return the resource of the rendered result. You should not use this
 | 
						|
     * method before you called either renderToOutput() or render(), as the
 | 
						|
     * image may not be completely rendered until then.
 | 
						|
     * 
 | 
						|
     * @return resource
 | 
						|
     */
 | 
						|
    public function getResource()
 | 
						|
    {
 | 
						|
        return $this->image;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
?>
 |