问题是您正在向 imagemagick 提供“线拆分器”(wordWrapAnnotation
)的输出,您正在向该输出utf8_decode
输入文本。如果您正在处理中文文本,这肯定是错误的。utf8_decode
只能处理可以转换为 ISO-8859-1(ASCII 最常见的 8 位扩展)的 UTF-8 文本。
现在,我希望你的文本是UTF-8编码的。如果不是,您可以像这样转换它:
$text = mb_convert_encoding($text, 'UTF-8', 'BIG-5');
或者像这样
$text = mb_convert_encoding($text, 'UTF-8', 'GB18030'); // only PHP >= 5.4.0
(在您的代码$text
中是$text1
和$text2
)。
然后(至少)有两件事要在您的代码中修复:
- 将文本“按原样”(不带
utf8_decode
)传递给wordWrapAnnotation
,
-
根据规范
setTextEncoding
将from的参数更改"utf-8"
为"UTF-8"
我希望您代码中的所有变量都在其中的某些缺失部分中进行了初始化。有了上面的两个更改(第二个可能不是必需的,但你永远不知道......),并且缺少的部分就位,我认为你的代码没有理由不工作,除非你的 TTF 文件损坏或Imagick
库坏了(基于imagemagick
它Imagick
的库是一个很棒的库,所以我认为最后一种可能性不大)。
编辑:
根据您的要求,我更新我的答案
a)mb_internal_encoding('utf-8')
正如您在回答中所说,设置对于解决方案非常重要,并且
b) 我对更好的分行器的建议,它对西方语言和中文都可以接受,这可能是使用韩语语标(日文汉字和韩文汉字)的其他语言的一个很好的起点:
function wordWrapAnnotation(&$image, &$draw, $text, $maxWidth)
{
$regex = '/( |(?=\p{Han})(?<!\p{Pi})(?<!\p{Ps})|(?=\p{Pi})|(?=\p{Ps}))/u';
$cleanText = trim(preg_replace('/[\s\v]+/', ' ', $text));
$strArr = preg_split($regex, $cleanText, -1, PREG_SPLIT_DELIM_CAPTURE |
PREG_SPLIT_NO_EMPTY);
$linesArr = array();
$lineHeight = 0;
$goodLine = '';
$spacePending = false;
foreach ($strArr as $str) {
if ($str == ' ') {
$spacePending = true;
} else {
if ($spacePending) {
$spacePending = false;
$line = $goodLine.' '.$str;
} else {
$line = $goodLine.$str;
}
$metrics = $image->queryFontMetrics($draw, $line);
if ($metrics['textWidth'] > $maxWidth) {
if ($goodLine != '') {
$linesArr[] = $goodLine;
}
$goodLine = $str;
} else {
$goodLine = $line;
}
if ($metrics['textHeight'] > $lineHeight) {
$lineHeight = $metrics['textHeight'];
}
}
}
if ($goodLine != '') {
$linesArr[] = $goodLine;
}
return array($linesArr, $lineHeight);
}
换句话说:首先通过用单个空格替换所有运行的空格(包括换行符)来清理输入,但前导和尾随空格除外,后者已被删除。然后在空格处拆分,或者就在没有“前导”字符(如左括号或左引号)的汉字符之前,或者就在“前导”字符之前。行被组合是为了不以超过$maxWidth
像素的水平水平渲染,除非分割规则无法做到这一点(在这种情况下,最终渲染可能会溢出)。在溢出情况下强制拆分的修改并不困难。请注意,例如,中文标点在 Unicode 中不归类为汉,因此,除了“前导”标点之外,