TYPO3 API  SVNRelease
class.tslib_gifbuilder.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Generating gif/png-files from TypoScript
00029  * Used by the menu-objects and imgResource in TypoScript.
00030  *
00031  * $Id: class.tslib_gifbuilder.php 10662 2011-02-28 19:28:53Z lolli $
00032  * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
00033  *
00034  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00035  */
00036 /**
00037  * [CLASS/FUNCTION INDEX of SCRIPT]
00038  *
00039  *
00040  *
00041  *  102: class tslib_gifBuilder extends t3lib_stdGraphic
00042  *  129:     function start($conf,$data)
00043  *  315:     function gifBuild()
00044  *  343:     function make()
00045  *
00046  *              SECTION: Various helper functions
00047  *  486:     function checkTextObj($conf)
00048  *  566:     function calcOffset($string)
00049  *  615:     function getResource($file,$fileArray)
00050  *  632:     function checkFile($file)
00051  *  643:     function fileName($pre)
00052  *  659:     function extension()
00053  *
00054  * TOTAL FUNCTIONS: 9
00055  * (This index is automatically created/updated by the extension "extdeveval")
00056  *
00057  */
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 /**
00080  * GIFBUILDER extension class.
00081  * This class allows for advanced rendering of images with various layers of images, text and graphical primitives.
00082  * The concept is known from TypoScript as "GIFBUILDER" where you can define a "numerical array" (TypoScript term as well) of "GIFBUILDER OBJECTS" (like "TEXT", "IMAGE", etc.) and they will be rendered onto an image one by one.
00083  * The name "GIFBUILDER" comes from the time where GIF was the only file format supported. PNG is just as well to create today (configured with TYPO3_CONF_VARS[GFX])
00084  * Not all instances of this class is truely building gif/png files by layers; You may also see the class instantiated for the purpose of using the scaling functions in the parent class, t3lib_stdGraphic.
00085  *
00086  * Here is an example of how to use this class (from tslib_content.php, function getImgResource):
00087  *
00088  * $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
00089  * $gifCreator->init();
00090  * $theImage='';
00091  * if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
00092  * $gifCreator->start($fileArray,$this->data);
00093  * $theImage = $gifCreator->gifBuild();
00094  * }
00095  * return $gifCreator->getImageDimensions($theImage);
00096  *
00097  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00098  * @package TYPO3
00099  * @subpackage tslib
00100  */
00101 class tslib_gifBuilder extends t3lib_stdGraphic {
00102 
00103         // Internal
00104     var $im = '';       // the main image
00105     var $w = 0;         // the image-width
00106     var $h = 0;         // the image-height
00107     var $map;           // map-data
00108     var $workArea;
00109     var $setup = Array ();      // This holds the operational setup for gifbuilder. Basically this is a TypoScript array with properties.
00110     var $combinedTextStrings = array();     // Contains all text strings used on this image
00111     var $combinedFileNames = array();       // Contains all filenames (basename without extension) used on this image
00112     var $data = Array();        // This is the array from which data->field: [key] is fetched. So this is the current record!
00113     var $objBB = Array();
00114     var $myClassName = 'gifbuilder';
00115     var $charRangeMap=array();
00116 
00117     /**
00118      * Initialization of the GIFBUILDER objects, in particular TEXT and IMAGE. This includes finding the bounding box, setting dimensions and offset values before the actual rendering is started.
00119      * Modifies the ->setup, ->objBB internal arrays
00120      * Should be called after the ->init() function which initializes the parent class functions/variables in general.
00121      * The class tslib_gmenu also uses gifbuilder and here there is an interesting use since the function findLargestDims() from that class calls the init() and start() functions to find the total dimensions before starting the rendering of the images.
00122      *
00123      * @param   array       TypoScript properties for the GIFBUILDER session. Stored internally in the variable ->setup
00124      * @param   array       The current data record from tslib_cObj. Stored internally in the variable ->data
00125      * @return  void
00126      * @see tslib_cObj::getImgResource(), tslib_gmenu::makeGifs(), tslib_gmenu::findLargestDims()
00127      */
00128     function start($conf,$data) {
00129 
00130         if (is_array($conf))    {
00131             $this->setup = $conf;
00132             $this->data = $data;
00133             $this->cObj =t3lib_div::makeInstance('tslib_cObj');
00134             $this->cObj->start($this->data);
00135 
00136 
00137             /* Hook preprocess gifbuilder conf
00138              * Added by Julle for 3.8.0
00139              *
00140              * Let's you pre-process the gifbuilder configuration. for
00141              * example you can split a string up into lines and render each
00142              * line as TEXT obj, see extension julle_gifbconf
00143              */
00144 
00145             if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess']))    {
00146                 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] as $_funcRef)    {
00147                     $_params = $this->setup;
00148                     $this->setup = t3lib_div::callUserFunction($_funcRef,$_params,$this);
00149                 }
00150             }
00151 
00152                 // Initializing global Char Range Map
00153             $this->charRangeMap = array();
00154             if (is_array($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.']))   {
00155                 foreach($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'] as $cRMcfgkey => $cRMcfg)    {
00156                     if (is_array($cRMcfg))  {
00157 
00158                             // Initializing:
00159                         $cRMkey = $GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'][substr($cRMcfgkey,0,-1)];
00160                         $this->charRangeMap[$cRMkey] = array();
00161                         $this->charRangeMap[$cRMkey]['charMapConfig'] =  $cRMcfg['charMapConfig.'];
00162                         $this->charRangeMap[$cRMkey]['cfgKey'] = substr($cRMcfgkey,0,-1);
00163                         $this->charRangeMap[$cRMkey]['multiplicator'] = (double)$cRMcfg['fontSizeMultiplicator'];
00164                         $this->charRangeMap[$cRMkey]['pixelSpace'] = intval($cRMcfg['pixelSpaceFontSizeRef']);
00165                     }
00166                 }
00167             }
00168 
00169                 // Getting sorted list of TypoScript keys from setup.
00170             $sKeyArray=t3lib_TStemplate::sortedKeyList($this->setup);
00171 
00172                 // Setting the background color, passing it through stdWrap
00173             if ($conf['backColor.'] || $conf['backColor'])  {
00174                 $this->setup['backColor'] = isset($this->setup['backColor.'])
00175                     ? trim($this->cObj->stdWrap($this->setup['backColor'], $this->setup['backColor.']))
00176                     : $this->setup['backColor'];
00177             }
00178             if (!$this->setup['backColor']) { $this->setup['backColor']='white'; }
00179 
00180             if ($conf['transparentColor.'] || $conf['transparentColor'])    {
00181                 $this->setup['transparentColor_array'] = isset($this->setup['transparentColor.'])
00182                     ? explode('|', trim($this->cObj->stdWrap($this->setup['transparentColor'], $this->setup['transparentColor.'])))
00183                     : explode('|', trim($this->setup['transparentColor']));
00184             }
00185 
00186             if(isset($this->setup['transparentBackground.'])) {
00187                 $this->setup['transparentBackground'] = $this->cOjb->stdWrap($this->setup['transparentBackground'], $this->setup['transparentBackground.']);
00188             }
00189             if(isset($this->setup['reduceColors.'])) {
00190                 $this->setup['reduceColors'] = $this->cOjb->stdWrap($this->setup['reduceColors'], $this->setup['reduceColors.']);
00191             }
00192 
00193                 // Set default dimensions
00194             if (isset($this->setup['XY.'])) {
00195                 $this->setup['XY'] = $this->cObj->stdWrap($this->setup['XY'], $this->setup['XY.']);
00196             }
00197             if (!$this->setup['XY'])    {$this->setup['XY']='120,50';}
00198 
00199 
00200                 // Checking TEXT and IMAGE objects for files. If any errors the objects are cleared.
00201                 // The Bounding Box for the objects is stored in an array
00202             foreach($sKeyArray as $theKey) {
00203                 $theValue = $this->setup[$theKey];
00204 
00205                 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
00206                         // Swipes through TEXT and IMAGE-objects
00207                     switch($theValue)   {
00208                         case 'TEXT':
00209                             if ($this->setup[$theKey.'.'] = $this->checkTextObj($conf)) {
00210 
00211                                     // Adjust font width if max size is set:
00212                                 $maxWidth = isset($this->setup[$theKey.'.']['maxWidth.'])
00213                                     ? $this->cObj->stdWrap($this->setup[$theKey.'.']['maxWidth'], $this->setup[$theKey.'.']['maxWidth.'])
00214                                     : $this->setup[$theKey.'.']['maxWidth'];
00215                                 if ($maxWidth)  {
00216                                     $this->setup[$theKey.'.']['fontSize'] = $this->fontResize($this->setup[$theKey.'.']); //RTF - this has to be done before calcBBox
00217                                 }
00218 
00219                                     // Calculate bounding box:
00220                                 $txtInfo=$this->calcBBox($this->setup[$theKey.'.']);
00221                                 $this->setup[$theKey.'.']['BBOX'] = $txtInfo;
00222                                 $this->objBB[$theKey] = $txtInfo;
00223                                 $this->setup[$theKey.'.']['imgMap'] = 0;
00224                             }
00225                         break;
00226                         case 'IMAGE':
00227                             $fileInfo = $this->getResource($conf['file'],$conf['file.']);
00228                             if ($fileInfo)  {
00229                                 $this->combinedFileNames[] = preg_replace('/\.[[:alnum:]]+$/','',basename($fileInfo[3]));
00230                                 $this->setup[$theKey.'.']['file'] = $fileInfo[3];
00231                                 $this->setup[$theKey.'.']['BBOX'] = $fileInfo;
00232                                 $this->objBB[$theKey] = $fileInfo;
00233                                 if ($conf['mask'])  {
00234                                     $maskInfo = $this->getResource($conf['mask'],$conf['mask.']);
00235                                     if ($maskInfo)  {
00236                                         $this->setup[$theKey.'.']['mask'] = $maskInfo[3];
00237                                     } else {
00238                                         $this->setup[$theKey.'.']['mask'] = '';
00239                                     }
00240                                 }
00241                             } else {
00242                                 unset($this->setup[$theKey.'.']);
00243                             }
00244                         break;
00245                     }
00246                         // Checks if disabled is set... (this is also done in menu.php / imgmenu!!)
00247                     if ($conf['if.'])   {
00248                         $cObj =t3lib_div::makeInstance('tslib_cObj');
00249                         $cObj->start($this->data);
00250 
00251                         if (!$cObj->checkIf($conf['if.']))  {
00252                             unset($this->setup[$theKey]);
00253                             unset($this->setup[$theKey.'.']);
00254                         }
00255                     }
00256                 }
00257             }
00258 
00259                 // Calculate offsets on elements
00260             $this->setup['XY'] = $this->calcOffset($this->setup['XY']);
00261 
00262             if(isset($this->setup['offset.'])) {
00263                 $this->setup['offset'] = $this->cObj->stdWrap($this->setup['offset'], $this->setup['offset.']);
00264             }
00265             $this->setup['offset'] = $this->calcOffset($this->setup['offset']);
00266 
00267             if(isset($this->setup['workArea.'])) {
00268                 $this->setup['workArea'] = $this->cObj->stdWrap($this->setup['workArea'], $this->setup['workArea.']);
00269             }
00270             $this->setup['workArea'] = $this->calcOffset($this->setup['workArea']);
00271 
00272             foreach ($sKeyArray as $theKey) {
00273                 $theValue=$this->setup[$theKey];
00274 
00275                 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
00276                     switch($theValue)   {
00277                         case 'TEXT':
00278                         case 'IMAGE':
00279                             if(isset($this->setup[$theKey.'.']['offset.'])) {
00280                                 $this->setup[$theKey.'.']['offset'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['offset'], $this->setup[$theKey.'.']['offset.']);
00281                             }
00282                             if ($this->setup[$theKey.'.']['offset'])    {
00283                                 $this->setup[$theKey.'.']['offset'] = $this->calcOffset($this->setup[$theKey.'.']['offset']);
00284                             }
00285                         break;
00286                         case 'BOX':
00287                         case 'ELLIPSE':
00288                             if(isset($this->setup[$theKey.'.']['dimensions.'])) {
00289                                 $this->setup[$theKey.'.']['dimensions'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['dimensions'], $this->setup[$theKey.'.']['dimensions.']);
00290                             }
00291                             if ($this->setup[$theKey.'.']['dimensions'])    {
00292                                 $this->setup[$theKey.'.']['dimensions'] = $this->calcOffset($this->setup[$theKey.'.']['dimensions']);
00293                             }
00294                         break;
00295                         case 'WORKAREA':
00296                             if(isset($this->setup[$theKey.'.']['set.'])) {
00297                                 $this->setup[$theKey.'.']['set'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['set'], $this->setup[$theKey.'.']['set.']);
00298                             }
00299                             if ($this->setup[$theKey.'.']['set'])   {
00300                                 $this->setup[$theKey.'.']['set'] = $this->calcOffset($this->setup[$theKey.'.']['set']);
00301                             }
00302                         break;
00303                         case 'CROP':
00304                             if(isset($this->setup[$theKey.'.']['crop.'])) {
00305                                 $this->setup[$theKey.'.']['crop'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['crop'], $this->setup[$theKey.'.']['crop.']);
00306                             }
00307                             if ($this->setup[$theKey.'.']['crop'])  {
00308                                 $this->setup[$theKey.'.']['crop'] = $this->calcOffset($this->setup[$theKey.'.']['crop']);
00309                             }
00310                         break;
00311                         case 'SCALE':
00312                             if(isset($this->setup[$theKey.'.']['width.'])) {
00313                                 $this->setup[$theKey.'.']['width'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['width'], $this->setup[$theKey.'.']['width.']);
00314                             }
00315                             if ($this->setup[$theKey.'.']['width']) {
00316                                 $this->setup[$theKey.'.']['width'] = $this->calcOffset($this->setup[$theKey.'.']['width']);
00317                             }
00318                             if(isset($this->setup[$theKey.'.']['height.'])) {
00319                                 $this->setup[$theKey.'.']['height'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['height'], $this->setup[$theKey.'.']['height.']);
00320                             }
00321                             if ($this->setup[$theKey.'.']['height'])    {
00322                                 $this->setup[$theKey.'.']['height'] = $this->calcOffset($this->setup[$theKey.'.']['height']);
00323                             }
00324                         break;
00325                     }
00326                 }
00327             }
00328                 // Get trivial data
00329             $XY = t3lib_div::intExplode(',',$this->setup['XY']);
00330             $maxWidth = isset($this->setup['maxWidth.'])
00331                 ? intval($this->cObj->stdWrap($this->setup['maxWidth'], $this->setup['maxWidth.']))
00332                 : intval($this->setup['maxWidth']);
00333             $maxHeight = isset($this->setup['maxHeight.'])
00334                 ? intval($this->cObj->stdWrap($this->setup['maxHeight'], $this->setup['maxHeight.']))
00335                 : intval($this->setup['maxHeight']);
00336 
00337             $XY[0] = t3lib_div::intInRange($XY[0],1, $maxWidth?$maxWidth:2000);
00338             $XY[1] = t3lib_div::intInRange($XY[1],1, $maxHeight?$maxHeight:2000);
00339             $this->XY = $XY;
00340             $this->w = $XY[0];
00341             $this->h = $XY[1];
00342             $this->OFFSET = t3lib_div::intExplode(',',$this->setup['offset']);
00343 
00344             $this->setWorkArea($this->setup['workArea']);   // this sets the workArea
00345             $this->defaultWorkArea = $this->workArea;   // this sets the default to the current;
00346         }
00347     }
00348 
00349     /**
00350      * Initiates the image file generation if ->setup is true and if the file did not exist already.
00351      * Gets filename from fileName() and if file exists in typo3temp/ dir it will - of course - not be rendered again.
00352      * Otherwise rendering means calling ->make(), then ->output(), then ->destroy()
00353      *
00354      * @return  string      The filename for the created GIF/PNG file. The filename will be prefixed "GB_"
00355      * @see make(), fileName()
00356      */
00357     function gifBuild() {
00358         if ($this->setup)   {
00359             $gifFileName = $this->fileName('GB/');  // Relative to PATH_site
00360             if (!file_exists($gifFileName)) {       // File exists
00361 
00362                     // Create temporary directory if not done:
00363                 $this->createTempSubDir('GB/');
00364 
00365                     // Create file:
00366                 $this->make();
00367                 $this->output($gifFileName);
00368                 $this->destroy();
00369             }
00370             return $gifFileName;
00371         }
00372     }
00373 
00374     /**
00375      * The actual rendering of the image file.
00376      * Basically sets the dimensions, the background color, the traverses the array of GIFBUILDER objects and finally setting the transparent color if defined.
00377      * Creates a GDlib resource in $this->im and works on that
00378      * Called by gifBuild()
00379      *
00380      * @return  void
00381      * @access private
00382      * @see gifBuild()
00383      */
00384     function make() {
00385             // Get trivial data
00386         $XY = $this->XY;
00387 
00388             // Gif-start
00389         $this->im = imagecreatetruecolor($XY[0], $XY[1]);
00390         $this->w = $XY[0];
00391         $this->h = $XY[1];
00392 
00393             // backColor is set
00394         $BGcols = $this->convertColor($this->setup['backColor']);
00395         $Bcolor = ImageColorAllocate($this->im, $BGcols[0],$BGcols[1],$BGcols[2]);
00396         ImageFilledRectangle($this->im, 0, 0, $XY[0], $XY[1], $Bcolor);
00397 
00398             // Traverse the GIFBUILDER objects an render each one:
00399         if (is_array($this->setup)) {
00400             $sKeyArray=t3lib_TStemplate::sortedKeyList($this->setup);
00401             foreach($sKeyArray as $theKey)  {
00402                 $theValue=$this->setup[$theKey];
00403                 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
00404                     $isStdWrapped = array();
00405                     foreach($conf as $key => $value) {
00406                         $parameter = rtrim($key,'.');
00407                         if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
00408                             $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
00409                             $isStdWrapped[$parameter] = 1;
00410                         }
00411                     }
00412                     switch($theValue)   {
00413                             // Images
00414                         case 'IMAGE':
00415                             if ($conf['mask'])  {
00416                                 $this->maskImageOntoImage($this->im,$conf,$this->workArea);
00417                             } else {
00418                                 $this->copyImageOntoImage($this->im,$conf,$this->workArea);
00419                             }
00420                         break;
00421 
00422                             // Text
00423                         case 'TEXT':
00424                             if (!$conf['hide']) {
00425                                 if (is_array($conf['shadow.'])) {
00426                                     $isStdWrapped = array();
00427                                     foreach($conf['shadow.'] as $key => $value) {
00428                                         $parameter = rtrim($key,'.');
00429                                         if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
00430                                             $conf['shadow.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
00431                                             $isStdWrapped[$parameter] = 1;
00432                                         }
00433                                     }
00434                                     $this->makeShadow($this->im,$conf['shadow.'],$this->workArea,$conf);
00435                                 }
00436                                 if (is_array($conf['emboss.'])) {
00437                                     $isStdWrapped = array();
00438                                     foreach($conf['emboss.'] as $key => $value) {
00439                                         $parameter = rtrim($key,'.');
00440                                         if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
00441                                             $conf['emboss.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
00442                                             $isStdWrapped[$parameter] = 1;
00443                                         }
00444                                     }
00445                                     $this->makeEmboss($this->im,$conf['emboss.'],$this->workArea,$conf);
00446                                 }
00447                                 if (is_array($conf['outline.']))    {
00448                                     $isStdWrapped = array();
00449                                     foreach($conf['outline.'] as $key => $value) {
00450                                         $parameter = rtrim($key,'.');
00451                                         if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
00452                                             $conf['outline.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
00453                                             $isStdWrapped[$parameter] = 1;
00454                                         }
00455                                     }
00456                                     $this->makeOutline($this->im,$conf['outline.'],$this->workArea,$conf);
00457                                 }
00458                                 $conf['imgMap']=1;
00459                                 $this->makeText($this->im,$conf,$this->workArea);
00460                             }
00461                         break;
00462 
00463                             // Text effects:
00464                         case 'OUTLINE':
00465                             if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.']))   {
00466                                 $this->makeOutline($this->im,$conf,$this->workArea,$txtConf);
00467                             }
00468                         break;
00469                         case 'EMBOSS':
00470                             if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.']))   {
00471                                 $this->makeEmboss($this->im,$conf,$this->workArea,$txtConf);
00472                             }
00473                         break;
00474                         case 'SHADOW':
00475                             if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.']))   {
00476                                 $this->makeShadow($this->im,$conf,$this->workArea,$txtConf);
00477                             }
00478                         break;
00479 
00480                             // Other
00481                         case 'BOX':
00482                             $this->makeBox($this->im,$conf,$this->workArea);
00483                         break;
00484                         case 'EFFECT':
00485                             $this->makeEffect($this->im,$conf);
00486                         break;
00487                         case 'ADJUST':
00488                             $this->adjust($this->im,$conf);
00489                         break;
00490                         case 'CROP':
00491                             $this->crop($this->im,$conf);
00492                         break;
00493                         case 'SCALE':
00494                             $this->scale($this->im,$conf);
00495                         break;
00496                         case 'WORKAREA':
00497                             if ($conf['set'])   {
00498                                 $this->setWorkArea($conf['set']);   // this sets the workArea
00499                             }
00500                             if (isset($conf['clear']))  {
00501                                 $this->workArea = $this->defaultWorkArea;   // this sets the current to the default;
00502                             }
00503                         break;
00504                         case 'ELLIPSE':
00505                             $this->makeEllipse($this->im, $conf, $this->workArea);
00506                         break;
00507                     }
00508                 }
00509             }
00510         }
00511 
00512 
00513         if ($this->setup['transparentBackground'])  {
00514                 // Auto transparent background is set
00515             $Bcolor = ImageColorClosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
00516             imagecolortransparent($this->im, $Bcolor);
00517         } elseif (is_array($this->setup['transparentColor_array'])) {
00518                 // Multiple transparent colors are set. This is done via the trick that all transparent colors get converted to one color and then this one gets set as transparent as png/gif can just have one transparent color.
00519             $Tcolor = $this->unifyColors($this->im, $this->setup['transparentColor_array'], intval($this->setup['transparentColor.']['closest']));
00520             if ($Tcolor>=0) {
00521                 imagecolortransparent($this->im, $Tcolor);
00522             }
00523         }
00524 
00525     }
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544     /*********************************************
00545      *
00546      * Various helper functions
00547      *
00548      ********************************************/
00549 
00550 
00551     /**
00552      * Initializing/Cleaning of TypoScript properties for TEXT GIFBUILDER objects
00553      *
00554      * 'cleans' TEXT-object; Checks fontfile and other vital setup
00555      * Finds the title if its a 'variable' (instantiates a cObj and loads it with the ->data record)
00556      * Performs caseshift if any.
00557      *
00558      * @param   array       GIFBUILDER object TypoScript properties
00559      * @return  array       Modified $conf array IF the "text" property is not blank
00560      * @access private
00561      */
00562     function checkTextObj($conf)    {
00563         $isStdWrapped = array();
00564         foreach($conf as $key => $value) {
00565             $parameter = rtrim($key,'.');
00566             if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
00567                 $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
00568                 $isStdWrapped[$parameter] = 1;
00569             }
00570         }
00571         $conf['fontFile']=$this->checkFile($conf['fontFile']);
00572         if (!$conf['fontFile']){$conf['fontFile']='t3lib/fonts/nimbus.ttf';}
00573         if (!$conf['iterations']){$conf['iterations'] = 1;}
00574         if (!$conf['fontSize']){$conf['fontSize']=12;}
00575         if ($conf['spacing'] || $conf['wordSpacing'])   {       // If any kind of spacing applys, we cannot use angles!!
00576             $conf['angle']=0;
00577         }
00578         if (!isset($conf['antiAlias'])){$conf['antiAlias']=1;}
00579         $cObj =t3lib_div::makeInstance('tslib_cObj');
00580         $cObj->start($this->data);
00581 
00582         $conf['fontColor'] = trim($conf['fontColor']);
00583             // Strip HTML
00584         if (!$conf['doNotStripHTML'])   {
00585             $conf['text'] = strip_tags($conf['text']);
00586         }
00587         $this->combinedTextStrings[] = strip_tags($conf['text']);
00588 
00589             // Max length = 100 if automatic line braks are not defined:
00590         if (!isset($conf['breakWidth']) || !$conf['breakWidth']) {
00591             $tlen = (intval($conf['textMaxLength']) ? intval($conf['textMaxLength']) : 100);
00592             if ($this->nativeCharset) {
00593                 $conf['text'] = $this->csConvObj->substr($this->nativeCharset, $conf['text'], 0, $tlen);
00594             } else {
00595                 $conf['text'] = substr($conf['text'], 0 , $tlen);
00596             }
00597         }
00598         if ((string)$conf['text']!='')  {
00599 
00600                 // Char range map thingie:
00601             $fontBaseName = basename($conf['fontFile']);
00602             if (is_array($this->charRangeMap[$fontBaseName]))   {
00603 
00604                     // Initialize splitRendering array:
00605                 if (!is_array($conf['splitRendering.']))    {
00606                     $conf['splitRendering.'] = array();
00607                 }
00608 
00609                 $cfgK = $this->charRangeMap[$fontBaseName]['cfgKey'];
00610                 if (!isset($conf['splitRendering.'][$cfgK]))    {   // Do not impose settings if a splitRendering object already exists:
00611                         // Set configuration:
00612                     $conf['splitRendering.'][$cfgK] = 'charRange';
00613                     $conf['splitRendering.'][$cfgK.'.'] = $this->charRangeMap[$fontBaseName]['charMapConfig'];
00614 
00615                         // multiplicator of fontsize:
00616                     if ($this->charRangeMap[$fontBaseName]['multiplicator'])    {
00617                         $conf['splitRendering.'][$cfgK.'.']['fontSize'] = round($conf['fontSize'] * $this->charRangeMap[$fontBaseName]['multiplicator']);
00618                     }
00619                         // multiplicator of pixelSpace:
00620                     if ($this->charRangeMap[$fontBaseName]['pixelSpace'])   {
00621                         $travKeys = array('xSpaceBefore','xSpaceAfter','ySpaceBefore','ySpaceAfter');
00622                         foreach($travKeys as $pxKey)    {
00623                             if (isset($conf['splitRendering.'][$cfgK.'.'][$pxKey])) {
00624                                 $conf['splitRendering.'][$cfgK.'.'][$pxKey] = round($conf['splitRendering.'][$cfgK.'.'][$pxKey] * ($conf['fontSize'] / $this->charRangeMap[$fontBaseName]['pixelSpace']));
00625                             }
00626                         }
00627                     }
00628                 }
00629             }
00630             if (is_array($conf['splitRendering.'])) {
00631                 foreach($conf['splitRendering.'] as $key => $value) {
00632                     if (is_array($conf['splitRendering.'][$key]))   {
00633                         if (isset($conf['splitRendering.'][$key]['fontFile']))  {
00634                             $conf['splitRendering.'][$key]['fontFile'] = $this->checkFile($conf['splitRendering.'][$key]['fontFile']);
00635                         }
00636                     }
00637                 }
00638             }
00639 
00640             return $conf;
00641         }
00642     }
00643 
00644     /**
00645      * Calculation of offset using "splitCalc" and insertion of dimensions from other GIFBUILDER objects.
00646      *
00647      * Example:
00648      * Input: 2+2, 2*3, 123, [10.w]
00649      * Output: 4,6,123,45  (provided that the width of object in position 10 was 45 pixels wide)
00650      *
00651      * @param   string      The string to resolve/calculate the result of. The string is divided by a comma first and each resulting part is calculated into an integer.
00652      * @return  string      The resolved string with each part (separated by comma) returned separated by comma
00653      * @access private
00654      */
00655     function calcOffset($string)    {
00656         $value = array();
00657         $numbers = t3lib_div::trimExplode(',', $this->calculateFunctions($string));
00658 
00659         foreach ($numbers as $key => $val) {
00660             if ((string)$val == (string)intval($val)) {
00661                 $value[$key] = intval($val);
00662             } else {
00663                 $value[$key] = $this->calculateValue($val);
00664             }
00665         }
00666 
00667         $string = implode(',', $value);
00668         return $string;
00669     }
00670 
00671     /**
00672      * Returns an "imgResource" creating an instance of the tslib_cObj class and calling tslib_cObj::getImgResource
00673      *
00674      * @param   string      Filename value OR the string "GIFBUILDER", see documentation in TSref for the "datatype" called "imgResource"
00675      * @param   array       TypoScript properties passed to the function. Either GIFBUILDER properties or imgResource properties, depending on the value of $file (whether that is "GIFBUILDER" or a file reference)
00676      * @return  array       Returns an array with file information if an image was returned. Otherwise false.
00677      * @access private
00678      * @see tslib_cObj::getImgResource()
00679      */
00680     function getResource($file,$fileArray)  {
00681         if (!t3lib_div::inList($this->imageFileExt, $fileArray['ext'])) {
00682             $fileArray['ext'] = $this->gifExtension;
00683         }
00684         $cObj =t3lib_div::makeInstance('tslib_cObj');
00685         $cObj->start($this->data);
00686         return $cObj->getImgResource($file,$fileArray);
00687     }
00688 
00689     /**
00690      * Returns the reference to a "resource" in TypoScript.
00691      *
00692      * @param   string      The resource value.
00693      * @return  string      Returns the relative filepath
00694      * @access private
00695      * @see t3lib_TStemplate::getFileName()
00696      */
00697     function checkFile($file)   {
00698         return $GLOBALS['TSFE']->tmpl->getFileName($file);
00699     }
00700 
00701     /**
00702      * Calculates the GIFBUILDER output filename/path based on a serialized, hashed value of this->setup
00703      *
00704      * @param   string      Filename prefix, eg. "GB_"
00705      * @return  string      The relative filepath (relative to PATH_site)
00706      * @access private
00707      */
00708     function fileName($pre) {
00709 
00710         $meaningfulPrefix = '';
00711 
00712         if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
00713             /** @var $basicFileFunctions t3lib_basicFileFunctions */
00714             $basicFileFunctions = t3lib_div::makeInstance('t3lib_basicFileFunctions');
00715             
00716             $meaningfulPrefix = implode('_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
00717             $meaningfulPrefix = $basicFileFunctions->cleanFileName($meaningfulPrefix);
00718             $meaningfulPrefix = substr($meaningfulPrefix, 0, intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix'])) . '_';
00719         }
00720 
00721             // WARNING: In PHP5 I discovered that rendering with freetype of Japanese letters was totally corrupt. Not only the wrong glyphs are printed but also some memory stack overflow resulted in strange additional chars - and finally the reason for this investigation: The Bounding box data was changing all the time resulting in new images being generated all the time. With PHP4 it works fine.
00722         return $this->tempPath .
00723                 $pre .
00724                 $meaningfulPrefix .
00725                 t3lib_div::shortMD5(serialize($this->setup)) .
00726                 '.' . $this->extension();
00727     }
00728 
00729     /**
00730      * Returns the file extension used in the filename
00731      *
00732      * @return  string      Extension; "jpg" or "gif"/"png"
00733      * @access private
00734      */
00735     function extension() {
00736         switch(strtolower($this->setup['format']))  {
00737             case 'jpg':
00738             case 'jpeg':
00739                 return 'jpg';
00740             break;
00741             case 'png':
00742                 return 'png';
00743             break;
00744             case 'gif':
00745                 return 'gif';
00746             break;
00747             default:
00748                 return $this->gifExtension;
00749             break;
00750         }
00751     }
00752 
00753     /**
00754      * Calculates the value concerning the dimensions of objects.
00755      *
00756      * @param   string      $string: The string to be calculated (e.g. "[20.h]+13")
00757      * @return  integer     The calculated value (e.g. "23")
00758      * @see     calcOffset()
00759      */
00760     protected function calculateValue($string) {
00761         $calculatedValue = 0;
00762         $parts = t3lib_div::splitCalc($string, '+-*/%');
00763 
00764         foreach ($parts as $part) {
00765             $theVal = $part[1];
00766             $sign = $part[0];
00767 
00768             if ((string)intval($theVal) == (string)$theVal) {
00769                 $theVal = intval($theVal);
00770             } elseif ('[' . substr($theVal, 1, -1) . ']' == $theVal) {
00771                 $objParts = explode('.', substr($theVal, 1, -1));
00772                 $theVal = 0;
00773                 if (isset($this->objBB[$objParts[0]])) {
00774                     if ($objParts[1] == 'w') {
00775                         $theVal = $this->objBB[$objParts[0]][0];
00776                     } elseif ($objParts[1] == 'h') {
00777                         $theVal = $this->objBB[$objParts[0]][1];
00778                     } elseif ($objParts[1] == 'lineHeight') {
00779                         $theVal = $this->objBB[$objParts[0]][2]['lineHeight'];
00780                     }
00781                     $theVal = intval($theVal);
00782                 }
00783             } elseif (floatval($theVal)) {
00784                 $theVal = floatval($theVal);
00785             } else {
00786                 $theVal = 0;
00787             }
00788 
00789             if ($sign == '-') {
00790                 $calculatedValue-= $theVal;
00791             } elseif ($sign == '+') {
00792                 $calculatedValue+= $theVal;
00793             } elseif ($sign == '/' && $theVal) {
00794                 $calculatedValue = $calculatedValue / $theVal;
00795             } elseif ($sign == '*') {
00796                 $calculatedValue = $calculatedValue * $theVal;
00797             } elseif ($sign == '%' && $theVal) {
00798                 $calculatedValue%= $theVal;
00799             }
00800         }
00801 
00802         return round($calculatedValue);
00803     }
00804 
00805     /**
00806      * Calculates special functions:
00807      * + max([10.h], [20.h])    -> gets the maximum of the given values
00808      *
00809      * @param   string      $string: The raw string with functions to be calculated
00810      * @return  string      The calculated values
00811      */
00812     protected function calculateFunctions($string) {
00813         if (preg_match_all('#max\(([^)]+)\)#', $string, $matches)) {
00814             foreach ($matches[1] as $index => $maxExpression) {
00815                 $string = str_replace(
00816                     $matches[0][$index],
00817                     $this->calculateMaximum(
00818                         $maxExpression
00819                     ),
00820                     $string
00821                 );
00822             }
00823         }
00824 
00825         return $string;
00826     }
00827 
00828     /**
00829      * Calculates the maximum of a set of values defined like "[10.h],[20.h],1000"
00830      *
00831      * @param   string      $string: The string to be used to calculate the maximum (e.g. "[10.h],[20.h],1000")
00832      * @return  integer     The maxium value of the given comma separated and calculated values
00833      */
00834     protected function calculateMaximum($string) {
00835         $parts = t3lib_div::trimExplode(',', $this->calcOffset($string), true);
00836         $maximum = (count($parts) ? max($parts) : 0);
00837         return $maximum;
00838     }
00839 }
00840 
00841 
00842 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_gifbuilder.php'])) {
00843     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_gifbuilder.php']);
00844 }
00845 
00846 ?>