Solved

Resizing and word-wrapping dynamic text to fit an image

Posted on 2004-08-31
19
1,061 Views
Last Modified: 2011-06-17
Hey guys,

I'm trying to make a script that displays a dynamic text (user input or from db) into an image within certain boundaries. The aim is to create warning labels similar to those you find on the cigarette packets.

Here is my code so far:

<?php

// Inställningar för typsnittet
$font_file = "verdana.ttf";
$font_size = 14;

// antal pixlar från toppen
$y_start = 40;

// Skriv rakt
$angle = 0;

// Hur lång får den vara

$max_width = 155;

// Text som ska visas
$text = "Smoking kills sooner or later.";

// Startpunkt (Centerering)
$line_width = imagettfbbox($font_size, $angle, $font_file, $text);
$x_start = ($max_width/ 2);

// Skapa bild och färg (och skicka till browser)
header("Content-type: image/gif");
$im = imagecreatefromgif("blank.gif");
$color = imagecolorallocate($im, 0, 0, 0);

// Skriv text till bild
imagettftext($im, $font_size, $angle, $x_start, $y_start, $color, $font_file, $text);

// Skapa och förstör bild
imagepng($im);
imagedestroy($im);
?>

I need help with a function that resizes and word-wraps the text so it fits the boundaries of the label. There are probably other issues that I haven't thought about so I would appreciate any help I can get as php is very new to me.

Here's the link to my test page: http://www.tuppjuck.com/temp/cigg2/test.php

Thank you for reding this!

/Cheers Nemo
0
Comment
Question by:NemoZ
19 Comments
 
LVL 1

Expert Comment

by:johanmulder
ID: 11941161
try to use the imagettbbox() function to discover the metrics of the inserted text.
Example code:

$spacing = 0.7;
$params = array("linespacing" => $spacing);

$box = imageftbbox ($size, 0, $font, $text, $params);
$tw=$box[4]-$box[0]; //image width
$th=($box[1]-$box[5])*$spacing; //image height

This code will create a textbox. $box is an array which stores the width,height, top, left, etc. of the textbox.

For more information you can visit http://www.php.net/manual/en/function.imageftbbox.php

Good Luck!
0
 
LVL 4

Expert Comment

by:iceboxman
ID: 11944134
If you are using a monospace font and know the number of characters to wrap with, you can use the wordwrap() function.
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11946168
I think this is doing everything you need.

It is VERY badly written. Sorry.

<?php
function calcSize($iFontSize)
      {
      global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight;

      $aLines = array();
      $sLine = '';
      foreach($aText as $iKey => $sWord)
            {
            $sLine = ltrim("$sLine $sWord",' ');
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
            $iWidth = ($aDimensions[2] - $aDimensions[0]);
            if ($iWidth > $iMaxWidth)
                  {
                  $sLine = substr($sLine,0,-1 - strlen($sWord));
                  $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
                  $aLines[] = $sLine;
                  $sLine = $sWord;
                  }
            }
      if ($sLine != '')
            {
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
            $aLines[] = $sLine;
            }
      $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0));
      $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7];
      if ((count($aLines) * $iLineHeight) >= $iMaxHeight)
            {
            return False;
            }
      else
            {
            return True;
            }
      }

$aText = explode(' ','Smoking will kill you and make everyone hate you.');
if (isset($_GET['Text']))
      {
      $aText = explode(' ',"{$_GET['Text']} ");
      }
$sFontFile = "verdana.ttf";
$iFontSize = 1;
$iMaxWidth = 250;
$iMaxHeight = 250;
$iLineHeight = 0;
$aLines = array();

while(calcSize(++$iFontSize) !== False);
calcSize(--$iFontSize);
$im = imagecreate($iMaxWidth,$iMaxHeight);
$colBlack = imagecolorallocate ($im, 0, 0, 0);
$colWhite = imagecolorallocate ($im, 255, 255, 255);
foreach($aLines as $iKey => $sLine)
      {
      imagefttext($im,$iFontSize,0,0,($iKey + 1) * $iLineHeight,$colWhite,$sFontFile,$sLine,array('linespacing' => 0));
      }
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11946211
Save the above script as wrap.php and then run it with ...

wrap.php?Text=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z

Or

