6

我在由 PHP GD 库创建的图像中使用 Verdana 字体。

imagettftext($image, $fontSize, 0, 70, $y, $color, $font, $username );

大多数情况下 imagettftext 非常适用于字符串。
但是我的一些用户在他们的名字中使用了奇怪的字符/符号。
所以当我尝试将他们的名字打印到图像上时。例如:
在此处输入图像描述

该用户使用ɦɪɲɣƙƨєʌɾ 符号。所以 Verdana 不能打印它们。

我用这个:

$username=iconv('UTF-8', 'ASCII//TRANSLIT', $username);

输出是这样的:
在此处输入图像描述

(当前语言环境在英语和德语之间发生变化。所以当前语言环境可能无法处理这些字符ɦɪɲɣƙƨєʌɾ:)

如果不写一个很大的块,似乎不可能音译ɦh, ɲto 。像这样nstr_replace()

  • 所以我想知道是否可以检查字体(Verdana)是否可以显示这些符号。如果其中一个字符不能在字符串中显示,那么我可以将一个空字符串传递给imagettftext方法。我可以检查字体中支持的字符吗?或者创建一个包含 Verdana 支持符号的字符映射,并检查我的字符串是否包含不支持的符号?(我认为由于这个问题
    是不可能的)

  • 或者也许是另一种解决方案,是否可以在中使用多种字体imagettftext()
    例如,首先尝试 Verdana,如果 Verdana 不涵盖该符号,则使用 Arial sans serif 等。

  • 或任何其他解决方案?

编辑:
似乎 Verdana 在我的文本中不支持这些 un​​icode 字符。
Verdana 支持的字符:http
://www.fileformat.info/info/unicode/font/verdana/grid.htm Verdana 未支持的字符: http ://www.fileformat.info/info/unicode/font/verdana/missing.htm

4

4 回答 4

4

我的第一选择是切换到支持您希望能够处理的所有字符的字体。但是不要指望一种字体会在 UTF-8 中实现数百万个可能的字符

现在,如果你想走 (lazy ;) 音译路线,我会参考Kemal Dağ 的这个答案

我现在手头没有 v5.4,所以我无法确定Transliterator,但 Kemal Dağ 的端口JTransliteration表现相当不错:

<?php
    require 'transliteration/JTransliteration.php';

    $input = 'ɦɪɲɣƙƨєʌɾ';
    echo JTransliteration::transliterate($input); // output: hIngk2ie^r

    $input = 'Хეλлఒ Wओრলद';
    echo JTransliteration::transliterate($input);

最后,如果您想检查给定字体是否支持给定字符,它会变得有点麻烦。这个库会有很大帮助。它需要 >= 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.phpR. Hill 的代码ord_utf8()

PS字符串“ɦɪɲɣƙƨєʌɾ”由国际音标中的字符组成。我不确定是否有任何语言环境支持这些字符(因为没有实际需要,因为它们不被任何真正的人类语言使用)。

于 2014-03-11T19:50:50.347 回答
3

只要您使用 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');

结果:

在此处输入图像描述

于 2014-03-17T12:10:51.710 回答
0

你设置正确的语言环境了吗?可能需要 iconv - http://cz1.php.net/manual/en/function.iconv.php#74101

于 2014-03-09T13:40:23.460 回答
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 编码的,所以它应该已经通过了。但是,以防万一您在编码方面犯了一些错误并且它无效(很容易发生),此检查可防止您查找错误的位置。

正如您已经输入问题的输出所示,您很可能在编码方面犯了错误,因为否则至少会正确显示支持的字符,但是不仅会遗漏一些字符,甚至会显示不同的字符. 错误编码的明显标志:

在此处输入图像描述

所以不要跳过这一步来实际验证所需的字符串编码。

这对于接下来的事情尤其重要:

您需要确保字体支持该字符串中的字母。Verdana 字体支持 794 个 Unicode 字符(完整列表)。如果您要查找的字符不是其中的一部分,则该imagettftext()功能无法显示它们,因为字体缺少它们。在这种情况下,您需要选择支持您正在寻找的 Unicode 字符的字体。Wikipedia 上提供了具有不同字体的概览表:

更多关于正确字体选择的指导可以在 Stackoverflow 上找到:

如果您在字符串变量中使用正确的编码,并且字体具有该字符串中编码的所有 Unicode 字符的字形,imagettftext则可以满足您的需求。

正如我在开头所写的那样,有很多地方可能会出错:如果您通过了编码检查并且字体已经支持所有字符,那么这里还有一个失败的地方:字符串是 UTF-8 编码的,但确实如此不包含您认为的字符。

于 2014-03-16T13:51:16.577 回答