397 Using Text and Fonts to Create Images Figure 19.5 A button generated by the make_button.php script. Listing 19.2 make_button.php—This Script Can Be Called from the Form in design_button.html or from Within an HTML Image Tag <?php // check we have the appropriate variable data // variables are button-text and color $button_text = $HTTP_POST_VARS['button_text']; $color = $HTTP_POST_VARS['color']; if (empty($button_text) || empty($color)) { echo 'Could not create image - form not filled out correctly'; exit; } // create an image of the right background and check size $im = imagecreatefrompng ($color.'-button.png'); $width_image = ImageSX($im); $height_image = ImageSY($im); // Our images need an 18 pixel margin in from the edge image $width_image_wo_margins = $width_image - (2 * 18); $height_image_wo_margins = $height_image - (2 * 18); // Work out if the font size will fit and make it smaller until it does // Start out with the biggest size that will reasonably fit on our buttons $font_size = 33; 24 525x ch19 1/24/03 2:57 PM Page 397 398 Chapter 19 Generating Images // you need to tell GD2 where your fonts reside putenv('GDFONTPATH=C:\WINNT\Fonts'); $fontname = 'arial'; do { $font_size ; // find out the size of the text at that font size $bbox=imagettfbbox ($font_size, 0, $fontname, $button_text); $right_text = $bbox[2]; // right co-ordinate $left_text = $bbox[0]; // left co-ordinate $width_text = $right_text - $left_text; // how wide is it? $height_text = abs($bbox[7] - $bbox[1]); // how tall is it? } while ( $font_size>8 && ( $height_text>$height_image_wo_margins || $width_text>$width_image_wo_margins ) ); if ( $height_text>$height_image_wo_margins || $width_text>$width_image_wo_margins ) { // no readable font size will fit on button echo 'Text given will not fit on button.<br />'; } else { // We have found a font size that will fit // Now work out where to put it $text_x = $width_image/2.0 - $width_text/2.0; $text_y = $height_image/2.0 - $height_text/2.0 ; if ($left_text < 0) $text_x += abs($left_text); // add factor for left overhang $above_line_text = abs($bbox[7]); // how far above the baseline? $text_y += $above_line_text; // add baseline factor $text_y -= 2; // adjustment factor for shape of our template $white = ImageColorAllocate ($im, 255, 255, 255); Listing 19.2 Continued 24 525x ch19 1/24/03 2:57 PM Page 398 399 Using Text and Fonts to Create Images ImageTTFText ($im, $font_size, 0, $text_x, $text_y, $white, $fontname, $button_text); Header ('Content-type: image/png'); ImagePng ($im); } ImageDestroy ($im); ?> This is one of the longest scripts we’ve looked at so far. Let’s step through it section by section.We begin with some basic error checking, and then set up the canvas on which we’re going to work. Setting Up the Base Canvas In Listing 19.2, rather than starting from scratch, we will start with an existing image for the button.We have a choice of three colors in the basic button: red (red-button.png), green (green-button.png), and blue (blue-button.png). The user’s chosen color is stored in the $color variable from the form. We begin by setting up a new image identifier based on the appropriate button: $im = imagecreatefrompng ($color.'-button.png'); The function ImageCreateFromPNG() takes the filename of a PNG as a parameter, and returns a new image identifier for an image containing a copy of that PNG. Note that this does not modify the base PNG in any way.We can use the ImageCreateFromJPEG() and ImageCreateFromGIF()functions in the same way if the appropriate support is installed. Note The call to ImageCreateFromPNG() only creates the image in memory. To save the image to a file or output it to the browser, we must call the ImagePNG() function. We’ll come to that in a minute, but we have other work to do with our image first. Fitting the Text onto the Button We have some text typed in by the user stored in the $button_text variable.What we want to do is print that text on the button in the largest font size that will fit.We do this by iteration, or strictly speaking, by iterative trial and error. We start by setting up some relevant variables.The first two are the height and width of the button image: $width_image = ImageSX($im); $height_image = ImageSY($im); Listing 19.2 Continued 24 525x ch19 1/24/03 2:57 PM Page 399 400 Chapter 19 Generating Images The second two represent a margin in from the edge of the button. Our button images are beveled, so we’ll need to leave room for that around the edges of the text. If you are using different images, this number will be different! In our case, the margin on each side is around 18 pixels. $width_image_wo_margins = $width_image - (2 * 18); $height_image_wo_margins = $height_image - (2 * 18); We also need to set up the initial font size.We start with 32 (actually 33, but we’ll decre- ment that in a minute) because this is about the biggest font that will fit on the button at all: $font_size = 33; With gd2, you need to tell it where your fonts live by setting the environment variable GDFONTPATH as follows: putenv('GDFONTPATH=C:\WINNT\Fonts'); We also set up the name of the font we want to use.We’re going to use this font with the TrueType functions, which will look for the font file in the above location and will append the file name with .ttf (TrueType Font). $fontname = 'arial'; Note that depending on your operating system you may have to add ‘.ttf ’ to the end of the font name. If you don’t have Arial (the font we use here) on your system, you can easily change this to another TrueType font. Now we loop, decrementing the font size at each iteration, until the submitted text will fit on the button reasonably: do { $font_size ; // find out the size of the text at that font size $bbox=imagettfbbox ($font_size, 0, $fontname, $button_text); $right_text = $bbox[2]; // right co-ordinate $left_text = $bbox[0]; // left co-ordinate $width_text = $right_text - $left_text; // how wide is it? $height_text = abs($bbox[7] - $bbox[1]); // how tall is it? } while ( $font_size>8 && ( $height_text>$height_image_wo_margins || $width_text>$width_image_wo_margins ) ); 24 525x ch19 1/24/03 2:57 PM Page 400 401 Using Text and Fonts to Create Images This code tests the size of the text by looking at what is called the bounding box of the text.We do this using the ImageGetTTFBBox() function, which is one of the TrueType font functions.We will, after we have figured out the size, print on the button using a Tr ueType font (in this case Arial, but you can use whatever you like) and the ImageTTFText() function. The bounding box of a piece of text is the smallest box you could draw around the text. An example of a bounding box is shown in Figure 19.6. Figure 19.6 Coordinates of the bounding box are given relative to the base- line.The origin of the coordinates is shown here as (0,0). To get the dimensions of the box, we call $bbox=imagettfbbox ($font_size, 0, $fontname, $button_text); This call says,“For given font size $font_size, with text slanted on an angle of zero degrees, using the TrueType font Arial, tell me the dimensions of the text in $button_text.” Note that you actually need to pass the path to the file containing the font into the function. In this case, it’s in the same directory as the script (the default), so we haven’t specified a longer path. The function returns an array containing the coordinates of the corners of the bounding box.The contents of the array are shown in Table 19.1. Table 19.1 Contents of the Bounding Box Array Array Index Contents 0X coordinate, lower-left corner 1Y coordinate, lower-left corner 2X coordinate, lower-right corner 3Y coordinate, lower-right corner 4X coordinate, upper-right corner 5Y coordinate, upper-right corner 6X coordinate, upper-left corner 7Y coordinate, upper-left corner To r emember what the contents of the array are, just remember that the numbering starts at the bottom-left corner of the bounding box and works its way around counter clockwise. 24 525x ch19 1/24/03 2:57 PM Page 401 . coordinate, lower-left corner 1Y coordinate, lower-left corner 2X coordinate, lower-right corner 3Y coordinate, lower-right corner 4X coordinate, upper-right corner 5Y coordinate, upper-right corner 6X. button.We have a choice of three colors in the basic button: red (red-button.png), green (green-button.png), and blue (blue-button.png). The user’s chosen color is stored in the $color variable. $button_text); $right_text = $bbox[2]; // right co-ordinate $left_text = $bbox[0]; // left co-ordinate $width_text = $right_text - $left_text; // how wide is it? $height_text = abs($bbox[7] - $bbox[1]); // how tall is