Imagettftext - incorrect line spacing - php

I have an problem with PHP function imagettftext. I have code for generating card images from database with text informations. And with some cards I have problem - words are written over each other (like here).
My code looks like this (font size changes depending on the length of the text)
$length = strlen($cardInfo->description);
if ($length < 15) {
$divide = 15;
$fontSize = 16;
$lineHeight = 25;
$startPos = 220;
} else if ($length < 70) {
$divide = 25;
$fontSize = 12;
$lineHeight = 18;
$startPos = 210;
} else if ($length < 110) {
$divide = 28;
$fontSize = 10;
$lineHeight = 14;
$startPos = 210;
} else {
$divide = 38;
$fontSize = 8;
$lineHeight = 13;
$startPos = 210;
}
$description = wordwrap($cardInfo->description, $divide, ">>>");
$lines = explode(">>>", $description);
$count = 0;
foreach ($lines as $line) {
$position = $count * $lineHeight;
$count++;
imagettftext($image, $fontSize, 0, 28, ($startPos + $position), $black, $font, $line);
}
and the text in the database looks like this:
Oblehací stroj
Imunita vůči střelám /Tato jednotka je imunní vůči střeleckým zraněním/
Other problem is with the line wrapping: here. I don't know why the word "jídlo" is on the next line.
Thank you for any answers!

Long time ago, I have written a quite complex class to archive a similar task.
I don't have this code anymore, but the steps are fairly simple.
First: Don't rely on the calculations, php does on rare fonts.
Php's wordwrap-function is senseless here, because you deal with a charset-width (e.g. tracking) unknown to php. Wordwrap assumes, that all characters have the same char-width.
So, you have to build your own wordwrap-function using imagettfbbox. Then, you'll have to determine the size of the lowercase "x"-letter and the uppercase "X"-letter. These letters are the norm to calculate your own line-height/line-spacing. I also recommend you to manually separate words, since PHP does not always recognize the white-space-width correctly.
Hope this could help you...

This works for me. You need arial.ttf and http://dark-project.cz/CardDatabase/cards/lehky_katapult.png.
class Test_Canvas {
protected $res=null;
public function __construct($width, $height) {
$this->res = imagecreatetruecolor($width, $height);
imagealphablending($this->res, true);
imagesavealpha($this->res, true);
imagefill($this->res, 0, 0, imagecolorallocatealpha($this->res, 0, 0, 0, 127));
}
public function copyTo(Test_Canvas $canvas, $x, $y) {
imagecopyresampled($canvas->res, $this->res, $x, $y, 0, 0, $this->getWidth(), $this->getHeight(), $this->getWidth(), $this->getHeight());
}
public function getWidth() {
return imagesx($this->res);
}
public function getHeight() {
return imagesy($this->res);
}
public function saveAsPNG() {
imagepng($this->res);
}
}
class Test_Canvas_Image_PNG extends Test_Canvas {
public function __construct($filename) {
$res = imagecreatefrompng($filename);
$w = imagesx($res);
$h = imagesy($res);
parent::__construct($w, $h);
imagecopymerge($this->res, $res, 0, 0, 0, 0, $w, $h, 100);
}
}
class Test_Canvas_Textarea extends Test_Canvas {
private $text;
private $fontsize;
private $fontfile;
public function __construct($width, $height, $text, $fontsize, $fontfile) {
parent::__construct($width, $height);
$this->text = $text;
$this->fontsize = $fontsize;
$this->fontfile = $fontfile;
$this->removeDuplicateWhitespace();
$this->formatText();
$this->applyText();
}
private function removeDuplicateWhitespace() {
$this->text = preg_replace('/[ \t]+/', ' ', $this->text);
}
private function formatText() {
$lines = explode("\n", $this->text);
$res = array();
foreach ($lines as $line) {
$res[] = $this->insertAdditionalLinebreaks($line);
}
$this->text = join("\n", $res);
}
private function insertAdditionalLinebreaks($line) {
$words = $this->splitWords($line);
$res = array();
$line = "";
while(count($words)) {
$word = array_shift($words);
$testLine = "{$line} {$word}";
$width = $this->getTextWidth($testLine);
if($width > $this->getWidth()) {
$res[] = $line;
$line = $word;
} elseif(!count($words)) {
$res[] = $testLine;
} else {
$line = $testLine;
}
}
return join("\n", $res);
}
private function getTextWidth($text) {
$boundaries = imagettfbbox($this->fontsize, 0, $this->fontfile, $text);
$x1 = min($boundaries[0], $boundaries[6]);
$x2 = max($boundaries[2], $boundaries[4]);
return $x2 - $x1;
}
private function splitWords($text) {
return explode(' ', $text);
}
private function applyText() {
$lines = explode("\n", $this->text);
foreach($lines as $lineNo => $line) {
imagettftext($this->res, $this->fontsize, 0, 0, ($lineNo + 1) * ($this->fontsize + 5), imagecolorallocate($this->res, 0, 0, 0), $this->fontfile, $line);
}
}
}
$rootPath = dirname(__FILE__).'/';
$imageFilename = "{$rootPath}test.png";
$description = "Oblehací stroj\nImunita vuci strelám /Tato jednotka je imunní vuci streleckým zranením/ ";
$description .= $description;
$description .= $description;
header('Content-Type: image/png');
$canvas = new Test_Canvas_Image_PNG($imageFilename);
$text = new Test_Canvas_Textarea(179, 92, $description, 9, 'arial.ttf');
$text->copyTo($canvas, 25, 193);
$canvas->saveAsPNG();

