1

I am using tFPDF (linked below). I cannot find a way to render text right --> left for Arabic language. It renders fine but it is left to right. Below is the library I am using. I looked at source code and couldn't figure out how to render right to left.

http://www.fpdf.org/en/script/script92.php

Walter Tross
  • 12,237
  • 2
  • 40
  • 64
Chris Muench
  • 17,444
  • 70
  • 209
  • 362

3 Answers3

4

Unfortunately it would be too hard to make the tFPDF library work for Arabic. This library only supports Arabic characters in their isolated form, instead of using their initial, medial or final form when they are in an initial, medial or final position in a word. See the document “Text Layout Requirements for the Arabic Script” by the W3C.

Furthermore it does not support true bidirectionality. Have a look at the document “Unicode Bidirectional Algorithm basics”, also by the W3C.

My suggestion is to use another library. The only non-commercial PHP library supporting RTL (right-to-left) scripts that I was able to find is TCPDF. The source code is on GitHub. It's based on the fpdf library just like tFPDF.

To try it out, all you have to do is

git clone https://github.com/tecnickcom/TCPDF.git
cd TCPDF/examples
# this is an example of an RTL script:
php example_018.php > example_018.pdf
open example_018.pdf

Starting from the example files I have put together the following example for Arabic (must be placed in the examples directory):

<?php
require_once('tcpdf_include.php');
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Walter Tross');
$pdf->SetTitle('TCPDF Arabic Example');
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$lg = Array();
$lg['a_meta_charset'] = 'UTF-8';
$lg['a_meta_dir'] = 'rtl';
$lg['a_meta_language'] = 'ar'; // 'ar' for Arabic
$lg['w_page'] = 'page';
$pdf->setLanguageArray($lg);
$pdf->SetFont('dejavusans', '', 12); // several fonts in TCPDF/fonts work
$pdf->AddPage();
$txt = <<<EOD
مرحبا يا عالم
hello world
EOD;
$pdf->setRTL(true); // optional here, depends on the desired BASE direction
$pdf->Write(0, $txt, '', 0, 'C', true, 0, false, false, 0); // 'C' for centered
$pdf->Output('hello_world_in_Arabic.pdf', 'I');

This is what is rendered at the center top of the resulting PDF: "hello world" in Arabic and in English

For some reason that I don't have the time to investigate now you have to redirect the output to a file, like with example_018.pdf above, but I'm sure this can be solved. (A quick hack would be to use output buffering.)

Instead of including tcpdf_include.php, which in turn includes all that is needed and much more, you will have to find a reasonable place for what you really need and a reasonable way to include only that.

And, of course, you will have to study a bit the examples in order to put together the code that works for you.

P.S.: I have taken the translation of "hello world" from the Wikipedia entry for the قلب programming language.

Walter Tross
  • 12,237
  • 2
  • 40
  • 64
  • I removed the answer, so you can delete that part. Your last 2 examples are identical. You may correct them. You use another library and sometimes that could not be possible, for example if you are using third party code. So the most accurate answer to this question is "There is no way to achieve the OP goal using tFPDF library". So this answer is technically incorrect. – developer_hatch Mar 23 '22 at 17:36
  • @AMonadisaMonoid thanks, I removed it. The two examples were identical, but _only on Chrome_. I tried Firefox and Safari, and both showed them different. There must be a bug in Chrome that causes zero-width spaces to be ignored. – Walter Tross Mar 23 '22 at 18:03
0

use this package to reshape your arabic string

import arabic_reshaper # pip install arabic_reshaper
expression = r"^[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]"
    if (re.search(expression, yourstring) is None):
        pdf.add_font('DejaVu', '', 'DejaVuSans.ttf', uni=True)
        pdf.set_font('DejaVu', '', 10)
        arabic_string = arabic_reshaper.reshape(yourstring)
        arabic_string = arabic_string[::-1]
        w = pdf.get_string_width(arabic_string) + 6
        pdf.cell(w, 9, arabic_string, 0, 1, 'L', 0)
0

I found a much simpler solution than using a PHP-based library. And it is based on the FPDF documented recommendation. The solution is based on the Arabic reshaper-3.0.0 (as @Abdelmoumen explained) and python-bidi-0.4.2 packages.

The answer on an FPDF encoding issue here explained what you need to use a different language successfully with FPDF. I followed the instructions but for Arabic. I downloaded the Amiri font from Google Fonts and placed it in a sub-directory named Amiri under the src/fonts directory.

This is my directories setup:

src/
├── fonts
│   ├── Amiri
│   │   ├── Amiri-Bold.pkl
│   │   ├── Amiri-Bold.ttf
│   │   ├── Amiri-BoldItalic.pkl
│   │   ├── Amiri-BoldItalic.ttf
│   │   ├── Amiri-Italic.pkl
│   │   ├── Amiri-Italic.ttf
│   │   ├── Amiri-Regular.cw127.pkl
│   │   ├── Amiri-Regular.pkl
│   │   ├── Amiri-Regular.ttf
│   │   └── OFL.txt
├── main.py
└── output.pdf

With that, if you follow the code below, you will get the shown result at the end.

import os

import fpdf
from arabic_reshaper import reshape
from bidi.algorithm import get_display

# fonts location
fpdf.set_global("SYSTEM_TTFONTS", os.path.join(os.path.dirname(__file__),'fonts'))

# a new fpdf object and page
pdf = fpdf.FPDF(orientation = 'L', unit = 'mm', format = 'A4')
pdf.add_page()

# add all the fonts and setup the font to use
pdf.add_font("Amiri", style="", fname="Amiri/Amiri-Regular.ttf", uni=True)
pdf.add_font("Amiri", style="I", fname="Amiri/Amiri-Italic.ttf", uni=True)
pdf.add_font("Amiri", style="B", fname="Amiri/Amiri-Bold.ttf", uni=True)
pdf.add_font("Amiri", style="BI", fname="Amiri/Amiri-BoldItalic.ttf", uni=True)
pdf.set_font("Amiri", size=12)
pdf.set_text_color(0, 0, 0)


"""
# ‘x’ and ‘y’ refer to the specified location on our page
# ‘w’ and ‘h’ refer to the dimensions of our cell
# ‘some_text’ is the string or number that is to be displayed
# ‘border’ indicates if a line must be drawn around the cell (0: no, 1: yes or L: left, T: top, R: right, B: bottom)
# ‘align’ indicates the alignment of the text (L: left, C: center, R: right)
# ‘fill’ indicates whether the cell background should be filled or not (True, False).

An A4 in Landscape orientation has width=297mm and height=210mm.
The top left corner is the (0,0) point.

(0,0)+-------------------------+
     |                         |
     |                         |
     |                         |
     |                         |
     |                         |
     |                         |
     +-------------------------+(297,210)

"""
x=133.5
y=100
w=30
h=10

# Add the arabic text and reshape it
some_text = 'نص باللغة العربية'
fixed_text = get_display(reshape(some_text))

# setup a cell and fill it with text
pdf.set_xy(x, y)
pdf.cell(w, h, fixed_text, border=1, align="C", fill=False)

# export the pdf
pdf.output("output.pdf")

enter image description here

zalsaeed
  • 51
  • 1
  • 4