wrap.php?Text=This is a test to see how good Richard's program is at wrapping a LOT of text into a very small area, made smaller by a VERY large amount of very boring text.

Oh.

Replace ...

$aText = explode(' ',"{$_GET['Text']} ");

with ...

$aText = explode(' ',stripslashes($_GET['Text']));

Richard.
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11949905
Thanks for all the answers. Specially Richard.

Your code works like a charm. I was just wondering if there is a way to centre the text, make the text black and the background white?

Also if possible it would be great if there could be a black border around the white background as well. That'll give the box the proper warning text look. If it's too much hassle I can fix it with a bit if html...

Thank you very much for helping me with this.
0
 
LVL 40

Accepted Solution

by:
RQuadling earned 400 total points
ID: 11949972
<?php
function calcSize($iFontSize)
     {
     global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight,$aWidths;

     $aLines = array();
     $aWidths = array();
     $sLine = '';
     foreach($aText as $iKey => $sWord)
          {
          $sLine = ltrim("$sLine $sWord",' ');
          $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
          $iWidth = ($aDimensions[2] - $aDimensions[0]);
          if ($iWidth > $iMaxWidth)
               {
               $sLine = substr($sLine,0,-1 - strlen($sWord));
               $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
               $aLines[] = $sLine;
               $aWidths[] = ($aDimensions[2] - $aDimensions[0]);
               $sLine = $sWord;
               }
          }
     if ($sLine != '')
          {
          $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0));
          $aLines[] = $sLine;
          $aWidths[] = ($aDimensions[2] - $aDimensions[0]);
          }
     $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0));
     $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7];
     if ((count($aLines) * $iLineHeight) >= $iMaxHeight)
          {
          return False;
          }
     else
          {
          return True;
          }
     }

$aText = explode(' ','Smoking will kill you and make everyone hate you.');
if (isset($_GET['Text']))
     {
     $aText = explode(' ',stripslashes($_GET['Text']));
     }
$sFontFile = "verdana.ttf";
$iFontSize = 1;
$iMaxWidth = 250;
$iMaxHeight = 250;
$iLineHeight = 0;
$aLines = array();
$aWidths = array();

while(calcSize(++$iFontSize) !== False);
calcSize(--$iFontSize);
$im = imagecreate(30 + $iMaxWidth,30 + $iMaxHeight);
$colBlack = imagecolorallocate ($im, 0, 0, 0);
$colWhite = imagecolorallocate ($im, 255, 255, 255);
imagefilledrectangle($im,10,10,20 + $iMaxWidth,20 + $iMaxHeight,$colWhite);
foreach($aLines as $iKey => $sLine)
     {
     imagefttext($im,$iFontSize,0,15 + (($iMaxWidth - $aWidths[$iKey]) / 2),10 + ($iKey + 1) * $iLineHeight,$colBlack,$sFontFile,$sLine,array('linespacing' => 0));
     }
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>

Not a lot different.

Richard.
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11950290
Wow... that's brilliant mate...

Thank you very much for the prompt reply and for helping me out.
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11950327
No problem.

I'd love to see the finished site when you've done!

Richard.
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11950379
np. I'll post it as soon as it's finished. :)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 3

Author Comment

by:NemoZ
ID: 11971579
Hey Richard,

The site is almost finished but I have a small problem with long words. If the word is too long it'll get cut off on both ends to fit the text area which makes the text almost unreadable.

 Is there a smart way to split long words into two pieces in grammatically correct way or at least resize them to fit in the window without getting cut off?

Thanks again for your assistance!

/Cheers Nemo
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11971706
Long words?

Like antidisestablishmentarianism?

I know (as an english speaker), that you COULD break at anti, antidis, but not really anything else.

And as for other languages, who knows!

Maybe you should check the length of the words going in and cap the reduction to something reasonable.

Richard.
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11971971
>Long words?
>Like antidisestablishmentarianism?

Yepp... ;)

To be honest I'm having great problems with understanding your code as I'm new to this stuff but the funny thing is that if I use a long word by itself it won't fit as it's not resized but if I use it in a long sentence it is resized perfectly.

If you have the time I would appreciate your help...

/Cheers Nemo


0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11972119
Can you give me an example?

The code is crap.

Here is a the code with a LOT of comments.

