src/reportlab/pdfbase/ttfonts.py
author rptlab
Tue, 30 Apr 2013 14:28:14 +0100
branchpy33
changeset 3723 99aa837b6703
parent 3721 0c93dd8ff567
child 3728 8559eca73c9c
permissions -rw-r--r--
second stage of port to Python 3.3; working hello world
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3617
ae5744e97c42 reportlab: copyright date changes
robin
parents: 3368
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2012
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     2
#see license.txt for license details
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
     3
__version__ = '$Id$'
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
     4
__doc__="""TrueType font support
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     5
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     6
This defines classes to represent TrueType fonts.  They know how to calculate
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     7
their own width and how to write themselves into PDF files.  They support
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     8
subsetting and embedding and can represent all 16-bit Unicode characters.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
     9
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    10
Note on dynamic fonts
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    11
---------------------
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    12
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    13
Usually a Font in ReportLab corresponds to a fixed set of PDF objects (Font,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    14
FontDescriptor, Encoding).  But with dynamic font subsetting a single TTFont
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    15
will result in a number of Font/FontDescriptor/Encoding object sets, and the
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    16
contents of those will depend on the actual characters used for printing.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    17
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    18
To support dynamic font subsetting a concept of "dynamic font" was introduced.
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
    19
Dynamic Fonts have a _dynamicFont attribute set to 1.
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    20
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
    21
Dynamic fonts have the following additional functions::
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    22
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
    23
    def splitString(self, text, doc):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    24
        '''Splits text into a number of chunks, each of which belongs to a
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    25
        single subset.  Returns a list of tuples (subset, string).  Use
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
    26
        subset numbers with getSubsetInternalName.  Doc is used to identify
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
    27
        a document so that different documents may have different dynamically
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
    28
        constructed subsets.'''
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    29
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    30
    def getSubsetInternalName(self, subset, doc):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    31
        '''Returns the name of a PDF Font object corresponding to a given
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    32
        subset of this dynamic font.  Use this function instead of
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    33
        PDFDocument.getInternalFontName.'''
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    34
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    35
You must never call PDFDocument.getInternalFontName for dynamic fonts.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    36
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    37
If you have a traditional static font, mapping to PDF text output operators
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
    38
is simple::
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    39
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    40
   '%s 14 Tf (%s) Tj' % (getInternalFontName(psfontname), text)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    41
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
    42
If you have a dynamic font, use this instead::
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    43
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
    44
   for subset, chunk in font.splitString(text, doc):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    45
       '%s 14 Tf (%s) Tj' % (font.getSubsetInternalName(subset, doc), chunk)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    46
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    47
(Tf is a font setting operator and Tj is a text ouput operator.  You should
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    48
also escape invalid characters in Tj argument, see TextObject._formatText.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    49
Oh, and that 14 up there is font size.)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    50
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    51
Canvas and TextObject have special support for dynamic fonts.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    52
"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    53
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    54
import string
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
    55
from struct import pack, unpack, error as structError
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    56
from reportlab.lib.utils import getBytesIO
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    57
from reportlab.pdfbase import pdfmetrics, pdfdoc
3340
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
    58
from reportlab import rl_config
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    59
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    60
class TTFError(pdfdoc.PDFError):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    61
    "TrueType font exception"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    62
    pass
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    63
2509
98368812d002 merge 2628:2629: ttfonts: altered subset naming
rgbecker
parents: 2501
diff changeset
    64
98368812d002 merge 2628:2629: ttfonts: altered subset naming
rgbecker
parents: 2501
diff changeset
    65
def SUBSETN(n,table=string.maketrans('0123456789','ABCDEFGHIJ')):
98368812d002 merge 2628:2629: ttfonts: altered subset naming
rgbecker
parents: 2501
diff changeset
    66
    return ('%6.6d'%n).translate(table)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    67
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    68
# Helpers
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    69
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    70
2217
18ff4aed511d Truetype fonts now convert latin-1 to utf8 if fed non-utf8
andy_robinson
parents: 2216
diff changeset
    71
from codecs import utf_8_encode, utf_8_decode, latin_1_decode
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    72
parse_utf8=lambda x, decode=utf_8_decode: list(map(ord,decode(x)[0]))
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    73
parse_latin1 = lambda x, decode=latin_1_decode: list(map(ord,decode(x)[0]))
2217
18ff4aed511d Truetype fonts now convert latin-1 to utf8 if fed non-utf8
andy_robinson
parents: 2216
diff changeset
    74
def latin1_to_utf8(text):
18ff4aed511d Truetype fonts now convert latin-1 to utf8 if fed non-utf8
andy_robinson
parents: 2216
diff changeset
    75
    "helper to convert when needed from latin input"
18ff4aed511d Truetype fonts now convert latin-1 to utf8 if fed non-utf8
andy_robinson
parents: 2216
diff changeset
    76
    return utf_8_encode(latin_1_decode(text)[0])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    77
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    78
def makeToUnicodeCMap(fontname, subset):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1682
diff changeset
    79
    """Creates a ToUnicode CMap for a given subset.  See Adobe
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    80
    _PDF_Reference (ISBN 0-201-75839-3) for more information."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    81
    cmap = [
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    82
        "/CIDInit /ProcSet findresource begin",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    83
        "12 dict begin",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    84
        "begincmap",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    85
        "/CIDSystemInfo",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    86
        "<< /Registry (%s)" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    87
        "/Ordering (%s)" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    88
        "/Supplement 0",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    89
        ">> def",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    90
        "/CMapName /%s def" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    91
        "/CMapType 2 def",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    92
        "1 begincodespacerange",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    93
        "<00> <%02X>" % (len(subset) - 1),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    94
        "endcodespacerange",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    95
        "%d beginbfchar" % len(subset)
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
    96
        ] + ["<%02X> <%04X>" % (i,v) for i,v in enumerate(subset)] + [
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    97
        "endbfchar",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    98
        "endcmap",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    99
        "CMapName currentdict /CMap defineresource pop",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   100
        "end",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   101
        "end"
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   102
        ]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   103
    return string.join(cmap, "\n")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   104
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   105
def splice(stream, offset, value):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   106
    """Splices the given value into stream at the given offset and
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   107
    returns the resulting stream (the original is unchanged)"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   108
    return stream[:offset] + value + stream[offset + len(value):]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   109
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   110
def _set_ushort(stream, offset, value):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   111
    """Writes the given unsigned short value into stream at the given
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   112
    offset and returns the resulting stream (the original is unchanged)"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   113
    return splice(stream, offset, pack(">H", value))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   114
2107
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   115
try:
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   116
    import _rl_accel
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   117
except ImportError:
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   118
    try:
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   119
        from reportlab.lib import _rl_accel
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   120
    except ImportError:
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   121
        _rl_accel = None
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   122
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   123
try:
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   124
    hex32 = _rl_accel.hex32
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   125
except:
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   126
    def hex32(i):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   127
        return '0X%8.8X' % (int(i)&0xFFFFFFFF)
2283
59e39a910aba Another attempt to fix up wanrings
rgbecker
parents: 2254
diff changeset
   128