You shouldn't use such estimates for the box you'll need.
The function imagettfbbox() can give you a definite answer to the box you'll need to display the text.
http://nl3.php.net/manual/en/function.imagettfbbox.php
Hope that helps.

Related

Blank pages when trying to do captcha

Hello i am learning php now and developing website for my education. I am facing problem if i try to add captcha image. I don't know where is the problem but instead of working captcha i get blank page.
I even tried few already done captchas from github but get same problem i think the problem could be with fonts but i am not sure "ts probably my stupidity and i am doing something wrong :D" . Anyway if anyone can help me with it it would be great.
code i tried to use:
captcha.php
<?php
class captcha {
private static $captcha = "__captcha__";
public static $font;
private static $width = 70;
private static $height = 70;
private static $font_size = 40;
private static $character_width = 40;
private static function session_exists() {
return isset($_SESSION);
}
private static function set_font() {
self::$font = self::$captcha;
$AnonymousClippings ='there is inserted chars from font you can';
self::$font = tempnam(sys_get_temp_dir(), self::$captcha);
$handle = fopen(self::$font,"w+");
fwrite($handle,base64_decode($AnonymousClippings));
fclose($handle);
return self::$font;
}
private static function get_random() {
$type = rand(0,2);
switch($type) {
case 2:
$random = chr(rand(65,90));
break;
case 1:
$random = chr(rand(97,122));
break;
default:
$random = rand(0,9);
}
return $random;
}
private static function generate_code($length) {
$code = null;
for($i = 0; $i < $length; $i++) {
$code .= self::get_random();
}
if(self::session_exists()) {
$_SESSION[self::$captcha] = $code;
}
self::$width = $length * self::$character_width;
return $code;
}
private static function get_width() {
return self::$width;
}
private static function get_height() {
return self::$height;
}
public static function image() {
$length = 6;
$code = self::generate_code($length);
self::set_font();
ob_start();
$image = imagecreatetruecolor(self::get_width(),self::get_height());
$white = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image, 0, 0, self::get_width(), self::get_height(), $white);
for($dot = 0; $dot < 2000; $dot++) {
$r = rand(0,255);
$g = rand(0,255);
$b = rand(0,255);
$dot_color = imagecolorallocate($image, $r, $g, $b);
$x1 = rand(0, self::get_width());
$y1 = rand(0, self::get_height());
$x2 = $x1 + 1;
$y2 = $y1 + 1;
imageline($image, $x1, $y1, $x2, $y2, $dot_color);
}
for($start = - $length; $start < 0; $start++) {
$color = imagecolorallocate($image, rand(0,177), rand(0,177), rand(0,177));
$character = substr($code, $start, 1);
$x = ($start+6) * self::$character_width;
$y = rand(self::get_height() - 20, self::get_height() - 10);
imagettftext($image, self::$font_size, 0, $x, $y, $color, self::$font, $character);
}
imagepng($image);
imagedestroy($image);
$source = ob_get_contents();
ob_end_clean();
unlink(self::$font);
return "data:image/png;base64,".base64_encode($source);
}
public static function get_code() {
if(self::session_exists()) {
return $_SESSION[self::$captcha];
}
return rand();
}
}
index.php file
<?php
session_start();
require_once("captcha.php");
if(isset($_POST['rCaptcha'])) {
echo captcha::image();
exit;
}
else if(isset($_POST["code"])) {
if($_POST["code"] == captcha::get_code()) {
echo "Good";
}
else {
echo "Bad";
}
echo "<br/>";
}
?>
<script>
function refreshCaptcha(target) {
var req = new XMLHttpRequest();
req.open("POST", window.location, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
target.src = req.responseText;
}
}
req.send("rCaptcha=true");
}
</script>
<form method="post" autocomplete="off">
<fieldset>
<legend>PHP Captcha</legend>
<input type="text" name="code" placeholder="Captcha Code" /><br/>
<img src="<?= captcha::image() ?>" onclick="refreshCaptcha(this)"
title="click to refresh" /><br/>
<input type="submit" value="Check" /><br/>
</fieldset>
</form>
For a start add those two lines in the beginning of your index.php file (after <?php):
error_reporting(-1);
ini_set('display_errors', 'On');
Then you will see the errors produced by php. It will be much more easy to debug your code!
In this case a semicolon is missing in line 16 in your captcha.php file:
$AnonymousClippings ='there is inserted chars from font you can'

How to add a simple message by 'echo' in invoice pdf format in Magento2?