<?php
// This function will see if the text ($aText) will fit into the are ($iMaxWidth, $iMaxHeight).
// It will set the lines of text to be displayed ($aLines).
// It will also set ($aWidths) for each line so it can be centered.
function calcSize($iFontSize)
     {
     global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight,$aWidths;

     $aLines = array(); // Start with no lines defined.
     $aWidths = array(); // Start with no widths defined.
     $sLine = ''; // Start with an empty line.
     foreach($aText as $iKey => $sWord) // For each word in the supplied text.
          {
          $sLine = ltrim("$sLine $sWord",' '); // Add the word to the line, with a space and remove any leading spaces.
          $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this line.
          $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
          if ($iWidth > $iMaxWidth) // If the width is GREATER than the maximum width, backtrack the last word.
               {
               $sLine = substr($sLine,0,-1 - strlen($sWord)); // Remove the last word from the line and the space.
               $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this backtracked line.
               $aLines[] = $sLine; // Save the line.
               $aWidths[] = ($aDimensions[2] - $aDimensions[0]); // Save the dimensions.
               $sLine = $sWord; // Start the line with the word that didn't fit.
               }
          }
     if ($sLine != '') // If the line is NOT empty, it means we have finished the words, but the last word has not been stored yet.
          {
          $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions.
          $aLines[] = $sLine; // Store the line.
          $aWidths[] = ($aDimensions[2] - $aDimensions[0]); // Store the width.
          }
     $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0)); // Get the dimensions for all the letters in this font at this fontsize.
     $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7]; // Calculate the line height.
     if ((count($aLines) * $iLineHeight) >= $iMaxHeight) // Would all the lines we have fit in the box?
          {
          return False; // NO.
          }
     else
          {
          return True; // Yes.
          }
     }

// What is the text we want to deal with.
$aText = explode(' ','Smoking will kill you and make everyone hate you.');

// If some text was supplied as a GET parameter, use this instead.
if (isset($_GET['Text']))
     {
     $aText = explode(' ',stripslashes($_GET['Text']));
     }
// NOTE: I have split the text at all the spaces as I want to deal with words when fitting the words to lines.

$sFontFile = "verdana.ttf"; // What font.
$iFontSize = 1; // Initial font size.
$iMaxWidth = 1000; // Maximum Text width.
$iMaxHeight = 1000; // Maximum Text height.
$iLineHeight = 0; // Actual Line Height
$aLines = array(); // Lines of words to be shown.
$aWidths = array(); // Widths of each line to be used when centering the lines.

while(calcSize(++$iFontSize) !== False); // See if the text at $iFontSize will fit into the box. If it does, then try again with the next font size.
calcSize(--$iFontSize); // We have reached here because the fontsize did NOT fit, so use the previous font size.
$im = imagecreate(30 + $iMaxWidth,30 + $iMaxHeight); // Create an image.
$colBlack = imagecolorallocate ($im, 0, 0, 0); // Add a black background.
$colWhite = imagecolorallocate ($im, 255, 255, 255); // Add a white colour.
imagefilledrectangle($im,10,10,20 + $iMaxWidth,20 + $iMaxHeight,$colWhite); // Draw a white box inside the image.
foreach($aLines as $iKey => $sLine) // For each line that was calculated add it to the image, centered.
     {
     imagefttext($im,$iFontSize,0,15 + (($iMaxWidth - $aWidths[$iKey]) / 2),10 + ($iKey + 1) * $iLineHeight,$colBlack,$sFontFile,$sLine,array('linespacing' => 0));
     }
// Output the image.
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11972324
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11972354
Aha.

Try ...

