[reportlab-users] RTL Support

Hosam Aly haly at centrivision.com
Tue Nov 17 13:23:24 EST 2009


Hello,


I have been working on supporting RTL functionality (as I described in
my previous message), and I was able to get much of this working by
adding just 1 line of code to the `PDFTextObject._formatText` function
(not counting some imports). I have also created a test case in
`test_paragraphs.py`, and it is working relatively fine. There are still
some corner cases to be addressed (as mentioned above), but they are
relatively rare. More work still needs to be done to support paragraph
direction and different character shapes (according to whether the
character appears at the beginning, the middle or the end of the word).

Please find attached a patch file for the latest revision on the public
Subversion repository as of the time of writing this message (revision
3585, 2009-11-17 4:42 PM). I am also writing it down below for the archive.



Best regards,


Hosam Aly

Software Engineer

Centrivision (http://www.centrivision.com/)

http://www.linkedin.com/in/hosamaly




--- BEGIN PATCH ---

Index: src/reportlab/pdfgen/textobject.py
===================================================================
--- src/reportlab/pdfgen/textobject.py (revision 3585)
+++ src/reportlab/pdfgen/textobject.py (working copy)
@@ -15,6 +15,17 @@
from reportlab.lib.utils import fp_str
from reportlab.pdfbase import pdfmetrics

+# try to import pyfribidi
+try:
+ import pyfribidi
+ log2vis = pyfribidi.log2vis
+ DIR_ON = pyfribidi.ON
+except:
+ import warnings
+ warnings.warn('pyfribidi is not installed - RTL not supported')
+ log2vis = None
+ DIR_ON = None
+
class _PDFColorSetter:
'''Abstracts the color setting operations; used in Canvas and
Textobject
asseumes we have a _code object'''
@@ -329,6 +340,15 @@

def _formatText(self, text):
"Generates PDF text output operator(s)"
+ ###################################################
+ # RTL text patch, Hosam Aly, November 2009
+ # <haly at centrivision.com>
+ # Based on the patch by Moshe Wagner, June 2009
+ # <moshe.wagner at gmail.com>
+ # Use pyfribidi to write the text in the correct visual order.
+ text = log2vis(text, base_direction = DIR_ON)
+ ###################################################
+
canv = self._canvas
font = pdfmetrics.getFont(self._fontname)
R = []
Index: tests/test_paragraphs.py
===================================================================
--- tests/test_paragraphs.py (revision 3583)
+++ tests/test_paragraphs.py (working copy)
@@ -160,6 +160,55 @@
showBoundary=1)
template.build(story,
onFirstPage=myFirstPage, onLaterPages=myLaterPages)
+
+ def test1(self):
+ def registerFont(filename):
+ from reportlab.pdfbase import pdfmetrics
+ from reportlab.pdfbase import ttfonts
+ from reportlab.lib.fonts import addMapping
+
+ face = ttfonts.TTFontFace(filename)
+ pdfmetrics.registerFont(ttfonts.TTFont(face.name, filename,
asciiReadable=0))
+ addMapping(face.familyName, face.bold, face.italic, face.name)
+
+ import os
+ fontDir = 'ttf-dejavu'
+ fontName = 'DejaVuSans'
+ registerFont(os.path.join('/usr/share/fonts/truetype/',
fontDir, fontName + '.ttf'))
+
+
+ story = []
+
+ #need a style
+ from reportlab.lib.enums import TA_RIGHT
+ styNormal = ParagraphStyle('normal', fontName = fontName,
alignment = TA_RIGHT)
+ styGreen = ParagraphStyle('green',parent=styNormal,textColor=green)
+
+ # some to test
+ stySpaced = ParagraphStyle('spaced',
+ parent=styNormal,
+ spaceBefore=12,
+ spaceAfter=12)
+
+
+ story.append(
+ Paragraph('\xd9\x87\xd8\xb0\xd9\x87
\xd9\x81\xd9\x82\xd8\xb1\xd8\xa9
\xd8\xb9\xd8\xa7\xd8\xaf\xd9\x8a\xd8\xa9. ', styNormal))
+ story.append(
+ Paragraph('\xd9\x87\xd8\xb0\xd9\x87
\xd8\xa7\xd9\x84\xd9\x81\xd9\x82\xd8\xb1\xd8\xa9
\xd9\x84\xd8\xaf\xd9\x8a\xd9\x87\xd8\xa7 12
\xd9\x86\xd9\x82\xd8\xb7\xd8\xa9
\xd9\x82\xd8\xa8\xd9\x84\xd9\x87\xd8\xa7
\xd9\x88\xd8\xa8\xd8\xb9\xd8\xaf\xd9\x87\xd8\xa7. ', stySpaced))
+ story.append(
+ Paragraph('\xd9\x87\xd8\xb0\xd9\x87
\xd8\xa7\xd9\x84\xd9\x81\xd9\x82\xd8\xb1\xd8\xa9
\xd8\xb9\xd8\xa7\xd8\xaf\xd9\x8a\xd8\xa9. ' +
+ randomText(), styNormal))
+
+ story.append(
+ Paragraph('<para spacebefore="12" spaceafter="12">' +
+ '\xd9\x87\xd8\xb0\xd9\x87
\xd8\xa7\xd9\x84\xd9\x81\xd9\x82\xd8\xb1\xd8\xa9
\xd9\x84\xd8\xaf\xd9\x8a\xd9\x87\xd8\xa7 12
\xd9\x86\xd9\x82\xd8\xb7\xd8\xa9
\xd9\x82\xd8\xa8\xd9\x84\xd9\x87\xd8\xa7
\xd9\x88\xd8\xa8\xd8\xb9\xd8\xaf\xd9\x87\xd8\xa7\xd8\x8c
\xd9\x85\xd8\xad\xd8\xaf\xd8\xaf\xd8\xa9 \xd8\xa8\xd9\x80 XML.
\xd8\xa5\xd9\x86\xd9\x87\xd8\xa7 \xd8\xaa\xd8\xb9\xd9\x85\xd9\x84
\xd8\xa3\xd9\x8a\xd8\xb6\xd8\xa7! \xd9\x80.'*5
+ +'</para',
+ styNormal))
+
+ template = SimpleDocTemplate(outputfile('test_paragraphs_ar.pdf'),
+ showBoundary=1)
+ template.build(story,
+ onFirstPage=myFirstPage, onLaterPages=myLaterPages)


def makeSuite():

--- END PATCH ---

-------------- next part --------------
A non-text attachment was scrubbed...
Name: reportlab-rtl.patch
Type: text/x-patch
Size: 4389 bytes
Desc: not available
Url : <http://two.pairlist.net/pipermail/reportlab-users/attachments/20091117/ca5db102/attachment.bin>


More information about the reportlab-users mailing list