I have generated an invoice slip from magento2 sales order's invoice option and got the screenshot for the reference, see the screenshot: https://prnt.sc/tje4zn
This is the file path for invoice pdf: /vendor/magento/module-sales/Model/Order/Pdf/AbstractPdf.php and below is the file code,
<?php
namespace Magento\Sales\Model\Order\Pdf;
use Magento\Framework\App\Filesystem\DirectoryList;
/**
* Sales Order PDF abstract model
*/
abstract class AbstractPdf extends \Magento\Framework\DataObject
{
public $y;
protected $_renderers = [];
const XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID = 'sales_pdf/invoice/put_order_id';
const XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID = 'sales_pdf/shipment/put_order_id';
const XML_PATH_SALES_PDF_CREDITMEMO_PUT_ORDER_ID = 'sales_pdf/creditmemo/put_order_id';
protected $_pdf;
abstract public function getPdf();
protected $_paymentData;
protected $string;
protected $_localeDate;
protected $_scopeConfig;
protected $_mediaDirectory;
protected $_rootDirectory;
protected $_pdfConfig;
protected $_pdfTotalFactory;
protected $_pdfItemsFactory;
protected $inlineTranslation;
protected $addressRenderer;
public function __construct(
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\Stdlib\StringUtils $string,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Framework\Filesystem $filesystem,
Config $pdfConfig,
\Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
\Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
\Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
array $data = []
) {
$this->addressRenderer = $addressRenderer;
$this->_paymentData = $paymentData;
$this->_localeDate = $localeDate;
$this->string = $string;
$this->_scopeConfig = $scopeConfig;
$this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->_rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
$this->_pdfConfig = $pdfConfig;
$this->_pdfTotalFactory = $pdfTotalFactory;
$this->_pdfItemsFactory = $pdfItemsFactory;
$this->inlineTranslation = $inlineTranslation;
parent::__construct($data);
}
public function widthForStringUsingFontSize($string, $font, $fontSize)
{
$drawingString = '"libiconv"' == ICONV_IMPL ? iconv(
'UTF-8',
'UTF-16BE//IGNORE',
$string
) : #iconv(
'UTF-8',
'UTF-16BE',
$string
);
$characters = [];
for ($i = 0; $i < strlen($drawingString); $i++) {
$characters[] = ord($drawingString[$i++]) << 8 | ord($drawingString[$i]);
}
$glyphs = $font->glyphNumbersForCharacters($characters);
$widths = $font->widthsForGlyphs($glyphs);
$stringWidth = array_sum($widths) / $font->getUnitsPerEm() * $fontSize;
return $stringWidth;
}
public function getAlignRight($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize, $padding = 5)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + $columnWidth - $width - $padding;
}
public function getAlignCenter($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + round(($columnWidth - $width) / 2);
}
protected function insertLogo(&$page, $store = null)
{
$this->y = $this->y ? $this->y : 815;
$image = $this->_scopeConfig->getValue(
'sales/identity/logo',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$store
);
if ($image) {
$imagePath = '/sales/store/logo/' . $image;
if ($this->_mediaDirectory->isFile($imagePath)) {
$image = \Zend_Pdf_Image::imageWithPath($this->_mediaDirectory->getAbsolutePath($imagePath));
$top = 830;
//top border of the page
$widthLimit = 270;
//half of the page width
$heightLimit = 270;
//assuming the image is not a "skyscraper"
$width = $image->getPixelWidth();
$height = $image->getPixelHeight();
//preserving aspect ratio (proportions)
$ratio = $width / $height;
if ($ratio > 1 && $width > $widthLimit) {
$width = $widthLimit;
$height = $width / $ratio;
} elseif ($ratio < 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $height * $ratio;
} elseif ($ratio == 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $widthLimit;
}
$y1 = $top - $height;
$y2 = $top;
$x1 = 25;
$x2 = $x1 + $width;
//coordinates after transformation are rounded by Zend
$page->drawImage($image, $x1, $y1, $x2, $y2);
$this->y = $y1 - 10;
}
}
}
protected function _formatAddress($address)
{
$return = [];
foreach (explode('|', $address) as $str) {
foreach ($this->string->split($str, 45, true, true) as $part) {
if (empty($part)) {
continue;
}
$return[] = $part;
}
}
return $return;
}
protected function _calcAddressHeight($address)
{
$y = 0;
foreach ($address as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 55, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$y += 15;
}
}
}
return $y;
}
protected function insertOrder(&$page, $obj, $putOrderId = true)
{
if ($obj instanceof \Magento\Sales\Model\Order) {
$shipment = null;
$order = $obj;
} elseif ($obj instanceof \Magento\Sales\Model\Order\Shipment) {
$shipment = $obj;
$order = $shipment->getOrder();
}
$this->y = $this->y ? $this->y : 815;
$top = $this->y;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->drawRectangle(25, $top, 570, $top - 55);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->setDocHeaderCoordinates([25, $top, 570, $top - 55]);
$this->_setFontRegular($page, 10);
if ($putOrderId) {
$page->drawText(__('Order No # ') . $order->getRealOrderId(), 35, $top -= 30, 'UTF-8');
$top +=15;
}
$top -=30;
$page->drawText(
__('Order Date: ') .
$this->_localeDate->formatDate(
$this->_localeDate->scopeDate(
$order->getStore(),
$order->getCreatedAt(),
true
),
\IntlDateFormatter::MEDIUM,
false
),
35,
$top,
'UTF-8'
);
$top -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $top, 275, $top - 25);
$page->drawRectangle(275, $top, 570, $top - 25);
/* Calculate blocks info */
/* Billing Address */
$billingAddress = $this->_formatAddress($this->addressRenderer->format($order->getBillingAddress(), 'pdf'));
/* Payment */
$paymentInfo = $this->_paymentData->getInfoBlock($order->getPayment())->setIsSecureMode(true)->toPdf();
$paymentInfo = htmlspecialchars_decode($paymentInfo, ENT_QUOTES);
$payment = explode('{{pdf_row_separator}}', $paymentInfo);
foreach ($payment as $key => $value) {
if (strip_tags(trim($value)) == '') {
unset($payment[$key]);
}
}
reset($payment);
/* Shipping Address and Method */
if (!$order->getIsVirtual()) {
/* Shipping Address */
$shippingAddress = $this->_formatAddress($this->addressRenderer->format($order->getShippingAddress(), 'pdf'));
$shippingMethod = $order->getShippingDescription();
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontBold($page, 12);
$page->drawText(__('Billed to:'), 35, $top - 15, 'UTF-8');
if (!$order->getIsVirtual()) {
$page->drawText(__('Shipped/Delivery to:'), 285, $top - 15, 'UTF-8');
} else {
$page->drawText(__('Payment Method:'), 285, $top - 15, 'UTF-8');
}
$addressesHeight = $this->_calcAddressHeight($billingAddress);
if (isset($shippingAddress)) {
$addressesHeight = max($addressesHeight, $this->_calcAddressHeight($shippingAddress));
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$page->drawRectangle(25, $top - 25, 570, $top - 33 - $addressesHeight);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontRegular($page, 10);
$this->y = $top - 40;
$addressesStartY = $this->y;
foreach ($billingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 35, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = $this->y;
if (!$order->getIsVirtual()) {
$this->y = $addressesStartY;
foreach ($shippingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = min($addressesEndY, $this->y);
$this->y = $addressesEndY;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 275, $this->y - 25);
$page->drawRectangle(275, $this->y, 570, $this->y - 25);
$this->y -= 15;
$this->_setFontBold($page, 12);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$page->drawText(__('Payment Method'), 35, $this->y, 'UTF-8');
$page->drawText(__('Shipping Method:'), 285, $this->y, 'UTF-8');
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$paymentLeft = 35;
$yPayments = $this->y - 15;
} else {
$yPayments = $addressesStartY;
$paymentLeft = 285;
}
foreach ($payment as $value) {
if (trim($value) != '') {
//Printing "Payment Method" lines
$value = preg_replace('/<br[^>]*>/i', "\n", $value);
foreach ($this->string->split($value, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), $paymentLeft, $yPayments, 'UTF-8');
$yPayments -= 15;
}
}
}
if ($order->getIsVirtual()) {
// replacement of Shipments-Payments rectangle block
$yPayments = min($addressesEndY, $yPayments);
$page->drawLine(25, $top - 25, 25, $yPayments);
$page->drawLine(570, $top - 25, 570, $yPayments);
$page->drawLine(25, $yPayments, 570, $yPayments);
$this->y = $yPayments - 15;
} else {
$topMargin = 15;
$methodStartY = $this->y;
$this->y -= 15;
foreach ($this->string->split($shippingMethod, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
$yShipments = $this->y;
$totalShippingChargesText = "(" . __(
'Total Shipping Charges'
) . " " . $order->formatPriceTxt(
$order->getShippingAmount()
) . ")";
$page->drawText($totalShippingChargesText, 285, $yShipments - $topMargin, 'UTF-8');
$yShipments -= $topMargin + 10;
$tracks = [];
if ($shipment) {
$tracks = $shipment->getAllTracks();
}
if (count($tracks)) {
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
$page->drawLine(400, $yShipments, 400, $yShipments - 10);
//$page->drawLine(510, $yShipments, 510, $yShipments - 10);
$this->_setFontRegular($page, 9);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
//$page->drawText(__('Carrier'), 290, $yShipments - 7 , 'UTF-8');
$page->drawText(__('Title'), 290, $yShipments - 7, 'UTF-8');
$page->drawText(__('Number'), 410, $yShipments - 7, 'UTF-8');
$yShipments -= 20;
$this->_setFontRegular($page, 8);
foreach ($tracks as $track) {
$maxTitleLen = 45;
$endOfTitle = strlen($track->getTitle()) > $maxTitleLen ? '...' : '';
$truncatedTitle = substr($track->getTitle(), 0, $maxTitleLen) . $endOfTitle;
$page->drawText($truncatedTitle, 292, $yShipments, 'UTF-8');
$page->drawText($track->getNumber(), 410, $yShipments, 'UTF-8');
$yShipments -= $topMargin - 5;
}
} else {
$yShipments -= $topMargin - 5;
}
$currentY = min($yPayments, $yShipments);
$page->drawLine(25, $methodStartY, 25, $currentY);
$page->drawLine(25, $currentY, 570, $currentY);
$page->drawLine(570, $currentY, 570, $methodStartY);
$this->y = $currentY;
$this->y -= 15;
}
}
public function insertDocumentNumber(\Zend_Pdf_Page $page, $text)
{
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$docHeader = $this->getDocHeaderCoordinates();
$page->drawText($text, 35, $docHeader[1] - 15, 'UTF-8');
}
protected function _sortTotalsList($a, $b)
{
if (!isset($a['sort_order']) || !isset($b['sort_order'])) {
return 0;
}
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return $a['sort_order'] > $b['sort_order'] ? 1 : -1;
}
protected function _getTotalsList()
{
$totals = $this->_pdfConfig->getTotals();
usort($totals, [$this, '_sortTotalsList']);
$totalModels = [];
foreach ($totals as $totalInfo) {
$class = empty($totalInfo['model']) ? null : $totalInfo['model'];
$totalModel = $this->_pdfTotalFactory->create($class);
$totalModel->setData($totalInfo);
$totalModels[] = $totalModel;
}
return $totalModels;
}
protected function insertTotals($page, $source)
{
$order = $source->getOrder();
$totals = $this->_getTotalsList();
$lineBlock = ['lines' => [], 'height' => 15];
foreach ($totals as $total) {
$total->setOrder($order)->setSource($source);
if ($total->canDisplay()) {
$total->setFontSize(10);
foreach ($total->getTotalsForDisplay() as $totalData) {
$lineBlock['lines'][] = [
[
'text' => $totalData['label'],
'feed' => 475,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold',
],
[
'text' => $totalData['amount'],
'feed' => 565,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold'
],
];
}
}
}
$this->y -= 20;
$page = $this->drawLineBlocks($page, [$lineBlock]);
return $page;
}
protected function _parseItemDescription($item)
{
$matches = [];
$description = $item->getDescription();
if (preg_match_all('/<li.*?>(.*?)<\/li>/i', $description, $matches)) {
return $matches[1];
}
return [$description];
}
protected function _beforeGetPdf()
{
$this->inlineTranslation->suspend();
}
protected function _afterGetPdf()
{
$this->inlineTranslation->resume();
}
protected function _formatOptionValue($value, $order)
{
$resultValue = '';
if (is_array($value)) {
if (isset($value['qty'])) {
$resultValue .= sprintf('%d', $value['qty']) . ' x ';
}
$resultValue .= $value['title'];
if (isset($value['price'])) {
$resultValue .= " " . $order->formatPrice($value['price']);
}
return $resultValue;
} else {
return $value;
}
}
protected function _initRenderer($type)
{
$rendererData = $this->_pdfConfig->getRenderersPerProduct($type);
foreach ($rendererData as $productType => $renderer) {
$this->_renderers[$productType] = ['model' => $renderer, 'renderer' => null];
}
}
protected function _getRenderer($type)
{
if (!isset($this->_renderers[$type])) {
$type = 'default';
}
if (!isset($this->_renderers[$type])) {
throw new \Magento\Framework\Exception\LocalizedException(__('We found an invalid renderer model.'));
}
if ($this->_renderers[$type]['renderer'] === null) {
$this->_renderers[$type]['renderer'] = $this->_pdfItemsFactory->get($this->_renderers[$type]['model']);
}
return $this->_renderers[$type]['renderer'];
}
public function getRenderer($type)
{
return $this->_getRenderer($type);
}
protected function _drawItem(\Magento\Framework\DataObject $item, \Zend_Pdf_Page $page, \Magento\Sales\Model\Order $order)
{
$type = $item->getOrderItem()->getProductType();
$renderer = $this->_getRenderer($type);
$renderer->setOrder($order);
$renderer->setItem($item);
$renderer->setPdf($this);
$renderer->setPage($page);
$renderer->setRenderedModel($this);
$renderer->draw();
return $renderer->getPage();
}
protected function _setFontRegular($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerif.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontBold($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifBold.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontItalic($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifItalic.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setPdf(\Zend_Pdf $pdf)
{
$this->_pdf = $pdf;
return $this;
}
protected function _getPdf()
{
if (!$this->_pdf instanceof \Zend_Pdf) {
throw new \Magento\Framework\Exception\LocalizedException(__('Please define the PDF object before using.'));
}
return $this->_pdf;
}
public function newPage(array $settings = [])
{
$pageSize = !empty($settings['page_size']) ? $settings['page_size'] : \Zend_Pdf_Page::SIZE_A4;
$page = $this->_getPdf()->newPage($pageSize);
$this->_getPdf()->pages[] = $page;
$this->y = 800;
return $page;
}
public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSettings = [])
{
foreach ($draw as $itemsProp) {
if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
throw new \Magento\Framework\Exception\LocalizedException(
__('We don\'t recognize the draw line data. Please define the "lines" array.')
);
}
$lines = $itemsProp['lines'];
$height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
if (empty($itemsProp['shift'])) {
$shift = 0;
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$top = 0;
foreach ($column['text'] as $part) {
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$shift += $maxHeight;
}
$itemsProp['shift'] = $shift;
}
if ($this->y - $itemsProp['shift'] < 15) {
$page = $this->newPage($pageSettings);
}
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
$top = 0;
foreach ($column['text'] as $part) {
if ($this->y - $lineSpacing < 15) {
$page = $this->newPage($pageSettings);
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
}
$feed = $column['feed'];
$textAlign = empty($column['align']) ? 'left' : $column['align'];
$width = empty($column['width']) ? 0 : $column['width'];
switch ($textAlign) {
case 'right':
if ($width) {
$feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
} else {
$feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
}
break;
case 'center':
if ($width) {
$feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
}
break;
default:
break;
}
$page->drawText($part, $feed, $this->y - $top, 'UTF-8');
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$this->y -= $maxHeight;
}
}
return $page;
}
}
I want to echo simple text message in the end of the file like <?php echo "NOTE: This is not a GST invoice. This is a packing slip only."; ?>
Please help how I can add this message to pdf invoice format as I have also mentioned in the screenshot above.
Many Thanks in Advance.
Assuming you have a custom MyCompany_Invoice module:
Put following content into the MyCompany/Invoice/etc/di.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Sales\Model\Order\Pdf\Invoice" type="MyCompany\Invoice\Model\Order\Pdf\InvoicePdf"/>
</config>
Now create MyCompany\Invoice\Model\Order\Pdf\InvoicePdf.php:
<?php
namespace MyCompany\Invoice\Model\Order\Pdf;
use \Magento\Sales\Model\Order\Pdf\Invoice;
class InvoicePdf extends Invoice
{
/**
* We only need to override the getPdf of Invoice,
* most of this method is copied directly from parent class
*
* #param array $invoices
* #return \Zend_Pdf
*/
public function getPdf($invoices = []) {
$this->_beforeGetPdf();
$this->_initRenderer('invoice');
$pdf = new \Zend_Pdf();
$this->_setPdf($pdf);
$style = new \Zend_Pdf_Style();
$this->_setFontBold($style, 10);
foreach ($invoices as $invoice) {
if ($invoice->getStoreId()) {
$this->_localeResolver->emulate($invoice->getStoreId());
$this->_storeManager->setCurrentStore($invoice->getStoreId());
}
$page = $this->newPage();
$order = $invoice->getOrder();
/* Add image */
$this->insertLogo($page, $invoice->getStore());
/* Add address */
$this->insertAddress($page, $invoice->getStore());
/* Add head */
$this->insertOrder(
$page,
$order,
$this->_scopeConfig->isSetFlag(
self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$order->getStoreId()
)
);
/* Add document text and number */
$this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
/* Add table */
$this->_drawHeader($page);
/* Add body */
foreach ($invoice->getAllItems() as $item) {
if ($item->getOrderItem()->getParentItem()) {
continue;
}
/* Draw item */
$this->_drawItem($item, $page, $order);
$page = end($pdf->pages);
}
/* Add totals */
$this->insertTotals($page, $invoice);
if ($invoice->getStoreId()) {
$this->_localeResolver->revert();
}
// draw custom notice
$this->drawNotice($page);
}
$this->_afterGetPdf();
return $pdf;
}
/**
* draw notice below content
*
* #param \Zend_Pdf_Page $page
*/
protected function drawNotice(\Zend_Pdf_Page $page) {
$iFontSize = 10; // font size
$iColumnWidth = 520; // whole page width
$iWidthBorder = 260; // half page width
$sNotice = "NOTE: This is not a GST invoice. This is a packing slip only."; // your message
$iXCoordinateText = 30;
$sEncoding = 'UTF-8';
$this->y -= 10; // move down on page
try {
$oFont = $this->_setFontRegular($page, $iFontSize);
$iXCoordinateText = $this->getAlignCenter($sNotice, $iXCoordinateText, $iColumnWidth, $oFont, $iFontSize); // center text coordinate
$page->setLineColor(new \Zend_Pdf_Color_Rgb(1, 0, 0)); // red lines
$iXCoordinateBorder = $iXCoordinateText - 10; // border is wider than text
// draw top border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw text
$this->y -= 15; // further down
$page->drawText($sNotice, $iXCoordinateText, $this->y, $sEncoding);
$this->y -= 10; // further down
// draw bottom border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw left border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder, $this->y + 25 /* back to first line */);
// draw right border
$page->drawLine($iXCoordinateBorder + $iWidthBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y + 25 /* back to first line */);
$this->y -= 10;
} catch (\Exception $exception) {
// handle
}
}
/**
* Draw header for item table
*
* #param \Zend_Pdf_Page $page
* #return void
*/
protected function _drawHeader(\Zend_Pdf_Page $page)
{
/* Add table head */
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 570, $this->y - 15);
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));
//columns headers
$lines[0][] = ['text' => __('Products'), 'feed' => 35];
$lines[0][] = ['text' => __('SKU'), 'feed' => 290, 'align' => 'right'];
// custom column
$lines[0][] = ['text' => __('HSN'), 'feed' => 290, 'align' => 'right'];
$lines[0][] = ['text' => __('Qty'), 'feed' => 435, 'align' => 'right'];
$lines[0][] = ['text' => __('Price'), 'feed' => 360, 'align' => 'right'];
$lines[0][] = ['text' => __('Tax'), 'feed' => 495, 'align' => 'right'];
$lines[0][] = ['text' => __('Subtotal'), 'feed' => 565, 'align' => 'right'];
$lineBlock = ['lines' => $lines, 'height' => 5];
$this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->y -= 20;
}
}
Let me know if you need the content of other files required for a module to work or if anything is not working for you as expected.
I did not try to change the text color yet, so you might need to find a solution for that by yourself.
EDIT: custom header added

