2

When I print invoice of arabic language order, I am getting incorrect characters in PDF file as per below image. Any solution for this ? enter image description here

1

It's not only Arabic, but also all other double-byte characters. There is no silver bullet for solving this issue, because Zend Pdf cannot generate PDF without embedding true type font (and Magento uses single byte font by default).

I always use my custom extension for changing PDF font file, but it uses overriding _setFont(Regular|Bold|Italic) methods (these are defined under Magento\Sales\Model\Order\Pdf classes).

So if you hope to change PDF font file, you have to create your custom module and override those methods.

  • I programmed one and implemented those three methods for bold, regular and italic and used Not -serief font (NotoSerif-Regular) as it is supports arabic but I got this error a:4:{i:0;s:30:"Unable to read version 4 table";i:1;s:5227:"#0 /var/www/html/magento217/vendor/magento/zendframework1/library/Zend/Pdf/Font.php(615): Zend_Pdf_Font::_extractTrueTypeFont(Object(Zend_Pdf_FileParserDataSource_File), 0) #1 /var/www/html/magento217/app/code/Rossmc/SalesPdfFonts/Model/Order/Pdf/SetFontTrait.php(39): Zend_Pdf_Font::fontWithPath('/var/www/html/m...') – Jsparo30 May 30 '18 at 14:56
0

I downloaded Fooman_PrintOrderPdf it worked fine with english language. But Arabic text was not rendered so I edited the file "PrintOrderPdf/Model/Pdf/Order.php"

I added some function to set Arabic font and fix character reverse issue

class Order extends Invoice{

/**
 * Check for Hebrew strings, if Hebrew is found the text is reversed.
 * This is because there is a bug with Zend PDF that reverses Hebrew words.
 * We are preemptively reversing them so when Zend Pdf reverses them it is actually correct the words back to normal.
 */
public function utf8HebrewStrrev($str) {
    preg_match('/\p{Arabic}/u', $str, $matches);

    if (count($matches) > 0) {
        preg_match_all('/./us', $str, $ar);
        $str = join('',array_reverse($ar[0]));
    }

    return $str;
}

/**
 * Set font as regular
 *
 * @param  \Zend_Pdf_Page $object
 * @param  int $size
 * @return \Zend_Pdf_Resource_Font
 */
protected function _setFontRegular($object, $size = 7)
{
    $font = \Zend_Pdf_Font::fontWithPath(
        $this->_rootDirectory->getAbsolutePath('lib/internal/ArabicFont/arabtype.ttf')
    );
    $object->setFont($font, $size);
    return $font;
}

/**
 * Set font as bold
 *
 * @param  \Zend_Pdf_Page $object
 * @param  int $size
 * @return \Zend_Pdf_Resource_Font
 */
protected function _setFontBold($object, $size = 7)
{
    $font = \Zend_Pdf_Font::fontWithPath(
        $this->_rootDirectory->getAbsolutePath('lib/internal/ArabicFont/arabtype.ttf')
    );
    $object->setFont($font, $size);
    return $font;
}

/**
 * Set font as italic
 *
 * @param  \Zend_Pdf_Page $object
 * @param  int $size
 * @return \Zend_Pdf_Resource_Font
 */
protected function _setFontItalic($object, $size = 7)
{
    $font = \Zend_Pdf_Font::fontWithPath(
        $this->_rootDirectory->getAbsolutePath('lib/internal/ArabicFont/arabtype.ttf')
    );
    $object->setFont($font, $size);
    return $font;
}

/**
 * Override from: \Magento\Sales\Model\Order\Pdf\AbstractPdf
 *
 * Insert order to pdf page
 *
 * @param \Zend_Pdf_Page &$page
 * @param \Magento\Sales\Model\Order $obj
 * @param bool $putOrderId
 * @return void
 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
 * @SuppressWarnings(PHPMD.NPathComplexity)
 * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
 */
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 # ') . $order->getRealOrderId(), 35, $top -= 30, 'UTF-8');
    }



    $page->drawText(
        __('Order Date: ') .
        //$orderDate,
            date("d-M-y", strtotime($order->getCreatedAt())), // keep date always in english
        35,
        $top -= 15,
        '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(__('Sold to:'), 35, $top - 15, 'UTF-8');

    if (!$order->getIsVirtual()) {
        $page->drawText(__('Ship 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) {
                // ---------- START: PdfFont Edit
                // Check for Hebrew text in billing address
                $part = $this->utf8HebrewStrrev($part);
                // ---------- END: PdfFont Edit
                $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) {
                    // ---------- START: PdfFont Edit
                    // check for Hebrew text in shipping address
                    $part = $this->utf8HebrewStrrev($part);
                    // ---------- END: PdfFont Edit
                    $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) {
                // ---------- START: PdfFont Edit
                // Check for Hebrew text in payment method
                $_value = $this->utf8HebrewStrrev($_value);
                // ---------- END: PdfFont Edit
                $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) {
            // ---------- START: PdfFont Edit
            // check for Hebrew text in Shipping methods
            $_value = $this->utf8HebrewStrrev($_value);
            // ---------- END: PdfFont Edit
            $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);

        // replacement of Shipments-Payments rectangle block
        $page->drawLine(25, $methodStartY, 25, $currentY);
        //left
        $page->drawLine(25, $currentY, 570, $currentY);
        //bottom
        $page->drawLine(570, $currentY, 570, $methodStartY);
        //right

        $this->y = $currentY;
        $this->y -= 15;
    }
}
/**
 * Return PDF document
 *
 * @param  \Magento\Sales\Model\Order[] $orders
 *
 * @return \Zend_Pdf
 */
public function getPdf($orders = [])
{
    $this->_beforeGetPdf();
    $this->_initRenderer('order');

    $pdf = new \Zend_Pdf();
    $this->_setPdf($pdf);

    foreach ($orders as $order) {
        if ($order->getStoreId()) {
            $this->_localeResolver->emulate($order->getStoreId());
            $this->_storeManager->setCurrentStore($order->getStoreId());
        }
        $page = $this->newPage();
        $this->_setFontBold($page, 10);
        $order->setOrder($order);
        /* Add image */
        $this->insertLogo($page, $order->getStore());
        /* Add address */
        $this->insertAddress($page, $order->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 table */
        $this->_drawHeader($page);
        /* Add body */
        foreach ($order->getAllItems() as $item) {
            if ($item->getParentItem()) {
                continue;
            }

            /* Keep it compatible with the invoice */
            $item->setQty($item->getQtyOrdered());
            $item->setOrderItem($item);

            /* Draw item */
            $this->_drawItem($item, $page, $order);
            $page = end($pdf->pages);
        }
        /* Add totals */
        $this->insertTotals($page, $order);
        if ($order->getStoreId()) {
            $this->_localeResolver->revert();
        }
    }
    $this->_afterGetPdf();
    return $pdf;
}

}

Also, I added the font files arabtype.ttf to lib.

Now the arabic characters show properly but words are not formed properly. The characters are shown split and not forming words properly.

Any help will be appreciated.

enter image description here

  • Hi, did you fix it ? – Jsparo30 May 27 '18 at 14:29
  • Not fixed yet. I am trying to develop new module with TCPDF library. But since I am busy with other critical tasks this one got delayed. – Abid Malik Jun 21 '18 at 14:39
  • This solution is not workout for me. using the same method but getting squares in invoice PDF. – Kartik Asodariya Jan 27 at 11:35
  • @kartik Did you add the fonts ? – Abid Malik Feb 6 at 6:55
  • @abid Even I'm trying to do the same thing. Also is it possible to change the direction from Right to left for Arabic content? – Yudi Mar 11 at 4:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.