<?php
// This function will see if the text ($aText) will fit into the are ($iMaxWidth, $iMaxHeight).
// It will set the lines of text to be displayed ($aLines).
// It will also set ($aWidths) for each line so it can be centered.
function calcSize($iFontSize)
      {
      global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight,$aWidths;
      
      $aLines = array(); // Start with no lines defined.
      $aWidths = array(); // Start with no widths defined.
      $sLine = ''; // Start with an empty line.
      
      foreach($aText as $iKey => $sWord) // For each word in the supplied text.
            {
            $sLine = ltrim("$sLine $sWord",' '); // Add the word to the line, with a space and remove any leading spaces.
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            if ($iWidth > $iMaxWidth) // If the width is GREATER than the maximum width, backtrack the last word.
                  {
                  $sLine = substr($sLine,0,-1 - strlen($sWord)); // Remove the last word from the line and the space.
                  $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this backtracked line.
                  $aLines[] = $sLine; // Save the line.
                  $aWidths[] = ($aDimensions[2] - $aDimensions[0]); // Save the dimensions.
                  $sLine = $sWord; // Start the line with the word that didn't fit.
                  }
            }
      if ($sLine != '') // If the line is NOT empty, it means we have finished the words, but the last word has not been stored yet.
            {
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions.
            $aLines[] = $sLine; // Store the line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            if ($iWidth > $iMaxWidth) // This test should only happen for 1 word sentences.
                  {
                  return False;
                  }
            }
      $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0)); // Get the dimensions for all the letters in this font at this fontsize.
      $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7]; // Calculate the line height.
      if ((count($aLines) * $iLineHeight) >= $iMaxHeight) // Would all the lines we have fit in the box?
            {
            return False; // NO.
            }
      else
            {
            return True; // Yes.
            }
      }

// What is the text we want to deal with.
$aText = explode(' ','Smoking will kill you and make everyone hate you.');

// If some text was supplied as a GET parameter, use this instead.
if (isset($_GET['Text']))
      {
      $aText = explode(' ',stripslashes($_GET['Text']));
}
// NOTE: I have split the text at all the spaces as I want to deal with words when fitting the words to lines.

$sFontFile = "verdana.ttf"; // What font.
$iFontSize = 1; // Initial font size.
$iMaxWidth = 1000; // Maximum Text width.
$iMaxHeight = 1000; // Maximum Text height.
$iLineHeight = 0; // Actual Line Height
$aLines = array(); // Lines of words to be shown.
$aWidths = array(); // Widths of each line to be used when centering the lines.

while(calcSize(++$iFontSize) !== False); // See if the text at $iFontSize will fit into the box. If it does, then try again with the next font size.
calcSize(--$iFontSize); // We have reached here because the fontsize did NOT fit, so use the previous font size.
$im = imagecreate(30 + $iMaxWidth,30 + $iMaxHeight); // Create an image.
$colBlack = imagecolorallocate ($im, 0, 0, 0); // Add a black background.
$colWhite = imagecolorallocate ($im, 255, 255, 255); // Add a white colour.
imagefilledrectangle($im,10,10,20 + $iMaxWidth,20 + $iMaxHeight,$colWhite); // Draw a white box inside the image.
foreach($aLines as $iKey => $sLine) // For each line that was calculated add it to the image, centered.
      {
      imagefttext($im,$iFontSize,0,15 + (($iMaxWidth - $aWidths[$iKey]) / 2),10 + ($iKey + 1) * $iLineHeight,$colBlack,$sFontFile,$sLine,array('linespacing' => 0));
      }
// Output the image.
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11972405
<?php
// This function will see if the text ($aText) will fit into the are ($iMaxWidth, $iMaxHeight).
// It will set the lines of text to be displayed ($aLines).
// It will also set ($aWidths) for each line so it can be centered.
function calcSize($iFontSize)
      {
      global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight,$aWidths;
      
      $aLines = array(); // Start with no lines defined.
      $aWidths = array(); // Start with no widths defined.
      $sLine = ''; // Start with an empty line.
      
      foreach($aText as $iKey => $sWord) // For each word in the supplied text.
            {
            $sLine = ltrim("$sLine $sWord",' '); // Add the word to the line, with a space and remove any leading spaces.
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            if ($iWidth > $iMaxWidth) // If the width is GREATER than the maximum width, backtrack the last word.
                  {
                  $sLine = substr($sLine,0,-1 - strlen($sWord)); // Remove the last word from the line and the space.
                  $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this backtracked line.
                  $aLines[] = $sLine; // Save the line.
                  $aWidths[] = ($aDimensions[2] - $aDimensions[0]); // Save the dimensions.
                  $sLine = $sWord; // Start the line with the word that didn't fit.
                  }
            }
      if ($sLine != '') // If the line is NOT empty, it means we have finished the words, but the last word has not been stored yet.
            {
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions.
            $aLines[] = $sLine; // Store the line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            $aWidths[] = $iWidth; // Store the width.
            if ($iWidth > $iMaxWidth) // This test should only happen for 1 word sentences.
                  {
                  return False;
                  }
            }
      $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0)); // Get the dimensions for all the letters in this font at this fontsize.
      $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7]; // Calculate the line height.
      if ((count($aLines) * $iLineHeight) >= $iMaxHeight) // Would all the lines we have fit in the box?
            {
            return False; // NO.
            }
      else
            {
            return True; // Yes.
            }
      }

