Details
-
Type:
Improvement
-
Status:
Open
-
Priority:
Minor
-
Resolution: Unresolved
-
Affects Version/s: 1.8.4
-
Fix Version/s: None
-
Component/s: Zend_Pdf
-
Labels:None
Description
Hi,
I felt the need to subclass Zend_Pdf_Page::drawText() to add possibility to align text on right (instead of left as default behaviour) or to center it horizontally.
It would be real great to have it handled natively by ZF, it would increase a lot flexibility on pdf generation.
Below is the code used (it requires to be able to retrieve width of text to be drawn and makes use of code presented in ZF-7146).
<?php require_once 'Zend/Pdf.php'; /** * Represent an order/bill pdf */ class Library_Pdf_Base extends Zend_Pdf { /** * Align text at left of provided coordinates */ const TEXT_ALIGN_LEFT = 'left'; /** * Align text at right of provided coordinates */ const TEXT_ALIGN_RIGHT = 'right'; /** * Center-text horizontally within provided coordinates */ const TEXT_ALIGN_CENTER = 'center'; /** * Extension of basic draw-text function to allow it to vertically center text * * @param Zend_Pdf_Page $page * @param string $text * @param int $x1 * @param int $y1 * @param int $x2 * @param int $position * @param string $encoding * @return self */ public function drawText(Zend_Pdf_Page $page, $text, $x1, $y1, $x2 = null, $position = self::TEXT_ALIGN_LEFT, $encoding = null) { $bottom = $y1; // could do the same for vertical-centering switch ($position) { case self::TEXT_ALIGN_LEFT: $left = $x1; break; case self::TEXT_ALIGN_RIGHT: $text_width = $this->getTextWidth($text, $page->getFont(), $page->getFontSize()); $left = $x1 - $text_width; break; case self::TEXT_ALIGN_CENTER: if (null === $x2) { throw new Exception("Cannot center text horizontally, x2 is not provided"); } $text_width = $this->getTextWidth($text, $page->getFont(), $page->getFontSize()); $box_width = $x2 - $x1; $left = $x1 + ($box_width - $text_width) / 2; break; default: throw new Exception("Invalid position value \"$position\""); } // display multi-line text foreach (explode(PHP_EOL, $text) as $i => $line) { $page->drawText($line, $left, $bottom - $i * $page->getFontSize(), $encoding); } return $this; } /** * Return length of generated string in points * * @param string $string * @param Zend_Pdf_Resource_Font $font * @param int $font_size * @return double */ public function getTextWidth($text, Zend_Pdf_Resource_Font $font, $font_size) { $drawing_text = iconv('', 'UTF-16BE', $text); $characters = array(); for ($i = 0; $i < strlen($drawing_text); $i++) { $characters[] = (ord($drawing_text[$i++]) << 8) | ord ($drawing_text[$i]); } $glyphs = $font->glyphNumbersForCharacters($characters); $widths = $font->widthsForGlyphs($glyphs); $text_width = (array_sum($widths) / $font->getUnitsPerEm()) * $font_size; return $text_width; } }
So far it did the job for me. We could even go further and add an $y2 argument to the function to allow to center text vertically too.
This is extremely useful when drawing table cells, if we want to center our text within cell (both horizontally & vertically).
Along with ZF-7145 which extend ::drawText() to render multi-line text, it improves a lot text-drawing functionnalities of Zend_Pdf.
Regards,
Remy
normally I would have extended Zend_Pdf_Page instead of Zend_Pdf, but as stated in http://framework.zend.com/issues/browse/ZF-7144, subclasses of Zend_Pdf_Page are hard to transparently use with Zend_Pdf => as a quick fix I subclassed Zend_Pdf and thus add extra first argument to function call (Zend_Pdf_Page $page).