Keep PNG transparency when extracting images from SWF with PHP

I am trying to extract images from SWF. The following code works, but when extracting png images, the background becomes opaque. Any help would be great; this is what I have:
class SWFextractImages {
private $swf;
private $jpegTables;
private $shipID;
public function doExtractImages($shipID, $b) {
$this->shipID = $shipID;
$this->swf = new SWF($b);
$this->jpegTables = '';
foreach ($this->swf->tags as $tag) {
if($tag['type']==6){
if($this->defineBits($tag)){
continue;
}
}
}
}
private function defineBits($tag) {
$ret = $this->swf->parseTag($tag);
$imageData = $ret['imageData'];
if (strlen($this->jpegTables) > 0) {
$imageData = substr($this->jpegTables, 0, -2) . substr($imageData, 2);
}
if($ret['characterId']==5){
$filename = sprintf('images/'.$this->shipID.'.jpg', $ret['characterId']);
file_put_contents($filename, $imageData);
return true;
}
}
}
Not sure if this will help, but this extracts other data from SWF file too. Here's the source code.
The function defineBits is only for jpg images
For png try this:
private function defineBitsLossless($tag) {
$ret = $this->swf->parseTag($tag);
$bitmapFormat = $ret['bitmapFormat'];
$bitmapWidth = $ret['bitmapWidth'];
$bitmapHeight = $ret['bitmapHeight'];
$pixelData = $ret['pixelData'];
$img = imageCreateTrueColor($bitmapWidth, $bitmapHeight);
if ($bitmapFormat == 3) {
$colorTable = $ret['colorTable'];
// Construct the colormap
$colors = array();
$i = 0;
$len = strlen($colorTable);
while ($i < $len) {
$red = ord($colorTable[$i++]);
$green = ord($colorTable[$i++]);
$blue = ord($colorTable[$i++]);
$colors[] = imageColorAllocate($img, $red, $green, $blue);
}
$bytesPerRow = $this->alignTo4bytes($bitmapWidth * 1); // 1 byte per sample
// Construct the image
for ($row = 0; $row < $bitmapHeight; $row++) {
$off = $bytesPerRow * $row;
for ($col = 0; $col < $bitmapWidth; $col++) {
$idx = ord($pixelData[$off++]);
imageSetPixel($img, $col, $row, $colors[$idx]);
}
}
} else if ($bitmapFormat == 4) {
$bytesPerRow = $this->alignTo4bytes($bitmapWidth * 2); // 2 bytes per sample
// Construct the image
for ($row = 0; $row < $bitmapHeight; $row++) {
$off = $bytesPerRow * $row;
for ($col = 0; $col < $bitmapWidth; $col++) {
$lo = ord($pixelData[$off++]);
$hi = ord($pixelData[$off++]);
$rgb = $lo + $hi * 256;
$red = ($rgb >> 10) & 0x1f; // 5 bits
$green = ($rgb >> 5) & 0x1f; // 5 bits
$blue = ($rgb) & 0x1f; // 5 bits
$color = imageColorAllocate($img, $red, $green, $blue);
imageSetPixel($img, $col, $row, $color);
}
}
} else if ($bitmapFormat == 5) {
$bytesPerRow = $this->alignTo4bytes($bitmapWidth * 4); // 4 bytes per sample
// Construct the image
for ($row = 0; $row < $bitmapHeight; $row++) {
$off = $bytesPerRow * $row;
for ($col = 0; $col < $bitmapWidth; $col++) {
$off++; // Reserved
$red = ord($pixelData[$off++]);
$green = ord($pixelData[$off++]);
$blue = ord($pixelData[$off++]);
$color = imageColorAllocate($img, $red, $green, $blue);
imageSetPixel($img, $col, $row, $color);
}
}
}
imagePNG($img, sprintf('images/img_%d.png', $ret['characterId']));
imageDestroy($img);
}
You can read more, understand more and use more from here

