我在PHP GD库创建的图像中使用了Verdana字体。
imagettftext($image, $fontSize, 0, 70, $y, $color, $font, $username );
大多数情况下,imagettftext非常适合字符串
但是我的一些用户在他们的名字中使用了奇怪的字符/符号
所以,当我尝试将他们的名字打印到图像时。例如:
此用户使用ɦɪɲɣƙƨєʌɾ
符号。所以Verdana无法打印出来。
我用过这个:
$username=iconv('UTF-8', 'ASCII//TRANSLIT', $username);
输出是这样的:
(当前语言环境在英语和德语之间发生变化。因此,当前的语言环境可能无法处理这些字符:ɦɪɲɣƙƨєʌɾ
)
似乎无法在不编写非常大的ɦ
块的情况下将h
音译为ɲ
,n
到str_replace()
。与this一样。
所以我想知道是否可以检查字体(Verdana)是否可以显示这些符号。如果其中一个字符无法在字符串中显示,那么我可以将空字符串传递给imagettftext
方法。我可以检查字体内支持的字符吗?或者创建一个包含Verdana支持的符号的字符映射,并检查我的字符串是否包含不支持的符号?
(我认为由于this question)
或许是另一种解决方案,是否可以在imagettftext()
中使用多种字体?
例如,首先尝试Verdana,如果Verdana没有涵盖那些符号使用Arial sans serif等。
或其他任何解决方案?
编辑:
似乎Verdana在我的文本中不支持这些unicode字符
Verdana支持角色:http://www.fileformat.info/info/unicode/font/verdana/grid.htm
Verdana不支持的字符:http://www.fileformat.info/info/unicode/font/verdana/missing.htm
答案 0 :(得分:4)
我的第一选择是切换到支持您希望能够处理的全部字符的字体。但是不要指望单个字体会实现million-or-so possible characters in UTF-8。
现在,如果您想采用(懒惰)音译路线,我会参考this answer from Kemal Dağ:
Transliterator
类我现在手头没有v5.4,所以我不知道Transliterator
,但是KemalDağ的JTransliteration
端口表现相当不错:
<?php
require 'transliteration/JTransliteration.php';
$input = 'ɦɪɲɣƙƨєʌɾ';
echo JTransliteration::transliterate($input); // output: hIngk2ie^r
$input = 'Хეλлఒ Wओრলद';
echo JTransliteration::transliterate($input);
最后,如果你想检查给定的字体是否支持给定的字符,它会变得更加毛茸茸。 This library会有很大帮助。它需要&gt; = 5.3(使用命名空间):
<?php
$fontFile = 'arial.ttf';
$charToCheck = 'ɣ';
require_once 'php-font-lib-master/src/FontLib/Autoloader.php';
use FontLib\Font;
use FontLib\TrueType\Collection;
$font = Font::load($fontFile);
if ($font instanceof Collection) {
$font = $font->getFont(0);
}
$subtable = null;
foreach($font->getData("cmap", "subtables") as $_subtable) {
if ($_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1) {
$subtable = $_subtable;
break;
}
}
if (isset($subtable["glyphIndexArray"][ord_utf8($charToCheck)])) {
$supported = 'Supported';
} else {
$supported = 'Not Supported';
}
echo "$charToCheck is $supported by font $fontFile";
function ord_utf8($c) {
$b0 = ord($c[0]);
if ( $b0 < 0x10 ) {
return $b0;
}
$b1 = ord($c[1]);
if ( $b0 < 0xE0 ) {
return (($b0 & 0x1F) << 6) + ($b1 & 0x3F);
}
return (($b0 & 0x0F) << 12) + (($b1 & 0x3F) << 6) + (ord($c[2]) & 0x3F);
}
来自font_info.php
和R. Hill的ord_utf8()
P.S。字符串“ɦɪɲɣƙƨєʌɾ”由国际音标字符组成。我不确定任何 locale 是否支持这些字符(因为它没有实际需要,因为它们不被任何真正的人类语言使用)。
答案 1 :(得分:2)
只要您使用的是UTF-8,UTF-8 True Type字体就没有理由显示这些字母(东亚字母的免责声明!)
这是我的简单示例,使用真正的字体:
// utf-8 text
$text = 'ɦɪɲɣƙƨєʌɾ';
// if text read from a file (for example)
// and the default locale (for most of western countries)
// is ISO-8859-1, you can simly convert it to
// utf-8 using:
//$text = utf8_encode($text);
$png = imagecreatefrompng('/tmp/sample.png');
$color = imagecolorallocate($png, 0, 0, 0);
// True type font that support UTF-8!!!!
$font = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf';
imagettftext($png, 50, 0, 50, 50, $color, $font, $text);
imagepng($png, '/tmp/test.png');
结果:
答案 2 :(得分:0)
您是否设置了正确的区域设置?对于iconv可以是必要的 - http://cz1.php.net/manual/en/function.iconv.php#74101
答案 3 :(得分:0)
您描述的问题有多个地方可能会失败,哪些对于您首先要做出正确决定如何最好地解决这个问题非常重要。
因为很多事情都可能出错,所以如果输入不符合预期,您需要提前失败。首先,必须验证字符串是否采用正确的编码方式,以便在调用该函数之前与imagettftext()
一起使用:
if (!preg_match('//u', $username)) {
throw new Exception(
sprintf(
"Username string %s can not be used with imagettftext()"
, var_export($username, true)
)
);
}
不这样做不会让你获得正确的结果。然后,如果此检查失败,则传递此解决方案的方法是确保字符串是UTF-8编码的。这或多或少是一个健全性检查,因为你说字符串已经是UTF-8编码,所以它应该已经通过。但是,如果您在编码时出现了一些错误并且无效(可能很容易发生),则此检查会阻止您查找错误的位置。
由于您已经在问题中显示的输出已经显示,您很可能在编码时出错了,因为否则支持的字符至少会正确显示,但不仅会遗漏一些字符,而且#&# 39;甚至显示不同的字符。编码错误的明确标志:
因此,请勿跳过此步骤以实际验证字符串所需的编码。
这对下一件事尤为重要:
您需要确保fontface支持该字符串中的字母。 Verdana字体支持794个Unicode字符(full list)。如果您要查找的字符不属于它,则imagettftext()
函数无法显示它们,因为字体缺少它们。在这种情况下,您需要选择支持您正在寻找的Unicode字符的字体。维基百科提供了包含不同字体的概述表:
有关正确字体选择的更多指导,请参阅Stackoverflow:
如果您在字符串变量中使用正确的编码,并且对该字符串中编码的所有Unicode字符使用具有字形的字体,imagettftext
确实可以满足您的需求。
正如我在开头写的那样,有很多地方可能会出错:如果你通过编码检查和字体支持所有字符,那么这里还有一个失败的地方:该字符串是UTF-8编码的,但它不包含您认为的字符。