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
00148 class t3lib_stdGraphic {
00149
00150
00151 var $combineScript = 'combine';
00152 var $noFramePrepended=0;
00153 var $GD2=0;
00154 var $imagecopyresized_fix=0;
00155 var $gifExtension = 'gif';
00156 var $TTFLocaleConv = '';
00157 var $enable_typo3temp_db_tracking = 0;
00158 var $imageFileExt = 'gif,jpg,jpeg,png,tif,bmp,tga,pcx,ai,pdf';
00159 var $webImageExt = 'gif,jpg,jpeg,png';
00160 var $maskNegate = '';
00161 var $NO_IM_EFFECTS = '';
00162 var $cmds = Array (
00163 'jpg' => '',
00164 'jpeg' => '',
00165 'gif' => '-colors 64',
00166 'png' => '-colors 64'
00167 );
00168 var $NO_IMAGE_MAGICK = '';
00169 var $V5_EFFECTS = 0;
00170 var $mayScaleUp = 1;
00171
00172
00173 var $filenamePrefix='';
00174 var $imageMagickConvert_forceFileNameBody='';
00175 var $dontCheckForExistingTempFile = 0;
00176 var $dontCompress=0;
00177 var $dontUnlinkTempFiles=0;
00178 var $alternativeOutputKey='';
00179
00180
00181 var $IM_commands = Array();
00182 var $workArea = Array();
00183
00184
00185 var $tempPath = 'typo3temp/';
00186 var $absPrefix = '';
00187 var $scalecmd = '-geometry';
00188 var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5';
00189 var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5';
00190 var $pixelLimitGif = 10000;
00191 var $colMap = Array (
00192 'aqua' => Array(0,255,255),
00193 'black' => Array(0,0,0),
00194 'blue' => Array(0,0,255),
00195 'fuchsia' => Array(255,0,255),
00196 'gray' => Array(128,128,128),
00197 'green' => Array(0,128,0),
00198 'lime' => Array(0,255,0),
00199 'maroon' => Array(128,0,0),
00200 'navy' => Array(0,0,128),
00201 'olive' => Array(128,128,0),
00202 'purple' => Array(128,0,128),
00203 'red' => Array(255,0,0),
00204 'silver' => Array(192,192,192),
00205 'teal' => Array(0,128,128),
00206 'yellow' => Array(255,255,0),
00207 'white' => Array(255,255,255)
00208 );
00209
00210
00211 var $csConvObj;
00212 var $nativeCharset='';
00213
00214
00215
00216
00217
00224 function init() {
00225 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
00226
00227
00228 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.intval($gfxConf['im_jpg_quality']);
00229
00230 if ($gfxConf['im_combine_filename']) $this->combineScript=$gfxConf['im_combine_filename'];
00231 if ($gfxConf['im_noFramePrepended']) $this->noFramePrepended=1;
00232
00233 if ($gfxConf['gdlib_2']) {
00234 $this->GD2 = 1;
00235 $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1;
00236 }
00237 if ($gfxConf['gdlib_png']) {
00238 $this->gifExtension='png';
00239 }
00240 if ($gfxConf['TTFLocaleConv']) {
00241 $this->TTFLocaleConv = $gfxConf['TTFLocaleConv'];
00242 }
00243 if ($gfxConf['enable_typo3temp_db_tracking']) {
00244 $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking'];
00245 }
00246
00247 $this->imageFileExt = $gfxConf['imagefile_ext'];
00248
00249
00250 if ($gfxConf['im_negate_mask']) {
00251
00252
00253
00254
00255 $this->maskNegate = ' -negate';
00256 }
00257 if ($gfxConf['im_no_effects']) {
00258
00259
00260
00261
00262 $this->NO_IM_EFFECTS = 1;
00263
00264 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']);
00265 }
00266
00267 if ($gfxConf['im_v5effects']) {
00268 $this->NO_IM_EFFECTS = 0;
00269 $this->V5_EFFECTS = 1;
00270
00271 if ($gfxConf['im_v5effects']>0) {
00272 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']).$this->v5_sharpen(10);
00273 }
00274 }
00275
00276 if (!$gfxConf['im']) {
00277 $this->NO_IMAGE_MAGICK = 1;
00278 }
00279
00280 if ($gfxConf['im_noScaleUp']) {
00281 $this->mayScaleUp=0;
00282 }
00283
00284 if (TYPO3_MODE=='FE') {
00285 $this->csConvObj = &$GLOBALS['TSFE']->csConvObj;
00286 } elseif(is_object($GLOBALS['LANG'])) {
00287 $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
00288 } else {
00289 $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
00290 }
00291 $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00326 function maskImageOntoImage(&$im,$conf,$workArea) {
00327 if ($conf['file'] && $conf['mask']) {
00328 $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
00329 $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
00330 if ($BBimage && $BBmask) {
00331 $w = imagesx($im);
00332 $h = imagesy($im);
00333 $tmpStr = $this->randomName();
00334 $theImage = $tmpStr.'_img.'.$this->gifExtension;
00335 $theDest = $tmpStr.'_dest.'.$this->gifExtension;
00336 $theMask = $tmpStr.'_mask.'.$this->gifExtension;
00337 $theMask2 = $tmpStr.'_mask2.'.trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']);
00338
00339 $cpImg = $this->imageCreateFromFile($BBimage[3]);
00340 $destImg = imagecreate($w,$h);
00341 ImageColorAllocate($destImg, 0,0,0);
00342 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00343 $this->ImageGif($destImg, $theImage);
00344 imageDestroy($cpImg);
00345 imageDestroy($destImg);
00346
00347 $cpImg = $this->imageCreateFromFile($BBmask[3]);
00348 $destImg = imagecreate($w,$h);
00349 ImageColorAllocate($destImg, 0,0,0);
00350 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
00351 $this->ImageGif($destImg, $theMask);
00352 imageDestroy($cpImg);
00353 imageDestroy($destImg);
00354
00355 $this->imageMagickExec($theMask,$theMask2,'-colorspace GRAY'.$this->maskNegate);
00356
00357 $this->ImageGif($im, $theDest);
00358
00359 $this->combineExec($theDest,$theImage,$theMask2,$theDest);
00360
00361 $backIm = $this->imageCreateFromFile($theDest);
00362 if ($backIm) {
00363 ImageColorTransparent($backIm,-1);
00364 $im = $backIm;
00365 }
00366
00367 if (!$this->dontUnlinkTempFiles) {
00368 unlink($theDest);
00369 unlink($theImage);
00370 unlink($theMask);
00371 unlink($theMask2);
00372 }
00373 }
00374 }
00375 }
00376
00386 function copyImageOntoImage(&$im,$conf,$workArea) {
00387 if ($conf['file']) {
00388 if ($conf['BBOX'][2]!=$this->gifExtension) {
00389 $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','','');
00390 $conf['file']=$conf['BBOX'][3];
00391 }
00392 $cpImg = $this->imageCreateFromFile($conf['file']);
00393 $this->copyGifOntoGif($im,$cpImg,$conf,$workArea);
00394 imageDestroy($cpImg);
00395 }
00396 }
00397
00408 function copyGifOntoGif(&$im,$cpImg,$conf,$workArea) {
00409 $cpW = imagesx($cpImg);
00410 $cpH = imagesy($cpImg);
00411 $tile = t3lib_div::intExplode(',',$conf['tile']);
00412 $tile[0] = t3lib_div::intInRange($tile[0],1,20);
00413 $tile[1] = t3lib_div::intInRange($tile[1],1,20);
00414 $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1]));
00415
00416 for ($xt=0;$xt<$tile[0];$xt++) {
00417 $Xstart=$cpOff[0]+$cpW*$xt;
00418 if ($Xstart+$cpW > $workArea[0]) {
00419
00420 if ($Xstart < $workArea[0]) {
00421 $cpImgCutX = $workArea[0]-$Xstart;
00422 $Xstart = $workArea[0];
00423 } else {
00424 $cpImgCutX = 0;
00425 }
00426 $w = $cpW-$cpImgCutX;
00427 if ($Xstart > $workArea[0]+$workArea[2]-$w) {
00428 $w = $workArea[0]+$workArea[2]-$Xstart;
00429 }
00430 if ($Xstart < $workArea[0]+$workArea[2]) {
00431
00432 for ($yt=0;$yt<$tile[1];$yt++) {
00433 $Ystart=$cpOff[1]+$cpH*$yt;
00434 if ($Ystart+$cpH > $workArea[1]) {
00435 if ($Ystart < $workArea[1]) {
00436 $cpImgCutY = $workArea[1]-$Ystart;
00437 $Ystart = $workArea[1];
00438 } else {
00439 $cpImgCutY = 0;
00440 }
00441 $h = $cpH-$cpImgCutY;
00442 if ($Ystart > $workArea[1]+$workArea[3]-$h) {
00443 $h = $workArea[1]+$workArea[3]-$Ystart;
00444 }
00445 if ($Ystart < $workArea[1]+$workArea[3]) {
00446 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00447 }
00448 }
00449 }
00450 }
00451 }
00452 }
00453 }
00454
00487 function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) {
00488 if ($this->imagecopyresized_fix) {
00489 $im_base = imagecreatetruecolor(imagesx($im), imagesy($im));
00490 imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im));
00491 imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00492 $im = $im_base;
00493 $this->makeEffect($im, Array('value'=>'colors=256'));
00494 } else {
00495 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
00496 }
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00536 function makeText(&$im,$conf,$workArea) {
00537
00538 $spacing = intval($conf['spacing']);
00539 $wordSpacing = intval($conf['wordSpacing']);
00540 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
00541
00542 $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']);
00543 $theText = $this->recodeString($conf['text']);
00544
00545 if ($conf['imgMap'] && is_array($conf['imgMap.'])) {
00546 $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']);
00547 }
00548 if (!$conf['hideButCreateMap']) {
00549
00550 $cols=$this->convertColor($conf['fontColor']);
00551
00552 if (!$conf['niceText']) {
00553
00554 $this->reduceColors($im,256, 200);
00555 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
00556
00557 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
00558
00559 for ($a=0; $a<$conf['iterations']; $a++) {
00560 if ($spacing || $wordSpacing) {
00561 $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']);
00562 } else {
00563 $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']);
00564 }
00565 }
00566 } else {
00567
00568 $w = imagesx($im);
00569 $h = imagesy($im);
00570 $tmpStr = $this->randomName();
00571
00572 $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension;
00573 $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension;
00574 $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension;
00575
00576 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
00577 $newW = ceil($sF*imagesx($im));
00578 $newH = ceil($sF*imagesy($im));
00579
00580
00581 $maskImg = imagecreate($newW, $newH);
00582 ImageColorAllocate($maskImg, 255,255,255);
00583 $Fcolor = ImageColorAllocate($maskImg, 0,0,0);
00584 if ($spacing || $wordSpacing) {
00585 $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF);
00586 } else {
00587 $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00588 }
00589 $this->ImageGif($maskImg, $fileMask);
00590 ImageDestroy($maskImg);
00591
00592
00593 if ($this->NO_IM_EFFECTS) {
00594 if ($this->maskNegate) {
00595 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!');
00596 } else {
00597 $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate');
00598 }
00599 } else {
00600 if ($this->maskNegate) {
00601 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']);
00602 } else {
00603 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate');
00604 }
00605 if ($conf['niceText.']['sharpen']) {
00606 if ($this->V5_EFFECTS) {
00607 $command.=$this->v5_sharpen($conf['niceText.']['sharpen']);
00608 } else {
00609 $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99);
00610 }
00611 }
00612 }
00613 $this->imageMagickExec($fileMask,$fileMask,$command);
00614
00615
00616 $colorImg = imagecreate($w,$h);
00617 ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
00618 $this->ImageGif($colorImg, $fileColor);
00619 ImageDestroy($colorImg);
00620
00621
00622 $this->ImageGif($im, $fileMenu);
00623
00624 $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu);
00625
00626 $backIm = $this->imageCreateFromFile($fileMenu);
00627 if ($backIm) {
00628 ImageColorTransparent($backIm,-1);
00629 $im = $backIm;
00630 }
00631
00632
00633 if (!$this->dontUnlinkTempFiles) {
00634 unlink($fileMenu);
00635 unlink($fileColor);
00636 unlink($fileMask);
00637 }
00638 }
00639 }
00640 }
00641
00652 function txtPosition($conf,$workArea,$BB) {
00653 $bbox = $BB[2];
00654 $angle=intval($conf['angle'])/180*pi();
00655 $conf['angle']=0;
00656 $straightBB = $this->calcBBox($conf);
00657
00658
00659 $result=Array();
00660 $result[2] = $BB[0];
00661 $result[3] = $BB[1];
00662 $w=$workArea[2];
00663 $h=$workArea[3];
00664
00665 switch($conf['align']) {
00666 case 'right':
00667 case 'center':
00668 $factor=abs(cos($angle));
00669 $sign=(cos($angle)<0)?-1:1;
00670 $len1 = $sign*$factor*$straightBB[0];
00671 $len2= $sign*$BB[0];
00672 $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1);
00673
00674 $factor=abs(sin($angle));
00675 $sign=(sin($angle)<0)?-1:1;
00676 $len1= $sign*$factor*$straightBB[0];
00677 $len2= $sign*$BB[1];
00678 $result[1]=ceil($len2*$factor+(1-$factor)*$len1);
00679 break;
00680 }
00681 switch($conf['align']) {
00682 case 'right':
00683 break;
00684 case 'center':
00685 $result[0] = round(($result[0])/2);
00686 $result[1] = round(($result[1])/2);
00687 break;
00688 default:
00689 $result[0]=0;
00690 $result[1]=0;
00691 break;
00692 }
00693 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset']));
00694 $result = $this->applyOffset($result,$workArea);
00695 return $result;
00696 }
00697
00706 function calcBBox($conf) {
00707 if (!$conf['niceText']) {
00708 $sF = 1;
00709 } else {
00710 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
00711 }
00712
00713 $spacing = intval($conf['spacing']);
00714 $wordSpacing = intval($conf['wordSpacing']);
00715 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
00716
00717 $spacing*=$sF;
00718 $wordSpacing*=$sF;
00719 $theText = $this->recodeString($conf['text']);
00720
00721 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
00722 $theBBoxInfo = $charInf;
00723 if ($conf['angle']) {
00724 $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]);
00725 $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]);
00726 $x=max($xArr)-min($xArr);
00727 $y=max($yArr)-min($yArr);
00728 } else {
00729 $x = ($charInf[2]-$charInf[0]);
00730 $y = ($charInf[1]-$charInf[7]);
00731 }
00732 if ($spacing || $wordSpacing) {
00733 $x=0;
00734 if (!$spacing && $wordSpacing) {
00735 $bits = explode(' ',$theText);
00736 while(list(,$word)=each($bits)) {
00737 $word.=' ';
00738 $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF);
00739 $wordW = ($wordInf[2]-$wordInf[0]);
00740 $x+=$wordW+$wordSpacing;
00741 }
00742 } else {
00743 $utf8Chars = $this->singleChars($theText);
00744
00745 foreach($utf8Chars as $char) {
00746 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF);
00747 $charW = ($charInf[2]-$charInf[0]);
00748 $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00749 }
00750 }
00751 }
00752
00753 if ($sF>1) {
00754 $x = ceil($x/$sF);
00755 $y = ceil($y/$sF);
00756 if (is_array($theBBoxInfo)) {
00757 reset($theBBoxInfo);
00758 while(list($key,$val)=each($theBBoxInfo)) {
00759 $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF);
00760 }
00761 }
00762 }
00763 return Array($x,$y,$theBBoxInfo);
00764 }
00765
00775 function addToMap($cords,$conf) {
00776 $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"';
00777
00778 $this->map.='<area'.
00779 ' shape="poly"'.
00780 ' coords="'.implode(',',$cords).'"'.
00781 ' href="'.htmlspecialchars($conf['url']).'"'.
00782 ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : '').
00783 $JS.
00784 (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : '').
00785 ' alt="'.htmlspecialchars($conf['altText']).'" />';
00786 }
00787
00798 function calcTextCordsForMap($cords,$offset, $conf) {
00799 $pars = t3lib_div::intExplode(',',$conf['explode'].',');
00800
00801 $newCords[0] = $cords[0]+$offset[0]-$pars[0];
00802 $newCords[1] = $cords[1]+$offset[1]+$pars[1];
00803 $newCords[2] = $cords[2]+$offset[0]+$pars[0];
00804 $newCords[3] = $cords[3]+$offset[1]+$pars[1];
00805 $newCords[4] = $cords[4]+$offset[0]+$pars[0];
00806 $newCords[5] = $cords[5]+$offset[1]-$pars[1];
00807 $newCords[6] = $cords[6]+$offset[0]-$pars[0];
00808 $newCords[7] = $cords[7]+$offset[1]-$pars[1];
00809
00810 return $newCords;
00811 }
00812
00833 function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1) {
00834
00835 $spacing*=$sF;
00836 $wordSpacing*=$sF;
00837
00838 if (!$spacing && $wordSpacing) {
00839 $bits = explode(' ',$text);
00840 reset($bits);
00841 while(list(,$word)=each($bits)) {
00842 $word.=' ';
00843 $word = $word;
00844 $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF);
00845 $wordW = ($wordInf[2]-$wordInf[0]);
00846 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF);
00847 $x+=$wordW+$wordSpacing;
00848 }
00849 } else {
00850 $utf8Chars = $this->singleChars($text);
00851
00852 foreach($utf8Chars as $char) {
00853 $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF);
00854 $charW = ($charInf[2]-$charInf[0]);
00855 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF);
00856 $x+=$charW+(($char==' ')?$wordSpacing:$spacing);
00857 }
00858 }
00859 }
00860
00870 function fontResize($conf) {
00871
00872 $maxWidth = intval($conf['maxWidth']);
00873 if ($maxWidth) {
00874 if ($spacing || $wordSpacing) {
00875 return $conf['fontSize'];
00876
00877 } else {
00878 do {
00879
00880 $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']);
00881 if ($conf['angle']< 0) {
00882 $pixelWidth = abs($bounds[4]-$bounds[0]);
00883 } elseif ($conf['angle'] > 0) {
00884 $pixelWidth = abs($bounds[2]-$bounds[6]);
00885 } else {
00886 $pixelWidth = abs($bounds[4]-$bounds[6]);
00887 }
00888
00889
00890 if ($pixelWidth <= $maxWidth) {
00891 break;
00892 } else {
00893 $conf['fontSize']--;
00894 }
00895 } while ($conf['fontSize']>1);
00896 }
00897 }
00898 return $conf['fontSize'];
00899 }
00900
00912 function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1) {
00913
00914
00915 $offsetInfo = array();
00916 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
00917
00918
00919 foreach($stringParts as $strCfg) {
00920
00921
00922 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
00923
00924
00925 if (!count($offsetInfo)) {
00926 $offsetInfo = $calc;
00927 } else {
00928 $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00929 $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00930 $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
00931 $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
00932 }
00933 }
00934
00935 return $offsetInfo;
00936 }
00937
00953 function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1) {
00954
00955
00956 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile);
00957 $x = ceil($sF*$x);
00958 $y = ceil($sF*$y);
00959
00960
00961 foreach($stringParts as $i => $strCfg) {
00962
00963
00964 $colorIndex = $color;
00965
00966
00967 if ($strCfg['color'] && $sF==1) {
00968 $cols = $this->convertColor($strCfg['color']);
00969 $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
00970 $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex;
00971 }
00972
00973
00974 if ($i) {
00975 $x+= intval($strCfg['xSpaceBefore']);
00976 $y-= intval($strCfg['ySpaceBefore']);
00977 }
00978
00979
00980 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
00981
00982
00983 $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
00984 $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
00985 $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
00986 }
00987 }
00988
00998 function splitString($string,$splitRendering,$fontSize,$fontFile) {
00999
01000
01001 $result = array();
01002 $result[] = array(
01003 'str' => $string,
01004 'fontSize' => $fontSize,
01005 'fontFile' => $fontFile
01006 );
01007
01008
01009
01010 if (is_array($splitRendering)) {
01011 $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering);
01012
01013
01014 foreach($sKeyArray as $key) {
01015 $cfg = $splitRendering[$key.'.'];
01016
01017
01018 switch((string)$splitRendering[$key]) {
01019 case 'highlightWord':
01020 if (strlen($cfg['value'])) {
01021 $newResult = array();
01022
01023
01024 foreach($result as $part) {
01025
01026 $explodedParts = explode($cfg['value'],$part['str']);
01027 foreach($explodedParts as $c => $expValue) {
01028 if (strlen($expValue)) {
01029 $newResult[] = array_merge($part,array('str' => $expValue));
01030 }
01031 if ($c+1 < count($explodedParts)) {
01032 $newResult[] = array(
01033 'str' => $cfg['value'],
01034 'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01035 'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01036 'color' => $cfg['color'],
01037 'xSpaceBefore' => $cfg['xSpaceBefore'],
01038 'xSpaceAfter' => $cfg['xSpaceAfter'],
01039 'ySpaceBefore' => $cfg['ySpaceBefore'],
01040 'ySpaceAfter' => $cfg['ySpaceAfter'],
01041 );
01042 }
01043 }
01044 }
01045
01046
01047 if (count($newResult)) {
01048 $result = $newResult;
01049 }
01050 }
01051 break;
01052 case 'charRange':
01053 if (strlen($cfg['value'])) {
01054
01055
01056 $ranges = t3lib_div::trimExplode(',',$cfg['value'],1);
01057 foreach($ranges as $i => $rangeDef) {
01058 $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]);
01059 if (!isset($ranges[$i][1])) $ranges[$i][1] = $ranges[$i][0];
01060 }
01061 $newResult = array();
01062
01063
01064 foreach($result as $part) {
01065
01066
01067 $currentState = -1;
01068 $bankAccum = '';
01069
01070
01071 $utf8Chars = $this->singleChars($part['str']);
01072 foreach($utf8Chars as $utfChar) {
01073
01074
01075 $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar);
01076 $inRange = 0;
01077 foreach($ranges as $rangeDef) {
01078 if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
01079 $inRange = 1;
01080 break;
01081 }
01082 }
01083 if ($currentState==-1) $currentState = $inRange;
01084
01085
01086 if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber)) {
01087
01088
01089 if (strlen($bankAccum)) {
01090 $newResult[] = array(
01091 'str' => $bankAccum,
01092 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01093 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01094 'color' => $currentState ? $cfg['color'] : '',
01095 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01096 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01097 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01098 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01099 );
01100 }
01101
01102
01103 $currentState = $inRange;
01104 $bankAccum = '';
01105 }
01106
01107
01108 $bankAccum.=$utfChar;
01109 }
01110
01111
01112 if (strlen($bankAccum)) {
01113 $newResult[] = array(
01114 'str' => $bankAccum,
01115 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
01116 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
01117 'color' => $currentState ? $cfg['color'] : '',
01118 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
01119 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
01120 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
01121 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
01122 );
01123 }
01124 }
01125
01126
01127 if (count($newResult)) {
01128 $result = $newResult;
01129 }
01130 }
01131 break;
01132 }
01133 }
01134 }
01135
01136 return $result;
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01169 function makeOutline(&$im,$conf,$workArea,$txtConf) {
01170 $thickness = intval($conf['thickness']);
01171 if ($thickness) {
01172 $txtConf['fontColor'] = $conf['color'];
01173 $outLineDist = t3lib_div::intInRange($thickness,1,2);
01174 for ($b=1;$b<=$outLineDist;$b++) {
01175 if ($b==1) {
01176 $it = 8;
01177 } else {
01178 $it = 16;
01179 }
01180 $outL = $this->circleOffset($b, $it);
01181 for ($a=0;$a<$it;$a++) {
01182 $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a]));
01183 }
01184 }
01185 }
01186 }
01187
01198 function circleOffset($distance, $iterations) {
01199 $res = Array();
01200 if ($distance && $iterations) {
01201 for ($a=0;$a<$iterations;$a++) {
01202 $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance);
01203 if ($yOff) {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));}
01204 $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance);
01205 if ($xOff) {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));}
01206 $res[$a] = Array($xOff,$yOff);
01207 }
01208 }
01209 return $res;
01210 }
01211
01222 function makeEmboss(&$im,$conf,$workArea,$txtConf) {
01223 $conf['color']=$conf['highColor'];
01224 $this->makeShadow($im,$conf,$workArea,$txtConf);
01225 $newOffset = t3lib_div::intExplode(',',$conf['offset']);
01226 $newOffset[0]*=-1;
01227 $newOffset[1]*=-1;
01228 $conf['offset']=implode(',',$newOffset);
01229 $conf['color']=$conf['lowColor'];
01230 $this->makeShadow($im,$conf,$workArea,$txtConf);
01231 }
01232
01244 function makeShadow(&$im,$conf,$workArea,$txtConf) {
01245 $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset']));
01246 $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99);
01247
01248 if (!$blurRate || $this->NO_IM_EFFECTS) {
01249 $txtConf['fontColor'] = $conf['color'];
01250 $this->makeText($im,$txtConf,$workArea);
01251 } else {
01252 $w = imagesx($im);
01253 $h = imagesy($im);
01254 $blurBorder= 3;
01255 $tmpStr = $this->randomName();
01256 $fileMenu = $tmpStr.'_menu.'.$this->gifExtension;
01257 $fileColor = $tmpStr.'_color.'.$this->gifExtension;
01258 $fileMask = $tmpStr.'_mask.'.$this->gifExtension;
01259
01260
01261 $blurColImg = imagecreate($w,$h);
01262 $bcols=$this->convertColor($conf['color']);
01263 ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
01264 $this->ImageGif($blurColImg, $fileColor);
01265 ImageDestroy($blurColImg);
01266
01267
01268 $blurTextImg = imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
01269 ImageColorAllocate($blurTextImg, 0,0,0);
01270 $txtConf['fontColor'] = 'white';
01271 $blurBordArr = Array($blurBorder,$blurBorder);
01272 $this->makeText($blurTextImg,$txtConf, $this->applyOffset($workArea,$blurBordArr));
01273 $this->ImageGif($blurTextImg, $fileMask);
01274 ImageDestroy($blurTextImg);
01275
01276
01277 $command='';
01278 $command.=$this->maskNegate;
01279
01280 if ($this->V5_EFFECTS) {
01281 $command.=$this->v5_blur($blurRate+1);
01282 } else {
01283
01284 $times = ceil($blurRate/10);
01285 $newBlurRate = $blurRate*4;
01286 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99);
01287 for ($a=0;$a<$times;$a++) {
01288 $command.=' -blur '.$blurRate;
01289 }
01290 }
01291
01292 $this->imageMagickExec($fileMask,$fileMask,$command);
01293
01294 $blurTextImg_tmp = $this->imageCreateFromFile($fileMask);
01295 if ($blurTextImg_tmp) {
01296
01297
01298 $blurTextImg = imagecreate($w,$h);
01299 $this->imagecopyresized($blurTextImg, $blurTextImg_tmp, 0, 0, $blurBorder, $blurBorder, $w, $h, $w, $h);
01300 ImageDestroy($blurTextImg_tmp);
01301
01302
01303 $intensity = 40;
01304 if ($conf['intensity']) {
01305 $intensity = t3lib_div::intInRange($conf['intensity'],0,100);
01306 }
01307 $intensity = ceil(255-($intensity/100*255));
01308 $this->inputLevels($blurTextImg,0,$intensity,$this->maskNegate);
01309
01310 $opacity = t3lib_div::intInRange(intval($conf['opacity']),0,100);
01311 if ($opacity && $opacity<100) {
01312 $high = ceil(255*$opacity/100);
01313 $this->outputLevels($blurTextImg,0,$high,$this->maskNegate);
01314 }
01315
01316 $this->ImageGif($blurTextImg, $fileMask);
01317 ImageDestroy($blurTextImg);
01318
01319
01320 $this->ImageGif($im, $fileMenu);
01321
01322 $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu);
01323
01324 $backIm = $this->imageCreateFromFile($fileMenu);
01325 if ($backIm) {
01326 ImageColorTransparent($backIm,-1);
01327 $im = $backIm;
01328 }
01329 }
01330
01331 if (!$this->dontUnlinkTempFiles) {
01332 unlink($fileMenu);
01333 unlink($fileColor);
01334 unlink($fileMask);
01335 }
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01374 function makeBox(&$im,$conf,$workArea) {
01375 $cords = t3lib_div::intExplode(',',$conf['dimensions'].',,,');
01376 $conf['offset']=$cords[0].','.$cords[1];
01377 $cords = $this->objPosition($conf,$workArea,Array($cords[2],$cords[3]));
01378 $cols=$this->convertColor($conf['color']);
01379 $this->reduceColors($im,256, 255);
01380 $tmpColor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
01381 imagefilledrectangle($im, $cords[0], $cords[1], $cords[0]+$cords[2]-1, $cords[1]+$cords[3]-1, $tmpColor);
01382 }
01383
01393 function makeEffect(&$im, $conf) {
01394 $commands = $this->IMparams($conf['value']);
01395 if ($commands) {
01396 $this->applyImageMagickToPHPGif($im, $commands);
01397 }
01398 }
01399
01408 function IMparams($setup) {
01409 if (!trim($setup)){return '';}
01410 $effects = explode('|', $setup);
01411 $commands = '';
01412 while(list(,$val)=each($effects)) {
01413 $pairs=explode('=',$val,2);
01414 $value = trim($pairs[1]);
01415 $effect = strtolower(trim($pairs[0]));
01416 switch($effect) {
01417 case 'gamma':
01418 $commands.=' -gamma '.doubleval($value);
01419 break;
01420 case 'blur':
01421 if (!$this->NO_IM_EFFECTS) {
01422 if ($this->V5_EFFECTS) {
01423 $commands.=$this->v5_blur($value);
01424 } else {
01425 $commands.=' -blur '.t3lib_div::intInRange($value,1,99);
01426 }
01427 }
01428 break;
01429 case 'sharpen':
01430 if (!$this->NO_IM_EFFECTS) {
01431 if ($this->V5_EFFECTS) {
01432 $commands.=$this->v5_sharpen($value);
01433 } else {
01434 $commands.=' -sharpen '.t3lib_div::intInRange($value,1,99);
01435 }
01436 }
01437 break;
01438 case 'rotate':
01439 $commands.=' -rotate '.t3lib_div::intInRange($value,0,360);
01440 break;
01441 case 'solarize':
01442 $commands.=' -solarize '.t3lib_div::intInRange($value,0,99);
01443 break;
01444 case 'swirl':
01445 $commands.=' -swirl '.t3lib_div::intInRange($value,0,1000);
01446 break;
01447 case 'wave':
01448 $params = t3lib_div::intExplode(',',$value);
01449 $commands.=' -wave '.t3lib_div::intInRange($params[0],0,99).'x'.t3lib_div::intInRange