Le problème est que vous fournissez à imagemagick la sortie d'un "séparateur de ligne" ( wordWrapAnnotation
), à laquelle vous êtes utf8_decode
la saisie du texte. C'est certainement une erreur, si vous avez affaire à du texte chinois. utf8_decode
ne peut traiter que du texte UTF-8 qui PEUT être converti en ISO-8859-1 (l'extension 8 bits la plus courante de l'ASCII).
Maintenant, j'espère que votre texte est UTF-8 encodé. S'il ne l'est pas, vous pouvez peut-être le convertir comme suit :
$text = mb_convert_encoding($text, 'UTF-8', 'BIG-5');
ou comme ceci
$text = mb_convert_encoding($text, 'UTF-8', 'GB18030'); // only PHP >= 5.4.0
(dans votre code $text
est plutôt $text1
y $text2
).
Il y a alors (au moins) deux choses à corriger dans votre code :
- transmettre le texte "tel quel" (sans
utf8_decode
) à wordWrapAnnotation
,
- changer l'argument de
setTextEncoding
de "utf-8"
à "UTF-8"
selon Spécifications
J'espère que toutes les variables de votre code sont initialisées dans une partie manquante de celui-ci. Avec les deux changements ci-dessus (le second pourrait ne pas être nécessaire, mais on ne sait jamais...), et avec les parties manquantes en place, je ne vois aucune raison pour laquelle votre code ne devrait pas fonctionner, à moins que votre fichier TTF ne soit cassé ou que la fonction Imagick
est cassé ( imagemagick
sur lequel Imagick
est basé, est une grande bibliothèque, donc je considère cette dernière possibilité plutôt improbable).
EDITAR:
Suite à votre demande, je mets à jour ma réponse avec
a) le fait que la mise mb_internal_encoding('utf-8')
est très important pour la solution, comme vous le dites dans votre réponse et
b) ma proposition pour un meilleur séparateur de ligne, qui fonctionne de manière acceptable pour les langues occidentales et pour le chinois, et qui est probablement un bon point de départ pour les autres langues utilisant les logogrammes Han (kanji japonais et hanja coréen) :
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 d'autres termes : l'entrée est d'abord nettoyée en remplaçant tous les espaces, y compris les nouvelles lignes, par un espace unique, à l'exception des espaces de tête et de queue, qui sont supprimés. Ensuite, elle est coupée soit aux espaces, soit juste avant les caractères Han qui ne sont pas précédés de caractères "de tête" (comme les parenthèses ouvrantes ou les guillemets ouvrants), soit juste avant les caractères "de tête". Les lignes sont assemblées de manière à ne pas être rendues en plus d'une ligne. $maxWidth
pixels horizontalement, sauf lorsque les règles de fractionnement ne le permettent pas (dans ce cas, le rendu final débordera probablement). Une modification visant à forcer le fractionnement dans les cas de débordement n'est pas difficile. Notez que, par exemple, la ponctuation chinoise n'est pas classée comme Han dans Unicode, de sorte que, à l'exception de la ponctuation "de tête", aucun saut de ligne ne peut être inséré avant elle par l'algorithme.