// What is the text we want to deal with.
$aText = explode(' ','Smoking will kill you and make everyone hate you.');

// If some text was supplied as a GET parameter, use this instead.
if (isset($_GET['Text']))
      {
      $aText = explode(' ',stripslashes($_GET['Text']));
}
// NOTE: I have split the text at all the spaces as I want to deal with words when fitting the words to lines.

$sFontFile = "verdana.ttf"; // What font.
$iFontSize = 1; // Initial font size.
$iMaxWidth = 300; // Maximum Text width.
$iMaxHeight = 300; // Maximum Text height.
$iLineHeight = 0; // Actual Line Height
$aLines = array(); // Lines of words to be shown.
$aWidths = array(); // Widths of each line to be used when centering the lines.

while(calcSize(++$iFontSize) !== False); // See if the text at $iFontSize will fit into the box. If it does, then try again with the next font size.
calcSize(--$iFontSize); // We have reached here because the fontsize did NOT fit, so use the previous font size.
$im = imagecreate(30 + $iMaxWidth,30 + $iMaxHeight); // Create an image which is 30px bigger.
$colBlack = imagecolorallocate ($im, 0, 0, 0); // Add a black background.
$colWhite = imagecolorallocate ($im, 255, 255, 255); // Add a white colour.
imagefilledrectangle($im,10,10,20 + $iMaxWidth,20 + $iMaxHeight,$colWhite); // Draw a white box inside the image which uses 10px on each side of the additional 30.
foreach($aLines as $iKey => $sLine) // For each line that was calculated add it to the image, centered.
      {
// Write the text 15px in from the left side giving a nice gap between the text and the border.
      imagefttext($im,$iFontSize,0,15 + (($iMaxWidth - $aWidths[$iKey]) / 2),10 + ($iKey + 1) * $iLineHeight,$colBlack,$sFontFile,$sLine,array('linespacing' => 0));
      }
// Output the image.
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>

Richard.
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 11972605
Ok. Try this and tell me.

