00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00155 class t3lib_stdGraphic {
00156
00157
00158 var $combineScript = 'combine';
00159 var $noFramePrepended=0;
00160 var $GD2=0;
00161 var $imagecopyresized_fix=0;
00162 var $gifExtension = 'gif';
00163 var $gdlibExtensions = '';
00164 var $truecolor = true;
00165 var $png_truecolor = false;
00166 var $truecolorColors = 0xffffff;
00167 var $TTFLocaleConv = '';
00168 var $enable_typo3temp_db_tracking = 0;
00169 var $imageFileExt = 'gif,jpg,jpeg,png,tif,bmp,tga,pcx,ai,pdf';
00170 var $webImageExt = 'gif,jpg,jpeg,png';
00171 var $maskNegate = '';
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
00185 var $filenamePrefix='';
00186 var $imageMagickConvert_forceFileNameBody='';
00187 var $dontCheckForExistingTempFile = 0;
00188 var $dontCompress=0;
00189 var $dontUnlinkTempFiles=0;
00190 var $alternativeOutputKey='';
00191
00192
00193 var $IM_commands = Array();
00194 var $workArea = Array();
00195
00196
00197 var $tempPath = 'typo3temp/';
00198 var $absPrefix = '';
00199 var $scalecmd = '-geometry';
00200 var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5';
00201 var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5';
00202 var $pixelLimitGif = 10000;
00203 var $colMap = Array (
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='';
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
00263 if ($this->truecolor) {
00264 if ($this->png_truecolor) {
00265 $this->cmds['png'] = '';
00266 }
00267 $this->cmds['gif'] = '';
00268 }
00269
00270
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
00294 if ($gfxConf['im_negate_mask']) {
00295
00296
00297
00298
00299 $this->maskNegate = ' -negate';
00300 }
00301 if ($gfxConf['im_no_effects']) {
00302
00303
00304
00305
00306 $this->NO_IM_EFFECTS = 1;
00307
00308 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality;
00309 }
00310
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
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'])) {
00331 $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
00332 } else {
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
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
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
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
00412 $this->ImageWrite($im, $theDest);
00413
00414 $this->combineExec($theDest,$theImage,$theMask,$theDest, true);
00415
00416 $backIm = $this->imageCreateFromFile($theDest);
00417 if ($backIm) {
00418 ImageColorTransparent($backIm,-1);
00419 $im = $backIm;
00420 }
00421
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]) {
00473
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]) {
00485
00486 for ($yt=0;$yt<$tile[1];$yt++) {
00487 $Ystart=$cpOff[1]+$cpH*$yt;
00488 if ($Ystart+$cpH > $workArea[1]) {
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]) {
00500 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00501 }
00502 }
00503 }
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));
00544 imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im));
00545 imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00546 $im = $im_base;
00547 if (!$this->truecolor) {
00548 $this->makeEffect($im, Array('value'=>'colors='.t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256)));
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
00579
00580
00581
00591 function makeText(&$im,$conf,$workArea) {
00592
00593 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00594
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
00603 $cols=$this->convertColor($conf['fontColor']);
00604
00605 if (!$conf['niceText']) {
00606
00607 if (!$this->truecolor) {
00608 $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
00609 $this->reduceColors($im, $reduce-49, $reduce-50);
00610 }
00611 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
00612
00613 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
00614
00615 for ($a=0; $a<$conf['iterations']; $a++) {
00616 if ($spacing || $wordSpacing) {
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 {
00623
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
00632 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
00633 $newW = ceil($sF*imagesx($im));
00634 $newH = ceil($sF*imagesy($im));
00635
00636
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) {
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
00650 if ($this->NO_IM_EFFECTS) {
00651 if ($this->maskNegate) {
00652 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!');
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
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
00681 $this->ImageWrite($im, $fileMenu);
00682
00683 $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu);
00684
00685 $backIm = $this->imageCreateFromFile($fileMenu);
00686 if ($backIm) {
00687 ImageColorTransparent($backIm,-1);
00688 $im = $backIm;
00689 }
00690
00691
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
00718 $result=Array();
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) {
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
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
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
00921 $maxWidth = intval($conf['maxWidth']);
00922 list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
00923 if ($maxWidth) {
00924 if ($spacing || $wordSpacing) {
00925 return $conf['fontSize'];
00926
00927 } else {
00928 do {
00929
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
00940 if ($pixelWidth <= $maxWidth) {
00941 break;
00942 } else {
00943 $conf['fontSize']--;
00944 }
00945 } while ($conf['fontSize']>1);
00946 }
00947 }
00948 return $conf['fontSize'];
00949 }
00950
00962 function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1) {
00963
00964
00965 $offsetInfo = array();
00966 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
00967
00968
00969 foreach($stringParts as $strCfg) {
00970 $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
00971 if (is_readable($fontFile)) {
00972
00973
00974 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']);
00975
00976
00977 if (!count($offsetInfo)) {
00978 $offsetInfo = $calc;
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
01012 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
01013 $x = ceil($sF*$x);
01014 $y = ceil($sF*$y);
01015
01016
01017 foreach($stringParts as $i => $strCfg) {
01018
01019
01020 $colorIndex = $color;
01021
01022
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
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
01039 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']);
01040
01041
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
01065 $result = array();
01066 $result[] = array(
01067 'str' => $string,
01068 'fontSize' => $fontSize,
01069 'fontFile' => $fontFile
01070 );
01071
01072
01073
01074 if (is_array($splitRendering)) {
01075 $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering);
01076
01077
01078 foreach($sKeyArray as $key) {
01079 $cfg = $splitRendering[$key.'.'];
01080
01081
01082 switch((string)$splitRendering[$key]) {
01083 case 'highlightWord':
01084 if (strlen($cfg['value'])) {
01085 $newResult = array();
01086
01087
01088 foreach($result as $part) {
01089
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
01111 if (count($newResult)) {
01112 $result = $newResult;
01113 }
01114 }
01115 break;
01116 case 'charRange':
01117 if (strlen($cfg['value'])) {
01118
01119
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
01128 foreach($result as $part) {
01129
01130
01131 $currentState = -1;
01132 $bankAccum = '';
01133
01134
01135 $utf8Chars = $this->singleChars($part['str']);
01136 foreach($utf8Chars as $utfChar) {
01137
01138
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;
01148
01149
01150 if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber)) {
01151
01152
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
01167 $currentState = $inRange;
01168 $bankAccum = '';
01169 }
01170
01171
01172 $bankAccum.=$utfChar;
01173 }
01174
01175
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
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 {
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
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) {
01346 $txtConf['fontColor'] = $conf['color'];
01347 $this->makeText($im,$txtConf,$workArea);
01348 } else {
01349 $w = imagesx($im);
01350 $h = imagesy($im);
01351 $blurBorder= 3;
01352 $tmpStr = $this->randomName();
01353 $fileMenu = $tmpStr.'_menu.'.$this->gifExtension;
01354 $fileColor = $tmpStr.'_color.'.$this->gifExtension;
01355 $fileMask = $tmpStr.'_mask.'.$this->gifExtension;
01356
01357
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
01366 $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
01367 $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0);
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);
01373 ImageDestroy($blurTextImg);
01374
01375
01376 $command='';
01377 $command.=$this->maskNegate;
01378
01379 if ($this->V5_EFFECTS) {
01380 $command.=$this->v5_blur($blurRate+1);
01381 } else {
01382
01383 $times = ceil($blurRate/10);
01384 $newBlurRate = $blurRate*4;
01385 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99);
01386 for ($a=0;$a<$times;$a++) {
01387 $command.=' -blur '.$blurRate;
01388 }
01389 }
01390
01391 $this->imageMagickExec($fileMask,$fileMask,$command.' +matte');