php imagettftext letter spacing
Asked Answered
C

6

7

Does anybody have a function that draws a ttf string (imagettftext) with specified letter spacing?

I cannot find any build-in GD function so I think that it should be done letter by letter adding some constant width.

Maybe someone have such function already :)

ps. the best font will be arial.ttf

Circumstantial answered 3/8, 2011 at 12:43 Comment(0)
C
27
function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0)
{        
    if ($spacing == 0)
    {
        imagettftext($image, $size, $angle, $x, $y, $color, $font, $text);
    }
    else
    {
        $temp_x = $x;
        for ($i = 0; $i < strlen($text); $i++)
        {
            $bbox = imagettftext($image, $size, $angle, $temp_x, $y, $color, $font, $text[$i]);
            $temp_x += $spacing + ($bbox[2] - $bbox[0]);
        }
    }
}

and the call:

imagettftextSp($image, 30, 0, 30, 30, $black, 'arial.ttf', $text, 23);

Function parameters order meets standard imagettftext parameters order, and the last parameter is optional $spacing parameter. If not set or the passed value is 0, the kerning / letter spacing is not set.

Circumstantial answered 4/8, 2011 at 6:37 Comment(3)
replace $text[$i] with mb_substr($text, $i, 1) to overcome trouble with mulitibyte charactersLocale
While I appreciate the efforts, I don't think this function is robust enough. It mangles the letter spacing when its iterated through like that. See for yourself. Compare a spacing of 0 with a spacing of 0.1, you'll notice the 0.1 kerning ends up being all over the place.Kerman
For future reference, there's a better answer to this problem here.Endocardium
B
12

I know this was answered a while back, but I needed a solution that had letter spacing and maintained the angular offsets.

I modified radzi's code to accomplish this:

function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0)
{        
    if ($spacing == 0)
    {
        imagettftext($image, $size, $angle, $x, $y, $color, $font, $text);
    }
    else
    {
        $temp_x = $x;
        $temp_y = $y;
        for ($i = 0; $i < strlen($text); $i++)
        {
            imagettftext($image, $size, $angle, $temp_x, $temp_y, $color, $font, $text[$i]);
            $bbox = imagettfbbox($size, 0, $font, $text[$i]);
            $temp_x += cos(deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0]));
            $temp_y -= sin(deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0]));
        }
    }
}
Bend answered 14/8, 2012 at 13:36 Comment(1)
Glad to see you gave back to the Stack Overflow community with this answer. Good show +1Switcheroo
D
9

Just to complete pidalia's answer (which is the best) to avoid some trouble with special char (like "é" or "à")

static function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0) {
    if ($spacing == 0) {
        imagettftext($image, $size, $angle, $x, $y, $color, $font, $text);
    } else {
        $temp_x = $x;
        $temp_y = $y;
        //to avoid special char problems
        $char_array = preg_split('//u',$text, -1, PREG_SPLIT_NO_EMPTY);
        foreach($char_array as $char) {
            imagettftext($image, $size, $angle, $temp_x, $temp_y, $color, $font, $char);
            $bbox = imagettfbbox($size, 0, $font, $char);
            $temp_x += cos(deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0]));
            $temp_y -= sin(deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0]));
        }
    }
}
Daughterinlaw answered 16/7, 2013 at 12:32 Comment(0)
O
2

GD doesn't support kerning, so you'll have to do it manually. Personally, I wrote a function that would write each letter separately. I can't find it right now, but it's something along the lines of:

function drawText(&$image, $text, $fgColor, $font, $fgColor, 
                   $fontSize = 14, $kerning = 0, $x = 0, $y = 0) {
    $letters = explode('', $text);

    foreach ($letters as $n => $letter) {
        $bbox = imagettftext($image, $fontSize, 0, $x, $y, $fgColor, $font, $letter);
        $x += $bbox[2] + $kerning;
    }
}
Optative answered 3/8, 2011 at 12:56 Comment(0)
L
1

I have tried all the answers here and none seems to do a decent job. If you draw the bounding box, this is what happens:

enter image description here

Clearly they are not evenly spaced. It appears that the bounding box, returned by imagettftext() and imagettfbbox(), only tells you what is drawn. This might seem enough, but it isn't, because of font kerning. This means that even when you say a letter should be draw at (x,y), that that will not be one of the coordinates of the bounding box. A correction for kerning is needed. enter image description here

I botched together this code for horizontal text:

function getBBoxW($bBox)
{
  return $bBox[2] - $bBox[0];
}


function imagettftextSpacing($image, $size, $x, $y, $color, $font, $text, $spacing = 0)
{
    $testStr = 'test';
    $testW   = getBBoxW(imagettfbbox($size, 0, $font, $testStr));
    foreach (mb_str_split($text) as $char)
    {
        $fullBox = imagettfbbox($size, 0, $font, $char . $testStr);
        imagettftext($image, $size, 0, $x - $fullBox[0], $y, $color, $font, $char);
        $x += $spacing + getBBoxW($fullBox) - $testW;
    }
}

The results are much better. Note that the $testStr can have any value.

Here's an example of the result, the first line is normal text, the second line has a negative spacing:

enter image description here enter image description here

Lepp answered 11/12, 2020 at 15:59 Comment(0)
B
-1

Try this function:

$image = imagecreatetruecolor(500,200);
$text = "Text to print";
$text_color=imagecolorallocate($image,255,255,255);
$font_size = 18;
$space = 8;
$font = "path_to_font/arial.ttf";
$x=20;
$y=20;
for ($i = 0; $i <strlen($text); $i++){
   $arr = imagettftext ($image, $font_size,0, $x, $y, $text_color, $font, $text{$i});
   $x = $arr[4]+$space;
}
imagejpeg($image);
destroyimage($image);
Bozuwa answered 3/8, 2011 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.