<?php
// This function will see if the text ($aText) will fit into the are ($iMaxWidth, $iMaxHeight).
// It will set the lines of text to be displayed ($aLines).
// It will also set ($aWidths) for each line so it can be centered.
function calcSize($iFontSize)
      {
      global $aLines,$aText,$sFontFile,$iMaxWidth,$iMaxHeight,$iLineHeight,$aWidths;
      
      $aLines = array(); // Start with no lines defined.
      $aWidths = array(); // Start with no widths defined.
      $sLine = ''; // Start with an empty line.
      
      foreach($aText as $iKey => $sWord) // For each word in the supplied text.
            {
            $sLine = ltrim("$sLine $sWord",' '); // Add the word to the line, with a space and remove any leading spaces.
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            if ($iWidth > $iMaxWidth) // If the width is GREATER than the maximum width, backtrack the last word.
                  {
                  $sLine = substr($sLine,0,-1 - strlen($sWord)); // Remove the last word from the line and the space.
                  $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions for this backtracked line.
                  $aLines[] = $sLine; // Save the line.
                  $aWidths[] = ($aDimensions[2] - $aDimensions[0]); // Save the dimensions.
                  $sLine = $sWord; // Start the line with the word that didn't fit.
                  }
            }
      if ($sLine != '') // If the line is NOT empty, it means we have finished the words, but the last word has not been stored yet.
            {
            $aDimensions = imageftbbox($iFontSize,0,$sFontFile,$sLine,array('linespacing' => 0)); // Get the dimensions.
            $aLines[] = $sLine; // Store the line.
            $iWidth = ($aDimensions[2] - $aDimensions[0]); // What is the width of this line.
            $aWidths[] = $iWidth; // Store the width.
            if ($iWidth > $iMaxWidth) // This test should only happen for 1 word sentences.
                  {
                  return False;
                  }
            }
      $aDimensions = imageftbbox($iFontSize,0,$sFontFile,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',array('linespacing' => 0)); // Get the dimensions for all the letters in this font at this fontsize.
      $iLineHeight = 4 + $aDimensions[1] - $aDimensions[7]; // Calculate the line height.
      if ((count($aLines) * $iLineHeight) >= $iMaxHeight) // Would all the lines we have fit in the box?
            {
            return False; // NO.
            }
      else
            {
            return True; // Yes.
            }
      }

session_start();

if (isset($_GET['Img']))
      {
      // What is the text we want to deal with.
      $aText = explode(' ',stripslashes($_SESSION['Text']));
      
      // NOTE: I have split the text at all the spaces as I want to deal with words when fitting the words to lines.
      
      $sFontFile = "verdana.ttf"; // What font.
      $iFontSize = 1; // Initial font size.
      $iMaxWidth = $_SESSION['MaxWidth']; // Maximum Text width.
      $iMaxHeight = $_SESSION['MaxHeight']; // Maximum Text height.
      $iLineHeight = 0; // Actual Line Height
      $aLines = array(); // Lines of words to be shown.
      $aWidths = array(); // Widths of each line to be used when centering the lines.
      
      while(calcSize(++$iFontSize) !== False); // See if the text at $iFontSize will fit into the box. If it does, then try again with the next font size.
      calcSize(--$iFontSize); // We have reached here because the fontsize did NOT fit, so use the previous font size.
      $im = imagecreate(30 + $iMaxWidth,30 + $iMaxHeight); // Create an image which is 30px bigger.
      $colBlack = imagecolorallocate ($im, 0, 0, 0); // Add a black background.
      $colWhite = imagecolorallocate ($im, 255, 255, 255); // Add a white colour.
      imagefilledrectangle($im,10,10,20 + $iMaxWidth,20 + $iMaxHeight,$colWhite); // Draw a white box inside the image which uses 10px on each side of the additional 30.
      foreach($aLines as $iKey => $sLine) // For each line that was calculated add it to the image, centered.
            {
      // Write the text 15px in from the left side giving a nice gap between the text and the border.
            imagefttext($im,$iFontSize,0,15 + (($iMaxWidth - $aWidths[$iKey]) / 2),10 + ($iKey + 1) * $iLineHeight,$colBlack,$sFontFile,$sLine,array('linespacing' => 0));
            }
      // Output the image.
      header("Content-type: image/png");
      imagepng($im);
      imagedestroy($im);
      }
else
      {
      if (isset($_POST['Text']))
            {
            $_SESSION['Text'] = $_POST['Text'];
            }
      else
            {
            $_SESSION['Text'] = 'Smoking will kill you and make everyone hate you.';
            }
      if (isset($_POST['MaxWidth']))
            {
            $_SESSION['MaxWidth'] = $_POST['MaxWidth'];
            }
      else
            {
            $_SESSION['MaxWidth'] = 300;
            }
      if (isset($_POST['MaxHeight']))
            {
            $_SESSION['MaxHeight'] = $_POST['MaxHeight'];
            }
      else
            {
            $_SESSION['MaxHeight'] = 300;
            }
      
      echo <<< END_HTML
<html>
<head>
<title>Word Wrapper</title>
</head>
<body>
<form name="formWordWrap" method="POST" name="WordWrap.php">
What do you want to say <input type="text" name="Text" size="50" maxlength="1000" value="{$_SESSION['Text']}"><br />
Width <input type="text" size="4" name="MaxWidth" maxlength="4" value="{$_SESSION['MaxWidth']}"><br />
Height <input type="text" size="4" name="MaxHeight" maxlength="4" value="{$_SESSION['MaxHeight']}"><br />
<input type="submit">
</form>
<hr />
<img src="{$_SERVER['PHP_SELF']}?Img=Yes">
</body>
</html>
END_HTML;
      }
?>      

ICQ : 1711757
AIM : RasterUK

Richard.
0
 
LVL 3

Author Comment

by:NemoZ
ID: 11974208
Thanks Bro. Your comments helped me tons. I promise to post the site when it's finished.

/Cheers Nemo
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 35987694
7 years on and I'm still waiting for a link ...
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now