/src/typo3_src-4.2.0alpha1/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 
00227         var $csConvObj;
00228         var $nativeCharset='';          // Is set to the native character set of the input strings.
00229 
00230 
00231 
00232 
00233 
00240         function init() {
00241                 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
00242 
00243                 if (function_exists('imagecreatefromjpeg')&&function_exists('imagejpeg'))       {
00244                         $this->gdlibExtensions .= ',jpg,jpeg';
00245                 }
00246                 if (function_exists('imagecreatefrompng')&&function_exists('imagepng')) {
00247                         $this->gdlibExtensions .= ',png';
00248                 }
00249                 if (function_exists('imagecreatefromgif')&&function_exists('imagegif')) {
00250                         $this->gdlibExtensions .= ',gif';
00251                 }
00252                 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['png_truecolor'])        {
00253                         $this->png_truecolor = true;
00254                 }
00255                 if (!$gfxConf['gdlib_2'] || !function_exists('imagecreatetruecolor'))   {
00256                         $this->truecolor = false;
00257                 }
00258                 if (!$gfxConf['im_version_5'])  {
00259                         $this->im_version_4 = true;
00260                 }
00261 
00262                         // When GIFBUILDER gets used in truecolor mode (GD2 required)
00263                 if ($this->truecolor)   {
00264                         if ($this->png_truecolor)       {
00265                                 $this->cmds['png'] = '';        // No colors parameter if we generate truecolor images.
00266                         }
00267                         $this->cmds['gif'] = '';        // No colors parameter if we generate truecolor images.
00268                 }
00269 
00270                         // Setting default JPG parameters:
00271                 $this->jpegQuality = t3lib_div::intInRange($gfxConf['jpg_quality'], 10, 100, 75);
00272                 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.$this->jpegQuality;
00273 
00274                 if ($gfxConf['im_combine_filename'])    $this->combineScript=$gfxConf['im_combine_filename'];
00275                 if ($gfxConf['im_noFramePrepended'])    $this->noFramePrepended=1;
00276 
00277                 if ($gfxConf['gdlib_2'])        {
00278                         $this->GD2 = 1;
00279                         $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1;
00280                 }
00281                 if ($gfxConf['gdlib_png'])      {
00282                         $this->gifExtension='png';
00283                 }
00284                 if ($gfxConf['TTFLocaleConv']) {
00285                         $this->TTFLocaleConv = $gfxConf['TTFLocaleConv'];
00286                 }
00287                 if ($gfxConf['enable_typo3temp_db_tracking']) {
00288                         $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking'];
00289                 }
00290 
00291                 $this->imageFileExt = $gfxConf['imagefile_ext'];
00292 
00293                         // This should be set if ImageMagick ver. 5+ is used.
00294                 if ($gfxConf['im_negate_mask']) {
00295                                 // Boolean. Indicates if the mask images should be inverted first.
00296                                 // This depends of the ImageMagick version. Below ver. 5.1 this should be false.
00297                                 // Above ImageMagick version 5.2+ it should be true.
00298                                 // Just set the flag if the masks works opposite the intension!
00299                         $this->maskNegate = ' -negate';
00300                 }
00301                 if ($gfxConf['im_no_effects'])  {
00302                                 // Boolean. This is necessary if using ImageMagick 5+.
00303                                 // Approved version for using effects is version 4.2.9.
00304                                 // Effects in Imagemagick 5+ tends to render very slowly!!
00305                                 // - therefore must be disabled in order not to perform sharpen, blurring and such.
00306                         $this->NO_IM_EFFECTS = 1;
00307 
00308                         $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality;
00309                 }
00310                         // ... but if 'im_v5effects' is set, don't care about 'im_no_effects'
00311                 if ($gfxConf['im_v5effects'])   {
00312                         $this->NO_IM_EFFECTS = 0;
00313                         $this->V5_EFFECTS = 1;
00314 
00315                         if ($gfxConf['im_v5effects']>0) {
00316                                 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['jpg_quality']).$this->v5_sharpen(10);
00317                         }
00318                 }
00319 
00320                 if (!$gfxConf['im'])    {
00321                         $this->NO_IMAGE_MAGICK = 1;
00322                 }
00323                         // Secures that images are not scaled up.
00324                 if ($gfxConf['im_noScaleUp']) {
00325                         $this->mayScaleUp=0;
00326                 }
00327 
00328                 if (TYPO3_MODE=='FE')   {
00329                         $this->csConvObj = &$GLOBALS['TSFE']->csConvObj;
00330                 } elseif(is_object($GLOBALS['LANG']))   {       // BE assumed:
00331                         $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
00332                 } else  {       // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example.
00333                         $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
00334                 }
00335                 $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
00336         }
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353         /*************************************************
00354          *
00355          * Layering images / "IMAGE" GIFBUILDER object
00356          *
00357          *************************************************/
00358 
00370         function maskImageOntoImage(&$im,$conf,$workArea)       {
00371                 if ($conf['file'] && $conf['mask'])     {
00372                         $imgInf = pathinfo($conf['file']);
00373                         $imgExt = strtolower($imgInf['extension']);
00374                         if (!t3lib_div::inList($this->gdlibExtensions, $imgExt))        {
00375                                 $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
00376                         } else  {
00377                                 $BBimage = $this->getImageDimensions($conf['file']);
00378                         }
00379                         $maskInf = pathinfo($conf['mask']);
00380                         $maskExt = strtolower($maskInf['extension']);
00381                         if (!t3lib_div::inList($this->gdlibExtensions, $maskExt))       {
00382                                 $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
00383                         } else  {
00384                                 $BBmask = $this->getImageDimensions($conf['mask']);
00385                         }
00386                         if ($BBimage && $BBmask)        {
00387                                 $w = imagesx($im);
00388                                 $h = imagesy($im);
00389                                 $tmpStr = $this->randomName();
00390                                 $theImage = $tmpStr.'_img.'.$this->gifExtension;
00391                                 $theDest = $tmpStr.'_dest.'.$this->gifExtension;
00392                                 $theMask = $tmpStr.'_mask.'.$this->gifExtension;
00393                                                 // prepare overlay image
00394                                 $cpImg = $this->imageCreateFromFile($BBimage[3]);
00395                                 $destImg = $this->imagecreate($w,$h);
00396                                 $Bcolor = ImageColorAllocate($destImg, 0,0,0);
00397                                 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
00398                                 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00399                                 $this->ImageWrite($destImg, $theImage);
00400                                 imageDestroy($cpImg);
00401                                 imageDestroy($destImg);
00402                                                 // prepare mask image
00403                                 $cpImg = $this->imageCreateFromFile($BBmask[3]);
00404                                 $destImg = $this->imagecreate($w,$h);
00405                                 $Bcolor = ImageColorAllocate($destImg, 0, 0, 0);
00406                                 ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
00407                                 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00408                                 $this->ImageWrite($destImg, $theMask);
00409                                 imageDestroy($cpImg);
00410                                 imageDestroy($destImg);
00411                                         // mask the images
00412                                 $this->ImageWrite($im, $theDest);
00413 
00414                                 $this->combineExec($theDest,$theImage,$theMask,$theDest, true);         // Let combineExec handle maskNegation
00415 
00416                                 $backIm = $this->imageCreateFromFile($theDest); // The main image is loaded again...
00417                                 if ($backIm)    {       // ... and if nothing went wrong we load it onto the old one.
00418                                         ImageColorTransparent($backIm,-1);
00419                                         $im = $backIm;
00420                                 }
00421                                         // unlink files from process
00422                                 if (!$this->dontUnlinkTempFiles)        {
00423                                         unlink($theDest);
00424                                         unlink($theImage);
00425                                         unlink($theMask);
00426                                 }
00427                         }
00428                 }
00429         }
00430 
00440         function copyImageOntoImage(&$im,$conf,$workArea)       {
00441                 if ($conf['file'])      {
00442                         if (!t3lib_div::inList($this->gdlibExtensions, $conf['BBOX'][2]))       {
00443                                 $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','','');
00444                                 $conf['file']=$conf['BBOX'][3];
00445                         }
00446                         $cpImg = $this->imageCreateFromFile($conf['file']);
00447                         $this->copyGifOntoGif($im,$cpImg,$conf,$workArea);
00448                         imageDestroy($cpImg);
00449                 }
00450         }
00451 
00462         function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)    {
00463                 $cpW = imagesx($cpImg);
00464                 $cpH = imagesy($cpImg);
00465                 $tile = t3lib_div::intExplode(',',$conf['tile']);
00466                 $tile[0] = t3lib_div::intInRange($tile[0],1,20);
00467                 $tile[1] = t3lib_div::intInRange($tile[1],1,20);
00468                 $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1]));
00469 
00470                 for ($xt=0;$xt<$tile[0];$xt++)  {
00471                         $Xstart=$cpOff[0]+$cpW*$xt;
00472                         if ($Xstart+$cpW > $workArea[0])        {       // if this image is inside of the workArea, then go on
00473                                         // X:
00474                                 if ($Xstart < $workArea[0])     {
00475                                         $cpImgCutX = $workArea[0]-$Xstart;
00476                                         $Xstart = $workArea[0];
00477                                 } else {
00478                                         $cpImgCutX = 0;
00479                                 }
00480                                 $w = $cpW-$cpImgCutX;
00481                                 if ($Xstart > $workArea[0]+$workArea[2]-$w)     {
00482                                         $w = $workArea[0]+$workArea[2]-$Xstart;
00483                                 }
00484                                 if ($Xstart < $workArea[0]+$workArea[2])        {       // if this image is inside of the workArea, then go on
00485                                                 // Y:
00486                                         for ($yt=0;$yt<$tile[1];$yt++)  {
00487                                                 $Ystart=$cpOff[1]+$cpH*$yt;
00488                                                 if ($Ystart+$cpH > $workArea[1])        {       // if this image is inside of the workArea, then go on
00489                                                         if ($Ystart < $workArea[1])     {
00490                                                                 $cpImgCutY = $workArea[1]-$Ystart;
00491                                                                 $Ystart = $workArea[1];
00492                                                         } else {
00493                                                                 $cpImgCutY = 0;
00494                                                         }
00495                                                         $h = $cpH-$cpImgCutY;
00496                                                         if ($Ystart > $workArea[1]+$workArea[3]-$h)     {
00497                                                                 $h = $workArea[1]+$workArea[3]-$Ystart;
00498                                                         }
00499                                                         if ($Ystart < $workArea[1]+$workArea[3])        {       // if this image is inside of the workArea, then go on
00500                                                                 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00501                                                         }
00502                                                 }
00503                                         }  // Y:
00504                                 }
00505                         }
00506                 }
00507         }
00508 
00541         function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)       {
00542                 if ($this->imagecopyresized_fix)        {
00543                         $im_base = $this->imagecreate(imagesx($im), imagesy($im));      // Make true color image
00544                         imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im));  // Copy the source image onto that
00545                         imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);   // Then copy the $cpImg onto that (the actual operation!)
00546                         $im = $im_base; // Set pointer
00547                         if (!$this->truecolor)  {
00548                                 $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!
00549                         }
00550                 } else {
00551                         imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00552                 }
00553         }
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576         /********************************
00577          *
00578          * Text / "TEXT" GIFBUILDER object
00579          *
00580          ********************************/
00581 
00591         function makeText(&$im,$conf,$workArea) {
00592                         // Spacing
00593                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00594                         // Position
00595                 $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']);
00596                 $theText = $this->recodeString($conf['text']);
00597 
00598                 if ($conf['imgMap'] && is_array($conf['imgMap.']))      {
00599                         $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']);
00600                 }
00601                 if (!$conf['hideButCreateMap']) {
00602                                 // Font Color:
00603                         $cols=$this->convertColor($conf['fontColor']);
00604                                 // NiceText is calculated
00605                         if (!$conf['niceText']) {
00606                                         // Font Color is reserved:
00607                                 if (!$this->truecolor)  {
00608                                         $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
00609                                         $this->reduceColors($im, $reduce-49, $reduce-50);       // If "reduce-49" colors (or more) are used reduce them to "reduce-50"
00610                                 }
00611                                 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
00612                                         // antiAliasing is setup:
00613                                 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
00614 
00615                                 for ($a=0; $a<$conf['iterations']; $a++)        {
00616                                         if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00617                                                 $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']);
00618                                         } else {
00619                                                 $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']);
00620                                         }
00621                                 }
00622                         } else {                // NICETEXT::
00623                                         // options anti_aliased and iterations is NOT available when doing this!!
00624                                 $w = imagesx($im);
00625                                 $h = imagesy($im);
00626                                 $tmpStr = $this->randomName();
00627 
00628                                 $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension;
00629                                 $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension;
00630                                 $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension;
00631                                         // Scalefactor
00632                                 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
00633                                 $newW = ceil($sF*imagesx($im));
00634                                 $newH = ceil($sF*imagesy($im));
00635 
00636                                         // Make mask
00637                                 $maskImg = $this->imagecreate($newW, $newH);
00638                                 $Bcolor = ImageColorAllocate($maskImg, 255,255,255);
00639                                 ImageFilledRectangle($maskImg, 0, 0, $newW, $newH, $Bcolor);
00640                                 $Fcolor = ImageColorAllocate($maskImg, 0,0,0);
00641                                 if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00642                                         $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF);
00643                                 } else {
00644                                         $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00645                                 }
00646                                 $this->ImageWrite($maskImg, $fileMask);
00647                                 ImageDestroy($maskImg);
00648 
00649                                         // Downscales the mask
00650                                 if ($this->NO_IM_EFFECTS)       {
00651                                         if ($this->maskNegate)  {
00652                                                 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!');             // Negate 2 times makes no negate...
00653                                         } else {
00654                                                 $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate');
00655                                         }
00656                                 } else {
00657                                         if ($this->maskNegate)  {
00658                                                 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']);
00659                                         } else {
00660                                                 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate');
00661                                         }
00662                                         if ($conf['niceText.']['sharpen']) {
00663                                                 if ($this->V5_EFFECTS)  {
00664                                                         $command.=$this->v5_sharpen($conf['niceText.']['sharpen']);
00665                                                 } else {
00666                                                         $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99);
00667                                                 }
00668                                         }
00669                                 }
00670 
00671                                 $this->imageMagickExec($fileMask,$fileMask,$command);
00672 
00673                                         // Make the color-file
00674                                 $colorImg = $this->imagecreate($w,$h);
00675                                 $Ccolor = ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
00676                                 ImageFilledRectangle($colorImg, 0, 0, $w, $h, $Ccolor);
00677                                 $this->ImageWrite($colorImg, $fileColor);
00678                                 ImageDestroy($colorImg);
00679 
00680                                         // The mask is applied
00681                                 $this->ImageWrite($im, $fileMenu);      // The main pictures is saved temporarily
00682 
00683                                 $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu);
00684 
00685                                 $backIm = $this->imageCreateFromFile($fileMenu);        // The main image is loaded again...
00686                                 if ($backIm)    {       // ... and if nothing went wrong we load it onto the old one.
00687                                         ImageColorTransparent($backIm,-1);
00688                                         $im = $backIm;
00689                                 }
00690 
00691                                         // Deleting temporary files;
00692                                 if (!$this->dontUnlinkTempFiles)        {
00693                                         unlink($fileMenu);
00694                                         unlink($fileColor);
00695                                         unlink($fileMask);
00696                                 }
00697                         }
00698                 }
00699         }
00700 
00711         function txtPosition($conf,$workArea,$BB) {
00712                 $bbox = $BB[2];
00713                 $angle=intval($conf['angle'])/180*pi();
00714                 $conf['angle']=0;
00715                 $straightBB = $this->calcBBox($conf);
00716 
00717                         // offset, align, valign, workarea
00718                 $result=Array();        // [0]=x, [1]=y, [2]=w, [3]=h
00719                 $result[2] = $BB[0];
00720                 $result[3] = $BB[1];
00721                 $w=$workArea[2];
00722                 $h=$workArea[3];
00723 
00724                 switch($conf['align'])  {
00725                         case 'right':
00726                         case 'center':
00727                                 $factor=abs(cos($angle));
00728                                 $sign=(cos($angle)<0)?-1:1;
00729                                 $len1 = $sign*$factor*$straightBB[0];
00730                                 $len2= $sign*$BB[0];
00731                                 $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1);
00732 
00733                                 $factor=abs(sin($angle));
00734                                 $sign=(sin($angle)<0)?-1:1;
00735                                 $len1= $sign*$factor*$straightBB[0];
00736                                 $len2= $sign*$BB[1];
00737                                 $result[1]=ceil($len2*$factor+(1-$factor)*$len1);
00738                         break;
00739                 }
00740                 switch($conf['align'])  {
00741                         case 'right':
00742                         break;
00743                         case 'center':
00744                                 $result[0] = round(($result[0])/2);
00745                                 $result[1] = round(($result[1])/2);
00746                         break;
00747                         default:
00748                                 $result[0]=0;
00749                                 $result[1]=0;
00750                         break;
00751                 }
00752                 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset']));
00753                 $result = $this->applyOffset($result,$workArea);
00754                 return $result;
00755         }
00756 
00765         function calcBBox($conf)        {
00766                 $sF = $this->getTextScalFactor($conf);
00767                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf, $sF);
00768                 $theText = $this->recodeString($conf['text']);
00769 
00770                 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00771                 $theBBoxInfo = $charInf;
00772                 if ($conf['angle'])     {
00773                         $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]);
00774                         $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]);
00775                         $x=max($xArr)-min($xArr);
00776                         $y=max($yArr)-min($yArr);
00777                 } else {
00778                         $x = ($charInf[2]-$charInf[0]);
00779                         $y = ($charInf[1]-$charInf[7]);
00780                 }
00781                 if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00782                         $x=0;
00783                         if (!$spacing && $wordSpacing)  {
00784                                 $bits = explode(' ',$theText);
00785                                 while(list(,$word)=each($bits)) {
00786                                         $word.=' ';
00787                                         $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF);
00788                                         $wordW = ($wordInf[2]-$wordInf[0]);
00789                                         $x+=$wordW+$wordSpacing;
00790                                 }
00791                         } else {
00792                                 $utf8Chars = $this->singleChars($theText);
00793                                         // For each UTF-8 char, do:
00794                                 foreach($utf8Chars as $char)    {
00795                                         $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF);
00796                                         $charW = ($charInf[2]-$charInf[0]);
00797                                         $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00798                                 }
00799                         }
00800                 }
00801 
00802                 if ($sF>1) {
00803                         $x = ceil($x/$sF);
00804                         $y = ceil($y/$sF);
00805                         if (is_array($theBBoxInfo))     {
00806                                 reset($theBBoxInfo);
00807                                 while(list($key,$val)=each($theBBoxInfo))       {
00808                                         $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF);
00809                                 }
00810                         }
00811                 }
00812                 return array($x,$y,$theBBoxInfo);
00813         }
00814 
00824         function addToMap($cords,$conf) {
00825                 $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"';
00826 
00827                 $this->map.='<area'.
00828                                 ' shape="poly"'.
00829                                 ' coords="'.implode(',',$cords).'"'.
00830                                 ' href="'.htmlspecialchars($conf['url']).'"'.
00831                                 ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : '').
00832                                 $JS.
00833                                 (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : '').
00834                                 ' alt="'.htmlspecialchars($conf['altText']).'" />';
00835         }
00836 
00847         function calcTextCordsForMap($cords,$offset, $conf)     {
00848                 $pars = t3lib_div::intExplode(',',$conf['explode'].',');
00849 
00850                 $newCords[0] = $cords[0]+$offset[0]-$pars[0];
00851                 $newCords[1] = $cords[1]+$offset[1]+$pars[1];
00852                 $newCords[2] = $cords[2]+$offset[0]+$pars[0];
00853                 $newCords[3] = $cords[3]+$offset[1]+$pars[1];
00854                 $newCords[4] = $cords[4]+$offset[0]+$pars[0];
00855                 $newCords[5] = $cords[5]+$offset[1]-$pars[1];
00856                 $newCords[6] = $cords[6]+$offset[0]-$pars[0];
00857                 $newCords[7] = $cords[7]+$offset[1]-$pars[1];
00858 
00859                 return $newCords;
00860         }
00861 
00882         function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)     {
00883 
00884                 $spacing*=$sF;
00885                 $wordSpacing*=$sF;
00886 
00887                 if (!$spacing && $wordSpacing)  {
00888                         $bits = explode(' ',$text);
00889                         reset($bits);
00890                         while(list(,$word)=each($bits)) {
00891                                 $word.=' ';
00892                                 $word = $word;
00893                                 $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF);
00894                                 $wordW = ($wordInf[2]-$wordInf[0]);
00895                                 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF);
00896                                 $x+=$wordW+$wordSpacing;
00897                         }
00898                 } else {
00899                         $utf8Chars = $this->singleChars($text);
00900                                 // For each UTF-8 char, do:
00901                         foreach($utf8Chars as $char)    {
00902                                 $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF);
00903                                 $charW = ($charInf[2]-$charInf[0]);
00904                                 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF);
00905                                 $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00906                         }
00907                 }
00908         }
00909 
00919         function fontResize($conf) {
00920                 // 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!!!!
00921                 $maxWidth = intval($conf['maxWidth']);
00922                 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00923                 if ($maxWidth)  {
00924                         if ($spacing || $wordSpacing)   {               // If any kind of spacing applys, we use this function:
00925                                 return $conf['fontSize'];
00926                                 //  ################ no calc for spacing yet !!!!!!
00927                         } else {
00928                                 do {
00929                                                 // determine bounding box.
00930                                         $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']);
00931                                         if ($conf['angle']< 0) {
00932                                                 $pixelWidth = abs($bounds[4]-$bounds[0]);
00933                                         } elseif ($conf['angle'] > 0) {
00934                                                 $pixelWidth = abs($bounds[2]-$bounds[6]);
00935                                         } else {
00936                                                 $pixelWidth = abs($bounds[4]-$bounds[6]);
00937                                         }
00938 
00939                                                 // Size is fine, exit:
00940                                         if ($pixelWidth <= $maxWidth)   {
00941                                                 break;
00942                                         } else {
00943                                                 $conf['fontSize']--;
00944                                         }
00945                                 } while ($conf['fontSize']>1);
00946                         }//if spacing
00947                 }
00948                 return $conf['fontSize'];
00949         }
00950 
00962         function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)     {
00963 
00964                         // Initialize:
00965                 $offsetInfo = array();
00966                 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
00967 
00968                         // Traverse string parts:
00969                 foreach($stringParts as $strCfg)        {
00970                         $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
00971                         if (is_readable($fontFile)) {
00972 
00973                                         // Calculate Bounding Box for part:
00974                                 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']);
00975 
00976                                         // Calculate offsets:
00977                                 if (!count($offsetInfo))        {
00978                                         $offsetInfo = $calc;    // First run, just copy over.
00979                                 } else {
00980                                         $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00981                                         $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00982                                         $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00983                                         $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00984                                 }
00985 
00986                         } else {
00987                                 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFBBoxWrapper()');
00988                         }
00989                 }
00990 
00991                 return $offsetInfo;
00992         }
00993 
01009         function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1) {
01010 
01011                         // Initialize:
01012                 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
01013                 $x = ceil($sF*$x);
01014                 $y = ceil($sF*$y);
01015 
01016                         // Traverse string parts:
01017                 foreach($stringParts as $i => $strCfg)  {
01018 
01019                                 // Initialize:
01020                         $colorIndex = $color;
01021 
01022                                 // Set custom color if any (only when niceText is off):
01023                         if ($strCfg['color'] && $sF==1) {
01024                                 $cols = $this->convertColor($strCfg['color']);
01025                                 $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
01026                                 $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex;
01027                         }
01028 
01029                                 // Setting xSpaceBefore
01030                         if ($i) {
01031                                 $x+= intval($strCfg['xSpaceBefore']);
01032                                 $y-= intval($strCfg['ySpaceBefore']);
01033                         }
01034 
01035                         $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
01036                         if (is_readable($fontFile)) {
01037 
01038                                         // Render part:
01039                                 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']);
01040 
01041                                         // Calculate offset to apply:
01042                                 $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
01043                                 $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
01044                                 $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
01045 
01046                         } else {
01047                                 debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFTextWrapper()');
01048                         }
01049 
01050                 }
01051         }
01052 
01062         function splitString($string,$splitRendering,$fontSize,$fontFile)       {
01063 
01064                         // Initialize by setting the whole string and default configuration as the first entry.
01065                 $result = array();
01066                 $result[] = array(
01067                         'str' => $string,
01068                         'fontSize' => $fontSize,
01069                         'fontFile' => $fontFile
01070                 );
01071 
01072                         // Traverse the split-rendering configuration:
01073                         // Splitting will create more entries in $result with individual configurations.
01074                 if (is_array($splitRendering))  {
01075                         $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering);
01076 
01077                                 // Traverse configured options:
01078                         foreach($sKeyArray as $key)     {
01079                                 $cfg = $splitRendering[$key.'.'];
01080 
01081                                         // Process each type of split rendering keyword:
01082                                 switch((string)$splitRendering[$key])   {
01083                                         case 'highlightWord':
01084                                                 if (strlen($cfg['value']))      {
01085                                                         $newResult = array();
01086 
01087                                                                 // Traverse the current parts of the result array:
01088                                                         foreach($result as $part)       {
01089                                                                         // Explode the string value by the word value to highlight:
01090                                                                 $explodedParts = explode($cfg['value'],$part['str']);
01091                                                                 foreach($explodedParts as $c => $expValue)      {
01092                                                                         if (strlen($expValue))  {
01093                                                                                 $newResult[] = array_merge($part,array('str' => $expValue));
01094                                                                         }
01095                                                                         if ($c+1 < count($explodedParts))       {
01096                                                                                 $newResult[] = array(
01097                                                                                         'str' => $cfg['value'],
01098                                                                                         'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01099                                                                                         'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01100                                                                                         'color' => $cfg['color'],
01101                                                                                         'xSpaceBefore' => $cfg['xSpaceBefore'],
01102                                                                                         'xSpaceAfter' => $cfg['xSpaceAfter'],
01103                                                                                         'ySpaceBefore' => $cfg['ySpaceBefore'],
01104                                                                                         'ySpaceAfter' => $cfg['ySpaceAfter'],
01105                                                                                 );
01106                                                                         }
01107                                                                 }
01108                                                         }
01109 
01110                                                                 // Set the new result as result array:
01111                                                         if (count($newResult))  {
01112                                                                 $result = $newResult;
01113                                                         }
01114                                                 }
01115                                         break;
01116                                         case 'charRange':
01117                                                 if (strlen($cfg['value']))      {
01118 
01119                                                                 // Initialize range:
01120                                                         $ranges = t3lib_div::trimExplode(',',$cfg['value'],1);
01121                                                         foreach($ranges as $i => $rangeDef)     {
01122                                                                 $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]);
01123                                                                 if (!isset($ranges[$i][1]))     $ranges[$i][1] = $ranges[$i][0];
01124                                                         }
01125                                                         $newResult = array();
01126 
01127                                                                 // Traverse the current parts of the result array:
01128                                                         foreach($result as $part)       {
01129 
01130                                                                         // Initialize:
01131                                                                 $currentState = -1;
01132                                                                 $bankAccum = '';
01133 
01134                                                                         // Explode the string value by the word value to highlight:
01135                                                                 $utf8Chars = $this->singleChars($part['str']);
01136                                                                 foreach($utf8Chars as $utfChar) {
01137 
01138                                                                                 // Find number and evaluate position:
01139                                                                         $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar);
01140                                                                         $inRange = 0;
01141                                                                         foreach($ranges as $rangeDef)   {
01142                                                                                 if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
01143                                                                                         $inRange = 1;
01144                                                                                         break;
01145                                                                                 }
01146                                                                         }
01147                                                                         if ($currentState==-1)  $currentState = $inRange;       // Initialize first char
01148 
01149                                                                                 // Switch bank:
01150                                                                         if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber))     {
01151 
01152                                                                                         // Set result:
01153                                                                                 if (strlen($bankAccum)) {
01154                                                                                         $newResult[] = array(
01155                                                                                                 'str' => $bankAccum,
01156                                                                                                 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01157                                                                                                 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01158                                                                                                 'color' => $currentState ? $cfg['color'] : '',
01159                                                                                                 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01160                                                                                                 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01161                                                                                                 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01162                                                                                                 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01163                                                                                         );
01164                                                                                 }
01165 
01166                                                                                         // Initialize new settings:
01167                                                                                 $currentState = $inRange;
01168                                                                                 $bankAccum = '';
01169                                                                         }
01170 
01171                                                                                 // Add char to bank:
01172                                                                         $bankAccum.=$utfChar;
01173                                                                 }
01174 
01175                                                                         // Set result for FINAL part:
01176                                                                 if (strlen($bankAccum)) {
01177                                                                         $newResult[] = array(
01178                                                                                 'str' => $bankAccum,
01179                                                                                 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01180                                                                                 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01181                                                                                 'color' => $currentState ? $cfg['color'] : '',
01182                                                                                 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01183                                                                                 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01184                                                                                 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01185                                                                                 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01186                                                                         );
01187                                                                 }
01188                                                         }
01189 
01190                                                                 // Set the new result as result array:
01191                                                         if (count($newResult))  {
01192                                                                 $result = $newResult;
01193                                                         }
01194                                                 }
01195                                         break;
01196                                 }
01197                         }
01198                 }
01199 
01200                 return $result;
01201         }
01202 
01212         function calcWordSpacing($conf, $scaleFactor=1) {
01213 
01214                 $spacing = intval($conf['spacing']);
01215                 $wordSpacing = intval($conf['wordSpacing']);
01216                 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
01217 
01218                 $spacing*=$scaleFactor;
01219                 $wordSpacing*=$scaleFactor;
01220 
01221                 return array($spacing,$wordSpacing);
01222         }
01223 
01231         function getTextScalFactor($conf) {
01232                 if (!$conf['niceText']) {
01233                         $sF = 1;
01234                 } else {                // NICETEXT::
01235                         $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
01236                 }
01237                 return $sF;
01238         }
01239 
01240 
01241 
01242 
01243 
01244 
01245 
01246 
01247 
01248 
01249 
01250         /*********************************************
01251          *
01252          * Other GIFBUILDER objects related to TEXT
01253          *
01254          *********************************************/
01255 
01266         function makeOutline(&$im,$conf,$workArea,$txtConf)     {
01267                 $thickness = intval($conf['thickness']);
01268                 if ($thickness) {
01269                         $txtConf['fontColor'] = $conf['color'];
01270                         $outLineDist = t3lib_div::intInRange($thickness,1,2);
01271                         for ($b=1;$b<=$outLineDist;$b++)        {
01272                                 if ($b==1)      {
01273                                         $it = 8;
01274                                 } else {
01275                                         $it = 16;
01276                                 }
01277                                 $outL = $this->circleOffset($b, $it);
01278                                 for ($a=0;$a<$it;$a++)  {
01279                                         $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a]));
01280                                 }
01281                         }
01282                 }
01283         }
01284 
01295         function circleOffset($distance, $iterations)   {
01296                 $res = Array();
01297                 if ($distance && $iterations)   {
01298                         for ($a=0;$a<$iterations;$a++)  {
01299                                 $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance);
01300                                 if ($yOff)      {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));}
01301                                 $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance);
01302                                 if ($xOff)      {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));}
01303                                 $res[$a] = Array($xOff,$yOff);
01304                         }
01305                 }
01306                 return $res;
01307         }
01308 
01319         function makeEmboss(&$im,$conf,$workArea,$txtConf)      {
01320                 $conf['color']=$conf['highColor'];
01321                 $this->makeShadow($im,$conf,$workArea,$txtConf);
01322                 $newOffset = t3lib_div::intExplode(',',$conf['offset']);
01323                 $newOffset[0]*=-1;
01324                 $newOffset[1]*=-1;
01325                 $conf['offset']=implode(',',$newOffset);
01326                 $conf['color']=$conf['lowColor'];
01327                 $this->makeShadow($im,$conf,$workArea,$txtConf);
01328         }
01329 
01341         function makeShadow(&$im,$conf,$workArea,$txtConf)      {
01342                 $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset']));
01343                 $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99);
01344 
01345                 if (!$blurRate || $this->NO_IM_EFFECTS) {               // No effects if ImageMagick ver. 5+
01346                         $txtConf['fontColor'] = $conf['color'];
01347                         $this->makeText($im,$txtConf,$workArea);
01348                 } else {
01349                         $w = imagesx($im);
01350                         $h = imagesy($im);
01351                         $blurBorder= 3; // area around the blur used for cropping something
01352                         $tmpStr = $this->randomName();
01353                         $fileMenu = $tmpStr.'_menu.'.$this->gifExtension;
01354                         $fileColor = $tmpStr.'_color.'.$this->gifExtension;
01355                         $fileMask = $tmpStr.'_mask.'.$this->gifExtension;
01356 
01357                                 // BlurColor Image laves
01358                         $blurColImg = $this->imagecreate($w,$h);
01359                         $bcols=$this->convertColor($conf['color']);
01360                         $Bcolor = ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
01361                         ImageFilledRectangle($blurColImg, 0, 0, $w, $h, $Bcolor);
01362                         $this->ImageWrite($blurColImg, $fileColor);
01363                         ImageDestroy($blurColImg);
01364 
01365                                 // The mask is made: BlurTextImage
01366                         $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
01367                         $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0);              // black background
01368                         ImageFilledRectangle($blurTextImg, 0, 0, $w+$blurBorder*2, $h+$blurBorder*2, $Bcolor);
01369                         $txtConf['fontColor'] = 'white';
01370                         $blurBordArr = Array($blurBorder,$blurBorder);
01371                         $this->makeText($blurTextImg,$txtConf,  $this->applyOffset($workArea,$blurBordArr));
01372                         $this->ImageWrite($blurTextImg, $fileMask);     // dump to temporary file
01373                         ImageDestroy($blurTextImg);     // destroy
01374 
01375 
01376                         $command='';
01377                         $command.=$this->maskNegate;
01378 
01379                         if ($this->V5_EFFECTS)  {
01380                                 $command.=$this->v5_blur($blurRate+1);
01381                         } else {
01382                                         // Blurring of the mask
01383                                 $times = ceil($blurRate/10);    // How many blur-commands that is executed. Min = 1;
01384                                 $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.
01385                                 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99);
01386                                 for ($a=0;$a<$times;$a++)       {               // Building blur-command
01387                                         $command.=' -blur '.$blurRate;
01388                                 }
01389                         }
01390 
01391                         $this->imageMagickExec($fileMask,$fileMask,$command.' +matte');