Forum Moderators: coopster

Message Too Old, No Replies

Splitting words at fixed lengths while accounting for font size

         

itledi

3:41 pm on Dec 9, 2007 (gmt 0)

10+ Year Member



I'm inserting a string of text into an image using the imagettftext() function. It's working great, except for when I have a long line of text that's wider than the image.

What I'm trying to do is to detect the width of string of text, and if it's wider than the image's width, than to break the line at word breaks, forcing the text to wrap.

There's a function called wordwrap() which would be very useful to me if my font was a fixed width font, but unfortunately it's not. However, I know I can detect the size of my text using imagettfbbox().

I'm having trouble getting started, and would greatly appreciate input. Maybe there's a function that does just this that I'm skipping? Maybe? Hopefully?

dreamcatcher

12:42 am on Dec 10, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can`t really detect the width of a string of text. Would the strlen [hk.php.net] function be useful?

dc

coopster

5:18 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



imagettfbbox() [php.net] would be the correct approach (if you are using truetype fonts) as it returns the bounding box of the text before you might apply it to your image. Compare the width of the bounding box by subtracting the leftmost corner of the bounding box from the rightmost corner of the bounding box (smallest from the largest) to determine the width of the bounding box before it would be applied to your image. If it is greater than the image width, you need to make adjustments to your text.

henry0

6:03 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Coopster, useful function.

Could you precise if the function looks for the font file? (possibly, because the manual states that one may use an URL)
if so then the file needs to be loaded on the server
or do I miss something?

coopster

6:15 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I have uploaded the font files that I intend to use to my server. I then set the font path/filename that I intend to use.

On a Windows server you will likely be set just using the font name as the function will do a little extra work in appending the .ttf extension and looking in your path. However, I recommend setting a font path to make your code more portable.

henry0

6:30 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for the details
I am on a RH, so I will load the fonts and set a path.
I do not have yet a need for it, but it really is handy, surely tomorrow will call for it :)

coopster

10:39 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I am on a RH, so I will load the fonts and set a path.

Careful with just "loading" fonts, there may be license agreement issues. I learned a lot about fonts while going through my own exercise. Some notes I took and some helpful links for future reference ...

I was attempting to use the GD Image applications in PHP and ran into an error when trying to write text to images. I was trying to invoke a font and the error log let me know that it could not find the font. I was not certain that the FreeType 2 fonts were on the system. It looks like PHP was compiled and configured with the necessary command line switch to support the FreeType2 font as the PHP manual pages (http://php.net/ref.image) state ...

To enable support for FreeType 2 add

--with-freetype-dir=DIR
.

... and my PHP configuration showed the switch listed with a directory value. Also, a phpinfo() script showed me the following for the GD environment:

GD Support enabled
GD Version bundled (2.0.28 compatible)
FreeType Support enabled
FreeType Linkage with freetype
FreeType Version 2.1.9
GIF Read Support enabled
GIF Create Support enabled
JPG Support enabled
PNG Support enabled
WBMP Support enabled
XBM Support enabled

But I was not certain how to check/confirm the font library was indeed installed. I found that you can run the following command to confirm:

rpm -qa ¦ grep -i freetype

Note: change the broken pipe to a normal pipe, as the forum breaks the pipe symbol

In my ignorance in regards to the subject, I thought fonts were just "there" once libraries were installed! I understand now from a bit of reading what freetype is, a font-rendering library, and that it does not contain any fonts of it's own, so to speak. So I started wondering if there exists a repository of "default" font types already installed, such as 'arial.ttf', 'times.ttf', etc. on my server? Or did I need to locate and download these font files in order to use them? Turns out it to be the latter, locate and download. I didn't realize that fonts are part of the OS when purchased (if the OS has license agreements with font providers/creators at that time) -- that's why there are so many by default in Windows! I did indeed find some free fonts including an open source solution for sans, serif and monospace fonts at gnome and a modified version of the same from dejavu:

[gnome.org...] (Bitstream Vera Fonts)
[dejavu.sourceforge.net...]
[redhat.com...]

But, better yet, I found the following:

[corefonts.sourceforge.net...]

Now my applications would produce the same font whether on Windows or *nix, without even a subtle difference.

Hope this helps future readers!

henry0

11:53 pm on Dec 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thank you so much for such a guideline and sharing your previous experience.
Funny how it never is as easy as it might look :)
a keeper; bookmarked!

itledi

1:08 am on Dec 12, 2007 (gmt 0)

10+ Year Member



Thanks everyone for the replies.

What I'm thinking about doing is taking the text string and then splitting it into words.

I would measure the length of the first word to detect if its under my width limit. If it is, I would concatenate my second word and detect it's length. I would add one word at a time, till the width is longer than my limit, then I would insert a line break and start measuring that first word on the new line, and keep adding words until that line is too long...

Repeat until all the words have been accounted for.

If I have a length requirement too, I could try the whole above approach using the default font size. If at any time I break that length, I start over, and kick my font size down a point, till the whole string fits within the width and length considerations.

I haven't actually coded this, but it looks like its going to be pretty resource intensive. Might somebody have some suggestions on how to make this process more efficient?

Thanks.

henry0

11:33 am on Dec 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



To look organized I guess your img will have a fixed width
if so, you could use a fixed font type and size and substr() [php.net]
Do a search here it has been pretty much covered.

gergoe

11:48 am on Dec 12, 2007 (gmt 0)

10+ Year Member



Some years ago I had to do more or less the same thing, but then I have it done with javascript and dhtml. The site in question was done with frames, so I added an empty frame, placed the text with the desired font settings in that frame, and after that, read the value of document.clientWidth (if I remember well, maybe offsetWidth that was). Of course I'd not do it with frames anymore, but probably you can achieve the same effect using a span too. Only problem that you can only do this on the client side, you can not use these "measurements" on the server...

itledi

2:33 pm on Dec 12, 2007 (gmt 0)

10+ Year Member



I'm stuck here in my script and was hoping for some guidance.

So far I have been able to explode my text into seperate words, and to count the width of each word.

What I need to do now is to see if the width of first word in the string is under X pixels, if so, concatenate a space the the second word, and to keep on adding words uptill the X limit.

When its over the limit, to make a second and following string with the remainder of the text.

$text=explode(" ",$text);
for ($i=0;$i<count($text);$i++){
$box[$i]=imagettfbbox(25,0,"font.ttf",$text[$i]);
$width[$i]=abs($box[$i][2]-$box[$i][0]);
echo $text[$i]." width: ".$width[$i]."<br />";
}

coopster

4:21 pm on Dec 12, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



So you have your widths stored in an array now. Next step would be to loop through those widths, adding them up and comparing them to your overall to see if it exceeds your limit. If so, store the current string in a new array (or write the text to the image) and begin a new string (a new line of text to place on the image).