/src/typo3_src-4.1.2/t3lib/class.t3lib_stdgraphic.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2007 Kasper Skaarhoj (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 ***************************************************************/
00155 class t3lib_stdGraphic  {
00156 
00157                 // Internal configuration, set in init()
00158         var $combineScript = 'combine';                         // The ImageMagick filename used for combining two images. This name changed during the versions.
00159         var $noFramePrepended=0;                                        // If set, there is no frame pointer prepended to the filenames.
00160         var $GD2=0;                                                                     // Set, if the GDlib used is version 2.
00161         var $imagecopyresized_fix=0;                            // If set, imagecopyresized will not be called directly. For GD2 (some PHP installs?)
00162         var $gifExtension = 'gif';                                      // This should be changed to 'png' if you want this class to read/make PNG-files instead!
00163         var $gdlibExtensions = '';                      // File formats supported by gdlib. This variable get's filled in "init" method
00164         var $truecolor = true;                                  // Internal variable which get's used to determine wheter GDlib should use function truecolor pendants
00165         var $png_truecolor = false;                                     // Set to true if generated png's should be truecolor by default
00166         var $truecolorColors = 0xffffff;                        // 16777216 Colors is the maximum value for PNG, JPEG truecolor images (24-bit, 8-bit / Channel)
00167         var $TTFLocaleConv = '';                                        // Used to recode input to TTF-functions for other charsets.
00168         var $enable_typo3temp_db_tracking = 0;          // If set, then all files in typo3temp will be logged in a database table. In addition to being a log of the files with original filenames, it also serves to secure that the same image is not rendered simultaneously by two different processes.
00169         var $imageFileExt = 'gif,jpg,jpeg,png,tif,bmp,tga,pcx,ai,pdf';  // Commalist of file extensions perceived as images by TYPO3. List should be set to 'gif,png,jpeg,jpg' if IM is not available. Lowercase and no spaces between!
00170         var $webImageExt = 'gif,jpg,jpeg,png';          // Commalist of web image extensions (can be shown by a webbrowser)
00171         var $maskNegate = '';                                           // Will be ' -negate' if ImageMagick ver 5.2+. See init();
00172         var $NO_IM_EFFECTS = '';
00173         var $cmds = Array (
00174                 'jpg' => '',
00175                 'jpeg' => '',
00176                 'gif' => '-colors 64',
00177                 'png' => '-colors 64'
00178         );
00179         var $NO_IMAGE_MAGICK = '';
00180         var $V5_EFFECTS = 0;
00181         var $im_version_4 = 0;
00182         var $mayScaleUp = 1;
00183 
00184                 // Variables for testing, alternative usage etc.
00185         var $filenamePrefix='';                                                         // Filename prefix for images scaled in imageMagickConvert()
00186         var $imageMagickConvert_forceFileNameBody='';           // Forcing the output filename of imageMagickConvert() to this value. However after calling imageMagickConvert() it will be set blank again.
00187         var $dontCheckForExistingTempFile = 0;                          // This flag should always be false. If set true, imageMagickConvert will always write a new file to the tempdir! Used for debugging.
00188         var $dontCompress=0;                                                            // Prevents imageMagickConvert() from compressing the gif-files with t3lib_div::gif_compress()
00189         var $dontUnlinkTempFiles=0;                                                     // For debugging ONLY!
00190         var $alternativeOutputKey='';                                           // For debugging only. Filenames will not be based on mtime and only filename (not path) will be used. This key is also included in the hash of the filename...
00191 
00192                 // Internal:
00193         var $IM_commands = Array();                                                     // All ImageMagick commands executed is stored in this array for tracking. Used by the Install Tools Image section
00194         var $workArea = Array();
00195 
00196                 // Constants:
00197         var $tempPath = 'typo3temp/';                                           // The temp-directory where to store the files. Normally relative to PATH_site but is allowed to be the absolute path AS LONG AS it is a subdir to PATH_site.
00198         var $absPrefix = '';                                                            // Prefix for relative paths. Used in "show_item.php" script. Is prefixed the output file name IN imageMagickConvert()
00199         var $scalecmd = '-geometry';                                            // ImageMagick scaling command; "-geometry" eller "-sample". Used in makeText() and imageMagickConvert()
00200         var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5';                 // Used by v5_blur() to simulate 10 continuous steps of blurring
00201         var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5';              // Used by v5_sharpen() to simulate 10 continuous steps of sharpening.
00202         var $pixelLimitGif = 10000;                                                     // This is the limit for the number of pixels in an image before it will be rendered as JPG instead of GIF/PNG
00203         var $colMap = Array (                                                           // Array mapping HTML color names to RGB values.
00204                 'aqua' => Array(0,255,255),
00205                 'black' => Array(0,0,0),
00206                 'blue' => Array(0,0,255),
00207                 'fuchsia' => Array(255,0,255),
00208                 'gray' => Array(128,128,128),
00209                 'green' => Array(0,128,0),
00210                 'lime' => Array(0,255,0),
00211                 'maroon' => Array(128,0,0),
00212                 'navy' => Array(0,0,128),
00213                 'olive' => Array(128,128,0),
00214                 'purple' => Array(128,0,128),
00215                 'red' => Array(255,0,0),
00216                 'silver' => Array(192,192,192),
00217                 'teal' => Array(0,128,128),
00218                 'yellow' => Array(255,255,0),
00219                 'white' => Array(255,255,255)
00220         );
00221 
00222                 // Charset conversion object:
00223         var $csConvObj;
00224         var $nativeCharset='';          // Is set to the native character set of the input strings.
00225 
00226 
00227 
00228 
00229 
00236         function init() {
00237                 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
00238 
00239                 if (function_exists('imagecreatefromjpeg')&&function_exists('imagejpeg'))       {
00240                         $this->gdlibExtensions .= ',jpg,jpeg';
00241                 }
00242                 if (function_exists('imagecreatefrompng')&&function_exists('imagepng')) {
00243                         $this->gdlibExtensions .= ',png';
00244                 }
00245                 if (function_exists('imagecreatefromgif')&&function_exists('imagegif')) {
00246                         $this->gdlibExtensions .= ',gif';
00247                 }
00248                 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['png_truecolor'])        {
00249                         $this->png_truecolor = true;
00250                 }
00251                 if (!$gfxConf['gdlib_2'] || !function_exists('imagecreatetruecolor'))   {
00252                         $this->truecolor = false;
00253                 }
00254                 if (!$gfxConf['im_version_5'])  {
00255                         $this->im_version_4 = true;
00256                 }
00257 
00258                         // When GIFBUILDER gets used in truecolor mode (GD2 required)
00259                 if ($this->truecolor)   {
00260                         if ($this->png_truecolor)       {
00261                                 $this->cmds['png'] = '';        // No colors parameter if we generate truecolor images.
00262                         }
00263                         $this->cmds['gif'] = '';        // No colors parameter if we generate truecolor images.
00264                 }
00265 
00266                         // Setting default JPG parameters:
00267                 $this->jpegQuality = t3lib_div::intInRange($gfxConf['jpg_quality'], 10, 100, 75);
00268                 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.$this->jpegQuality;
00269 
00270                 if ($gfxConf['im_combine_filename'])    $this->combineScript=$gfxConf['im_combine_filename'];
00271                 if ($gfxConf['im_noFramePrepended'])    $this->noFramePrepended=1;
00272 
00273                 if ($gfxConf['gdlib_2'])        {
00274                         $this->GD2 = 1;
00275                         $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1;
00276                 }
00277                 if ($gfxConf['gdlib_png'])      {
00278                         $this->gifExtension='png';
00279                 }
00280                 if ($gfxConf['TTFLocaleConv']) {
00281                         $this->TTFLocaleConv = $gfxConf['TTFLocaleConv'];
00282                 }
00283                 if ($gfxConf['enable_typo3temp_db_tracking']) {
00284                         $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking'];
00285                 }
00286 
00287                 $this->imageFileExt = $gfxConf['imagefile_ext'];
00288 
00289                         // This should be set if ImageMagick ver. 5+ is used.
00290                 if ($gfxConf['im_negate_mask']) {
00291                                 // Boolean. Indicates if the mask images should be inverted first.
00292                                 // This depends of the ImageMagick version. Below ver. 5.1 this should be false.
00293                                 // Above ImageMagick version 5.2+ it should be true.
00294                                 // Just set the flag if the masks works opposite the intension!
00295                         $this->maskNegate = ' -negate';
00296                 }
00297                 if ($gfxConf['im_no_effects'])  {
00298                                 // Boolean. This is necessary if using ImageMagick 5+.
00299                                 // Approved version for using effects is version 4.2.9.
00300                                 // Effects in Imagemagick 5+ tends to render very slowly!!
00301                                 // - therefore must be disabled in order not to perform sharpen, blurring and such.
00302                         $this->NO_IM_EFFECTS = 1;
00303 
00304                         $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality;
00305                 }
00306                         // ... but if 'im_v5effects' is set, don't care about 'im_no_effects'
00307                 if ($gfxConf['im_v5effects'])   {
00308                         $this->NO_IM_EFFECTS = 0;
00309                         $this->V5_EFFECTS = 1;
00310 
00311                         if ($gfxConf['im_v5effects']>0) {
00312                                 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['jpg_quality']).$this->v5_sharpen(10);
00313                         }
00314                 }
00315 
00316                 if (!$gfxConf['im'])    {
00317                         $this->NO_IMAGE_MAGICK = 1;
00318                 }
00319                         // Secures that images are not scaled up.
00320                 if ($gfxConf['im_noScaleUp']) {
00321                         $this->mayScaleUp=0;
00322                 }
00323 
00324                 if (TYPO3_MODE=='FE')   {
00325                         $this->csConvObj = &$GLOBALS['TSFE']->csConvObj;
00326                 } elseif(is_object($GLOBALS['LANG']))   {       // BE assumed:
00327                         $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
00328                 } else  {       // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example.
00329                         $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
00330                 }
00331                 $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
00332         }
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349         /*************************************************
00350          *
00351          * Layering images / "IMAGE" GIFBUILDER object
00352          *
00353          *************************************************/
00354 
00366         function maskImageOntoImage(&$im,$conf,$workArea)       {
00367                 if ($conf['file'] && $conf['mask'])     {
00368                         $imgInf = pathinfo($conf['file']);
00369                         $imgExt = strtolower($imgInf['extension']);
00370                         if (!t3lib_div::inList($this->gdlibExtensions, $imgExt))        {
00371                                 $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
00372                         } else  {
00373                                 $BBimage = $this->getImageDimensions($conf['file']);
00374                         }
00375                         $maskInf = pathinfo($conf['mask']);
00376                         $maskExt = strtolower($maskInf['extension']);
00377                         if (!t3lib_div::inList($this->gdlibExtensions, $maskExt))       {
00378                                 $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
00379                         } else  {
00380                                 $BBmask = $this->getImageDimensions($conf['mask']);
00381                         }
00382                         if ($BBimage && $BBmask)        {
00383                                 $w = imagesx($im);
00384                                 $h = imagesy($im);
00385                                 $tmpStr = $this->randomName();
00386                                 $theImage = $tmpStr.'_img.'.$this->gifExtension;
00387                                 $theDest = $tmpStr.'_dest.'.$this->gifExtension;
00388                                 $theMask = $tmpStr.'_mask.'.$this->gifExtension;
00389                                                 // prepare overlay image
00390                                 $cpImg = $this->imageCreateFromFile($BBimage[3]);
00391                                 $destImg = $this->imagecreate($w,$h);
00392                                 $Bcolor = ImageColorAllocate($destImg, 0,0,0);
00393                                 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
00394                                 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00395                                 $this->ImageWrite($destImg, $theImage);
00396                                 imageDestroy($cpImg);
00397                                 imageDestroy($destImg);
00398                                                 // prepare mask image
00399                                 $cpImg = $this->imageCreateFromFile($BBmask[3]);
00400                                 $destImg = $this->imagecreate($w,$h);
00401                                 $Bcolor = ImageColorAllocate($destImg, 0, 0, 0);
00402                                 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
00403                                 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00404                                 $this->ImageWrite($destImg, $theMask);
00405                                 imageDestroy($cpImg);
00406                                 imageDestroy($destImg);
00407                                         // mask the images
00408                                 $this->ImageWrite($im, $theDest);
00409 
00410                                 $this->combineExec($theDest,$theImage,$theMask,$theDest, true);         // Let combineExec handle maskNegation
00411 
00412                                 $backIm = $this->imageCreateFromFile($theDest); // The main image is loaded again...
00413                                 if ($backIm)    {       // ... and if nothing went wrong we load it onto the old one.
00414                                         ImageColorTransparent($backIm,-1);
00415                                         $im = $backIm;
00416                                 }
00417                                         // unlink files from process
00418                                 if (!$this->dontUnlinkTempFiles)        {
00419                                         unlink($theDest);
00420                                         unlink($theImage);
00421                                         unlink($theMask);
00422                                 }
00423                         }
00424                 }
00425         }
00426 
00436         function copyImageOntoImage(&$im,$conf,$workArea)       {
00437                 if ($conf['file'])      {
00438                         if (!t3lib_div::inList($this->gdlibExtensions, $conf['BBOX'][2]))       {
00439                                 $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','','');
00440                                 $conf['file']=$conf['BBOX'][3];
00441                         }
00442                         $cpImg = $this->imageCreateFromFile($conf['file']);
00443                         $this->copyGifOntoGif($im,$cpImg,$conf,$workArea);
00444                         imageDestroy($cpImg);
00445                 }
00446         }
00447 
00458         function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)    {
00459                 $cpW = imagesx($cpImg);
00460                 $cpH = imagesy($cpImg);
00461                 $tile = t3lib_div::intExplode(',',$conf['tile']);
00462                 $tile[0] = t3lib_div::intInRange($tile[0],1,20);
00463                 $tile[1] = t3lib_div::intInRange($tile[1],1,20);
00464                 $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1]));
00465 
00466                 for ($xt=0;$xt<$tile[0];$xt++)  {
00467                         $Xstart=$cpOff[0]+$cpW*$xt;
00468                         if ($Xstart+$cpW > $workArea[0])        {       // if this image is inside of the workArea, then go on
00469                                         // X:
00470                                 if ($Xstart < $workArea[0])     {
00471                                         $cpImgCutX = $workArea[0]-$Xstart;
00472                                         $Xstart = $workArea[0];
00473                                 } else {
00474                                         $cpImgCutX = 0;
00475                                 }
00476                                 $w = $cpW-$cpImgCutX;
00477                                 if ($Xstart > $workArea[0]+$workArea[2]-$w)     {
00478                                         $w = $workArea[0]+$workArea[2]-$Xstart;
00479                                 }
00480                                 if ($Xstart < $workArea[0]+$workArea[2])        {       // if this image is inside of the workArea, then go on
00481                                                 // Y:
00482                                         for ($yt=0;$yt<$tile[1];$yt++)  {
00483                                                 $Ystart=$cpOff[1]+$cpH*$yt;
00484                                                 if ($Ystart+$cpH > $workArea[1])        {       // if this image is inside of the workArea, then go on
00485                                                         if ($Ystart < $workArea[1])     {
00486                                                                 $cpImgCutY = $workArea[1]-$Ystart;
00487                                                                 $Ystart = $workArea[1];
00488                                                         } else {
00489                                                                 $cpImgCutY = 0;
00490                                                         }
00491                                                         $h = $cpH-$cpImgCutY;
00492                                                         if ($Ystart > $workArea[1]+$workArea[3]-$h)     {
00493                                                                 $h = $workArea[1]+$workArea[3]-$Ystart;
00494                                                         }
00495                                                         if ($Ystart < $workArea[1]+$workArea[3])        {       // if this image is inside of the workArea, then go on
00496                                                                 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00497                                                         }
00498                                                 }
00499                                         }  // Y:
00500                                 }
00501                         }
00502                 }
00503         }
00504 
00537         function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)       {
00538                 if ($this->imagecopyresized_fix)        {
00539                         $im_base = $this->imagecreate(imagesx($im), imagesy($im));      // Make true color image
00540                         imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im));  // Copy the source image onto that
00541                         imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);   // Then copy the $cpImg onto that (the actual operation!)
00542                         $im = $im_base; // Set pointer
00543                         if (!$this->truecolor)  {
00544                                 $this->makeEffect($im, Array('value'=>'colors='.t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256)));                // Reduce to "reduceColors" colors - make SURE that IM is working then!
00545                         }
00546                 } else {
00547                         imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00548                 }
00549         }
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572         /********************************
00573          *
00574          * Text / "TEXT" GIFBUILDER object
00575          *
00576          ********************************/
00577 
00587         function makeText(&$im,$conf,$workArea) {
00588                         // Spacing
00589                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00590                         // Position
00591                 $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']);
00592                 $theText = $this->recodeString($conf['text']);
00593 
00594                 if ($conf['imgMap'] && is_array($conf['imgMap.']))      {
00595                         $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']);
00596                 }
00597                 if (!$conf['hideButCreateMap']) {
00598                                 // Font Color:
00599                         $cols=$this->convertColor($conf['fontColor']);
00600                                 // NiceText is calculated
00601                         if (!$conf['niceText']) {
00602                                         // Font Color is reserved:
00603                                 if (!$this->truecolor)  {
00604                                         $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
00605                                         $this->reduceColors($im, $reduce-49, $reduce-50);       // If "reduce-49" colors (or more) are used reduce them to "reduce-50"
00606                                 }
00607                                 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
00608                                         // antiAliasing is setup:
00609                                 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
00610 
00611                                 for ($a=0; $a<$conf['iterations']; $a++)        {
00612                                         if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00613                                                 $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']);
00614                                         } else {
00615                                                 $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']);
00616                                         }
00617                                 }
00618                         } else {                // NICETEXT::
00619                                         // options anti_aliased and iterations is NOT available when doing this!!
00620                                 $w = imagesx($im);
00621                                 $h = imagesy($im);
00622                                 $tmpStr = $this->randomName();
00623 
00624                                 $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension;
00625                                 $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension;
00626                                 $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension;
00627                                         // Scalefactor
00628                                 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
00629                                 $newW = ceil($sF*imagesx($im));
00630                                 $newH = ceil($sF*imagesy($im));
00631 
00632                                         // Make mask
00633                                 $maskImg = $this->imagecreate($newW, $newH);
00634                                 $Bcolor = ImageColorAllocate($maskImg, 255,255,255);
00635                                 ImageFilledRectangle($maskImg, 0, 0, $newW, $newH, $Bcolor);
00636                                 $Fcolor = ImageColorAllocate($maskImg, 0,0,0);
00637                                 if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00638                                         $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF);
00639                                 } else {
00640                                         $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00641                                 }
00642                                 $this->ImageWrite($maskImg, $fileMask);
00643                                 ImageDestroy($maskImg);
00644 
00645                                         // Downscales the mask
00646                                 if ($this->NO_IM_EFFECTS)       {
00647                                         if ($this->maskNegate)  {
00648                                                 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!');             // Negate 2 times makes no negate...
00649                                         } else {
00650                                                 $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate');
00651                                         }
00652                                 } else {
00653                                         if ($this->maskNegate)  {
00654                                                 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']);
00655                                         } else {
00656                                                 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate');
00657                                         }
00658                                         if ($conf['niceText.']['sharpen']) {
00659                                                 if ($this->V5_EFFECTS)  {
00660                                                         $command.=$this->v5_sharpen($conf['niceText.']['sharpen']);
00661                                                 } else {
00662                                                         $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99);
00663                                                 }
00664                                         }
00665                                 }
00666 
00667                                 $this->imageMagickExec($fileMask,$fileMask,$command);
00668 
00669                                         // Make the color-file
00670                                 $colorImg = $this->imagecreate($w,$h);
00671                                 $Ccolor = ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
00672                                 ImageFilledRectangle($colorImg, 0, 0, $w, $h, $Ccolor);
00673                                 $this->ImageWrite($colorImg, $fileColor);
00674                                 ImageDestroy($colorImg);
00675 
00676                                         // The mask is applied
00677                                 $this->ImageWrite($im, $fileMenu);      // The main pictures is saved temporarily
00678 
00679                                 $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu);
00680 
00681                                 $backIm = $this->imageCreateFromFile($fileMenu);        // The main image is loaded again...
00682                                 if ($backIm)    {       // ... and if nothing went wrong we load it onto the old one.
00683                                         ImageColorTransparent($backIm,-1);
00684                                         $im = $backIm;
00685                                 }
00686 
00687                                         // Deleting temporary files;
00688                                 if (!$this->dontUnlinkTempFiles)        {
00689                                         unlink($fileMenu);
00690                                         unlink($fileColor);
00691                                         unlink($fileMask);
00692                                 }
00693                         }
00694                 }
00695         }
00696 
00707         function txtPosition($conf,$workArea,$BB) {
00708                 $bbox = $BB[2];
00709                 $angle=intval($conf['angle'])/180*pi();
00710                 $conf['angle']=0;
00711                 $straightBB = $this->calcBBox($conf);
00712 
00713                         // offset, align, valign, workarea
00714                 $result=Array();        // [0]=x, [1]=y, [2]=w, [3]=h
00715                 $result[2] = $BB[0];
00716                 $result[3] = $BB[1];
00717                 $w=$workArea[2];
00718                 $h=$workArea[3];
00719 
00720                 switch($conf['align'])  {
00721                         case 'right':
00722                         case 'center':
00723                                 $factor=abs(cos($angle));
00724                                 $sign=(cos($angle)<0)?-1:1;
00725                                 $len1 = $sign*$factor*$straightBB[0];
00726                                 $len2= $sign*$BB[0];
00727                                 $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1);
00728 
00729                                 $factor=abs(sin($angle));
00730                                 $sign=(sin($angle)<0)?-1:1;
00731                                 $len1= $sign*$factor*$straightBB[0];
00732                                 $len2= $sign*$BB[1];
00733                                 $result[1]=ceil($len2*$factor+(1-$factor)*$len1);
00734                         break;
00735                 }
00736                 switch($conf['align'])  {
00737                         case 'right':
00738                         break;
00739                         case 'center':
00740                                 $result[0] = round(($result[0])/2);
00741                                 $result[1] = round(($result[1])/2);
00742                         break;
00743                         default:
00744                                 $result[0]=0;
00745                                 $result[1]=0;
00746                         break;
00747                 }
00748                 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset']));
00749                 $result = $this->applyOffset($result,$workArea);
00750                 return $result;
00751         }
00752 
00761         function calcBBox($conf)        {
00762                 $sF = $this->getTextScalFactor($conf);
00763                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf, $sF);
00764                 $theText = $this->recodeString($conf['text']);
00765 
00766                 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00767                 $theBBoxInfo = $charInf;
00768                 if ($conf['angle'])     {
00769                         $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]);
00770                         $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]);
00771                         $x=max($xArr)-min($xArr);
00772                         $y=max($yArr)-min($yArr);
00773                 } else {
00774                         $x = ($charInf[2]-$charInf[0]);
00775                         $y = ($charInf[1]-$charInf[7]);
00776                 }
00777                 if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00778                         $x=0;
00779                         if (!$spacing && $wordSpacing)  {
00780                                 $bits = explode(' ',$theText);
00781                                 while(list(,$word)=each($bits)) {
00782                                         $word.=' ';
00783                                         $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF);
00784                                         $wordW = ($wordInf[2]-$wordInf[0]);
00785                                         $x+=$wordW+$wordSpacing;
00786                                 }
00787                         } else {
00788                                 $utf8Chars = $this->singleChars($theText);
00789                                         // For each UTF-8 char, do:
00790                                 foreach($utf8Chars as $char)    {
00791                                         $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF);
00792                                         $charW = ($charInf[2]-$charInf[0]);
00793                                         $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00794                                 }
00795                         }
00796                 }
00797 
00798                 if ($sF>1) {
00799                         $x = ceil($x/$sF);
00800                         $y = ceil($y/$sF);
00801                         if (is_array($theBBoxInfo))     {
00802                                 reset($theBBoxInfo);
00803                                 while(list($key,$val)=each($theBBoxInfo))       {
00804                                         $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF);
00805                                 }
00806                         }
00807                 }
00808                 return array($x,$y,$theBBoxInfo);
00809         }
00810 
00820         function addToMap($cords,$conf) {
00821                 $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"';
00822 
00823                 $this->map.='<area'.
00824                                 ' shape="poly"'.
00825                                 ' coords="'.implode(',',$cords).'"'.
00826                                 ' href="'.htmlspecialchars($conf['url']).'"'.
00827                                 ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : '').
00828                                 $JS.
00829                                 (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : '').
00830                                 ' alt="'.htmlspecialchars($conf['altText']).'" />';
00831         }
00832 
00843         function calcTextCordsForMap($cords,$offset, $conf)     {
00844                 $pars = t3lib_div::intExplode(',',$conf['explode'].',');
00845 
00846                 $newCords[0] = $cords[0]+$offset[0]-$pars[0];
00847                 $newCords[1] = $cords[1]+$offset[1]+$pars[1];
00848                 $newCords[2] = $cords[2]+$offset[0]+$pars[0];
00849                 $newCords[3] = $cords[3]+$offset[1]+$pars[1];
00850                 $newCords[4] = $cords[4]+$offset[0]+$pars[0];
00851                 $newCords[5] = $cords[5]+$offset[1]-$pars[1];
00852                 $newCords[6] = $cords[6]+$offset[0]-$pars[0];
00853                 $newCords[7] = $cords[7]+$offset[1]-$pars[1];
00854 
00855                 return $newCords;
00856         }
00857 
00878         function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)     {
00879 
00880                 $spacing*=$sF;
00881                 $wordSpacing*=$sF;
00882 
00883                 if (!$spacing && $wordSpacing)  {
00884                         $bits = explode(' ',$text);
00885                         reset($bits);
00886                         while(list(,$word)=each($bits)) {
00887                                 $word.=' ';
00888                                 $word = $word;
00889                                 $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF);
00890                                 $wordW = ($wordInf[2]-$wordInf[0]);
00891                                 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF);
00892                                 $x+=$wordW+$wordSpacing;
00893                         }
00894                 } else {
00895                         $utf8Chars = $this->singleChars($text);
00896                                 // For each UTF-8 char, do:
00897                         foreach($utf8Chars as $char)    {
00898                                 $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF);
00899                                 $charW = ($charInf[2]-$charInf[0]);
00900                                 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF);
00901                                 $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00902                         }
00903                 }
00904         }
00905 
00915         function fontResize($conf) {
00916                 // you have to use +calc options like [10.h] in 'offset' to get the right position of your text-image, if you use +calc in XY height!!!!
00917                 $maxWidth = intval($conf['maxWidth']);
00918                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00919                 if ($maxWidth)  {
00920                         if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00921                                 return $conf['fontSize'];
00922                                 //  ################ no calc for spacing yet !!!!!!
00923                         } else {
00924                                 do {
00925                                                 // determine bounding box.
00926                                         $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']);
00927                                         if ($conf['angle']< 0) {
00928                                                 $pixelWidth = abs($bounds[4]-$bounds[0]);
00929                                         } elseif ($conf['angle'] > 0) {
00930                                                 $pixelWidth = abs($bounds[2]-$bounds[6]);
00931                                         } else {
00932                                                 $pixelWidth = abs($bounds[4]-$bounds[6]);
00933                                         }
00934 
00935                                                 // Size is fine, exit:
00936                                         if ($pixelWidth <= $maxWidth)   {
00937                                                 break;
00938                                         } else {
00939                                                 $conf['fontSize']--;
00940                                         }
00941                                 } while ($conf['fontSize']>1);
00942                         }//if spacing
00943                 }
00944                 return $conf['fontSize'];
00945         }
00946 
00958         function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)     {
00959 
00960                         // Initialize:
00961                 $offsetInfo = array();
00962                 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
00963 
00964                         // Traverse string parts:
00965                 foreach($stringParts as $strCfg)        {
00966                         $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
00967                         if (is_readable($fontFile)) {
00968 
00969                                         // Calculate Bounding Box for part:
00970                                 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']);
00971 
00972                                         // Calculate offsets:
00973                                 if (!count($offsetInfo))        {
00974                                         $offsetInfo = $calc;    // First run, just copy over.
00975                                 } else {
00976                                         $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00977                                         $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00978                                         $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00979                                         $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00980                                 }
00981 
00982                         } else {
00983                                 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFBBoxWrapper()');
00984                         }
00985                 }
00986 
00987                 return $offsetInfo;
00988         }
00989 
01005         function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1) {
01006 
01007                         // Initialize:
01008                 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
01009                 $x = ceil($sF*$x);
01010                 $y = ceil($sF*$y);
01011 
01012                         // Traverse string parts:
01013                 foreach($stringParts as $i => $strCfg)  {
01014 
01015                                 // Initialize:
01016                         $colorIndex = $color;
01017 
01018                                 // Set custom color if any (only when niceText is off):
01019                         if ($strCfg['color'] && $sF==1) {
01020                                 $cols = $this->convertColor($strCfg['color']);
01021                                 $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
01022                                 $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex;
01023                         }
01024 
01025                                 // Setting xSpaceBefore
01026                         if ($i) {
01027                                 $x+= intval($strCfg['xSpaceBefore']);
01028                                 $y-= intval($strCfg['ySpaceBefore']);
01029                         }
01030 
01031                         $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
01032                         if (is_readable($fontFile)) {
01033 
01034                                         // Render part:
01035                                 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']);
01036 
01037                                         // Calculate offset to apply:
01038                                 $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
01039                                 $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
01040                                 $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
01041 
01042                         } else {
01043                                 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFTextWrapper()');
01044                         }
01045 
01046                 }
01047         }
01048 
01058         function splitString($string,$splitRendering,$fontSize,$fontFile)       {
01059 
01060                         // Initialize by setting the whole string and default configuration as the first entry.
01061                 $result = array();
01062                 $result[] = array(
01063                         'str' => $string,
01064                         'fontSize' => $fontSize,
01065                         'fontFile' => $fontFile
01066                 );
01067 
01068                         // Traverse the split-rendering configuration:
01069                         // Splitting will create more entries in $result with individual configurations.
01070                 if (is_array($splitRendering))  {
01071                         $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering);
01072 
01073                                 // Traverse configured options:
01074                         foreach($sKeyArray as $key)     {
01075                                 $cfg = $splitRendering[$key.'.'];
01076 
01077                                         // Process each type of split rendering keyword:
01078                                 switch((string)$splitRendering[$key])   {
01079                                         case 'highlightWord':
01080                                                 if (strlen($cfg['value']))      {
01081                                                         $newResult = array();
01082 
01083                                                                 // Traverse the current parts of the result array:
01084                                                         foreach($result as $part)       {
01085                                                                         // Explode the string value by the word value to highlight:
01086                                                                 $explodedParts = explode($cfg['value'],$part['str']);
01087                                                                 foreach($explodedParts as $c => $expValue)      {
01088                                                                         if (strlen($expValue))  {
01089                                                                                 $newResult[] = array_merge($part,array('str' => $expValue));
01090                                                                         }
01091                                                                         if ($c+1 < count($explodedParts))       {
01092                                                                                 $newResult[] = array(
01093                                                                                         'str' => $cfg['value'],
01094                                                                                         'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01095                                                                                         'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01096                                                                                         'color' => $cfg['color'],
01097                                                                                         'xSpaceBefore' => $cfg['xSpaceBefore'],
01098                                                                                         'xSpaceAfter' => $cfg['xSpaceAfter'],
01099                                                                                         'ySpaceBefore' => $cfg['ySpaceBefore'],
01100                                                                                         'ySpaceAfter' => $cfg['ySpaceAfter'],
01101                                                                                 );
01102                                                                         }
01103                                                                 }
01104                                                         }
01105 
01106                                                                 // Set the new result as result array:
01107                                                         if (count($newResult))  {
01108                                                                 $result = $newResult;
01109                                                         }
01110                                                 }
01111                                         break;
01112                                         case 'charRange':
01113                                                 if (strlen($cfg['value']))      {
01114 
01115                                                                 // Initialize range:
01116                                                         $ranges = t3lib_div::trimExplode(',',$cfg['value'],1);
01117                                                         foreach($ranges as $i => $rangeDef)     {
01118                                                                 $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]);
01119                                                                 if (!isset($ranges[$i][1]))     $ranges[$i][1] = $ranges[$i][0];
01120                                                         }
01121                                                         $newResult = array();
01122 
01123                                                                 // Traverse the current parts of the result array:
01124                                                         foreach($result as $part)       {
01125 
01126                                                                         // Initialize:
01127                                                                 $currentState = -1;
01128                                                                 $bankAccum = '';
01129 
01130                                                                         // Explode the string value by the word value to highlight:
01131                                                                 $utf8Chars = $this->singleChars($part['str']);
01132                                                                 foreach($utf8Chars as $utfChar) {
01133 
01134                                                                                 // Find number and evaluate position:
01135                                                                         $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar);
01136                                                                         $inRange = 0;
01137                                                                         foreach($ranges as $rangeDef)   {
01138                                                                                 if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
01139                                                                                         $inRange = 1;
01140                                                                                         break;
01141                                                                                 }
01142                                                                         }
01143                                                                         if ($currentState==-1)  $currentState = $inRange;       // Initialize first char
01144 
01145                                                                                 // Switch bank:
01146                                                                         if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber))     {
01147 
01148                                                                                         // Set result:
01149                                                                                 if (strlen($bankAccum)) {
01150                                                                                         $newResult[] = array(
01151                                                                                                 'str' => $bankAccum,
01152                                                                                                 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01153                                                                                                 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01154                                                                                                 'color' => $currentState ? $cfg['color'] : '',
01155                                                                                                 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01156                                                                                                 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01157                                                                                                 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01158                                                                                                 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01159                                                                                         );
01160                                                                                 }
01161 
01162                                                                                         // Initialize new settings:
01163                                                                                 $currentState = $inRange;
01164                                                                                 $bankAccum = '';
01165                                                                         }
01166 
01167                                                                                 // Add char to bank:
01168                                                                         $bankAccum.=$utfChar;
01169                                                                 }
01170 
01171                                                                         // Set result for FINAL part:
01172                                                                 if (strlen($bankAccum)) {
01173                                                                         $newResult[] = array(
01174                                                                                 'str' => $bankAccum,
01175                                                                                 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01176                                                                                 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01177                                                                                 'color' => $currentState ? $cfg['color'] : '',
01178                                                                                 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01179                                                                                 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01180                                                                                 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01181                                                                                 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01182                                                                         );
01183                                                                 }
01184                                                         }
01185 
01186                                                                 // Set the new result as result array:
01187                                                         if (count($newResult))  {
01188                                                                 $result = $newResult;
01189                                                         }
01190                                                 }
01191                                         break;
01192                                 }
01193                         }
01194                 }
01195 
01196                 return $result;
01197         }
01198 
01208         function calcWordSpacing($conf, $scaleFactor=1) {
01209 
01210                 $spacing = intval($conf['spacing']);
01211                 $wordSpacing = intval($conf['wordSpacing']);
01212                 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
01213 
01214                 $spacing*=$scaleFactor;
01215                 $wordSpacing*=$scaleFactor;
01216 
01217                 return array($spacing,$wordSpacing);
01218         }
01219 
01227         function getTextScalFactor($conf) {
01228                 if (!$conf['niceText']) {
01229                         $sF = 1;
01230                 } else {                // NICETEXT::
01231                         $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
01232                 }
01233                 return $sF;
01234         }
01235 
01236 
01237 
01238 
01239 
01240 
01241 
01242 
01243 
01244 
01245 
01246         /*********************************************
01247          *
01248          * Other GIFBUILDER objects related to TEXT
01249          *
01250          *********************************************/
01251 
01262         function makeOutline(&$im,$conf,$workArea,$txtConf)     {
01263                 $thickness = intval($conf['thickness']);
01264                 if ($thickness) {
01265                         $txtConf['fontColor'] = $conf['color'];
01266                         $outLineDist = t3lib_div::intInRange($thickness,1,2);
01267                         for ($b=1;$b<=$outLineDist;$b++)        {
01268                                 if ($b==1)      {
01269                                         $it = 8;
01270                                 } else {
01271                                         $it = 16;
01272                                 }
01273                                 $outL = $this->circleOffset($b, $it);
01274                                 for ($a=0;$a<$it;$a++)  {
01275                                         $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a]));
01276                                 }
01277                         }
01278                 }
01279         }
01280 
01291         function circleOffset($distance, $iterations)   {
01292                 $res = Array();
01293                 if ($distance && $iterations)   {
01294                         for ($a=0;$a<$iterations;$a++)  {
01295                                 $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance);
01296                                 if ($yOff)      {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));}
01297                                 $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance);
01298                                 if ($xOff)      {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));}
01299                                 $res[$a] = Array($xOff,$yOff);
01300                         }
01301                 }
01302                 return $res;
01303         }
01304 
01315         function makeEmboss(&$im,$conf,$workArea,$txtConf)      {
01316                 $conf['color']=$conf['highColor'];
01317                 $this->makeShadow($im,$conf,$workArea,$txtConf);
01318                 $newOffset = t3lib_div::intExplode(',',$conf['offset']);
01319                 $newOffset[0]*=-1;
01320                 $newOffset[1]*=-1;
01321                 $conf['offset']=implode(',',$newOffset);
01322                 $conf['color']=$conf['lowColor'];
01323                 $this->makeShadow($im,$conf,$workArea,$txtConf);
01324         }
01325 
01337         function makeShadow(&$im,$conf,$workArea,$txtConf)      {
01338                 $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset']));
01339                 $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99);
01340 
01341                 if (!$blurRate || $this->NO_IM_EFFECTS) {               // No effects if ImageMagick ver. 5+
01342                         $txtConf['fontColor'] = $conf['color'];
01343                         $this->makeText($im,$txtConf,$workArea);
01344                 } else {
01345                         $w = imagesx($im);
01346                         $h = imagesy($im);
01347                         $blurBorder= 3; // area around the blur used for cropping something
01348                         $tmpStr = $this->randomName();
01349                         $fileMenu = $tmpStr.'_menu.'.$this->gifExtension;
01350                         $fileColor = $tmpStr.'_color.'.$this->gifExtension;
01351                         $fileMask = $tmpStr.'_mask.'.$this->gifExtension;
01352 
01353                                 // BlurColor Image laves
01354                         $blurColImg = $this->imagecreate($w,$h);
01355                         $bcols=$this->convertColor($conf['color']);
01356                         $Bcolor = ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
01357                         ImageFilledRectangle($blurColImg, 0, 0, $w, $h, $Bcolor);
01358                         $this->ImageWrite($blurColImg, $fileColor);
01359                         ImageDestroy($blurColImg);
01360 
01361                                 // The mask is made: BlurTextImage
01362                         $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
01363                         $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0);              // black background
01364                         ImageFilledRectangle($blurTextImg, 0, 0, $w+$blurBorder*2, $h+$blurBorder*2, $Bcolor);
01365                         $txtConf['fontColor'] = 'white';
01366                         $blurBordArr = Array($blurBorder,$blurBorder);
01367                         $this->makeText($blurTextImg,$txtConf,  $this->applyOffset($workArea,$blurBordArr));
01368                         $this->ImageWrite($blurTextImg, $fileMask);     // dump to temporary file
01369                         ImageDestroy($blurTextImg);     // destroy
01370 
01371 
01372                         $command='';
01373                         $command.=$this->maskNegate;
01374 
01375                         if ($this->V5_EFFECTS)  {
01376                                 $command.=$this->v5_blur($blurRate+1);
01377                         } else {
01378                                         // Blurring of the mask
01379                                 $times = ceil($blurRate/10);    // How many blur-commands that is executed. Min = 1;
01380                                 $newBlurRate = $blurRate*4;             // Here I boost the blur-rate so that it is 100 already at 25. The rest is done by up to 99 iterations of the blur-command.
01381                                 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99);
01382                                 for ($a=0;$a<$times;$a++)       {               // Building blur-command
01383                                         $command.=' -blur '.$blurRate;
01384                                 }
01385                         }
01386 
01387                         $this->