captcha modify six letters

i have following captcha code:
<?php
class CaptchaView extends View
{
private $fontsDir = 'captcha_resources/fonts/';
private $backgroundsDir = 'captcha_resources/backgrounds/';
private static $dirCache = array();
public function render($controller)
{
$code = $controller->viewVars["code"];
/**
* The next part is orginnaly written by ted from mastercode.nl and modified for using in this mod.
**/
header("content-type:image/png");
header('Cache-control: no-cache, no-store');
$width = 100;
$height = 30;
$img = imagecreatefrompng(self::backgroundImage());
// add noise
for ($i = 0; $i < 1; $i++) {
$horizontal_progress = 0;
$vertical_pos = rand(1, $height / 2);
do {
$horizontal_step_size = floor(rand(1, $width / 5));
imageline($img, $horizontal_progress, $vertical_pos, ($horizontal_progress += $horizontal_step_size), ($vertical_pos = rand(1, $height)), self::color("tekst"));
} while ($horizontal_progress < $width);
}
$background = imagecolorallocate($img, self::color("bg"), self::color("bg"), self::color("bg"));
for ($g = 0; $g < 30; $g++) {
$t = rand(10, 20);
$t = $t[0];
$ypos = rand(0, $height);
$xpos = rand(0, $width);
$kleur = imagecolorallocate($img, self::color("bgtekst"), self::color("bgtekst"), self::color("bgtekst"));
imagettftext($img, self::size(), self::move(), $xpos, $ypos, $kleur, self::font(), $t);
}
$stukje = $width / (strlen($code) + 3) + 5;
for ($j = 0; $j < strlen($code); $j++) {
$tek = $code[$j];
$ypos = rand(23, 27);
$xpos = $stukje * ($j + 1) - 5;
$color2 = imagecolorallocate($img, self::color("tekst"), self::color("tekst"), self::color("tekst"));
imagettftext($img, self::size(), self::move(), $xpos, $ypos, $color2, self::font(), $tek);
}
imagepng($img);
imagedestroy($img);
}
/**
* Some functions :)
* Also orginally written by mastercode.nl
**/
/**
* Function to create a random color
* #auteur mastercode.nl
* #param $type string Mode for the color
* #return int
**/
private static function color($type)
{
switch ($type) {
case "bg":
$color = rand(224, 255);
break;
case "tekst":
$color = rand(0, 127);
break;
case "bgtekst":
$color = rand(200, 224);
break;
default:
$color = rand(0, 255);
break;
}
return $color;
}
/**
* Function to ranom the size
* #auteur mastercode.nl
* #return int
**/
private static function size()
{
return rand(18, 22);
}
/**
* Function to random the posistion
* #auteur mastercode.nl
* #return int
**/
private static function move()
{
return rand(-22, 22);
}
/**
* Function to return a ttf file from fonts map
* #auteur mastercode.nl
* #return string
**/
function randomFileByExt($dir, $ext)
{
$f = opendir($dir);
if (empty(self::$dirCache[$dir])) {
$ar = array();
while (($file = #readdir($f)) !== false) {
if (!in_array($file, array('.', '..')) && substr_compare($file, $ext, -strlen($ext)) == 0) {
$ar[] = $file;
}
}
self::$dirCache[$dir] = $ar;
} else {
$ar = self::$dirCache[$dir];
}
if (count($ar)) {
$i = rand(0, (count($ar) - 1));
return $dir . $ar[$i];
}
}
private function backgroundImage()
{
return self::randomFileByExt(Config::get("VIEWS_PATH") . $this->backgroundsDir, ".png");
}
private function font()
{
return self::randomFileByExt(Config::get("VIEWS_PATH") . $this->fontsDir, ".ttf");
}
}
actually it display 4 letters with a disturbed background
i want block some spam bot them i think to modify code to increase security increasing number of letters
can you tell me how to modify it to display 6 letters instead of 4?
1) Best solution is to implement existing Captcha like reCaptcha or so..
docs : http://code.google.com/intl/en_EN/apis/recaptcha/intro.html
PHP : http://code.google.com/intl/en_EN/apis/recaptcha/docs/php.html
2) To modify your code to push 6 instead of 4 letters edit part of code like this:
$stukje = $width / (strlen($code) + 5) + 5; //instead of "+3) +5;"
should do the trick, but I can't test it, since I don't know in which mod it was used (what CMS, PHP Framework,...)

