El problema es que están alimentando ImageMagick la salida de un "divisor de línea" (wordWrapAnnotation
), al que están utf8_decode
ing la entrada de texto. Esto está mal, seguro, si está tratando con texto chino. utf8_decode
solo puede tratar con texto UTF-8 que PUEDE convertirse a ISO-8859-1 (la extensión más común de 8 bits de ASCII).
Ahora, espero que su texto esté codificado en UTF-8. Si no es así, usted podría ser capaz de convertir de esta manera:
$text = mb_convert_encoding($text, 'UTF-8', 'BIG-5');
o como esto
$text = mb_convert_encoding($text, 'UTF-8', 'GB18030'); // only PHP >= 5.4.0
(en su código $text
es bastante $text1
y $text2
).
Entonces hay (al menos) dos cosas que arreglar en el código:
- pasar el texto "tal cual" (sin
utf8_decode
) a wordWrapAnnotation
,
- cambio el argumento de
setTextEncoding
de "utf-8"
a "UTF-8"
según specs
espero que todas las variables en su código se inicializan en alguna parte que falta de la misma. Con los dos cambios anteriores (el segundo puede no ser necesario, pero nunca se sabe ...), y con las partes faltantes en su lugar, no veo ninguna razón por la cual su código no debería funcionar, a menos que su archivo TTF se rompa o el Imagick
biblioteca está rota (imagemagick
, en la que se basa Imagick
, es una gran biblioteca, por lo que considero que esta última posibilidad es bastante improbable).
EDIT:
Tras su solicitud, puedo actualizar mi respuesta con
a) el hecho de que la fijación de mb_internal_encoding('utf-8')
es muy importante para la solución, como usted dice en su answer, y
b) mi propuesta de un mejor divisor de línea, que funciona aceptablemente para idiomas occidentales y para chino, y ese es probablemente un buen punto de partida para otros idiomas que usan logogramas Han (kanji japonés y hanja coreano):
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);
}
En palabras: la entrada se limpia primero reemplazando todas las ejecuciones de espacios en blanco, incluidas las líneas nuevas, con un solo espacio, excepto el espacio en blanco inicial y posterior, que se elimina. Luego se divide en espacios o justo antes de que los caracteres Han no vayan precedidos por caracteres "iniciales" (como abrir paréntesis o comillas de apertura), o justo antes de caracteres "iniciales". Las líneas se ensamblan para no renderizarse en más de $maxWidth
píxeles horizontalmente, excepto cuando esto no sea posible con las reglas de división (en cuyo caso la representación final probablemente se desborde). Una modificación para forzar la división en casos de desbordamiento no es difícil. Tenga en cuenta que, por ejemplo, la puntuación china no se clasifica como Han en Unicode, por lo que, salvo la puntuación "inicial", el algoritmo no puede insertar ningún salto de línea.
texto en chino? ¿Qué hay de crear primero un gráfico de los símbolos chinos y luego combinarlo en la imagen? – hakre
¿Cómo puedo hacer eso? –
Bueno, para cada personaje chino, crea una imagen que lo muestre. Luego, junte estas imágenes, por ejemplo. Puede que no sea el mejor método, pero podría ahorrarte el problema de usar alguna fuente china. – hakre