How to define swash font with PHP and GD

I have the following code to print text on an image. I also add a debug frame around the text. However, I noticed that the text on the left is outside the field that PHP gives me with imagettfbbox .

enter image description here

This seems like a drag and drop problem with the font. Is it worth explaining this? Can I determine the distance between the beginning of the skew and the actual position of imagettfbbox ?

I don't think this is a font problem, as I tried it with several script style fonts and the results were similar.

 <?php $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); $dimensions = imagettfbbox($size, 0, $font, $text); imagefilledrectangle( $image, $dimensions[0] + 40, $dimensions[7] + 50, $dimensions[2] + 40, $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); 

The code and font can be found here: https://github.com/AydinHassan/image-swash-example

If you specify VHOST in the repository, you can just click swash.php

+6
source share
1 answer

Edit: This seems to be fixed in PHP 7.0.12 (bug # 53504 ), so the code below is not required.


Based on the comments in the PHP manual , I wrote the following function to calculate and return the difference between where GD thinks about the left side of the bounding box and where the leftmost pixel is:

 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]); } 

This can be easily integrated into your script:

 $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); 

This gives me the following result:

script result

I ran it with several other fonts and sizes and it seems to be accurate to 1 pixel.

+2
source

All Articles