src/reportlab/pdfbase/ttfonts.py
author robin <robin@reportlab.com>
Tue, 07 Mar 2017 10:00:34 +0000
changeset 4330 617ffa6bbdc8
parent 4263 b53fd36c6e4b
child 4367 9960d82643bf
permissions -rw-r--r--
changes for release 3.4.0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4330
617ffa6bbdc8 changes for release 3.4.0
robin <robin@reportlab.com>
parents: 4263
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2017
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
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
    54
from struct import pack, unpack, error as structError
3875
54709854f3e3 ttfonts.py: fix checking of psName
robin
parents: 3841
diff changeset
    55
from reportlab.lib.utils import getBytesIO, isPy3, bytestr, isUnicode, char2int
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    56
from reportlab.pdfbase import pdfmetrics, pdfdoc
3340
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
    57
from reportlab import rl_config
3781
df8b57380768 import from reportlab.lib.lib.rl_accel
robin
parents: 3766
diff changeset
    58
from reportlab.lib.rl_accel import hex32, add32, calcChecksum, instanceStringWidthTTF
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
    59
from collections import namedtuple
4262
94d26172a3bc add rl_settings allowTTFSubsetting; version-->3.3.4
robin
parents: 4252
diff changeset
    60
import os, time
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    61
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    62
class TTFError(pdfdoc.PDFError):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    63
    "TrueType font exception"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    64
    pass
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    65
2509
98368812d002 merge 2628:2629: ttfonts: altered subset naming
rgbecker
parents: 2501
diff changeset
    66
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    67
if isPy3:
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    68
    def SUBSETN(n,table=bytes.maketrans(b'0123456789',b'ABCDEFGIJK')):
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    69
        return bytes('%6.6d'%n,'ASCII').translate(table)
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    70
else:
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    71
    import string
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    72
    def SUBSETN(n,table=string.maketrans(b'0123456789',b'ABCDEFGIJK'),translate=string.translate):
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
    73
        return translate('%6.6d'%n,table)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    74
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    75
# Helpers
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    76
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    77
def makeToUnicodeCMap(fontname, subset):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1682
diff changeset
    78
    """Creates a ToUnicode CMap for a given subset.  See Adobe
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    79
    _PDF_Reference (ISBN 0-201-75839-3) for more information."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    80
    cmap = [
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    81
        "/CIDInit /ProcSet findresource begin",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    82
        "12 dict begin",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    83
        "begincmap",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    84
        "/CIDSystemInfo",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    85
        "<< /Registry (%s)" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    86
        "/Ordering (%s)" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    87
        "/Supplement 0",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    88
        ">> def",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    89
        "/CMapName /%s def" % fontname,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    90
        "/CMapType 2 def",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    91
        "1 begincodespacerange",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    92
        "<00> <%02X>" % (len(subset) - 1),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    93
        "endcodespacerange",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    94
        "%d beginbfchar" % len(subset)
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
    95
        ] + ["<%02X> <%04X>" % (i,v) for i,v in enumerate(subset)] + [
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    96
        "endbfchar",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    97
        "endcmap",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    98
        "CMapName currentdict /CMap defineresource pop",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
    99
        "end",
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   100
        "end"
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
   101
        ]
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   102
    return '\n'.join(cmap)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   103
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   104
def splice(stream, offset, value):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   105
    """Splices the given value into stream at the given offset and
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   106
    returns the resulting stream (the original is unchanged)"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   107
    return stream[:offset] + value + stream[offset + len(value):]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   108
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   109
def _set_ushort(stream, offset, value):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   110
    """Writes the given unsigned short value into stream at the given
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   111
    offset and returns the resulting stream (the original is unchanged)"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   112
    return splice(stream, offset, pack(">H", value))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   113
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   114
# TrueType font handling
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   115
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   116
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   117
GF_ARG_1_AND_2_ARE_WORDS        = 1 << 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   118
GF_ARGS_ARE_XY_VALUES           = 1 << 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   119
GF_ROUND_XY_TO_GRID             = 1 << 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   120
GF_WE_HAVE_A_SCALE              = 1 << 3
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   121
GF_RESERVED                     = 1 << 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   122
GF_MORE_COMPONENTS              = 1 << 5
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   123
GF_WE_HAVE_AN_X_AND_Y_SCALE     = 1 << 6
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   124
GF_WE_HAVE_A_TWO_BY_TWO         = 1 << 7
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   125
GF_WE_HAVE_INSTRUCTIONS         = 1 << 8
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   126
GF_USE_MY_METRICS               = 1 << 9
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   127
GF_OVERLAP_COMPOUND             = 1 << 10
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   128
GF_SCALED_COMPONENT_OFFSET      = 1 << 11
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   129
GF_UNSCALED_COMPONENT_OFFSET    = 1 << 12
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   130
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   131
def TTFOpenFile(fn):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   132
    '''Opens a TTF file possibly after searching TTFSearchPath
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   133
    returns (filename,file)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   134
    '''
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   135
    from reportlab.lib.utils import rl_isfile, open_for_read
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   136
    try:
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   137
        f = open_for_read(fn,'rb')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   138
        return fn, f
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   139
    except IOError:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   140
        import os
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   141
        if not os.path.isabs(fn):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   142
            for D in rl_config.TTFSearchPath:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   143
                tfn = os.path.join(D,fn)
2254
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   144
                if rl_isfile(tfn):
7f11f5116770 Now works in compact distro
rgbecker
parents: 2217
diff changeset
   145
                    f = open_for_read(tfn,'rb')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   146
                    return tfn, f
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   147
        raise TTFError('Can\'t open file "%s"' % fn)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   148
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   149
class TTFontParser:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   150
    "Basic TTF file parser"
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   151
    ttfVersions = (0x00010000,0x74727565,0x74746366)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   152
    ttcVersions = (0x00010000,0x00020000)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   153
    fileKind='TTF'
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   154
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   155
    def __init__(self, file, validate=0,subfontIndex=0):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   156
        """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
   157
        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
   158
        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
   159
        """
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   160
        self.validate = validate
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   161
        self.readFile(file)
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   162
        self._filename = getattr(file,'name','')
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   163
        if self._filename.startswith('<'):
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   164
            self._filename = ''
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   165
        isCollection = self.readHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   166
        if isCollection:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   167
            self.readTTCHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   168
            self.getSubfont(subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   169
        else:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   170
            if self.validate: self.checksumFile()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   171
            self.readTableDirectory()
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
   172
            self.subfontNameX = b''
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   173
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   174
    def readTTCHeader(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   175
        self.ttcVersion = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   176
        self.fileKind = 'TTC'
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   177
        self.ttfVersions = self.ttfVersions[:-1]
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   178
        if self.ttcVersion not in self.ttcVersions: 
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   179
            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
   180
        self.numSubfonts = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   181
        self.subfontOffsets = []
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   182
        a = self.subfontOffsets.append
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   183
        for i in xrange(self.numSubfonts):
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   184
            a(self.read_ulong())
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   185
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   186
    def getSubfont(self,subfontIndex):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   187
        if self.fileKind!='TTC':
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   188
            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
   189
        try:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   190
            pos = self.subfontOffsets[subfontIndex]
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   191
        except IndexError:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   192
            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
   193
        self.seek(pos)
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   194
        self.readHeader()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   195
        self.readTableDirectory()
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
   196
        self.subfontNameX = bytestr('-'+str(subfontIndex))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   197
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   198
    def readTableDirectory(self):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   199
        try:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   200
            self.numTables = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   201
            self.searchRange = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   202
            self.entrySelector = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   203
            self.rangeShift = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   204
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   205
            # Read table directory
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   206
            self.table = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   207
            self.tables = []
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   208
            for n in xrange(self.numTables):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   209
                record = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   210
                record['tag'] = self.read_tag()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   211
                record['checksum'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   212
                record['offset'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   213
                record['length'] = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   214
                self.tables.append(record)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   215
                self.table[record['tag']] = record
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   216
        except:
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   217
            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
   218
        if self.validate: self.checksumTables()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   219
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   220
    def readHeader(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   221
        '''read the sfnt header at the current position'''
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   222
        try:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   223
            self.version = version = self.read_ulong()
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   224
        except:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   225
            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
   226
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   227
        if version==0x4F54544F:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   228
            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
   229
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   230
        if version not in self.ttfVersions:
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   231
            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
   232
        return version==self.ttfVersions[-1]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   233
3132
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   234
    def readFile(self,f):
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   235
        if hasattr(f,'read'):
4159
55e2cc52641c use Marius' idea for name
robin
parents: 4158
diff changeset
   236
            self.filename = getattr(f,'name','(ttf)')   #good idea Marius
4158
b591b402f4cf ttfonts.py: attempt to close open file resource leakage rported by Marius Gedminus
robin
parents: 4141
diff changeset
   237
            self._ttf_data = f.read()
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   238
        else:
3132
f87241ffab1c ttfonts.py: allow unicode filenames (suggestion from Yoann Roman <yroman-reportlab@altalang.com>)
rgbecker
parents: 3127
diff changeset
   239
            self.filename, f = TTFOpenFile(f)
4158
b591b402f4cf ttfonts.py: attempt to close open file resource leakage rported by Marius Gedminus
robin
parents: 4141
diff changeset
   240
            self._ttf_data = f.read()
b591b402f4cf ttfonts.py: attempt to close open file resource leakage rported by Marius Gedminus
robin
parents: 4141
diff changeset
   241
            f.close()
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   242
        self._pos = 0
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   243
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   244
    def checksumTables(self):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   245
        # Check the checksums for all tables
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   246
        for t in self.tables:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   247
            table = self.get_chunk(t['offset'], t['length'])
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   248
            checksum = calcChecksum(table)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   249
            if t['tag'] == 'head':
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   250
                adjustment = unpack('>l', table[8:8+4])[0]
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   251
                checksum = add32(checksum, -adjustment)
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   252
            xchecksum = t['checksum']
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   253
            if xchecksum != checksum:
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   254
                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
   255
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   256
    def checksumFile(self):
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
   257
        # Check the checksums for the whole file
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   258
        checksum = calcChecksum(self._ttf_data)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   259
        if 0xB1B0AFBA!=checksum:
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   260
            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
   261
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   262
    def get_table_pos(self, tag):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   263
        "Returns the offset and size of a given TTF table."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   264
        offset = self.table[tag]['offset']
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   265
        length = self.table[tag]['length']
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   266
        return (offset, length)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   267
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   268
    def seek(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   269
        "Moves read pointer to a given offset in file."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   270
        self._pos = pos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   271
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   272
    def skip(self, delta):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   273
        "Skip the given number of bytes."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   274
        self._pos = self._pos + delta
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   275
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   276
    def seek_table(self, tag, offset_in_table = 0):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   277
        """Moves read pointer to the given offset within a given table and
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   278
        returns absolute offset of that position in the file."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   279
        self._pos = self.get_table_pos(tag)[0] + offset_in_table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   280
        return self._pos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   281
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   282
    if isPy3:
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   283
        def read_tag(self):
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   284
            "Read a 4-character tag"
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   285
            self._pos += 4
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   286
            return str(self._ttf_data[self._pos - 4:self._pos],'utf8')
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   287
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   288
        def get_chunk(self, pos, length):
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   289
            "Return a chunk of raw data at given position"
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
   290
            return bytes(self._ttf_data[pos:pos+length])
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   291
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   292
        def read_uint8(self):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   293
            self._pos += 1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   294
            return int(self._ttf_data[self._pos-1])
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   295
    else:
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   296
        def read_tag(self):
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   297
            "Read a 4-character tag"
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   298
            self._pos += 4
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   299
            return self._ttf_data[self._pos - 4:self._pos]
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   300
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   301
        def get_chunk(self, pos, length):
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   302
            "Return a chunk of raw data at given position"
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3763
diff changeset
   303
            return self._ttf_data[pos:pos+length]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   304
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   305
        def read_uint8(self):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   306
            self._pos += 1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   307
            return ord(self._ttf_data[self._pos-1])
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   308
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   309
    def read_ushort(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   310
        "Reads an unsigned short"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   311
        self._pos += 2
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   312
        return unpack('>H',self._ttf_data[self._pos-2:self._pos])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   313
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   314
    def read_ulong(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   315
        "Reads an unsigned long"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   316
        self._pos += 4
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   317
        return unpack('>L',self._ttf_data[self._pos - 4:self._pos])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   318
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   319
    def read_short(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   320
        "Reads a signed short"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   321
        self._pos += 2
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   322
        try:
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   323
            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
   324
        except structError as error:
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   325
            raise TTFError(error)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   326
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   327
    def get_ushort(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   328
        "Return an unsigned short at given position"
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   329
        return unpack('>H',self._ttf_data[pos:pos+2])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   330
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   331
    def get_ulong(self, pos):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   332
        "Return an unsigned long at given position"
2709
c2bae81ad867 reportlab: new ttfonts checksum
rgbecker
parents: 2678
diff changeset
   333
        return unpack('>L',self._ttf_data[pos:pos+4])[0]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   334
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   335
    def get_table(self, tag):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   336
        "Return the given TTF table"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   337
        pos, length = self.get_table_pos(tag)
2123
78becbedca0c Change to _ttf_data
rgbecker
parents: 2107
diff changeset
   338
        return self._ttf_data[pos:pos+length]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   339
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   340
class TTFontMaker:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   341
    "Basic TTF file generator"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   342
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   343
    def __init__(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   344
        "Initializes the generator."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   345
        self.tables = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   346
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   347
    def add(self, tag, data):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   348
        "Adds a table to the TTF file."
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   349
        if tag == 'head':
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   350
            data = splice(data, 8, b'\0\0\0\0')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   351
        self.tables[tag] = data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   352
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   353
    def makeStream(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   354
        "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
   355
        stm = getBytesIO()
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   356
        write = stm.write
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   357
3934
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   358
        tables = self.tables
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   359
        numTables = len(tables)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   360
        searchRange = 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   361
        entrySelector = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   362
        while searchRange * 2 <= numTables:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   363
            searchRange = searchRange * 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   364
            entrySelector = entrySelector + 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   365
        searchRange = searchRange * 16
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   366
        rangeShift = numTables * 16 - searchRange
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   367
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   368
        # Header
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   369
        write(pack(">lHHHH", 0x00010000, numTables, searchRange,
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   370
                                 entrySelector, rangeShift))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   371
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   372
        # Table directory
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   373
        offset = 12 + numTables * 16
3934
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   374
        wStr = (lambda x:write(bytes(tag,'latin1'))) if isPy3 else write
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   375
        tables_items = list(sorted(tables.items()))
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   376
        for tag, data in tables_items:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   377
            if tag == 'head':
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   378
                head_start = offset
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   379
            checksum = calcChecksum(data)
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   380
            wStr(tag)
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   381
            write(pack(">LLL", checksum, offset, len(data)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   382
            paddedLength = (len(data)+3)&~3
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   383
            offset = offset + paddedLength
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   384
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   385
        # Table data
3934
e03fc86d636c ttfonts.py: fix lambda vs if expression duh!
robin
parents: 3875
diff changeset
   386
        for tag, data in tables_items:
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   387
            data += b"\0\0\0"
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   388
            write(data[:len(data)&~3])
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   389
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   390
        checksum = calcChecksum(stm.getvalue())
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   391
        checksum = add32(0xB1B0AFBA, -checksum)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   392
        stm.seek(head_start + 8)
3127
953069f62709 ttfonts.py: small improvements copied from jython development
rgbecker
parents: 3032
diff changeset
   393
        write(pack('>L', checksum))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   394
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   395
        return stm.getvalue()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   396
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   397
#this is used in the cmap encoding fmt==2 case
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   398
CMapFmt2SubHeader = namedtuple('CMapFmt2SubHeader', 'firstCode entryCount idDelta idRangeOffset')
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   399
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   400
class TTFontFile(TTFontParser):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   401
    "TTF file parser and generator"
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   402
    _agfnc = 0
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   403
    _agfnm = {}
1637
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)
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   453
        for i in xrange(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()
4100
542ded76176d ttfonts.py: fix reading font names in py3; contributed by masayuko @ bitbucket
robin
parents: 4055
diff changeset
   473
                        A(bytes([char]) if isPy3 else chr(char))
2566
a3ba2f7b6e2b ttfonts.py: fix index bug in name table read
rgbecker
parents: 2509
diff changeset
   474
                        length -= 1
4100
542ded76176d ttfonts.py: fix reading font names in py3; contributed by masayuko @ bitbucket
robin
parents: 4055
diff changeset
   475
                    N = b''.join(N)
2566
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:
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   488
            psName = names[6]
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   489
        elif names[4] is not None:
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   490
            psName = names[4]
3275
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:
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   493
            psName = names[1]
3275
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:
4213
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   499
            if rl_config.autoGenerateTTFMissingTTFName:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   500
                fn = self._filename
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   501
                if fn:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   502
                    bfn = os.path.splitext(os.path.basename(fn))[0]
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   503
                if not fn:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   504
                    psName = bytestr('_RL_%s_%s_TTF' % (time.time(), self.__class__._agfnc))
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   505
                    self.__class__._agfnc += 1
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   506
                else:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   507
                    psName = self._agfnm.get(fn,'')
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   508
                    if not psName:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   509
                        if bfn:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   510
                            psName = bytestr('_RL_%s_TTF' % bfn)
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   511
                        else:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   512
                            psName = bytestr('_RL_%s_%s_TTF' % (time.time(), self.__class__._agfnc))
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   513
                            self.__class__._agfnc += 1
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   514
                        self._agfnm[fn] = psName
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   515
            else:
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   516
                raise TTFError("Could not find PostScript font name")
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   517
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   518
        psName = psName.replace(b" ", b"-")  #Dinu Gherman's fix for font names with spaces
577178727e17 autoGenerateMissingTTFName
robin
parents: 4159
diff changeset
   519
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   520
        for c in psName:
3875
54709854f3e3 ttfonts.py: fix checking of psName
robin
parents: 3841
diff changeset
   521
            if char2int(c)>126 or c in b' [](){}<>/%':
54709854f3e3 ttfonts.py: fix checking of psName
robin
parents: 3841
diff changeset
   522
                raise TTFError("psName=%r contains invalid character %s" % (psName,ascii(c)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   523
        self.name = psName
2201
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   524
        self.familyName = names[1] or psName
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   525
        self.styleName = names[2] or 'Regular'
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   526
        self.fullName = names[4] or psName
aa4ec6c9942c Improve error handling & naming
rgbecker
parents: 2129
diff changeset
   527
        self.uniqueFontID = names[3] or psName
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   528
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   529
        # head - Font header table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   530
        self.seek_table("head")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   531
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   532
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   533
            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
   534
        self.fontRevision = self.read_ushort(), self.read_ushort()
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   535
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   536
        self.skip(4)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   537
        magic = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   538
        if magic != 0x5F0F3CF5:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   539
            raise TTFError('Invalid head table magic %04x' % magic)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   540
        self.skip(2)
2774
ad67eff48c23 ttfonts.py: add _bbox (bbox in orig units) and unitsPerEm to TTFontFace
rgbecker
parents: 2768
diff changeset
   541
        self.unitsPerEm = unitsPerEm = self.read_ushort()
2782
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
   542
        scale = lambda x, unitsPerEm=unitsPerEm: x * 1000. / unitsPerEm
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   543
        self.skip(16)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   544
        xMin = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   545
        yMin = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   546
        xMax = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   547
        yMax = self.read_short()
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   548
        self.bbox = list(map(scale, [xMin, yMin, xMax, yMax]))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   549
        self.skip(3*2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   550
        indexToLocFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   551
        glyphDataFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   552
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   553
        # OS/2 - OS/2 and Windows metrics table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   554
        # (needs data from head table)
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   555
        subsettingAllowed = True
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   556
        if "OS/2" in self.table:
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   557
            self.seek_table("OS/2")
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   558
            version = self.read_ushort()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   559
            self.skip(2)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   560
            usWeightClass = self.read_ushort()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   561
            self.skip(2)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   562
            fsType = self.read_ushort()
4262
94d26172a3bc add rl_settings allowTTFSubsetting; version-->3.3.4
robin
parents: 4252
diff changeset
   563
            if fsType==0x0002 or (fsType & 0x0300):
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   564
                subsettingAllowed = os.path.basename(self.filename) not in rl_config.allowTTFSubsetting
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   565
            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
   566
            sTypoAscender = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   567
            sTypoDescender = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   568
            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
   569
            self.descent = scale(sTypoDescender)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   570
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   571
            if version > 1:
2581
f953beeaa16f ttfonts.py: fix up to use struct properly
rgbecker
parents: 2575
diff changeset
   572
                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
   573
                sCapHeight = self.read_short()
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   574
                self.capHeight = scale(sCapHeight)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   575
            else:
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   576
                self.capHeight = self.ascent
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   577
        else:
1718
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   578
            # 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
   579
            # cope.  The data is not very important anyway.
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   580
            usWeightClass = 500
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   581
            self.ascent = scale(yMax)
d9df24d9a50e Support Apple TTFs: different signature and optional OS/2 table
mgedmin
parents: 1690
diff changeset
   582
            self.descent = scale(yMin)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   583
            self.capHeight = self.ascent
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   584
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   585
        # 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
   586
        # 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
   587
        self.stemV = 50 + int((usWeightClass / 65.0) ** 2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   588
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   589
        # post - PostScript table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   590
        # (needs data from OS/2 table)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   591
        self.seek_table("post")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   592
        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
   593
        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
   594
            # 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
   595
            # 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
   596
            # 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
   597
            # try to remove this check altogether.
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   598
            raise TTFError('Unknown post table version %d.%04x' % (ver_maj, ver_min))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   599
        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
   600
        self.underlinePosition = self.read_short()
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   601
        self.underlineThickness = self.read_short()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   602
        isFixedPitch = self.read_ulong()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   603
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   604
        self.flags = FF_SYMBOLIC        # All fonts that contain characters
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   605
                                        # outside the original Adobe character
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   606
                                        # set are considered "symbolic".
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
   607
        if self.italicAngle!= 0:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   608
            self.flags = self.flags | FF_ITALIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   609
        if usWeightClass >= 600:        # FW_REGULAR == 500, FW_SEMIBOLD == 600
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   610
            self.flags = self.flags | FF_FORCEBOLD
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   611
        if isFixedPitch:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   612
            self.flags = self.flags | FF_FIXED
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   613
        # XXX: FF_SERIF?  FF_SCRIPT?  FF_ALLCAP?  FF_SMALLCAP?
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   614
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   615
        # hhea - Horizontal header table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   616
        self.seek_table("hhea")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   617
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   618
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   619
            raise TTFError('Unknown hhea table version %d.%04x' % (ver_maj, ver_min))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   620
        self.skip(28)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   621
        metricDataFormat = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   622
        if metricDataFormat != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   623
            raise TTFError('Unknown horizontal metric data format (%d)' % metricDataFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   624
        numberOfHMetrics = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   625
        if numberOfHMetrics == 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   626
            raise TTFError('Number of horizontal metrics is 0')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   627
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   628
        # maxp - Maximum profile table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   629
        self.seek_table("maxp")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   630
        ver_maj, ver_min = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   631
        if ver_maj != 1:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   632
            raise TTFError('Unknown maxp table version %d.%04x' % (ver_maj, ver_min))
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   633
        self.numGlyphs = numGlyphs = self.read_ushort()
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   634
        if not subsettingAllowed:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   635
            if self.numGlyphs>0xFF:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   636
                raise TTFError('Font does not allow subsetting/embedding (%04X)' % fsType)
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   637
            else:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   638
                self._full_font = True
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   639
        else:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
   640
            self._full_font = False
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   641
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   642
        if not charInfo:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   643
            self.charToGlyph = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   644
            self.defaultWidth = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   645
            self.charWidths = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   646
            return
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   647
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   648
        if glyphDataFormat != 0:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   649
            raise TTFError('Unknown glyph data format (%d)' % glyphDataFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   650
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   651
        # cmap - Character to glyph index mapping table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   652
        cmap_offset = self.seek_table("cmap")
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   653
        cmapVersion = self.read_ushort()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   654
        cmapTableCount = self.read_ushort()
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   655
        if cmapTableCount==0 and cmapVersion!=0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   656
            cmapTableCount, cmapVersion = cmapVersion, cmapTableCount
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   657
        encoffs = None
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   658
        enc = 0
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   659
        for n in xrange(cmapTableCount):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   660
            platform = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   661
            encoding = self.read_ushort()
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   662
            offset = self.read_ulong()
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   663
            if platform==3:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   664
                enc = 1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   665
                encoffs = offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   666
            elif platform==1 and encoding==0 and enc!=1:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   667
                enc = 2
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   668
                encoffs = offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   669
            elif platform==1 and encoding==1:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   670
                enc = 1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   671
                encoffs = offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   672
            elif platform==0 and encoding!=5:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   673
                enc = 1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   674
                encoffs = offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   675
        if encoffs is None:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   676
            raise TTFError('could not find a suitable cmap encoding')
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   677
        encoffs += cmap_offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   678
        self.seek(encoffs)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   679
        fmt = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   680
        self.charToGlyph = charToGlyph = {}
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   681
        glyphToChar = {}
4141
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   682
        if fmt in (13,12,10,8):
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   683
            self.skip(2)    #padding
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   684
            length = self.read_ulong()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   685
            lang = self.read_ulong()
4141
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   686
        else:
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   687
            length = self.read_ushort()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   688
            lang = self.read_ushort()
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   689
        if fmt==0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   690
            T = [self.read_uint8() for i in xrange(length-6)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   691
            for unichar in xrange(min(256,self.numGlyphs,len(table))):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   692
                glyph = T[glyph]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   693
                charToGlyph[unichar] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   694
                glyphToChar.setdefault(glyph,[]).append(unichar)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   695
        elif fmt==4:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   696
            limit = encoffs + length
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   697
            segCount = int(self.read_ushort() / 2.0)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   698
            self.skip(6)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   699
            endCount = [self.read_ushort() for _ in xrange(segCount)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   700
            self.skip(2)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   701
            startCount = [self.read_ushort() for _ in xrange(segCount)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   702
            idDelta = [self.read_short() for _ in xrange(segCount)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   703
            idRangeOffset_start = self._pos
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   704
            idRangeOffset = [self.read_ushort() for _ in xrange(segCount)]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   705
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   706
            # Now it gets tricky.
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   707
            for n in xrange(segCount):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   708
                for unichar in xrange(startCount[n], endCount[n] + 1):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   709
                    if idRangeOffset[n] == 0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   710
                        glyph = (unichar + idDelta[n]) & 0xFFFF
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   711
                    else:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   712
                        offset = (unichar - startCount[n]) * 2 + idRangeOffset[n]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   713
                        offset = idRangeOffset_start + 2 * n + offset
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   714
                        if offset >= limit:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   715
                            # workaround for broken fonts (like Thryomanes)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   716
                            glyph = 0
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   717
                        else:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   718
                            glyph = self.get_ushort(offset)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   719
                            if glyph != 0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   720
                                glyph = (glyph + idDelta[n]) & 0xFFFF
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   721
                    charToGlyph[unichar] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   722
                    glyphToChar.setdefault(glyph,[]).append(unichar)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   723
        elif fmt==6:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   724
            first = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   725
            count = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   726
            for glyph in xrange(first,first+count):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   727
                unichar = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   728
                charToGlyph[unichar] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   729
                glyphToChar.setdefault(glyph,[]).append(unichar)
4141
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   730
        elif fmt==10:
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   731
            first = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   732
            count = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   733
            for glyph in xrange(first,first+count):
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   734
                unichar = self.read_ushort()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   735
                charToGlyph[unichar] = glyph
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   736
                glyphToChar.setdefault(glyph,[]).append(unichar)
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   737
        elif fmt==12:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   738
            segCount = self.read_ulong()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   739
            for n in xrange(segCount):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   740
                start = self.read_ulong()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   741
                end = self.read_ulong()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   742
                inc = self.read_ulong() - start
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   743
                for unichar in xrange(start,end+1):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   744
                    glyph = unichar + inc
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   745
                    charToGlyph[unichar] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   746
                    glyphToChar.setdefault(glyph,[]).append(unichar)
4141
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   747
        elif fmt==13:
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   748
            segCount = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   749
            for n in xrange(segCount):
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   750
                start = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   751
                end = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   752
                gid = self.read_ulong()
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   753
                for unichar in xrange(start,end+1):
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   754
                    charToGlyph[unichar] = gid
d530e1a4afe7 experimental ttf cmaps 10 & 13; version-->3.1.38
robin
parents: 4106
diff changeset
   755
                    glyphToChar.setdefault(gid,[]).append(unichar)
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   756
        elif fmt==2:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   757
            T = [self.read_ushort() for i in xrange(256)]   #subheader keys
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   758
            maxSHK = max(T)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   759
            SH = []
4101
29a9e68d8845 ttfonts.py: fix typo/bug in format2 reported by rmathot@bitbucket.org
robin
parents: 4100
diff changeset
   760
            for i in xrange(maxSHK+1):
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   761
                firstCode = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   762
                entryCount = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   763
                idDelta = self.read_ushort()
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   764
                idRangeOffset = (self.read_ushort()-(maxSHK-i)*8-2)>>1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   765
                SH.append(CMapFmt2SubHeader(firstCode,entryCount,idDelta,idRangeOffset))
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   766
            #number of glyph indexes to read. it is the length of the entire subtable minus that bit we've read so far
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   767
            entryCount = (length-(self._pos-(cmap_offset+encoffs)))>>1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   768
            glyphs = [self.read_short() for i in xrange(entryCount)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   769
            last = -1
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   770
            for unichar in xrange(256):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   771
                if T[unichar]==0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   772
                    #Special case, single byte encoding entry, look unichar up in subhead
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   773
                    if last!=-1:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   774
                        glyph = 0
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   775
                    elif (unichar<SH[0].firstCode or unichar>=SH[0].firstCode+SH[0].entryCount or
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   776
                            SH[0].idRangeOffset+(unichar-SH[0].firstCode)>=entryCount):
1749
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   777
                        glyph = 0
3e11c6e8efa6 Added a workaround for some broken TTFs (like Thyromanes)
mgedmin
parents: 1748
diff changeset
   778
                    else:
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   779
                        glyph = glyphs[SH[0].idRangeOffset+(unichar-SH[0].firstCode)]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   780
                        if glyph!=0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   781
                            glyph += SH[0].idDelta
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   782
                    #assume the single byte codes are ascii
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   783
                    if glyph!=0 and glyph<self.numGlyphs:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   784
                        charToGlyph[unichar] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   785
                        glyphToChar.setdefault(glyph,[]).append(unichar)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   786
                else:
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   787
                    k = T[unichar]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   788
                    for j in xrange(SH[k].entryCount):
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   789
                        if SH[k].idRangeOffset+j>=entryCount:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   790
                            glyph = 0
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   791
                        else:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   792
                            glyph = glyphs[SH[k].idRangeOffset+j]
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   793
                            if glyph!= 0:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   794
                                glyph += SH[k].idDelta
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   795
                        if glyph!=0 and glyph<self.numGlyphs:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   796
                            enc = (unichar<<8)|(j+SH[k].firstCode)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   797
                            charToGlyph[enc] = glyph
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   798
                            glyphToChar.setdefault(glyph,[]).append(enc)
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   799
                    if last==-1:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   800
                        last = unichar
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   801
        else:
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   802
            raise ValueError('Unsupported cmap encoding format %d' % fmt)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   803
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   804
        # hmtx - Horizontal metrics table
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   805
        # (needs data from hhea, maxp, and cmap tables)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   806
        self.seek_table("hmtx")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   807
        aw = None
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   808
        self.charWidths = {}
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   809
        self.hmetrics = []
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   810
        for glyph in xrange(numberOfHMetrics):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   811
            # advance width and left side bearing.  lsb is actually signed
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   812
            # short, but we don't need it anyway (except for subsetting)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   813
            aw, lsb = self.read_ushort(), self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   814
            self.hmetrics.append((aw, lsb))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   815
            aw = scale(aw)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   816
            if glyph == 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   817
                self.defaultWidth = aw
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   818
            if glyph in glyphToChar:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   819
                for char in glyphToChar[glyph]:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   820
                    self.charWidths[char] = aw
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   821
        for glyph in xrange(numberOfHMetrics, numGlyphs):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   822
            # the rest of the table only lists advance left side bearings.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   823
            # so we reuse aw set by the last iteration of the previous loop
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   824
            lsb = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   825
            self.hmetrics.append((aw, lsb))
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   826
            if glyph in glyphToChar:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   827
                for char in glyphToChar[glyph]:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   828
                    self.charWidths[char] = aw
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   829
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   830
        # loca - Index to location
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   831
        self.seek_table('loca')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   832
        self.glyphPos = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   833
        if indexToLocFormat == 0:
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   834
            for n in xrange(numGlyphs + 1):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   835
                self.glyphPos.append(self.read_ushort() << 1)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   836
        elif indexToLocFormat == 1:
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   837
            for n in xrange(numGlyphs + 1):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   838
                self.glyphPos.append(self.read_ulong())
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   839
        else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   840
            raise TTFError('Unknown location table format (%d)' % indexToLocFormat)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   841
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   842
    # Subsetting
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   843
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   844
    def makeSubset(self, subset):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   845
        """Create a subset of a TrueType font"""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   846
        output = TTFontMaker()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   847
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   848
        # Build a mapping of glyphs in the subset to glyph numbers in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   849
        # the original font.  Also build a mapping of UCS codes to
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   850
        # glyph values in the new font.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   851
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1682
diff changeset
   852
        # Start with 0 -> 0: "missing character"
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   853
        glyphMap = [0]                  # new glyph index -> old glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   854
        glyphSet = {0:0}                # old glyph index -> new glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   855
        codeToGlyph = {}                # unicode -> new glyph index
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   856
        for code in subset:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   857
            if code in self.charToGlyph:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   858
                originalGlyphIdx = self.charToGlyph[code]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   859
            else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   860
                originalGlyphIdx = 0
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   861
            if originalGlyphIdx not in glyphSet:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   862
                glyphSet[originalGlyphIdx] = len(glyphMap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   863
                glyphMap.append(originalGlyphIdx)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   864
            codeToGlyph[code] = glyphSet[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   865
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   866
        # Also include glyphs that are parts of composite glyphs
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   867
        start = self.get_table_pos('glyf')[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   868
        n = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   869
        while n < len(glyphMap):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   870
            originalGlyphIdx = glyphMap[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   871
            glyphPos = self.glyphPos[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   872
            glyphLen = self.glyphPos[originalGlyphIdx + 1] - glyphPos
3275
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   873
            n += 1
c53e22ea435f ttfonts.py: fix problems parsing 6000 ttfs contributed by Jerry Casiano
rgbecker
parents: 3132
diff changeset
   874
            if not glyphLen: continue
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   875
            self.seek(start + glyphPos)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   876
            numberOfContours = self.read_short()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   877
            if numberOfContours < 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   878
                # composite glyph
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   879
                self.skip(8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   880
                flags = GF_MORE_COMPONENTS
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   881
                while flags & GF_MORE_COMPONENTS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   882
                    flags = self.read_ushort()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   883
                    glyphIdx = self.read_ushort()
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   884
                    if glyphIdx not in glyphSet:
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   885
                        glyphSet[glyphIdx] = len(glyphMap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   886
                        glyphMap.append(glyphIdx)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   887
                    if flags & GF_ARG_1_AND_2_ARE_WORDS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   888
                        self.skip(4)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   889
                    else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   890
                        self.skip(2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   891
                    if flags & GF_WE_HAVE_A_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   892
                        self.skip(2)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   893
                    elif flags & GF_WE_HAVE_AN_X_AND_Y_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   894
                        self.skip(4)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   895
                    elif flags & GF_WE_HAVE_A_TWO_BY_TWO:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   896
                        self.skip(8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   897
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   898
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   899
        # The following tables are simply copied from the original
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   900
        for tag in ('name', 'OS/2', 'cvt ', 'fpgm', 'prep'):
1682
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   901
            try:
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   902
                output.add(tag, self.get_table(tag))
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   903
            except KeyError:
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   904
                # Apparently some of the tables are optional (cvt, fpgm, prep).
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   905
                # 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
   906
                # been caught before.
e2639301c342 Marius' path for non-standard TrueType files
andy_robinson
parents: 1664
diff changeset
   907
                pass
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   908
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   909
        # post - PostScript
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   910
        post = b"\x00\x03\x00\x00" + self.get_table('post')[4:16] + b"\x00" * 16
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   911
        output.add('post', post)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   912
4106
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   913
        numGlyphs = len(glyphMap)
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   914
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   915
        # hmtx - Horizontal Metrics
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   916
        hmtx = []
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   917
        for n in xrange(numGlyphs):
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   918
            aw, lsb = self.hmetrics[glyphMap[n]]
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   919
            hmtx.append(int(aw))
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   920
            hmtx.append(int(lsb))
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   921
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   922
        #work out n as 0 or first aw that's the start of a run
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   923
        n = len(hmtx)-2
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   924
        while n and hmtx[n]==hmtx[n-2]:
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   925
            n -= 2
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   926
        if not n: n = 2                 #need at least one pair
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   927
        numberOfHMetrics = n>>1         #number of full H Metric pairs
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   928
        hmtx = hmtx[:n] + hmtx[n+1::2]  #full pairs + all the trailing lsb's
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   929
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   930
        hmtx = pack(*([">%dH" % len(hmtx)] + hmtx))
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   931
        output.add('hmtx', hmtx)
cc61aadfa32a ttfonts.py: fix horizontal metrics (htmx table) computation
robin
parents: 4101
diff changeset
   932
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   933
        # hhea - Horizontal Header
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   934
        hhea = self.get_table('hhea')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   935
        hhea = _set_ushort(hhea, 34, numberOfHMetrics)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   936
        output.add('hhea', hhea)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   937
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   938
        # maxp - Maximum Profile
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   939
        maxp = self.get_table('maxp')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   940
        maxp = _set_ushort(maxp, 4, numGlyphs)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   941
        output.add('maxp', maxp)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   942
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   943
        # cmap - Character to glyph mapping
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   944
        # XXX maybe use format 0 if possible, not 6?
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   945
        entryCount = len(subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   946
        length = 10 + entryCount * 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   947
        cmap = [0, 1,           # version, number of tables
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   948
                1, 0, 0,12,     # platform, encoding, offset (hi,lo)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   949
                6, length, 0,   # format, length, language
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   950
                0,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   951
                entryCount] + \
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   952
               list(map(codeToGlyph.get, subset))
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
   953
        cmap = pack(*([">%dH" % len(cmap)] + cmap))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   954
        output.add('cmap', cmap)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   955
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   956
        # glyf - Glyph data
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   957
        glyphData = self.get_table('glyf')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   958
        offsets = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   959
        glyf = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   960
        pos = 0
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
   961
        for n in xrange(numGlyphs):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   962
            offsets.append(pos)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   963
            originalGlyphIdx = glyphMap[n]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   964
            glyphPos = self.glyphPos[originalGlyphIdx]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   965
            glyphLen = self.glyphPos[originalGlyphIdx + 1] - glyphPos
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   966
            data = glyphData[glyphPos:glyphPos+glyphLen]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   967
            # Fix references in composite glyphs
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   968
            if glyphLen > 2 and unpack(">h", data[:2])[0] < 0:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   969
                # composite glyph
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   970
                pos_in_glyph = 10
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   971
                flags = GF_MORE_COMPONENTS
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   972
                while flags & GF_MORE_COMPONENTS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   973
                    flags = unpack(">H", data[pos_in_glyph:pos_in_glyph+2])[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   974
                    glyphIdx = unpack(">H", data[pos_in_glyph+2:pos_in_glyph+4])[0]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   975
                    data = _set_ushort(data, pos_in_glyph + 2, glyphSet[glyphIdx])
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   976
                    pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   977
                    if flags & GF_ARG_1_AND_2_ARE_WORDS:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   978
                        pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   979
                    else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   980
                        pos_in_glyph = pos_in_glyph + 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   981
                    if flags & GF_WE_HAVE_A_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   982
                        pos_in_glyph = pos_in_glyph + 2
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   983
                    elif flags & GF_WE_HAVE_AN_X_AND_Y_SCALE:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   984
                        pos_in_glyph = pos_in_glyph + 4
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   985
                    elif flags & GF_WE_HAVE_A_TWO_BY_TWO:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   986
                        pos_in_glyph = pos_in_glyph + 8
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   987
            glyf.append(data)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   988
            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
   989
            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
   990
                padding = 4 - pos % 4
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   991
                glyf.append(b'\0' * padding)
1745
1915be8a52df Align glyphs at dword boundaries as recommended by the TTF spec. (also fixes a bug)
mgedmin
parents: 1721
diff changeset
   992
                pos = pos + padding
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   993
        offsets.append(pos)
3766
4fa0f4494409 ttfonts.py: py33 branch at least can draw to PDF
robin
parents: 3765
diff changeset
   994
        output.add('glyf', b''.join(glyf))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   995
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   996
        # loca - Index to location
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   997
        loca = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   998
        if (pos + 1) >> 1 > 0xFFFF:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
   999
            indexToLocFormat = 1        # long format
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1000
            for offset in offsets:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1001
                loca.append(offset)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1002
            loca = pack(*([">%dL" % len(loca)] + loca))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1003
        else:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1004
            indexToLocFormat = 0        # short format
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1005
            for offset in offsets:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1006
                loca.append(offset >> 1)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1007
            loca = pack(*([">%dH" % len(loca)] + loca))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1008
        output.add('loca', loca)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1009
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1010
        # head - Font header
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1011
        head = self.get_table('head')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1012
        head = _set_ushort(head, 50, indexToLocFormat)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1013
        output.add('head', head)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1014
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1015
        return output.makeStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1016
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1017
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1018
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1019
# TrueType font embedding
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1020
#
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1021
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1022
# PDF font flags (see PDF Reference Guide table 5.19)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1023
FF_FIXED        = 1 <<  1-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1024
FF_SERIF        = 1 <<  2-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1025
FF_SYMBOLIC     = 1 <<  3-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1026
FF_SCRIPT       = 1 <<  4-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1027
FF_NONSYMBOLIC  = 1 <<  6-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1028
FF_ITALIC       = 1 <<  7-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1029
FF_ALLCAP       = 1 << 17-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1030
FF_SMALLCAP     = 1 << 18-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1031
FF_FORCEBOLD    = 1 << 19-1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1032
2216
aadcd9dc9480 Font reregistration cleanup
andy_robinson
parents: 2201
diff changeset
  1033
class TTFontFace(TTFontFile, pdfmetrics.TypeFace):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1034
    """TrueType typeface.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1035
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1036
    Conceptually similar to a single byte typeface, but the glyphs are
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1037
    identified by UCS character codes instead of glyph names."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1038
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
  1039
    def __init__(self, filename, validate=0, subfontIndex=0):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1040
        "Loads a TrueType font from filename."
2216
aadcd9dc9480 Font reregistration cleanup
andy_robinson
parents: 2201
diff changeset
  1041
        pdfmetrics.TypeFace.__init__(self, None)
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
  1042
        TTFontFile.__init__(self, filename, validate=validate, subfontIndex=subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1043
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1044
    def getCharWidth(self, code):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1045
        "Returns the width of character U+<code>"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1046
        return self.charWidths.get(code, self.defaultWidth)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1047
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1048
    def addSubsetObjects(self, doc, fontname, subset):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1049
        """Generate a TrueType font subset and add it to the PDF document.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1050
        Returns a PDFReference to the new FontDescriptor object."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1051
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1052
        fontFile = pdfdoc.PDFStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1053
        fontFile.content = self.makeSubset(subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1054
        fontFile.dictionary['Length1'] = len(fontFile.content)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1055
        if doc.compression:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1056
            fontFile.filters = [pdfdoc.PDFZCompress]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1057
        fontFileRef = doc.Reference(fontFile, 'fontFile:%s(%s)' % (self.filename, fontname))
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1058
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1059
        flags = self.flags & ~ FF_NONSYMBOLIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1060
        flags = flags | FF_SYMBOLIC
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1061
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1062
        fontDescriptor = pdfdoc.PDFDictionary({
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1063
            'Type': '/FontDescriptor',
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1064
            'Ascent': self.ascent,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1065
            'CapHeight': self.capHeight,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1066
            'Descent': self.descent,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1067
            'Flags': flags,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1068
            'FontBBox': pdfdoc.PDFArray(self.bbox),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1069
            'FontName': pdfdoc.PDFName(fontname),
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1070
            'ItalicAngle': self.italicAngle,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1071
            'StemV': self.stemV,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1072
            'FontFile2': fontFileRef,
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1073
            })
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1074
        return doc.Reference(fontDescriptor, 'fontDescriptor:' + fontname)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1075
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1076
class TTEncoding:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1077
    """Encoding for TrueType fonts (always UTF-8).
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1078
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1079
    TTEncoding does not directly participate in PDF object creation, since
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1080
    we need a number of different 8-bit encodings for every generated font
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1081
    subset.  TTFont itself cares about that."""
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1082
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1083
    def __init__(self):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1084
        self.name = "UTF-8"
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1085
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1086
class TTFont:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1087
    """Represents a TrueType font.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1088
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1089
    Its encoding is always UTF-8.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1090
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1091
    Note: you cannot use the same TTFont object for different documents
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1092
    at the same time.
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1093
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1094
    Example of usage:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1095
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1096
        font = ttfonts.TTFont('PostScriptFontName', '/path/to/font.ttf')
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1097
        pdfmetrics.registerFont(font)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1098
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1099
        canvas.setFont('PostScriptFontName', size)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1100
        canvas.drawString(x, y, "Some text encoded in UTF-8")
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1101
    """
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1102
    class State:
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1103
        namePrefix = 'F'
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1104
        def __init__(self,asciiReadable=None,ttf=None):
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1105
            A = self.assignments = {}
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1106
            self.nextCode = 0
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1107
            self.internalName = None
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1108
            self.frozen = 0
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1109
            if getattr(getattr(ttf,'face',None),'_full_font',None):
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1110
                C = set(self.charToGlyph.keys())
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1111
                for n in xrange(256):
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1112
                    if n in C:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1113
                        A[n] = n
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1114
                        C.remove(n)
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1115
                for n in C:
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1116
                    A[n] = n
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1117
                self.subsets = [[n for n in A]]
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1118
                self.frozen = True
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1119
                return
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1120
3340
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
  1121
            if asciiReadable is None:
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
  1122
                asciiReadable = rl_config.ttfAsciiReadable
7dce483dd143 ttfonts.py: use rl_config for standard asciiReadable
rgbecker
parents: 3326
diff changeset
  1123
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1124
            if asciiReadable:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1125
                # Let's add the first 128 unicodes to the 0th subset, so ' '
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1126
                # always has code 32 (for word spacing to work) and the ASCII
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1127
                # output is readable
4055
39186be8447c ttfonts.py: attempt to improve cmap encodings handling (works for me with formats=4 & 12)
robin
parents: 4051
diff changeset
  1128
                subset0 = list(xrange(128))
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1129
                self.subsets = [subset0]
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1130
                for n in subset0:
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1131
                    A[n] = n
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1132
                self.nextCode = 128
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1133
            else:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1134
                self.subsets = [[32]*33]
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1135
                A[32] = 32
2501
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1136
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1137
    _multiByte = 1      # We want our own stringwidth
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1138
    _dynamicFont = 1    # We want dynamic subsetting
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1139
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1140
    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
  1141
        """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
  1142
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
  1143
        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
  1144
        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
  1145
        """
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1146
        self.fontName = name
2582
4a008286f3dc reportlab: wastefully allow TTFont to use ttc files
rgbecker
parents: 2581
diff changeset
  1147
        self.face = TTFontFace(filename, validate=validate, subfontIndex=subfontIndex)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1148
        self.encoding = TTEncoding()
2678
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1149
        from weakref import WeakKeyDictionary
38d18a697cd0 reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents: 2645
diff changeset
  1150
        self.state = WeakKeyDictionary()
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1151
        if asciiReadable is None:
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3340
diff changeset
  1152
            asciiReadable = rl_config.ttfAsciiReadable
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1153
        self._asciiReadable = asciiReadable
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1154
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1155
    def stringWidth(self,text,size,encoding='utf8'):
3781
df8b57380768 import from reportlab.lib.lib.rl_accel
robin
parents: 3766
diff changeset
  1156
        return instanceStringWidthTTF(self,text,size,encoding)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1157
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1158
    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
  1159
        '''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
  1160
        if asciiReadable is None:
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1161
            asciiReadable = self._asciiReadable
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1162
        try:
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1163
            state = self.state[doc]
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1164
        except KeyError:
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1165
            state = self.state[doc] = TTFont.State(asciiReadable,self)
2785
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1166
            if namePrefix is not None:
5e9233938058 ttfonts.py: allow for different subset name prefix
rgbecker
parents: 2782
diff changeset
  1167
                state.namePrefix = namePrefix
2782
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1168
        return state
d21452d865f2 ttfonts.py: pdfbase/ttfonts.py: add _assignState, fix scale, remove _bbox
rgbecker
parents: 2774
diff changeset
  1169
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2566
diff changeset
  1170
    def splitString(self, text, doc, encoding='utf-8'):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1171
        """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
  1172
        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
  1173
        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
  1174
        subsets when building different documents at the same time."""
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1175
        asciiReadable = self._asciiReadable
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1176
        try: state = self.state[doc]
4263
b53fd36c6e4b support small ttfs which don't allow subsets
robin
parents: 4262
diff changeset
  1177
        except KeyError: state = self.state[doc] = TTFont.State(asciiReadable,self)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1178
        curSet = -1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1179
        cur = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1180
        results = []
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1181
        if not isUnicode(text):
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1182
            text = text.decode('utf-8')     # encoding defaults to utf-8
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1183
        assignments = state.assignments
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1184
        subsets = state.subsets
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2566
diff changeset
  1185
        for code in map(ord,text):
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1186
            if code in assignments:
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1187
                n = assignments[code]
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1188
            else:
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1189
                if state.frozen:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1190
                    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
  1191
                n = state.nextCode
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1192
                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
  1193
                    # make code 32 always be a space character
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1194
                    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
  1195
                    state.nextCode += 1
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1196
                    n = state.nextCode
98a53df9b49e ttfonts.py: apply Albertas Agejevas' <alga@pov.lt> spaces patch to fix para splitting
rgbecker
parents: 2341
diff changeset
  1197
                state.nextCode += 1
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1198
                assignments[code] = n
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1199
                if n>32:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1200
                    if not(n&0xFF): subsets.append([])
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1201
                    subsets[n >> 8].append(code)
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1202
                else:
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1203
                    subsets[0][n] = code
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1204
            if (n >> 8) != curSet:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1205
                if cur:
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1206
                    results.append((curSet,bytes(cur) if isPy3 else ''.join(chr(c) for c in cur)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1207
                curSet = (n >> 8)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1208
                cur = []
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1209
            cur.append(n & 0xFF)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1210
        if cur:
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1211
            results.append((curSet,bytes(cur) if isPy3 else ''.join(chr(c) for c in cur)))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1212
        return results
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1213
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1214
    def getSubsetInternalName(self, subset, doc):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1215
        """Returns the name of a PDF Font object corresponding to a given
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1216
        subset of this dynamic font.  Use this function instead of
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1217
        PDFDocument.getInternalFontName."""
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1218
        try: state = self.state[doc]
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1219
        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
  1220
        if subset < 0 or subset >= len(state.subsets):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1221
            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
  1222
        if state.internalName is None:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3275
diff changeset
  1223
            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
  1224
            doc.fontMapping[self.fontName] = '/' + state.internalName
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1225
            doc.delayedFonts.append(self)
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1226
        return '/%s+%d' % (state.internalName, subset)
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1227
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1228
    def addObjects(self, doc):
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1229
        """Makes  one or more PDF objects to be added to the document.  The
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1230
        caller supplies the internal name to be used (typically F1, F2, ... in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1231
        sequence).
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1232
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1233
        This method creates a number of Font and FontDescriptor objects.  Every
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1234
        FontDescriptor is a (no more than) 256 character subset of the original
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1235
        TrueType font."""
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1236
        try: state = self.state[doc]
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1237
        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
  1238
        state.frozen = 1
2645
ba65582b2f3f ttfonts.py: asciReadable kw arg added
rgbecker
parents: 2606
diff changeset
  1239
        for n,subset in enumerate(state.subsets):
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1240
            internalName = self.getSubsetInternalName(n, doc)[1:]
3841
72bbe8c8295c ttfonts.py: fix up so we produce bytes again
robin
parents: 3781
diff changeset
  1241
            baseFontName = (b''.join((SUBSETN(n),b'+',self.face.name,self.face.subfontNameX))).decode('pdfdoc')
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1242
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1243
            pdfFont = pdfdoc.PDFTrueTypeFont()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1244
            pdfFont.__Comment__ = 'Font %s subset %d' % (self.fontName, n)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1245
            pdfFont.Name = internalName
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1246
            pdfFont.BaseFont = baseFontName
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1247
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1248
            pdfFont.FirstChar = 0
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1249
            pdfFont.LastChar = len(subset) - 1
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1250
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
  1251
            widths = list(map(self.face.getCharWidth, subset))
1637
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1252
            pdfFont.Widths = pdfdoc.PDFArray(widths)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1253
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1254
            cmapStream = pdfdoc.PDFStream()
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1255
            cmapStream.content = makeToUnicodeCMap(baseFontName, subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1256
            if doc.compression:
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1257
                cmapStream.filters = [pdfdoc.PDFZCompress]
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1258
            pdfFont.ToUnicode = doc.Reference(cmapStream, 'toUnicodeCMap:' + baseFontName)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1259
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1260
            pdfFont.FontDescriptor = self.face.addSubsetObjects(doc, baseFontName, subset)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1261
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1262
            # link it in
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1263
            ref = doc.Reference(pdfFont, internalName)
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1264
            fontDict = doc.idToObject['BasicFonts'].dict
ab6e7091da40 Added Marius Gedminas' TTF support
rgbecker
parents:
diff changeset
  1265
            fontDict[internalName] = pdfFont
1690
2adbe2b8005a Allow use of a TTFont on different documents at the same time
mgedmin
parents: 1683
diff changeset
  1266
        del self.state[doc]