支持自动换行、像素定位、限宽、任意对齐方式、RGB和哈希颜色值,返回实际起点坐标和宽高
/*绝大部分情况下九种对齐方式就足够用了,本方法是以传入的$x、$y值为参照点,根据$pos值进行相对偏移,从左向右、从上往下分9个点*/
public static function writeOnImg(\GdImage &$img,string $str,int $maxWidth,int $fontSize,int $x,int $y,int|string $color,int $pos=0,int $lineHeight=0,string $font='path/to/fontFile.ttf') : array
{
if($str=='') return [$x,$y,0,0];
if($lineHeight<1) $lineHeight=intval($fontSize*1.6); //默认行高是字符尺寸的1.6倍
$arr=preg_split('/(?<!^)(?!$)/u',$str);
$i=0;
$lines=[''];
$width=0;
foreach($arr AS $w){
if($w!==PHP_EOL){
$box=imagettfbbox($fontSize,0,$font,$lines[$i].$w);
$lineWidth=$box[2]-$box[0];
if($lineWidth<=$maxWidth){ //如果未超宽就拼接到本行
if($lineWidth>$width) $width=$lineWidth; //实际宽度取最大值
$lines[$i].=$w;
}else $lines[++$i]=$w; //如果超宽了就重启一行
}else $lines[++$i]=''; //遇到换行符就重启一行
}
//计算实际高度,此时$box刚好在最后一行,当然前提是最后一个字符不能是换行符!
$height=(count($lines)-1)*$lineHeight+$box[7]-$box[1];
if($pos>0){
$x=(int)round($x-$pos%3/2*$width); //横向偏移
$y=(int)round($y-intval($pos/3)/2*$height); //竖向偏移
}
if(is_string($color)) $color=self::setImgColor($img,$color);
foreach($lines AS $line => $text){
if($text!=='') imagettftext($img,$fontSize,0,$x,$lineHeight*$line+$y,$color,$font,$text);
}
return [$x,$y,$width,$height];
}
/*设定颜色*/
public static function setImgColor(\GdImage $img,string $color) : int
{
preg_match("/^rgb\(([0-9]{0,3})\,\s*([0-9]{0,3})\,\s*([0-9]{0,3})\)/",$color,$match);
if(!isset($match[3])||!is_numeric($match[1])||!is_numeric($match[2])||!is_numeric($match[3])){
$color=str_replace('#','',$color);
switch(strlen($color)){
case 3:
$r=substr($color,0,1);
$g=substr($color,1,1);
$b=substr($color,2,1);
$arr=[hexdec($r.$r),hexdec($g.$g),hexdec($b.$b)];
break;
case 6:
$arr=[hexdec(substr($color,0,2)),hexdec(substr($color,2,2)),hexdec(substr($color,4,2))];
break;
default: throw new \MyException('未知的哈希颜色值!');
}
}else $arr=array_slice($match,1,3);
return imagecolorallocate($img,...$arr);
}