[reportlab-users] Problems with truetype barcode font
Marius Gedminas
reportlab-users@reportlab.com
Tue, 28 Oct 2003 15:12:07 +0200
--rS8CxjVDS/+yyDmU
Content-Type: multipart/mixed; boundary="1yeeQ81UyVL57Vl7"
Content-Disposition: inline
--1yeeQ81UyVL57Vl7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Tue, Oct 28, 2003 at 02:53:08PM +0200, Shayan Raghavjee wrote:
> Thanks for the reply, probably gonna have to find another font. I'm=20
> afriad I didn't get an attachment with the email, I'd be happy to run it=
=20
> if you emailed it to me.
D'uh. Guess who forgot to actually attach the attachment? ;-)
Marius Gedminas
--=20
Voodoo Programming: Things programmers do that they know shouldn't work but
they try anyway, and which sometimes actually work, such as recompiling
everything.
-- Karl Lehenbauer
--1yeeQ81UyVL57Vl7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ttftest.py"
#!/usr/bin/python
# Spike TrueType/OpenType subsetting
# Data Type Description
# ------------- -------------------------------------------------------------
# BYTE 8-bit unsigned integer.
# CHAR 8-bit signed integer.
# USHORT 16-bit unsigned integer.
# SHORT 16-bit signed integer.
# ULONG 32-bit unsigned integer.
# LONG 32-bit signed integer.
# Fixed 32-bit signed fixed-point number (16.16)
# FUNIT Smallest measurable distance in the em space.
# F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14).
# LONGDATETIME Date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a signed 64-bit integer.
# Tag Array of four uint8s (length = 32 bits) used to identify a script, language system, feature, or baseline
# GlyphID Glyph index number, same as uint16(length = 16 bits)
# Offset Offset to a table, same as uint16 (length = 16 bits), NULL offset = 0x0000
#
# NOTE: All numbers are big-endian
# Font file begins with an offset table:
# Fixed sfnt version 0x00010000 for TrueType outlines, 'OTTO' for OpenType with CFF outlines (not relevant here)
# USHORT numTables number of tables
# USHORT searchRange 16 * max(2^n <= numTables)
# USHORT entrySelector max(n: 2^n <= numTables)
# USHORT rangeShift numTables * 16 - searchRange
# ------------------------------ (12 bytes)
# Table directory follows. Each entry is 12 bytes. Entries are sorted by
# tag in lexicographical order. Offsets are from the start of the font file.
# Entry format:
# ULONG tag 4-byte identifier
# ULONG checkSum CheckSum for this table
# ULONG offset Offset from beginning of font file
# ULONG length length of this table
# Checksum calculation:
# ULONG
# CalcTableChecksum(ULONG *Table, ULONG Length)
# {
# ULONG Sum = 0L;
# ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG);
#
# while (Table < EndPtr)
# Sum += *Table++;
# return Sum;
# }
#
# Note: This function implies that the length of a table must be a multiple of
# four bytes. In fact, a font is not considered structurally proper without the
# correct padding. All tables must begin on four byte boundries, and any
# remaining space between tables is padded with zeros. The length of all tables
# should be recorded in the table directory with their actual length (not their
# padded length).
ttf_tables = {
# Required Tables
'cmap': "Character to glyph mapping",
'head': "Font header",
'hhea': "Horizontal header",
'hmtx': "Horizontal metrics",
'maxp': "Maximum profile",
'name': "Naming table",
'OS/2': "OS/2 and Windows specific metrics",
'post': "PostScript information",
# Tables Related to TrueType Outlines
'cvt ': "Control Value Table",
'fpgm': "Font program",
'glyf': "Glyph data",
'loca': "Index to location",
'prep': "CVT program",
# Tables Related to PostScript Outlines
'CFF ': "PostScript font program (compact font format)",
# Obsolete Multiple Master support
'fvar': "obsolete",
'MMSD': "obsolete",
'MMFX': "obsolete",
# Advanced Typographic Tables
'BASE': 'Baseline data',
'GDEF': 'Glyph definition data',
'GPOS': 'Glyph positioning data',
'GSUB': 'Glyph substitution data',
'JSTF': 'Justification data',
# Tables Related to Bitmap Glyphs
'EBDT': 'Embedded bitmap data',
'EBLC': 'Embedded bitmap location data',
'EBSC': 'Embedded bitmap scaling data',
# Other OpenType Tables
'DSIG': 'Digital signature',
'gasp': 'Grid-fitting/Scan-conversion',
'hdmx': 'Horizontal device metrics',
'kern': 'Kerning',
'LTSH': 'Linear threshold data',
'PCLT': 'PCL 5 data',
'VDMX': 'Vertical device metrics',
'vhea': 'Vertical Metrics header',
'vmtx': 'Vertical Metrics',
'VORG': 'Vertical Origin',
}
class TTFParser:
def __init__(self, file):
"Creates a TrueType font file parser. File can be a file name, or a file object."
if type(file) == type(""):
file = open(file, "rb")
self.file = file
version = self.read_ulong()
if version == 0x4F54544F:
raise 'TTFError', 'OpenType fonts with PostScript outlines are not supported'
if version != 0x00010000:
raise 'TTFError', 'Not a TrueType font'
self.numTables = self.read_ushort()
self.searchRange = self.read_ushort()
self.entrySelector = self.read_ushort()
self.rangeShift = self.read_ushort()
self.table = {}
self.tables = []
for n in range(self.numTables):
record = {}
record['tag'] = self.read_tag()
record['checkSum'] = self.read_ulong()
record['offset'] = self.read_ulong()
record['length'] = self.read_ulong()
self.tables.append(record)
self.table[record['tag']] = record
def get_table_pos(self, tag):
tag = (tag + " ")[:4]
offset = self.table[tag]['offset']
length = self.table[tag]['length']
return (offset, length)
def get_table(self, tag):
offset, length = self.get_table_pos(tag)
self.file.seek(offset)
return self.file.read(length)
def tell(self):
return self.file.tell()
def seek(self, pos):
self.file.seek(pos)
def skip(self, delta):
self.file.seek(pos, 1)
def seek_table(self, tag, offset_in_table = 0):
pos = self.get_table_pos(tag)[0] + offset_in_table
self.file.seek(pos)
return pos
def read_tag(self):
return self.file.read(4)
def read_ushort(self):
s = self.file.read(2)
return (ord(s[0]) << 8) + ord(s[1])
def read_short(self):
us = self.read_ushort()
if us >= 0x8000:
return us - 0x10000
else:
return us
def read_ulong(self):
s = self.file.read(4)
return (ord(s[0]) << 24) + (ord(s[1]) << 16) + (ord(s[2]) << 8) + ord(s[3])
def debug_printHeader(self):
print "sfnt version: 1.0"
print "numTables: %d" % self.numTables
print "searchRange: %d" % self.searchRange
print "entrySelector: %d" % self.entrySelector
print "rangeShift: %d" % self.rangeShift
def debug_printIndex(self):
print "Tag Offset Length Checksum"
print "---- ----------- -------- ----------"
for record in self.tables:
print "%(tag)4s +0x%(offset)08X %(length)8d 0x%(checkSum)08x" % record,
if ttf_tables.has_key(record['tag']):
print "", ttf_tables[record['tag']],
print
if __name__ == "__main__":
import sys
if len(sys.argv) == 2:
ttf = TTFParser(sys.argv[1])
ttf.debug_printHeader()
print
ttf.debug_printIndex()
elif len(sys.argv) == 3 and sys.argv[2] == "--perms":
ttf = TTFParser(sys.argv[1])
fsType = ttf.get_table("OS/2")[8:10]
fsType = (ord(fsType[0]) << 8) + ord(fsType[1])
## print "fsType: %04X" % fsType
if fsType == 0:
print "0000 - Installable embedding"
if fsType & 0x0001:
print "0001 - Reserved"
if fsType & 0x0002:
print "0002 - Restricted license embedding (CANNOT EMBED)"
if fsType & 0x0004:
print "0004 - Preview & print embedding"
if fsType & 0x0008:
print "0008 - Editable embedding"
for i in range(4, 8):
if fsType & (1 << i):
print "%04X - Reserved" % (1 << i)
if fsType & 0x0100:
print "0100 - No subsetting"
if fsType & 0x0200:
print "0200 - Bitmap embeding only"
for i in range(10, 16):
if fsType & (1 << i):
print "%04X - Reserved" % (1 << i)
elif len(sys.argv) == 3 and sys.argv[2] == "--cmap":
ttf = TTFParser(sys.argv[1])
start = ttf.seek_table("cmap")
version = ttf.read_ushort()
print "cmap version: %d" % version
numTables = ttf.read_ushort()
print
print "Plat. Enc. Fmt. Offset"
print "----- ----- ----- -----------"
for n in range(numTables):
platform = ttf.read_ushort()
encoding = ttf.read_ushort()
offset = ttf.read_ulong()
pos = ttf.tell()
ttf.seek(start + offset)
format = ttf.read_ushort()
ttf.seek(pos)
print "%5d %5d %5d +0x%08X" % (platform, encoding, format, offset)
elif len(sys.argv) == 3:
ttf = TTFParser(sys.argv[1])
sys.stdout.write(ttf.get_table(sys.argv[2]))
else:
print "Usage: %s filename -- print TTF info" % sys.argv[0]
print " %s filename tag > output -- extract TTF table" % sys.argv[0]
--1yeeQ81UyVL57Vl7--
--rS8CxjVDS/+yyDmU
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)
iD8DBQE/nmsnkVdEXeem148RAjZEAJ44EOH4m6fAXvgjYMxXreehb6JXEwCfUCMG
emvFLVNBYIi6ecv2plSWsEg=
=O310
-----END PGP SIGNATURE-----
--rS8CxjVDS/+yyDmU--