[reportlab-users] ReportLab + Macintosh TTFs

Marius Gedminas reportlab-users@reportlab.com
Tue, 2 Jul 2002 17:19:02 +0200


Dinu Gherman sent me a couple of Macintosh TTF files which did not work
with ReportLab 1.14.  Here's the patch to make them work.

(BTW I don't know what kind of encoding MacRoman is, I just assumed it
was a superset of ASCII.)

Index: pdfbase/ttfonts.py
===================================================================
RCS file: /cvsroot/reportlab/reportlab/pdfbase/ttfonts.py,v
retrieving revision 1.1
diff -u -p -r1.1 ttfonts.py
--- pdfbase/ttfonts.py  28 May 2002 15:33:57 -0000      1.1
+++ pdfbase/ttfonts.py  2 Jul 2002 14:54:58 -0000
@@ -433,13 +433,28 @@ class TTFontFile(TTFontParser):
                 self.seek(string_data_offset + offset)
                 if length % 2 != 0:
                     raise TTFError, "PostScript name is UTF-16BE string of odd length"
+                length = length / 2
                 psName = ""
-                while length > 1:
+                while length > 0:
                     char = self.read_ushort()
-                    if char < 0x20 or char > 0x7E:
+                    if char < 33 or char > 126 or chr(char) in \
+                       ('[', ']', '(', ')', '{', '}', '<', '>', '/', '%'):
                         raise TTFError, "PostScript contains invalid character U+%04X" % char
                     psName = psName + chr(char)
-                    length = length - 2
+                    length = length - 1
+                break
+            elif platformId == 1 and encodingId == 0 and languageId == 0 \
+               and nameId == 6: # Macintosh, Roman, English, PS Name
+                # According to OpenType spec, if PS name exists, it must exist
+                # both in MS Unicode and Macintosh Roman formats.  Apparently,
+                # you can find live TTF fonts which only have Macintosh format.
+                psName = self.get_chunk(string_data_offset + offset, length)
+                for char in psName:
+                    char = ord(char)
+                    if char < 33 or char > 126 or chr(char) in \
+                       ('[', ']', '(', ')', '{', '}', '<', '>', '/', '%'):
+                        raise TTFError, "PostScript contains invalid character %02X" % char
+                break
         if not psName:
             raise TTFError, "Could not find PostScript font name"
         self.name = psName
@@ -556,8 +571,14 @@ class TTFontFile(TTFontParser):
                 format = self.get_ushort(cmap_offset + offset)
                 if format == 4:
                     unicode_cmap_offset = cmap_offset + offset
+                    break
+            elif platformID == 0: # Unicode -- assume all encodings are compatible
+                format = self.get_ushort(cmap_offset + offset)
+                if format == 4:
+                    unicode_cmap_offset = cmap_offset + offset
+                    break
         if unicode_cmap_offset is None:
-            raise TTFError, 'Font does not have cmap for Unicode (platform 3, encoding 1, format 4)'
+            raise TTFError, 'Font does not have cmap for Unicode (platform 3, encoding 1, format 4 or platform 0 any encoding format 4)'
         self.seek(unicode_cmap_offset + 6)
         segCount = self.read_ushort() / 2
         self.skip(6)


Marius Gedminas
-- 
If you are smart enough to know that you're not smart enough to be an
Engineer, then you're in Business.