Wordwrap in PHP


Wordwrap by width using PHP

The other day, I was writing some code for a live text preview for an application in AngularJS. ┬áThis is for purchasing customized gift cards from Giftcards.com. The text preview is for a greeting card and is implemented in HTML5’s canvas. Another image of the previewed item is constructed server side and is shown to the user as a checkout preview. I found that PHP’s wordwrap function did not wrap by width, but by number of characters, much to my chagrin. So if you wanted to calculate exactly where to wrap strings of different sizes and different fonts, you were ‘gunna have a bad time.’

 

This is the way I approached solving the issue. Please challenge and recommend better solutions, if you should find an alternate way to handle this.

private function wordWrapByWidth($font, $fontSize, $text, $wrapWidth)
{
	 $totalArray = array();
	 $wordsArray = explode(' ', $text);
	 $wordsMax = count($wordsArray);

	 //Reinsert spaces to each string for width and calculate size
	 for ($i=0; $i<$wordsMax; $i++) {
               $wordsArray[$i] = $wordsArray[$i] . ' ';
               $wordWidth = imagettfbbox($fontSize, 0, $font, $wordsArray[$i]);
               $totalArray[$i] = array('word' => $wordsArray[$i], 'width' => $wordWidth[2]);
	  }

		$formattedText = $this->wrapLines($totalArray, $wrapWidth);
		return $formattedText;
}
	private function wrapLines($words, $wrapWidth)
	{
		$lineWidth = 0;
		$wordArray = array();
		while ($word = array_shift($words)) {
			//if (There is a word whose length is longer than the actual wrap, bust it up as many times as needed) {
			//	
			//}
			$lineWidth += $word['width'];
			if ($lineWidth > $wrapWidth) {
				while ($wordContainer = array_shift($wordArray)) {
					$line .= $wordContainer['word'];
				}
				$wordArray[] = $word;
				$lineWidth = 0;
				$text[] = $line.PHP_EOL;
				$line = null;
			} else {
				$wordArray[] = $word;
				//If a selected word contains a line break, break and start over
				if(preg_match("/[\r|\n]+/", $word['word'])) {
					while ($wordContainer = array_shift($wordArray)) {
						$line .= $wordContainer['word'];
					}
					$lineWidth = 0;
					$text[] = $line;
					$line = null;
				}
			}
		}

		//Include last line that did not overflow
		if (!empty($wordArray)) {
			while ($wordContainer = array_shift($wordArray)) {
				$line .= $wordContainer['word'];
			}
			$text[] = rtrim($line);
		}
		return $text;
	}