Why is this code to center text on a PDF using the PHP Zend_Pdf Library not working?

I'm attempting to dynamically create PDF documents on the server and send them to the client using the Zend_Pdf library. All text on the PDF needs to be center aligned to the page, which will be letter-sized, landscape. Using functions that I have found multiple times on various sites, I'm having a problem - the center justification is off. All text is appearing way too far to the left. Here is my code:
<?
require('Zend/Pdf.php');
$font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA);
$pdf = new Zend_Pdf();
// Create a new page, add to page listing
$pdfPage = $pdf->newPage(Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE);
$pdf->pages[] = $pdfPage;
// Add certify that
$pdfPage->setFont($font, 15.75);
drawCenteredText($pdfPage, "THIS IS TO CERTIFY THAT", 378);
// Add name
$pdfPage->setFont($font, 39.75);
drawCenteredText($pdfPage, "Example Name", 314.25);
// Headers
header("Content-type: application/pdf");
header("Content-Disposition: inline; filename=\"cert.pdf\"");
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
// Output PDF
echo $pdf->render();
function drawCenteredText($page, $text, $bottom) {
$text_width = getTextWidth($text, $page->getFont(), $page->getFontSize());
$box_width = $page->getWidth();
$left = ($box_width - $text_width) / 2;
$page->drawText($text, $left, $bottom, 'UTF-8');
}
function getTextWidth($text, $font, $font_size) {
$drawing_text = iconv('', 'UTF-8', $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;
}
?>
...and this is the result.
In case anyone else runs into a similar problem, the issue is here:
function getTextWidth($text, $font, $font_size) {
$drawing_text = iconv('', 'UTF-8', $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;
}
When building the characters array, the characters are being loaded incorrectly - 8 bits, not 16.
$characters[] = ord ($drawing_text[$i]);
This solves the problem, and correctly calculates text width.
try to use this function:
/**
* Return length of generated string in points
*
* #param string $text
* #param Zend_Pdf_Resource_Font|Zend_Pdf_Page $font
* #param int $fontSize
* #return double
*/
public static function getTextWidth($text, $resource, $fontSize = null/*, $encoding = null*/) {
//if( $encoding == null ) $encoding = 'UTF-8';
if( $resource instanceof Zend_Pdf_Page ){
$font = $resource->getFont();
$fontSize = $resource->getFontSize();
}elseif( $resource instanceof Zend_Pdf_Resource_Font ){
$font = $resource;
if( $fontSize === null ) throw new Exception('The fontsize is unknown');
}
if( !$font instanceof Zend_Pdf_Resource_Font ){
throw new Exception('Invalid resource passed');
}
$drawingText = $text;//iconv ( '', $encoding, $text );
$characters = array ();
for($i = 0; $i < strlen ( $drawingText ); $i ++) {
$characters [] = ord ( $drawingText [$i] );
}
$glyphs = $font->glyphNumbersForCharacters ( $characters );
$widths = $font->widthsForGlyphs ( $glyphs );
$textWidth = (array_sum ( $widths ) / $font->getUnitsPerEm ()) * $fontSize;
return $textWidth;
}
and call it on your render function, like:
if ($this->getAlign() == self::TEXT_ALIGN_CENTER)
{
$x = ($currentPage->getWidth() - $this->getTextWidth($text, $currentPage)) / 2;
}
...
$currentPage->drawText($text, $x, $y, ...);
If there is anyone looking for solution to Latin american characters like ó,á,é this worked for me
try {
$drawing_text = iconv('UTF-8', 'UTF-8', $text);
$characters = array();
for ($i = 0; $i < strlen($drawing_text); $i++) {
$characters[] = ord ($drawing_text[$i]);
}
$glyphs = $font->glyphNumbersForCharacters($characters);
$widths = $font->widthsForGlyphs($glyphs);
$text_width = (array_sum($widths) / $font->getUnitsPerEm()) * $font_size;
return $text_width;
} catch (\Exception $e) {
//echo "$e";
}

Categories