try:
2711
3d307d53dff7 fix up to use Martin Loewis' better checksum approach
rgbecker
parents: 2709
diff changeset
   129
    add32 = _rl_accel.add32L
3d307d53dff7 fix up to use Martin Loewis' better checksum approach
rgbecker
parents: 2709
diff changeset
   130
    calcChecksum = _rl_accel.calcChecksumL
1758
af03014bd624 Added Ury Marshak's checksum speedup
rgbecker
parents: 1750
diff changeset
   131
except:
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   132
    def add32(x, y):
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   133
        "Calculate (x + y) modulo 2**32"
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   134
        return (x+y) & 0xFFFFFFFF
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   135
2107
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   136
    def calcChecksum(data):
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   137
        """Calculates TTF-style checksums"""
2107
b2d72a7129e8 Back to int checksum & add32
rgbecker
parents: 2096
diff changeset
   138
        if len(data)&3: data = data + (4-(len(data)&3))*"\0"
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   139
        return sum(unpack(">%dl" % (len(data)>>2), data)) & 0xFFFFFFFF
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   140
del _rl_accel
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   141
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   142
# TrueType font handling
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   143
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   144
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   145
GF_ARG_1_AND_2_ARE_WORDS        = 1 << 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   146
GF_ARGS_ARE_XY_VALUES           = 1 << 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   147
GF_ROUND_XY_TO_GRID             = 1 << 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   148
GF_WE_HAVE_A_SCALE              = 1 << 3
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   149
GF_RESERVED                     = 1 << 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   150
GF_MORE_COMPONENTS              = 1 << 5
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   151
GF_WE_HAVE_AN_X_AND_Y_SCALE     = 1 << 6
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   152
GF_WE_HAVE_A_TWO_BY_TWO         = 1 << 7
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   153
GF_WE_HAVE_INSTRUCTIONS         = 1 << 8
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   154
GF_USE_MY_METRICS               = 1 << 9
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   155
GF_OVERLAP_COMPOUND             = 1 << 10
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   156
GF_SCALED_COMPONENT_OFFSET      = 1 << 11
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   157
GF_UNSCALED_COMPONENT_OFFSET    = 1 << 12
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   158
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   159
def TTFOpenFile(fn):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   160
    '''Opens a TTF file possibly after searching TTFSearchPath
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   161
    returns (filename,file)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   162
    '''
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   163
    from reportlab.lib.utils import rl_isfile, open_for_read
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   164
    try:
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   165
        f = open_for_read(fn,'rb')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   166
        return fn, f
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   167
    except IOError:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   168
        import os
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   169
        if not os.path.isabs(fn):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   170
            for D in rl_config.TTFSearchPath:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   171
                tfn = os.path.join(D,fn)
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   172
                if rl_isfile(tfn):
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   173
                    f = open_for_read(tfn,'rb')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   174
                    return tfn, f
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   175
        raise TTFError('Can\'t open file "%s"' % fn)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   176
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   177
class TTFontParser:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   178
    "Basic TTF file parser"
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   179
    ttfVersions = (0x00010000,0x74727565,0x74746366)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   180
    ttcVersions = (0x00010000,0x00020000)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   181
    fileKind='TTF'
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   182
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   183
    def __init__(self, file, validate=0,subfontIndex=0):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   184
        """Loads and parses a TrueType font file.  file can be a filename or a
1748
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   185
        file object.  If validate is set to a false values, skips checksum
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   186
        validation.  This can save time, especially if the font is large.
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   187
        """
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   188
        self.validate = validate
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   189
        self.readFile(file)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   190
        isCollection = self.readHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   191
        if isCollection:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   192
            self.readTTCHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   193
            self.getSubfont(subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   194
        else:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   195
            if self.validate: self.checksumFile()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   196
            self.readTableDirectory()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   197
            self.subfontNameX = ''
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   198
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   199
    def readTTCHeader(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   200
        self.ttcVersion = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   201
        self.fileKind = 'TTC'
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   202
        self.ttfVersions = self.ttfVersions[:-1]
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   203
        if self.ttcVersion not in self.ttcVersions: 
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   204
            raise TTFError('"%s" is not a %s file: can\'t read version 0x%8.8x' %(self.filename,self.fileKind,self.ttcVersion))
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   205
        self.numSubfonts = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   206
        self.subfontOffsets = []
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   207
        a = self.subfontOffsets.append
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   208
        for i in range(self.numSubfonts):
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   209
            a(self.read_ulong())
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   210
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   211
    def getSubfont(self,subfontIndex):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   212
        if self.fileKind!='TTC':
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   213
            raise TTFError('"%s" is not a TTC file: use this method' % (self.filename,self.fileKind))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   214
        try:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   215
            pos = self.subfontOffsets[subfontIndex]
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   216
        except IndexError:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   217
            raise TTFError('TTC file "%s": bad subfontIndex %s not in [0,%d]' % (self.filename,subfontIndex,self.numSubfonts-1))
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   218
        self.seek(pos)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   219
        self.readHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   220
        self.readTableDirectory()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   221
        self.subfontNameX = '-'+str(subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   222
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   223
    def readTableDirectory(self):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   224
        try:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   225
            self.numTables = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   226
            self.searchRange = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   227
            self.entrySelector = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   228
            self.rangeShift = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   229
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   230
            # Read table directory
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   231
            self.table = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   232
            self.tables = []
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   233
            for n in range(self.numTables):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   234
                record = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   235
                record['tag'] = self.read_tag()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   236
                record['checksum'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   237
                record['offset'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   238
                record['length'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   239
                self.tables.append(record)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   240
                self.table[record['tag']] = record
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   241
        except:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   242
            raise TTFError('Corrupt %s file "%s" cannot read Table Directory' % (self.fileKind, self.filename))
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   243
        if self.validate: self.checksumTables()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   244
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   245
    def readHeader(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   246
        '''read the sfnt header at the current position'''
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   247
        try:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   248
            self.version = version = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   249
        except:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   250
            raise TTFError('"%s" is not a %s file: can\'t read version' %(self.filename,self.fileKind))
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   251
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   252
        if version==0x4F54544F:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   253
            raise TTFError('%s file "%s": postscript outlines are not supported'%(self.fileKind,self.filename))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   254
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   255
        if version not in self.ttfVersions:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   256
            raise TTFError('Not a TrueType font: version=0x%8.8X' % version)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   257
        return version==self.ttfVersions[-1]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   258
3132
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   259
    def readFile(self,f):
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   260
        if hasattr(f,'read'):
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   261
            self.filename = '(ttf)'
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   262
        else:
3132
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   263
            self.filename, f = TTFOpenFile(f)
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   264
3132
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   265
        self._ttf_data = f.read()
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   266
        self._pos = 0
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   267
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   268
    def checksumTables(self):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   269
        # Check the checksums for all tables
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   270
        for t in self.tables:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   271
            table = self.get_chunk(t['offset'], t['length'])
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   272
            checksum = calcChecksum(table)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   273
            if t['tag'] == 'head':
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   274
                adjustment = unpack('>l', table[8:8+4])[0]
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   275
                checksum = add32(checksum, -adjustment)
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   276
            xchecksum = t['checksum']
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   277
            if xchecksum != checksum:
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   278
                raise TTFError('TTF file "%s": invalid checksum %s table: %s (expected %s)' % (self.filename,hex32(checksum),t['tag'],hex32(xchecksum)))
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   279
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   280
    def checksumFile(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   281
        # Check the checksums for the whole file
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   282
        checksum = calcChecksum(self._ttf_data)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   283
        if 0xB1B0AFBA!=checksum:
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   284
            raise TTFError('TTF file "%s": invalid checksum %s (expected 0xB1B0AFBA) len: %d &3: %d' % (self.filename,hex32(checksum),len(self._ttf_data),(len(self._ttf_data)&3)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   285
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   286
    def get_table_pos(self, tag):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   287
        "Returns the offset and size of a given TTF table."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   288
        offset = self.table[tag]['offset']
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   289
        length = self.table[tag]['length']
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   290
        return (offset, length)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   291
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   292
    def seek(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   293
        "Moves read pointer to a given offset in file."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   294
        self._pos = pos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   295
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   296
    def skip(self, delta):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   297
        "Skip the given number of bytes."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   298
        self._pos = self._pos + delta
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   299
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   300
    def seek_table(self, tag, offset_in_table = 0):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   301
        """Moves read pointer to the given offset within a given table and
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   302
        returns absolute offset of that position in the file."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   303
        self._pos = self.get_table_pos(tag)[0] + offset_in_table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   304
        return self._pos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   305
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   306
    def read_tag(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   307
        "Read a 4-character tag"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   308
        self._pos += 4
2123
78becbedca0c Change to _ttf_data
rgbecker
parents: 2107
diff changeset
   309
        return self._ttf_data[self._pos - 4:self._pos]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   310
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   311
    def read_ushort(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   312
        "Reads an unsigned short"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   313
        self._pos += 2
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   314
        return unpack('>H',self._ttf_data[self._pos-2:self._pos])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   315
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   316
    def read_ulong(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   317
        "Reads an unsigned long"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   318
        self._pos += 4
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   319
        return unpack('>L',self._ttf_data[self._pos - 4:self._pos])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   320
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   321
    def read_short(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   322
        "Reads a signed short"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   323
        self._pos += 2
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   324
        try:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   325
            return unpack('>h',self._ttf_data[self._pos-2:self._pos])[0]
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   326
        except structError as error:
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   327
            raise TTFError(error)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   328
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   329
    def get_ushort(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   330
        "Return an unsigned short at given position"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   331
        return unpack('>H',self._ttf_data[pos:pos+2])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   332
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   333
    def get_ulong(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   334
        "Return an unsigned long at given position"
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   335
        return unpack('>L',self._ttf_data[pos:pos+4])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   336
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   337
    def get_chunk(self, pos, length):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   338
        "Return a chunk of raw data at given position"
2123
78becbedca0c Change to _ttf_data
rgbecker
parents: 2107
diff changeset
   339
        return self._ttf_data[pos:pos+length]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   340
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   341
    def get_table(self, tag):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   342
        "Return the given TTF table"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   343
        pos, length = self.get_table_pos(tag)
2123
78becbedca0c Change to _ttf_data
rgbecker
parents: 2107
diff changeset
   344
        return self._ttf_data[pos:pos+length]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   345
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   346
class TTFontMaker:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   347
    "Basic TTF file generator"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   348
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   349
    def __init__(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   350
        "Initializes the generator."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   351
        self.tables = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   352
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   353
    def add(self, tag, data):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   354
        "Adds a table to the TTF file."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   355
        if tag == 'head':
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   356
            data = splice(data, 8, '\0\0\0\0')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   357
        self.tables[tag] = data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   358
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   359
    def makeStream(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   360
        "Finishes the generation and returns the TTF file as a string"
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   361
        stm = getBytesIO()
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   362
        write = stm.write
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   363
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   364
        numTables = len(self.tables)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   365
        searchRange = 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   366
        entrySelector = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   367
        while searchRange * 2 <= numTables:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   368
            searchRange = searchRange * 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   369
            entrySelector = entrySelector + 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   370
        searchRange = searchRange * 16
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   371
        rangeShift = numTables * 16 - searchRange
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   372
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   373
        # Header
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   374
        write(pack(">lHHHH", 0x00010000, numTables, searchRange,
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   375
                                 entrySelector, rangeShift))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   376
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   377
        # Table directory
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   378
        tables = list(self.tables.items())
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   379
        tables.sort()     # XXX is this the correct order?
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   380
        offset = 12 + numTables * 16
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   381
        for tag, data in tables:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   382
            if tag == 'head':
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   383
                head_start = offset
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   384
            checksum = calcChecksum(data)
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   385
            write(tag)
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   386
            write(pack(">LLL", checksum, offset, len(data)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   387
            paddedLength = (len(data)+3)&~3
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   388
            offset = offset + paddedLength
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   389
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   390
        # Table data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   391
        for tag, data in tables:
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   392
            data += "\0\0\0"
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   393
            write(data[:len(data)&~3])
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   394
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   395
        checksum = calcChecksum(stm.getvalue())
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   396
        checksum = add32(0xB1B0AFBA, -checksum)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   397
        stm.seek(head_start + 8)
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   398
        write(pack('>L', checksum))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   399
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   400
        return stm.getvalue()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   401
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   402
class TTFontFile(TTFontParser):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   403
    "TTF file parser and generator"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   404
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   405
    def __init__(self, file, charInfo=1, validate=0,subfontIndex=0):
1748
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   406
        """Loads and parses a TrueType font file.
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   407
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   408
        file can be a filename or a file object.  If validate is set to a false
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   409
        values, skips checksum validation.  This can save time, especially if
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   410
        the font is large.  See TTFontFile.extractInfo for more information.
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   411
        """
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   412
        TTFontParser.__init__(self, file, validate=validate,subfontIndex=subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   413
        self.extractInfo(charInfo)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   414
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   415
    def extractInfo(self, charInfo=1):
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   416
        """
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   417
        Extract typographic information from the loaded font file.
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   418
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   419
        The following attributes will be set::
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   420
        
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   421
            name         PostScript font name
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   422
            flags        Font flags
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   423
            ascent       Typographic ascender in 1/1000ths of a point
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   424
            descent      Typographic descender in 1/1000ths of a point
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   425
            capHeight    Cap height in 1/1000ths of a point (0 if not available)
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   426
            bbox         Glyph bounding box [l,t,r,b] in 1/1000ths of a point
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   427
            _bbox        Glyph bounding box [l,t,r,b] in unitsPerEm
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   428
            unitsPerEm   Glyph units per em
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   429
            italicAngle  Italic angle in degrees ccw
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   430
            stemV        stem weight in 1/1000ths of a point (approximate)
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   431
        
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   432
        If charInfo is true, the following will also be set::
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   433
        
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   434
            defaultWidth   default glyph width in 1/1000ths of a point
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   435
            charWidths     dictionary of character widths for every supported UCS character
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   436
                           code
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   437
        
1748
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   438
        This will only work if the font has a Unicode cmap (platform 3,
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
   439
        encoding 1, format 4 or platform 0 any encoding format 4).  Setting
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   440
        charInfo to false avoids this requirement
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3021
diff changeset
   441
        
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   442
        """
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   443
        # name - Naming table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   444
        name_offset = self.seek_table("name")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   445
        format = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   446
        if format != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   447
            raise TTFError("Unknown name table format (%d)" % format)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   448
        numRecords = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   449
        string_data_offset = name_offset + self.read_ushort()
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   450
        names = {1:None,2:None,3:None,4:None,6:None}
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   451
        K = list(names.keys())
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   452
        nameCount = len(names)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   453
        for i in range(numRecords):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   454
            platformId = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   455
            encodingId = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   456
            languageId = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   457
            nameId = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   458
            length = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   459
            offset = self.read_ushort()
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   460
            if nameId not in K: continue
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   461
            N = None
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   462
            if platformId == 3 and encodingId == 1 and languageId == 0x409: # Microsoft, Unicode, US English, PS Name
2566
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   463
                opos = self._pos
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   464
                try:
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   465
                    self.seek(string_data_offset + offset)
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   466
                    if length % 2 != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   467
                        raise TTFError("PostScript name is UTF-16BE string of odd length")
2566
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   468
                    length /= 2
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   469
                    N = []
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   470
                    A = N.append
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   471
                    while length > 0:
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   472
                        char = self.read_ushort()
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   473
                        A(chr(char))
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   474
                        length -= 1
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   475
                    N = ''.join(N)
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   476
                finally:
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   477
                    self._pos = opos
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   478
            elif platformId == 1 and encodingId == 0 and languageId == 0: # Macintosh, Roman, English, PS Name
1664
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   479
                # According to OpenType spec, if PS name exists, it must exist
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   480
                # both in MS Unicode and Macintosh Roman formats.  Apparently,
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   481
                # you can find live TTF fonts which only have Macintosh format.
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   482
                N = self.get_chunk(string_data_offset + offset, length)
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   483
            if N and names[nameId]==None:
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   484
                names[nameId] = N
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   485
                nameCount -= 1
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   486
                if nameCount==0: break
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   487
        if names[6] is not None:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   488
            psName = names[6].replace(" ", "-")  #Dinu Gherman's fix for font names with spaces
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   489
        elif names[4] is not None:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   490
            psName = names[4].replace(" ", "-")
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   491
        # Fine, one last try before we bail.
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   492
        elif names[1] is not None:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   493
            psName = names[1].replace(" ", "-")
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   494
        else:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   495
            psName = None
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   496
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   497
        # Don't just assume, check for None since some shoddy fonts cause crashes here...
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   498
        if not psName:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   499
            raise TTFError("Could not find PostScript font name")
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   500
        for c in psName:
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   501
            oc = ord(c)
2768
7af1018f9411 ttfonts.py: small change inspired by Dinu Gherman
rgbecker
parents: 2711
diff changeset
   502
            if oc>126 or c in ' [](){}<>/%':
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   503
                raise TTFError("psName=%r contains invalid character '%s' ie U+%04X" % (psName,c,ord(c)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   504
        self.name = psName
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   505
        self.familyName = names[1] or psName
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   506
        self.styleName = names[2] or 'Regular'
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   507
        self.fullName = names[4] or psName
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   508
        self.uniqueFontID = names[3] or psName
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   509
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   510
        # head - Font header table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   511
        self.seek_table("head")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   512
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   513
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   514
            raise TTFError('Unknown head table version %d.%04x' % (ver_maj, ver_min))
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   515
        self.fontRevision = self.read_ushort(), self.read_ushort()
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   516
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   517
        self.skip(4)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   518
        magic = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   519
        if magic != 0x5F0F3CF5:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   520
            raise TTFError('Invalid head table magic %04x' % magic)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   521
        self.skip(2)
2774
ad67eff48c23 ttfonts.py: add _bbox (bbox in orig units) and unitsPerEm to TTFontFace
rgbecker
parents: 2768
diff changeset
   522
        self.unitsPerEm = unitsPerEm = self.read_ushort()
2782
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
   523
        scale = lambda x, unitsPerEm=unitsPerEm: x * 1000. / unitsPerEm
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   524
        self.skip(16)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   525
        xMin = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   526
        yMin = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   527
        xMax = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   528
        yMax = self.read_short()
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   529
        self.bbox = list(map(scale, [xMin, yMin, xMax, yMax]))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   530
        self.skip(3*2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   531
        indexToLocFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   532
        glyphDataFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   533
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   534
        # OS/2 - OS/2 and Windows metrics table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   535
        # (needs data from head table)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   536
        if "OS/2" in self.table:
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   537
            self.seek_table("OS/2")
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   538
            version = self.read_ushort()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   539
            self.skip(2)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   540
            usWeightClass = self.read_ushort()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   541
            self.skip(2)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   542
            fsType = self.read_ushort()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   543
            if fsType == 0x0002 or (fsType & 0x0300) != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   544
                raise TTFError('Font does not allow subsetting/embedding (%04X)' % fsType)
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   545
            self.skip(58)   #11*2 + 10 + 4*4 + 4 + 3*2
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   546
            sTypoAscender = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   547
            sTypoDescender = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   548
            self.ascent = scale(sTypoAscender)      # XXX: for some reason it needs to be multiplied by 1.24--1.28
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   549
            self.descent = scale(sTypoDescender)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   550
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   551
            if version > 1:
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   552
                self.skip(16)   #3*2 + 2*4 + 2
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   553
                sCapHeight = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   554
                self.capHeight = scale(sCapHeight)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   555
            else:
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   556
                self.capHeight = self.ascent
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   557
        else:
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   558
            # Microsoft TTFs require an OS/2 table; Apple ones do not.  Try to
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   559
            # cope.  The data is not very important anyway.
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   560
            usWeightClass = 500
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   561
            self.ascent = scale(yMax)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   562
            self.descent = scale(yMin)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   563
            self.capHeight = self.ascent
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   564
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   565
        # There's no way to get stemV from a TTF file short of analyzing actual outline data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   566
        # This fuzzy formula is taken from pdflib sources, but we could just use 0 here
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   567
        self.stemV = 50 + int((usWeightClass / 65.0) ** 2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   568
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   569
        # post - PostScript table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   570
        # (needs data from OS/2 table)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   571
        self.seek_table("post")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   572
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
1721
2cace59f0f50 Support POST table version 4 as found in some Apple TTFs.
mgedmin
parents: 1719
diff changeset
   573
        if ver_maj not in (1, 2, 3, 4):
2cace59f0f50 Support POST table version 4 as found in some Apple TTFs.
mgedmin
parents: 1719
diff changeset
   574
            # Adobe/MS documents 1, 2, 2.5, 3; Apple also has 4.
2cace59f0f50 Support POST table version 4 as found in some Apple TTFs.
mgedmin
parents: 1719
diff changeset
   575
            # From Apple docs it seems that we do not need to care
2cace59f0f50 Support POST table version 4 as found in some Apple TTFs.
mgedmin
parents: 1719
diff changeset
   576
            # about the exact version, so if you get this error, you can
2cace59f0f50 Support POST table version 4 as found in some Apple TTFs.
mgedmin
parents: 1719
diff changeset
   577
            # try to remove this check altogether.
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   578
            raise TTFError('Unknown post table version %d.%04x' % (ver_maj, ver_min))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   579
        self.italicAngle = self.read_short() + self.read_ushort() / 65536.0
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   580
        self.underlinePosition = self.read_short()
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   581
        self.underlineThickness = self.read_short()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   582
        isFixedPitch = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   583
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   584
        self.flags = FF_SYMBOLIC        # All fonts that contain characters
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   585
                                        # outside the original Adobe character
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   586
                                        # set are considered "symbolic".
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   587
        if self.italicAngle!= 0:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   588
            self.flags = self.flags | FF_ITALIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   589
        if usWeightClass >= 600:        # FW_REGULAR == 500, FW_SEMIBOLD == 600
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   590
            self.flags = self.flags | FF_FORCEBOLD
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   591
        if isFixedPitch:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   592
            self.flags = self.flags | FF_FIXED
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   593
        # XXX: FF_SERIF?  FF_SCRIPT?  FF_ALLCAP?  FF_SMALLCAP?
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   594
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   595
        # hhea - Horizontal header table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   596
        self.seek_table("hhea")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   597
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   598
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   599
            raise TTFError('Unknown hhea table version %d.%04x' % (ver_maj, ver_min))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   600
        self.skip(28)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   601
        metricDataFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   602
        if metricDataFormat != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   603
            raise TTFError('Unknown horizontal metric data format (%d)' % metricDataFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   604
        numberOfHMetrics = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   605
        if numberOfHMetrics == 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   606
            raise TTFError('Number of horizontal metrics is 0')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   607
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   608
        # maxp - Maximum profile table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   609
        self.seek_table("maxp")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   610
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   611
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   612
            raise TTFError('Unknown maxp table version %d.%04x' % (ver_maj, ver_min))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   613
        numGlyphs = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   614
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   615
        if not charInfo:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   616
            self.charToGlyph = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   617
            self.defaultWidth = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   618
            self.charWidths = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   619
            return
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   620
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   621
        if glyphDataFormat != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   622
            raise TTFError('Unknown glyph data format (%d)' % glyphDataFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   623
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   624
        # cmap - Character to glyph index mapping table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   625
        cmap_offset = self.seek_table("cmap")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   626
        self.skip(2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   627
        cmapTableCount = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   628
        unicode_cmap_offset = None
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   629
        for n in range(cmapTableCount):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   630
            platformID = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   631
            encodingID = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   632
            offset = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   633
            if platformID == 3 and encodingID == 1: # Microsoft, Unicode
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   634
                format = self.get_ushort(cmap_offset + offset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   635
                if format == 4:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   636
                    unicode_cmap_offset = cmap_offset + offset
1664
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   637
                    break
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   638
            elif platformID == 0: # Unicode -- assume all encodings are compatible
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   639
                format = self.get_ushort(cmap_offset + offset)
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   640
                if format == 4:
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   641
                    unicode_cmap_offset = cmap_offset + offset
09dcb3294a0d Applied Marius' patch for TrueType fonts converted from OS X .dfont files.
dinu_gherman
parents: 1637
diff changeset
   642
                    break
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   643
        if unicode_cmap_offset is None:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   644
            raise TTFError('Font does not have cmap for Unicode (platform 3, encoding 1, format 4 or platform 0 any encoding format 4)')
1749
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   645
        self.seek(unicode_cmap_offset + 2)
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   646
        length = self.read_ushort()
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   647
        limit = unicode_cmap_offset + length
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   648
        self.skip(2)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   649
        segCount = int(self.read_ushort() / 2.0)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   650
        self.skip(6)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   651
        endCount = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   652
        self.skip(2)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   653
        startCount = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   654
        idDelta = list(map(lambda x, self=self: self.read_short(), range(segCount)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   655
        idRangeOffset_start = self._pos
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   656
        idRangeOffset = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   657
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   658
        # Now it gets tricky.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   659
        glyphToChar = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   660
        charToGlyph = {}
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   661
        for n in range(segCount):
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   662
            for unichar in range(startCount[n], endCount[n] + 1):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   663
                if idRangeOffset[n] == 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   664
                    glyph = (unichar + idDelta[n]) & 0xFFFF
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   665
                else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   666
                    offset = (unichar - startCount[n]) * 2 + idRangeOffset[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   667
                    offset = idRangeOffset_start + 2 * n + offset
1749
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   668
                    if offset >= limit:
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   669
                        # workaround for broken fonts (like Thryomanes)
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   670
                        glyph = 0
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   671
                    else:
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   672
                        glyph = self.get_ushort(offset)
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   673
                        if glyph != 0:
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   674
                            glyph = (glyph + idDelta[n]) & 0xFFFF
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   675
                charToGlyph[unichar] = glyph
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   676
                if glyph in glyphToChar:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   677
                    glyphToChar[glyph].append(unichar)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   678
                else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   679
                    glyphToChar[glyph] = [unichar]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   680
        self.charToGlyph = charToGlyph
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   681
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   682
        # hmtx - Horizontal metrics table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   683
        # (needs data from hhea, maxp, and cmap tables)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   684
        self.seek_table("hmtx")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   685
        aw = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   686
        self.charWidths = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   687
        self.hmetrics = []
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   688
        for glyph in range(numberOfHMetrics):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   689
            # advance width and left side bearing.  lsb is actually signed
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   690
            # short, but we don't need it anyway (except for subsetting)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   691
            aw, lsb = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   692
            self.hmetrics.append((aw, lsb))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   693
            aw = scale(aw)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   694
            if glyph == 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   695
                self.defaultWidth = aw
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   696
            if glyph in glyphToChar:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   697
                for char in glyphToChar[glyph]:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   698
                    self.charWidths[char] = aw
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   699
        for glyph in range(numberOfHMetrics, numGlyphs):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   700
            # the rest of the table only lists advance left side bearings.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   701
            # so we reuse aw set by the last iteration of the previous loop
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   702
            lsb = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   703
            self.hmetrics.append((aw, lsb))
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   704
            if glyph in glyphToChar:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   705
                for char in glyphToChar[glyph]:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   706
                    self.charWidths[char] = aw
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   707
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   708
        # loca - Index to location
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   709
        self.seek_table('loca')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   710
        self.glyphPos = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   711
        if indexToLocFormat == 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   712
            for n in range(numGlyphs + 1):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   713
                self.glyphPos.append(self.read_ushort() << 1)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   714
        elif indexToLocFormat == 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   715
            for n in range(numGlyphs + 1):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   716
                self.glyphPos.append(self.read_ulong())
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   717
        else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   718
            raise TTFError('Unknown location table format (%d)' % indexToLocFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   719
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   720
    # Subsetting
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   721
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   722
    def makeSubset(self, subset):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   723
        """Create a subset of a TrueType font"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   724
        output = TTFontMaker()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   725
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   726
        # Build a mapping of glyphs in the subset to glyph numbers in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   727
        # the original font.  Also build a mapping of UCS codes to
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   728
        # glyph values in the new font.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   729
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1682
diff changeset
   730
        # Start with 0 -> 0: "missing character"
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   731
        glyphMap = [0]                  # new glyph index -> old glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   732
        glyphSet = {0:0}                # old glyph index -> new glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   733
        codeToGlyph = {}                # unicode -> new glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   734
        for code in subset:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   735
            if code in self.charToGlyph:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   736
                originalGlyphIdx = self.charToGlyph[code]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   737
            else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   738
                originalGlyphIdx = 0
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   739
            if originalGlyphIdx not in glyphSet:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   740
                glyphSet[originalGlyphIdx] = len(glyphMap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   741
                glyphMap.append(originalGlyphIdx)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   742
            codeToGlyph[code] = glyphSet[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   743
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   744
        # Also include glyphs that are parts of composite glyphs
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   745
        start = self.get_table_pos('glyf')[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   746
        n = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   747
        while n < len(glyphMap):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   748
            originalGlyphIdx = glyphMap[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   749
            glyphPos = self.glyphPos[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   750
            glyphLen = self.glyphPos[originalGlyphIdx + 1] - glyphPos
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   751
            n += 1
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   752
            if not glyphLen: continue
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   753
            self.seek(start + glyphPos)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   754
            numberOfContours = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   755
            if numberOfContours < 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   756
                # composite glyph
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   757
                self.skip(8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   758
                flags = GF_MORE_COMPONENTS
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   759
                while flags & GF_MORE_COMPONENTS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   760
                    flags = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   761
                    glyphIdx = self.read_ushort()
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   762
                    if glyphIdx not in glyphSet:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   763
                        glyphSet[glyphIdx] = len(glyphMap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   764
                        glyphMap.append(glyphIdx)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   765
                    if flags & GF_ARG_1_AND_2_ARE_WORDS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   766
                        self.skip(4)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   767
                    else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   768
                        self.skip(2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   769
                    if flags & GF_WE_HAVE_A_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   770
                        self.skip(2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   771
                    elif flags & GF_WE_HAVE_AN_X_AND_Y_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   772
                        self.skip(4)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   773
                    elif flags & GF_WE_HAVE_A_TWO_BY_TWO:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   774
                        self.skip(8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   775
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   776
        numGlyphs = n = len(glyphMap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   777
        while n > 1 and self.hmetrics[n][0] == self.hmetrics[n - 1][0]:
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   778
            n -= 1
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   779
        numberOfHMetrics = n
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   780
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   781
        # The following tables are simply copied from the original
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   782
        for tag in ('name', 'OS/2', 'cvt ', 'fpgm', 'prep'):
1682
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   783
            try:
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   784
                output.add(tag, self.get_table(tag))
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   785
            except KeyError:
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   786
                # Apparently some of the tables are optional (cvt, fpgm, prep).
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   787
                # The lack of the required ones (name, OS/2) would have already
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   788
                # been caught before.
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   789
                pass
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   790
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   791
        # post - PostScript
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   792
        post = "\x00\x03\x00\x00" + self.get_table('post')[4:16] + "\x00" * 16
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   793
        output.add('post', post)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   794
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   795
        # hhea - Horizontal Header
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   796
        hhea = self.get_table('hhea')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   797
        hhea = _set_ushort(hhea, 34, numberOfHMetrics)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   798
        output.add('hhea', hhea)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   799
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   800
        # maxp - Maximum Profile
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   801
        maxp = self.get_table('maxp')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   802
        maxp = _set_ushort(maxp, 4, numGlyphs)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   803
        output.add('maxp', maxp)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   804
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   805
        # cmap - Character to glyph mapping
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   806
        # XXX maybe use format 0 if possible, not 6?
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   807
        entryCount = len(subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   808
        length = 10 + entryCount * 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   809
        cmap = [0, 1,           # version, number of tables
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   810
                1, 0, 0,12,     # platform, encoding, offset (hi,lo)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   811
                6, length, 0,   # format, length, language
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   812
                0,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   813
                entryCount] + \
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   814
               list(map(codeToGlyph.get, subset))
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   815
        cmap = pack(*([">%dH" % len(cmap)] + cmap))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   816
        output.add('cmap', cmap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   817
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1682
diff changeset
   818
        # hmtx - Horizontal Metrics
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   819
        hmtx = []
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   820
        for n in range(numGlyphs):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   821
            originalGlyphIdx = glyphMap[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   822
            aw, lsb = self.hmetrics[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   823
            if n < numberOfHMetrics:
2831
a9dc5ad8aa9e ttfonts.py: remove deprecation warning
rgbecker
parents: 2785
diff changeset
   824
                hmtx.append(int(aw))
a9dc5ad8aa9e ttfonts.py: remove deprecation warning
rgbecker
parents: 2785
diff changeset
   825
            hmtx.append(int(lsb))
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   826
        hmtx = pack(*([">%dH" % len(hmtx)] + hmtx))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   827
        output.add('hmtx', hmtx)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   828
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   829
        # glyf - Glyph data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   830
        glyphData = self.get_table('glyf')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   831
        offsets = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   832
        glyf = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   833
        pos = 0
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   834
        for n in range(numGlyphs):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   835
            offsets.append(pos)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   836
            originalGlyphIdx = glyphMap[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   837
            glyphPos = self.glyphPos[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   838
            glyphLen = self.glyphPos[originalGlyphIdx + 1] - glyphPos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   839
            data = glyphData[glyphPos:glyphPos+glyphLen]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   840
            # Fix references in composite glyphs
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   841
            if glyphLen > 2 and unpack(">h", data[:2])[0] < 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   842
                # composite glyph
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   843
                pos_in_glyph = 10
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   844
                flags = GF_MORE_COMPONENTS
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   845
                while flags & GF_MORE_COMPONENTS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   846
                    flags = unpack(">H", data[pos_in_glyph:pos_in_glyph+2])[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   847
                    glyphIdx = unpack(">H", data[pos_in_glyph+2:pos_in_glyph+4])[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   848
                    data = _set_ushort(data, pos_in_glyph + 2, glyphSet[glyphIdx])
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   849
                    pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   850
                    if flags & GF_ARG_1_AND_2_ARE_WORDS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   851
                        pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   852
                    else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   853
                        pos_in_glyph = pos_in_glyph + 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   854
                    if flags & GF_WE_HAVE_A_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   855
                        pos_in_glyph = pos_in_glyph + 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   856
                    elif flags & GF_WE_HAVE_AN_X_AND_Y_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   857
                        pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   858
                    elif flags & GF_WE_HAVE_A_TWO_BY_TWO:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   859
                        pos_in_glyph = pos_in_glyph + 8
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   860
            glyf.append(data)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   861
            pos = pos + glyphLen
1745
1915be8a52df Align glyphs at dword boundaries as recommended by the TTF spec. (also fixes a bug)
mgedmin
parents: 1721
diff changeset
   862
            if pos % 4 != 0:
1915be8a52df Align glyphs at dword boundaries as recommended by the TTF spec. (also fixes a bug)
mgedmin
parents: 1721
diff changeset
   863
                padding = 4 - pos % 4
1915be8a52df Align glyphs at dword boundaries as recommended by the TTF spec. (also fixes a bug)
mgedmin
parents: 1721
diff changeset
   864
                glyf.append('\0' * padding)
1915be8a52df Align glyphs at dword boundaries as recommended by the TTF spec. (also fixes a bug)
mgedmin
parents: 1721
diff changeset
   865
                pos = pos + padding
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   866
        offsets.append(pos)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   867
        output.add('glyf', string.join(glyf, ""))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   868
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   869
        # loca - Index to location
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   870
        loca = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   871
        if (pos + 1) >> 1 > 0xFFFF:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   872
            indexToLocFormat = 1        # long format
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   873
            for offset in offsets:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   874
                loca.append(offset)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   875
            loca = pack(*([">%dL" % len(loca)] + loca))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   876
        else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   877
            indexToLocFormat = 0        # short format
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   878
            for offset in offsets:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   879
                loca.append(offset >> 1)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   880
            loca = pack(*([">%dH" % len(loca)] + loca))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   881
        output.add('loca', loca)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   882
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   883
        # head - Font header
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   884
        head = self.get_table('head')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   885
        head = _set_ushort(head, 50, indexToLocFormat)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   886
        output.add('head', head)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   887
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   888
        return output.makeStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   889
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   890
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   891
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   892
# TrueType font embedding
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   893
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   894
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   895
# PDF font flags (see PDF Reference Guide table 5.19)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   896
FF_FIXED        = 1 <<  1-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   897
FF_SERIF        = 1 <<  2-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   898
FF_SYMBOLIC     = 1 <<  3-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   899
FF_SCRIPT       = 1 <<  4-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   900
FF_NONSYMBOLIC  = 1 <<  6-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   901
FF_ITALIC       = 1 <<  7-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   902
FF_ALLCAP       = 1 << 17-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   903
FF_SMALLCAP     = 1 << 18-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   904
FF_FORCEBOLD    = 1 << 19-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   905
2216
aadcd9dc9480 Font reregistration cleanup
andy_robinson
parents: 2201
diff changeset
   906
class TTFontFace(TTFontFile, pdfmetrics.TypeFace):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   907
    """TrueType typeface.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   908
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   909
    Conceptually similar to a single byte typeface, but the glyphs are
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   910
    identified by UCS character codes instead of glyph names."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   911
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   912
    def __init__(self, filename, validate=0, subfontIndex=0):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   913
        "Loads a TrueType font from filename."
2216
aadcd9dc9480 Font reregistration cleanup
andy_robinson
parents: 2201
diff changeset
   914
        pdfmetrics.TypeFace.__init__(self, None)
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   915
        TTFontFile.__init__(self, filename, validate=validate, subfontIndex=subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   916
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   917
    def getCharWidth(self, code):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   918
        "Returns the width of character U+<code>"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   919
        return self.charWidths.get(code, self.defaultWidth)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   920
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   921
    def addSubsetObjects(self, doc, fontname, subset):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   922
        """Generate a TrueType font subset and add it to the PDF document.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   923
        Returns a PDFReference to the new FontDescriptor object."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   924
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   925
        fontFile = pdfdoc.PDFStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   926
        fontFile.content = self.makeSubset(subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   927
        fontFile.dictionary['Length1'] = len(fontFile.content)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   928
        if doc.compression:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   929
            fontFile.filters = [pdfdoc.PDFZCompress]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   930
        fontFileRef = doc.Reference(fontFile, 'fontFile:%s(%s)' % (self.filename, fontname))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   931
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   932
        flags = self.flags & ~ FF_NONSYMBOLIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   933
        flags = flags | FF_SYMBOLIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   934
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   935
        fontDescriptor = pdfdoc.PDFDictionary({
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   936
            'Type': '/FontDescriptor',
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   937
            'Ascent': self.ascent,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   938
            'CapHeight': self.capHeight,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   939
            'Descent': self.descent,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   940
            'Flags': flags,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   941
            'FontBBox': pdfdoc.PDFArray(self.bbox),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   942
            'FontName': pdfdoc.PDFName(fontname),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   943
            'ItalicAngle': self.italicAngle,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   944
            'StemV': self.stemV,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   945
            'FontFile2': fontFileRef,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   946
            })
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   947
        return doc.Reference(fontDescriptor, 'fontDescriptor:' + fontname)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   948
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   949
class TTEncoding:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   950
    """Encoding for TrueType fonts (always UTF-8).
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   951
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   952
    TTEncoding does not directly participate in PDF object creation, since
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   953
    we need a number of different 8-bit encodings for every generated font
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   954
    subset.  TTFont itself cares about that."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   955
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   956
    def __init__(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   957
        self.name = "UTF-8"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   958
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   959
class TTFont:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   960
    """Represents a TrueType font.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   961
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   962
    Its encoding is always UTF-8.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   963
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   964
    Note: you cannot use the same TTFont object for different documents
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   965
    at the same time.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   966
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   967
    Example of usage:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   968
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   969
        font = ttfonts.TTFont('PostScriptFontName', '/path/to/font.ttf')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   970
        pdfmetrics.registerFont(font)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   971
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   972
        canvas.setFont('PostScriptFontName', size)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   973
        canvas.drawString(x, y, "Some text encoded in UTF-8")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   974
    """
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   975
    class State:
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
   976
        namePrefix = 'F'
3340
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
   977
        def __init__(self,asciiReadable=None):
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   978
            self.assignments = {}
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   979
            self.nextCode = 0
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   980
            self.internalName = None
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   981
            self.frozen = 0
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
   982
3340
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
   983
            if asciiReadable is None:
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
   984
                asciiReadable = rl_config.ttfAsciiReadable
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
   985
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   986
            if asciiReadable:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   987
                # Let's add the first 128 unicodes to the 0th subset, so ' '
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   988
                # always has code 32 (for word spacing to work) and the ASCII
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   989
                # output is readable
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   990
                subset0 = list(range(128))
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   991
                self.subsets = [subset0]
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   992
                for n in subset0:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   993
                    self.assignments[n] = n
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   994
                self.nextCode = 128
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   995
            else:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   996
                self.subsets = [[32]*33]
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   997
                self.assignments[32] = 32
2501
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
   998
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   999
    _multiByte = 1      # We want our own stringwidth
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1000
    _dynamicFont = 1    # We want dynamic subsetting
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1001
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1002
    def __init__(self, name, filename, validate=0, subfontIndex=0,asciiReadable=None):
1748
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
  1003
        """Loads a TrueType font from filename.
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
  1004
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
  1005
        If validate is set to a false values, skips checksum validation.  This
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
  1006
        can save time, especially if the font is large.
e69910cfc3b8 Let TTFont users disable checksum validation. Also, don't parse the same TTF info twice (in TTFontFace and TTFontFile constructors).
mgedmin
parents: 1745
diff changeset
  1007
        """
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1008
        self.fontName = name
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
  1009
        self.face = TTFontFace(filename, validate=validate, subfontIndex=subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1010
        self.encoding = TTEncoding()
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1011
        from weakref import WeakKeyDictionary
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1012
        self.state = WeakKeyDictionary()
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1013
        if asciiReadable is None:
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1014
            asciiReadable = rl_config.ttfAsciiReadable
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1015
        self._asciiReadable = asciiReadable
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1016
2606
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1017
    def _py_stringWidth(self, text, size, encoding='utf-8'):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1018
        "Calculate text width"
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1019
        if not isinstance(text,str):
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1020
            text = str(text, encoding or 'utf-8')   # encoding defaults to utf-8
2606
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1021
        g = self.face.charWidths.get
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1022
        dw = self.face.defaultWidth
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1023
        return 0.001*size*sum([g(ord(u),dw) for u in text])
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1024
    stringWidth = _py_stringWidth
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1025
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1026
    def _assignState(self,doc,asciiReadable=None,namePrefix=None):
2782
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1027
        '''convenience function for those wishing to roll their own state properties'''
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1028
        if asciiReadable is None:
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1029
            asciiReadable = self._asciiReadable
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1030
        try:
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1031
            state = self.state[doc]
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1032
        except KeyError:
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1033
            state = self.state[doc] = TTFont.State(asciiReadable)
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1034
            if namePrefix is not None:
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1035
                state.namePrefix = namePrefix
2782
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1036
        return state
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1037
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2566
diff changeset
  1038
    def splitString(self, text, doc, encoding='utf-8'):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1039
        """Splits text into a number of chunks, each of which belongs to a
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1040
        single subset.  Returns a list of tuples (subset, string).  Use subset
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1041
        numbers with getSubsetInternalName.  Doc is needed for distinguishing
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1042
        subsets when building different documents at the same time."""
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1043
        asciiReadable = self._asciiReadable
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1044
        try: state = self.state[doc]
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1045
        except KeyError: state = self.state[doc] = TTFont.State(asciiReadable)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1046
        curSet = -1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1047
        cur = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1048
        results = []
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1049
        if not isinstance(text,str):
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1050
            text = str(text, encoding or 'utf-8')   # encoding defaults to utf-8
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1051
        assignments = state.assignments
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1052
        subsets = state.subsets
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2566
diff changeset
  1053
        for code in map(ord,text):
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1054
            if code in assignments:
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1055
                n = assignments[code]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1056
            else:
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1057
                if state.frozen:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1058
                    raise pdfdoc.PDFError("Font %s is already frozen, cannot add new character U+%04X" % (self.fontName, code))
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1059
                n = state.nextCode
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1060
                if n&0xFF==32:
2501
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1061
                    # make code 32 always be a space character
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1062
                    if n!=32: subsets[n >> 8].append(32)
2501
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1063
                    state.nextCode += 1
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1064
                    n = state.nextCode
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1065
                state.nextCode += 1
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1066
                assignments[code] = n
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1067
                if n>32:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1068
                    if not(n&0xFF): subsets.append([])
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1069
                    subsets[n >> 8].append(code)
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1070
                else:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1071
                    subsets[0][n] = code
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1072
            if (n >> 8) != curSet:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1073
                if cur:
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1074
                    results.append((curSet, ''.join(map(chr,cur))))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1075
                curSet = (n >> 8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1076
                cur = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1077
            cur.append(n & 0xFF)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1078
        if cur:
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1079
            results.append((curSet,''.join(map(chr,cur))))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1080
        return results
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1081
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1082
    def getSubsetInternalName(self, subset, doc):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1083
        """Returns the name of a PDF Font object corresponding to a given
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1084
        subset of this dynamic font.  Use this function instead of
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1085
        PDFDocument.getInternalFontName."""
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1086
        try: state = self.state[doc]
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1087
        except KeyError: state = self.state[doc] = TTFont.State(self._asciiReadable)
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1088
        if subset < 0 or subset >= len(state.subsets):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1089
            raise IndexError('Subset %d does not exist in font %s' % (subset, self.fontName))
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1090
        if state.internalName is None:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1091
            state.internalName = state.namePrefix +repr(len(doc.fontMapping) + 1)
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1092
            doc.fontMapping[self.fontName] = '/' + state.internalName
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1093
            doc.delayedFonts.append(self)
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1094
        return '/%s+%d' % (state.internalName, subset)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1095
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1096
    def addObjects(self, doc):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1097
        """Makes  one or more PDF objects to be added to the document.  The
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1098
        caller supplies the internal name to be used (typically F1, F2, ... in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1099
        sequence).
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1100
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1101
        This method creates a number of Font and FontDescriptor objects.  Every
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1102
        FontDescriptor is a (no more than) 256 character subset of the original
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1103
        TrueType font."""
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1104
        try: state = self.state[doc]
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1105
        except KeyError: state = self.state[doc] = TTFont.State(self._asciiReadable)
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1106
        state.frozen = 1
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1107
        for n,subset in enumerate(state.subsets):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1108
            internalName = self.getSubsetInternalName(n, doc)[1:]
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
  1109
            baseFontName = "%s+%s%s" % (SUBSETN(n),self.face.name,self.face.subfontNameX)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1110
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1111
            pdfFont = pdfdoc.PDFTrueTypeFont()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1112
            pdfFont.__Comment__ = 'Font %s subset %d' % (self.fontName, n)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1113
            pdfFont.Name = internalName
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1114
            pdfFont.BaseFont = baseFontName
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1115
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1116
            pdfFont.FirstChar = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1117
            pdfFont.LastChar = len(subset) - 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1118
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1119
            widths = list(map(self.face.getCharWidth, subset))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1120
            pdfFont.Widths = pdfdoc.PDFArray(widths)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1121
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1122
            cmapStream = pdfdoc.PDFStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1123
            cmapStream.content = makeToUnicodeCMap(baseFontName, subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1124
            if doc.compression:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1125
                cmapStream.filters = [pdfdoc.PDFZCompress]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1126
            pdfFont.ToUnicode = doc.Reference(cmapStream, 'toUnicodeCMap:' + baseFontName)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1127
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1128
            pdfFont.FontDescriptor = self.face.addSubsetObjects(doc, baseFontName, subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1129
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1130
            # link it in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1131
            ref = doc.Reference(pdfFont, internalName)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1132
            fontDict = doc.idToObject['BasicFonts'].dict
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1133
            fontDict[internalName] = pdfFont
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1134
        del self.state[doc]
2606
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1135
try:
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1136
    from _rl_accel import _instanceStringWidthTTF
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1137
    import new
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1138
    TTFont.stringWidth = new.instancemethod(_instanceStringWidthTTF,None,TTFont)
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1139
except ImportError:
185b990e8e60 ttfonts.py: allow for _rl_accel._instanceStringWidthTTF
rgbecker
parents: 2582
diff changeset
  1140
    pass