如何使用PHP和GD来解释字体冲突

时间:2015-12-04 18:04:44

标签: php image fonts gd php-gd

我有以下代码在图像上打印文本。我还在文本周围添加了一个调试框。但是,我注意到左边的文本位于PHP为我提供SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1 , Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1 , Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2 , Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2 , Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2 , Q_LVL_2.count FROM POSTS_COMMON AS Q_LVL_1 , ( SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count FROM POSTS_COMMON AS P INNER JOIN ( SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_F.count FROM ( SELECT CORE_RATING.post_id as post_id, ABS(CORE_RATING.diff) as ABS_diff, CORE_F.count FROM ( SELECT post_id_B as post_id, site_rating_A - site_rating_B as diff FROM POSTS_RATING_DIFFS WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id ) as CORE_RATING LEFT JOIN ( SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}' ) as CORE_F ON (CORE_RATING.post_id = CORE_F.post_id_winner OR CORE_RATING.post_id = CORE_F.post_id_loser) WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id AND '<combination of CORE_F.count and CORE_RATING.diff>' = MAX ( SELECT '<combination of CORE_F_2.count and CORE_RATING_2.diff>' FROM ( SELECT site_rating_A - site_rating_B as diff FROM POSTS_RATING_DIFFS WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id ) as CORE_RATING_2 LEFT JOIN ( SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}' ) as CORE_F_2 ON (CORE_RATING_2.post_id = CORE_F_2.post_id_winner OR CORE_RATING_2.post_id = CORE_F_2.post_id_loser) ) /* END MAX */ ) AS CORE_P GROUP BY CORE_P.count, ABS(CORE_P.diff) ) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id ) AS Q_LVL_2 ORDER BY RAND() LIMIT 20

的框之外

enter image description here

这看起来像字体swash的问题。无论如何还有这个吗?我可以计算出斜线开始与react-native start 给我的实际位置之间的距离吗?

我不认为这是字体的问题,因为我尝试使用一些脚本样式字体并且结果相似。

imagettfbbox

此处提供代码和字体:https://github.com/AydinHassan/image-swash-example

如果您在存储库中指向VHOST,则只需点击imagettfbbox

即可

1 个答案:

答案 0 :(得分:2)

编辑: 这似乎已在PHP 7.0.12中修复(错误#53504),因此不需要以下代码。< / p>

基于comment in the PHP manual我编写了以下函数来计算并返回GD认为边界框左侧的位置与最左侧像素的位置之间的差异:

function xadjust($size, $angle, $fontfile, $text)
{
    $bbox = imagettfbbox($size, $angle, $fontfile, $text);

    $width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
    $height = $bbox[1] - $bbox[7]; // lower left y - upper left y;

    // create an image with height and width doubled to fit any 'swash'.
    $im = imagecreatetruecolor($width * 2, $height * 2);

    // set background color to opaque black.
    imagefill($im, 0, 0, 0x00000000);

    // draw the text in opaque white.
    imagettftext(
        $im,
        $size,
        0,
        $width / 2,
        $height,
        0x00ffffff,
        $fontfile,
        $text
    );

    // set the min-width to its possible maximum.
    $min_x = $width * 2;

    for ($x = 0; $x < $width * 2; $x++) {
        // each x-pixel (horizontal)
        for ($y = 0; $y < $height * 2; $y++) {
            // each y-pixel (vertical)
            if (imagecolorat($im, $x, $y) > 0) {
                // non-black pixel found!
                $min_x = min($x, $min_x);
            }
        }
    }

    imagedestroy($im);

    // return the difference between where GD thinks the bounding box is and
    // where we found the leftmost non-black pixel.
    return (($width / 2) - $min_x) - abs($bbox[0]);
}

这可以很容易地集成到您的脚本中:

$font       = 'scriptin.ttf';
$text       = 'Ipsum';
$size       = 30;
$image      = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour   = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));

imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);

$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.

$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
    $image,
    $dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
    $dimensions[7] + 50,
    $dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
    $dimensions[3] + 50,
    imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);

imagettftext(
    $image,
    $size,
    0,
    40,
    50,
    $fontColour,
    $font,
    $text
);

header('Content-Type: image/png');
imagepng($image);

这给了我以下输出:

script result

我使用其他一些字体和大小运行它,它似乎准确到1像素。