Some non-official OT tables from rrboerts. He wrote:
There are also some new files, for SING glyphlet support, that you may or may not want to add, because they are not in the OpenType spec. M_E_T_A_.py # SING glyphlet meta data table. see 'http://partners.adobe.com/public/developer/opentype/gdk/topic.html" S_I_N_G_.py # SING glyphlet basic info. See same web site as for META data table. G_M_A_P_.py # Summary of sing glyphlet info that has been stuck into a parent font. Not documented anywhere yet. G_P_K_G_.py # Opaque wrapper for SING glyphlet info; travels with application document. Is also stuck into augmented parent font. Not documented anywhere yet git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@507 4cde692c-a291-49d1-8350-778aa11640f8
This commit is contained in:
parent
192655c661
commit
4cc0051c08
@ -42,7 +42,7 @@ When using TTX from the command line there are a bunch of extra options, these a
|
||||
The following tables are currently supported:
|
||||
<BLOCKQUOTE><TT>
|
||||
<!-- begin table list -->
|
||||
BASE, CFF, DSIG, GDEF, GPOS, GSUB, JSTF, LTSH, OS/2, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID, TSIJ, TSIP, TSIS, TSIV, VORG, cmap, cvt, fpgm, gasp, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, post, prep, vhea and vmtx
|
||||
BASE, CFF, DSIG, GDEF, GMAP, GPKG, GPOS, GSUB, JSTF, LTSH, META, OS/2, SING, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID, TSIJ, TSIP, TSIS, TSIV, VORG, cmap, cvt, fpgm, gasp, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, post, prep, vhea and vmtx
|
||||
<!-- end table list -->
|
||||
</TT></BLOCKQUOTE>
|
||||
Other tables are dumped as hexadecimal data.
|
||||
|
139
Lib/fontTools/ttLib/tables/G_M_A_P_.py
Normal file
139
Lib/fontTools/ttLib/tables/G_M_A_P_.py
Normal file
@ -0,0 +1,139 @@
|
||||
import DefaultTable
|
||||
import sstruct
|
||||
from types import StringType
|
||||
from fontTools.misc.textTools import safeEval, num2binary, binary2num
|
||||
|
||||
GMAPFormat = """
|
||||
> # big endian
|
||||
tableVersionMajor: H
|
||||
tableVersionMinor: H
|
||||
flags: H
|
||||
recordsCount: H
|
||||
recordsOffset: H
|
||||
fontNameLength: H
|
||||
"""
|
||||
# psFontName is a byte string which follows the record above. This is zero padded
|
||||
# to the beginning of the records array. The recordsOffsst is 32 bit aligned.
|
||||
|
||||
GMAPRecordFormat1 = """
|
||||
> # big endian
|
||||
UV: L
|
||||
cid: H
|
||||
gid: H
|
||||
ggid: H
|
||||
name: 32s
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class GMAPRecord:
|
||||
def __init__(self, uv = 0, cid = 0, gid = 0, ggid = 0, name = ""):
|
||||
self.UV = uv
|
||||
self.cid = cid
|
||||
self.gid = gid
|
||||
self.ggid = ggid
|
||||
self.name = name
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.begintag("GMAPRecord")
|
||||
writer.newline()
|
||||
writer.simpletag("UV", value=self.UV)
|
||||
writer.newline()
|
||||
writer.simpletag("cid", value=self.cid)
|
||||
writer.newline()
|
||||
writer.simpletag("gid", value=self.gid)
|
||||
writer.newline()
|
||||
writer.simpletag("glyphletGid", value=self.gid)
|
||||
writer.newline()
|
||||
writer.simpletag("GlyphletName", value=self.name)
|
||||
writer.newline()
|
||||
writer.endtag("GMAPRecord")
|
||||
writer.newline()
|
||||
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
value = attrs["value"]
|
||||
if name == "GlyphletName":
|
||||
self.name = value
|
||||
else:
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
def compile(self, ttFont):
|
||||
if self.UV == None:
|
||||
self.UV = 0
|
||||
nameLen = len(self.name)
|
||||
if nameLen < 32:
|
||||
self.name = self.name + "\0"*(32 - nameLen)
|
||||
data = sstruct.pack(GMAPRecordFormat1, self)
|
||||
return data
|
||||
|
||||
def __repr__(self):
|
||||
return "GMAPRecord[ UV: " + str(self.UV) + ", cid: " + str(self.cid) + ", gid: " + str(self.gid) + ", ggid: " + str(self.ggid) + ", Glyphlet Name: " + str(self.name) + " ]"
|
||||
|
||||
|
||||
class table_G_M_A_P_(DefaultTable.DefaultTable):
|
||||
|
||||
dependencies = []
|
||||
|
||||
def decompile(self, data, ttFont):
|
||||
dummy, newData = sstruct.unpack2(GMAPFormat, data, self)
|
||||
self.psFontName = newData[:self.fontNameLength]
|
||||
assert (self.recordsOffset % 4) == 0, "GMAP error: recordsOffset is not 32 bit aligned."
|
||||
newData = data[self.recordsOffset:]
|
||||
self.gmapRecords = []
|
||||
for i in range (self.recordsCount):
|
||||
gmapRecord, newData = sstruct.unpack2(GMAPRecordFormat1, newData, GMAPRecord())
|
||||
gmapRecord.name = gmapRecord.name.strip('\0')
|
||||
self.gmapRecords.append(gmapRecord)
|
||||
|
||||
|
||||
def compile(self, ttFont):
|
||||
self.recordsCount = len(self.gmapRecords)
|
||||
self.fontNameLength = len(self.psFontName)
|
||||
self.recordsOffset = 4 *(((self.fontNameLength + 12) + 3) /4)
|
||||
data = sstruct.pack(GMAPFormat, self)
|
||||
data = data + self.psFontName
|
||||
data = data + "\0" * (self.recordsOffset - len(data))
|
||||
for record in self.gmapRecords:
|
||||
data = data + record.compile(ttFont)
|
||||
return data
|
||||
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.comment("Most of this table will be recalculated by the compiler")
|
||||
writer.newline()
|
||||
formatstring, names, fixes = sstruct.getformat(GMAPFormat)
|
||||
for name in names:
|
||||
value = getattr(self, name)
|
||||
writer.simpletag(name, value=value)
|
||||
writer.newline()
|
||||
writer.simpletag("PSFontName", value=self.psFontName)
|
||||
writer.newline()
|
||||
for gmapRecord in self.gmapRecords:
|
||||
gmapRecord.toXML(writer, ttFont)
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
if name == "GMAPRecord":
|
||||
if not hasattr(self, "gmapRecords"):
|
||||
self.gmapRecords = []
|
||||
gmapRecord = GMAPRecord()
|
||||
self.gmapRecords.append(gmapRecord)
|
||||
for element in content:
|
||||
if isinstance(element, StringType):
|
||||
continue
|
||||
gmapRecord.fromXML(element, ttFont)
|
||||
else:
|
||||
value = attrs["value"]
|
||||
if name == "PSFontName":
|
||||
self.psFontName = value
|
||||
else:
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
135
Lib/fontTools/ttLib/tables/G_P_K_G_.py
Normal file
135
Lib/fontTools/ttLib/tables/G_P_K_G_.py
Normal file
@ -0,0 +1,135 @@
|
||||
import DefaultTable
|
||||
import sstruct
|
||||
import array
|
||||
import Numeric
|
||||
from types import StringType
|
||||
from fontTools.misc.textTools import safeEval, readHex
|
||||
from fontTools import ttLib
|
||||
|
||||
GPKGFormat = """
|
||||
> # big endian
|
||||
version: H
|
||||
flags: H
|
||||
numGMAPs: H
|
||||
numGlyplets: H
|
||||
"""
|
||||
# psFontName is a byte string which follows the record above. This is zero padded
|
||||
# to the beginning of the records array. The recordsOffsst is 32 bit aligned.
|
||||
|
||||
|
||||
class table_G_P_K_G_(DefaultTable.DefaultTable):
|
||||
|
||||
def decompile(self, data, ttFont):
|
||||
dummy, newData = sstruct.unpack2(GPKGFormat, data, self)
|
||||
|
||||
GMAPoffsets = array.array("L")
|
||||
endPos = (self.numGMAPs+1) * 4
|
||||
GMAPoffsets.fromstring(newData[:endPos])
|
||||
if ttLib.endian <> "big":
|
||||
GMAPoffsets.byteswap()
|
||||
self.GMAPs = []
|
||||
for i in range(self.numGMAPs):
|
||||
start = GMAPoffsets[i]
|
||||
end = GMAPoffsets[i+1]
|
||||
self.GMAPs.append(data[start:end])
|
||||
pos = endPos
|
||||
endPos = pos + (self.numGlyplets + 1)*4
|
||||
glyphletOffsets = array.array("L")
|
||||
glyphletOffsets.fromstring(newData[pos:endPos])
|
||||
if ttLib.endian <> "big":
|
||||
glyphletOffsets.byteswap()
|
||||
self.glyphlets = []
|
||||
for i in range(self.numGlyplets):
|
||||
start = glyphletOffsets[i]
|
||||
end = glyphletOffsets[i+1]
|
||||
self.glyphlets.append(data[start:end])
|
||||
|
||||
|
||||
def compile(self, ttFont):
|
||||
self.numGMAPs = len(self.GMAPs)
|
||||
self.numGlyplets = len(self.glyphlets)
|
||||
GMAPoffsets = [0]*(self.numGMAPs + 1)
|
||||
glyphletOffsets = [0]*(self.numGlyplets + 1)
|
||||
|
||||
dataList =[ sstruct.pack(GPKGFormat, self)]
|
||||
|
||||
pos = len(dataList[0]) + (self.numGMAPs + 1)*4 + (self.numGlyplets + 1)*4
|
||||
GMAPoffsets[0] = pos
|
||||
for i in range(1, self.numGMAPs +1):
|
||||
pos += len(self.GMAPs[i-1])
|
||||
GMAPoffsets[i] = pos
|
||||
gmapArray = Numeric.array(GMAPoffsets, Numeric.UInt32)
|
||||
if ttLib.endian <> "big":
|
||||
gmapArray = gmapArray.byteswapped()
|
||||
dataList.append(gmapArray.tostring())
|
||||
|
||||
glyphletOffsets[0] = pos
|
||||
for i in range(1, self.numGlyplets +1):
|
||||
pos += len(self.glyphlets[i-1])
|
||||
glyphletOffsets[i] = pos
|
||||
glyphletArray = Numeric.array(glyphletOffsets, Numeric.UInt32)
|
||||
if ttLib.endian <> "big":
|
||||
glyphletArray = glyphletArray.byteswapped()
|
||||
dataList.append(glyphletArray.tostring())
|
||||
dataList += self.GMAPs
|
||||
dataList += self.glyphlets
|
||||
data = "".join(dataList)
|
||||
return data
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.comment("Most of this table will be recalculated by the compiler")
|
||||
writer.newline()
|
||||
formatstring, names, fixes = sstruct.getformat(GPKGFormat)
|
||||
for name in names:
|
||||
value = getattr(self, name)
|
||||
writer.simpletag(name, value=value)
|
||||
writer.newline()
|
||||
|
||||
writer.begintag("GMAPs")
|
||||
writer.newline()
|
||||
for gmapData in self.GMAPs:
|
||||
writer.begintag("hexdata")
|
||||
writer.newline()
|
||||
writer.dumphex(gmapData)
|
||||
writer.endtag("hexdata")
|
||||
writer.newline()
|
||||
writer.endtag("GMAPs")
|
||||
writer.newline()
|
||||
|
||||
writer.begintag("glyphlets")
|
||||
writer.newline()
|
||||
for glyphletData in self.glyphlets:
|
||||
writer.begintag("hexdata")
|
||||
writer.newline()
|
||||
writer.dumphex(glyphletData)
|
||||
writer.endtag("hexdata")
|
||||
writer.newline()
|
||||
writer.endtag("glyphlets")
|
||||
writer.newline()
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
if name == "GMAPs":
|
||||
if not hasattr(self, "GMAPs"):
|
||||
self.GMAPs = []
|
||||
for element in content:
|
||||
if isinstance(element, StringType):
|
||||
continue
|
||||
itemName, itemAttrs, itemContent = element
|
||||
if itemName == "hexdata":
|
||||
self.GMAPs.append(readHex(itemContent))
|
||||
elif name == "glyphlets":
|
||||
if not hasattr(self, "glyphlets"):
|
||||
self.glyphlets = []
|
||||
for element in content:
|
||||
if isinstance(element, StringType):
|
||||
continue
|
||||
itemName, itemAttrs, itemContent = element
|
||||
if itemName == "hexdata":
|
||||
self.glyphlets.append(readHex(itemContent))
|
||||
else:
|
||||
value = attrs["value"]
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
329
Lib/fontTools/ttLib/tables/M_E_T_A_.py
Normal file
329
Lib/fontTools/ttLib/tables/M_E_T_A_.py
Normal file
@ -0,0 +1,329 @@
|
||||
import DefaultTable
|
||||
import struct, sstruct
|
||||
from fontTools.misc.textTools import safeEval
|
||||
import string
|
||||
from types import FloatType, ListType, StringType, TupleType
|
||||
import sys
|
||||
METAHeaderFormat = """
|
||||
> # big endian
|
||||
tableVersionMajor: H
|
||||
tableVersionMinor: H
|
||||
metaEntriesVersionMajor: H
|
||||
metaEntriesVersionMinor: H
|
||||
unicodeVersion: L
|
||||
metaFlags: H
|
||||
nMetaRecs: H
|
||||
"""
|
||||
# This record is followed by nMetaRecs of METAGlyphRecordFormat.
|
||||
# This in turn is followd by as many METAStringRecordFormat entries
|
||||
# as specified by the METAGlyphRecordFormat entries
|
||||
# this is followed by the strings specifried in the METAStringRecordFormat
|
||||
METAGlyphRecordFormat = """
|
||||
> # big endian
|
||||
glyphID: H
|
||||
nMetaEntry: H
|
||||
"""
|
||||
# This record is followd by a variable data length field:
|
||||
# USHORT or ULONG hdrOffset
|
||||
# Offset from start of META table to the beginning
|
||||
# of this glyphs array of ns Metadata string entries.
|
||||
# Size determined by metaFlags field
|
||||
# METAGlyphRecordFormat entries must be sorted by glyph ID
|
||||
|
||||
METAStringRecordFormat = """
|
||||
> # big endian
|
||||
labelID: H
|
||||
stringLen: H
|
||||
"""
|
||||
# This record is followd by a variable data length field:
|
||||
# USHORT or ULONG stringOffset
|
||||
# METAStringRecordFormat entries must be sorted in order of labelID
|
||||
# There may be more than one entry with the same labelID
|
||||
# There may be more than one strign with the same content.
|
||||
|
||||
# Strings shall be Unicode UTF-8 encoded, and null-terminated.
|
||||
|
||||
METALabelDict = {
|
||||
0 : "MojikumiX4051", # An integer in the range 1-20
|
||||
1 : "UNIUnifiedBaseChars",
|
||||
2 : "BaseFontName",
|
||||
3 : "Language",
|
||||
4 : "CreationDate",
|
||||
5 : "FoundryName",
|
||||
6 : "FoundryCopyright",
|
||||
7 : "OwnerURI",
|
||||
8 : "WritingScript",
|
||||
10 : "StrokeCount",
|
||||
11 : "IndexingRadical",
|
||||
}
|
||||
|
||||
|
||||
def getLabelString(labelID):
|
||||
try:
|
||||
label = METALabelDict[labelID]
|
||||
except KeyError:
|
||||
label = "Unknown label"
|
||||
return str(label)
|
||||
|
||||
|
||||
class table_M_E_T_A_(DefaultTable.DefaultTable):
|
||||
|
||||
dependencies = []
|
||||
|
||||
def decompile(self, data, ttFont):
|
||||
dummy, newData = sstruct.unpack2(METAHeaderFormat, data, self)
|
||||
self.glyphRecords = []
|
||||
for i in range(self.nMetaRecs):
|
||||
glyphRecord, newData = sstruct.unpack2(METAGlyphRecordFormat, newData, GlyphRecord())
|
||||
if self.metaFlags == 0:
|
||||
[glyphRecord.offset] = struct.unpack(">H", newData[:2])
|
||||
newData = newData[2:]
|
||||
elif self.metaFlags == 1:
|
||||
[glyphRecord.offset] = struct.unpack(">H", newData[:4])
|
||||
newData = newData[4:]
|
||||
else:
|
||||
assert 0, "The metaFlags field in the META table header has a value other than 0 or 1 :" + str(self.metaFlags)
|
||||
glyphRecord.stringRecs = []
|
||||
newData = data[glyphRecord.offset:]
|
||||
for j in range(glyphRecord.nMetaEntry):
|
||||
stringRec, newData = sstruct.unpack2(METAStringRecordFormat, newData, StringRecord())
|
||||
if self.metaFlags == 0:
|
||||
[stringRec.offset] = struct.unpack(">H", newData[:2])
|
||||
newData = newData[2:]
|
||||
else:
|
||||
[stringRec.offset] = struct.unpack(">H", newData[:4])
|
||||
newData = newData[4:]
|
||||
stringRec.string = data[stringRec.offset:stringRec.offset + stringRec.stringLen]
|
||||
glyphRecord.stringRecs.append(stringRec)
|
||||
self.glyphRecords.append(glyphRecord)
|
||||
|
||||
def compile(self, ttFont):
|
||||
offsetOK = 0
|
||||
self.nMetaRecs = len(self.glyphRecords)
|
||||
count = 0
|
||||
while ( offsetOK != 1):
|
||||
count = count + 1
|
||||
if count > 4:
|
||||
pdb_set_trace()
|
||||
metaData = sstruct.pack(METAHeaderFormat, self)
|
||||
stringRecsOffset = len(metaData) + self.nMetaRecs * (6 + 2*(self.metaFlags & 1))
|
||||
stringRecSize = (6 + 2*(self.metaFlags & 1))
|
||||
for glyphRec in self.glyphRecords:
|
||||
glyphRec.offset = stringRecsOffset
|
||||
if (glyphRec.offset > 65535) and ((self.metaFlags & 1) == 0):
|
||||
self.metaFlags = self.metaFlags + 1
|
||||
offsetOK = -1
|
||||
break
|
||||
metaData = metaData + glyphRec.compile(self)
|
||||
stringRecsOffset = stringRecsOffset + (glyphRec.nMetaEntry * stringRecSize)
|
||||
# this will be the String Record offset for the next GlyphRecord.
|
||||
if offsetOK == -1:
|
||||
offsetOK = 0
|
||||
continue
|
||||
|
||||
# metaData now contains the header and all of the GlyphRecords. Its length should bw
|
||||
# the offset to the first StringRecord.
|
||||
stringOffset = stringRecsOffset
|
||||
for glyphRec in self.glyphRecords:
|
||||
assert (glyphRec.offset == len(metaData)), "Glyph record offset did not compile correctly! for rec:" + str(glyphRec)
|
||||
for stringRec in glyphRec.stringRecs:
|
||||
stringRec.offset = stringOffset
|
||||
if (stringRec.offset > 65535) and ((self.metaFlags & 1) == 0):
|
||||
self.metaFlags = self.metaFlags + 1
|
||||
offsetOK = -1
|
||||
break
|
||||
metaData = metaData + stringRec.compile(self)
|
||||
stringOffset = stringOffset + stringRec.stringLen
|
||||
if offsetOK == -1:
|
||||
offsetOK = 0
|
||||
continue
|
||||
|
||||
if ((self.metaFlags & 1) == 1) and (stringOffset < 65536):
|
||||
self.metaFlags = self.metaFlags - 1
|
||||
continue
|
||||
else:
|
||||
offsetOK = 1
|
||||
|
||||
|
||||
# metaData now contains the header and all of the GlyphRecords and all of the String Records.
|
||||
# Its length should be the offset to the first string datum.
|
||||
for glyphRec in self.glyphRecords:
|
||||
for stringRec in glyphRec.stringRecs:
|
||||
assert (stringRec.offset == len(metaData)), "String offset did not compile correctly! for string:" + str(stringRec.string)
|
||||
metaData = metaData + stringRec.string
|
||||
|
||||
return metaData
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.comment("Lengths and number of entries in this table will be recalculated by the compiler")
|
||||
writer.newline()
|
||||
formatstring, names, fixes = sstruct.getformat(METAHeaderFormat)
|
||||
for name in names:
|
||||
value = getattr(self, name)
|
||||
writer.simpletag(name, value=value)
|
||||
writer.newline()
|
||||
for glyphRec in self.glyphRecords:
|
||||
glyphRec.toXML(writer, ttFont)
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
if name == "GlyphRecord":
|
||||
if not hasattr(self, "glyphRecords"):
|
||||
self.glyphRecords = []
|
||||
glyphRec = GlyphRecord()
|
||||
self.glyphRecords.append(glyphRec)
|
||||
for element in content:
|
||||
if isinstance(element, StringType):
|
||||
continue
|
||||
glyphRec.fromXML(element, ttFont)
|
||||
glyphRec.offset = -1
|
||||
glyphRec.nMetaEntry = len(glyphRec.stringRecs)
|
||||
else:
|
||||
value = attrs["value"]
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
class GlyphRecord:
|
||||
def __init__(self):
|
||||
self.glyphID = -1
|
||||
self.nMetaEntry = -1
|
||||
self.offset = -1
|
||||
self.stringRecs = []
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.begintag("GlyphRecord")
|
||||
writer.newline()
|
||||
writer.simpletag("glyphID", value=self.glyphID)
|
||||
writer.newline()
|
||||
writer.simpletag("nMetaEntry", value=self.nMetaEntry)
|
||||
writer.newline()
|
||||
for stringRec in self.stringRecs:
|
||||
stringRec.toXML(writer, ttFont)
|
||||
writer.endtag("GlyphRecord")
|
||||
writer.newline()
|
||||
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
if name == "StringRecord":
|
||||
stringRec = StringRecord()
|
||||
self.stringRecs.append(stringRec)
|
||||
for element in content:
|
||||
if isinstance(element, StringType):
|
||||
continue
|
||||
stringRec.fromXML(element, ttFont)
|
||||
stringRec.stringLen = len(stringRec.string)
|
||||
else:
|
||||
value = attrs["value"]
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
||||
|
||||
def compile(self, parentTable):
|
||||
data = sstruct.pack(METAGlyphRecordFormat, self)
|
||||
if parentTable.metaFlags == 0:
|
||||
datum = struct.pack(">H", self.offset)
|
||||
elif parentTable.metaFlags == 1:
|
||||
datum = struct.pack(">L", self.offset)
|
||||
data = data + datum
|
||||
return data
|
||||
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Compare method, so a list of NameRecords can be sorted
|
||||
according to the spec by just sorting it..."""
|
||||
return cmp(self.glyphID, other.glyphID)
|
||||
|
||||
def __repr__(self):
|
||||
return "GlyphRecord[ glyphID: " + str(self.glyphID) + ", nMetaEntry: " + str(self.nMetaEntry) + ", offset: " + str(self.offset) + " ]"
|
||||
|
||||
|
||||
def mapXMLToUTF8(string):
|
||||
uString = u""
|
||||
strLen = len(string)
|
||||
i = 0
|
||||
while i < strLen:
|
||||
prefixLen = 0
|
||||
if (string[i:i+3] == "&#x"):
|
||||
prefixLen = 3
|
||||
elif (string[i:i+7] == "&#x"):
|
||||
prefixLen = 7
|
||||
if prefixLen:
|
||||
i = i+prefixLen
|
||||
j= i
|
||||
while string[i] != ";":
|
||||
i = i+1
|
||||
valStr = string[j:i]
|
||||
|
||||
uString = uString + unichr(eval('0x' + valStr))
|
||||
else:
|
||||
uString = uString + unichr(ord(string[i]))
|
||||
i = i +1
|
||||
|
||||
return uString.encode('utf8')
|
||||
|
||||
|
||||
def mapUTF8toXML(string):
|
||||
uString = string.decode('utf8')
|
||||
string = ""
|
||||
for uChar in uString:
|
||||
i = ord(uChar)
|
||||
if (i < 0x80) and (i > 0x1F):
|
||||
string = string + chr(i)
|
||||
else:
|
||||
string = string + "&#x" + hex(i)[2:] + ";"
|
||||
return string
|
||||
|
||||
|
||||
class StringRecord:
|
||||
def __init__(self):
|
||||
self.labelID = -1
|
||||
self.string = ""
|
||||
self.stringLen = -1
|
||||
self.offset = -1
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.begintag("StringRecord")
|
||||
writer.newline()
|
||||
writer.simpletag("labelID", value=self.labelID)
|
||||
writer.comment(getLabelString(self.labelID))
|
||||
writer.newline()
|
||||
writer.newline()
|
||||
writer.simpletag("string", value=mapUTF8toXML(self.string))
|
||||
writer.newline()
|
||||
writer.endtag("StringRecord")
|
||||
writer.newline()
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
value = attrs["value"]
|
||||
if name == "string":
|
||||
self.string = mapXMLToUTF8(value)
|
||||
else:
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
||||
|
||||
def compile(self, parentTable):
|
||||
data = sstruct.pack(METAStringRecordFormat, self)
|
||||
if parentTable.metaFlags == 0:
|
||||
datum = struct.pack(">H", self.offset)
|
||||
elif parentTable.metaFlags == 1:
|
||||
datum = struct.pack(">L", self.offset)
|
||||
data = data + datum
|
||||
return data
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""Compare method, so a list of NameRecords can be sorted
|
||||
according to the spec by just sorting it..."""
|
||||
return cmp(self.labelID, other.labelID)
|
||||
|
||||
def __repr__(self):
|
||||
return "StringRecord [ labelID: " + str(self.labelID) + " aka " + getLabelString(self.labelID) \
|
||||
+ ", offset: " + str(self.offset) + ", length: " + str(self.stringLen) + ", string: " +self.string + " ]"
|
||||
|
102
Lib/fontTools/ttLib/tables/S_I_N_G_.py
Normal file
102
Lib/fontTools/ttLib/tables/S_I_N_G_.py
Normal file
@ -0,0 +1,102 @@
|
||||
import DefaultTable
|
||||
import sstruct
|
||||
import struct
|
||||
import time
|
||||
import string
|
||||
from fontTools.misc.textTools import safeEval, num2binary, binary2num
|
||||
|
||||
SINGFormat = """
|
||||
> # big endian
|
||||
tableVersionMajor: H
|
||||
tableVersionMinor: H
|
||||
glyphletVersion: H
|
||||
permissions: h
|
||||
mainGID: H
|
||||
unitsPerEm: H
|
||||
vertAdvance: h
|
||||
vertOrigin: h
|
||||
uniqueName: 28s
|
||||
METAMD5: 16s
|
||||
nameLength: 1s
|
||||
"""
|
||||
# baseGlyphName is a byte string which follows the record above.
|
||||
|
||||
|
||||
|
||||
class table_S_I_N_G_(DefaultTable.DefaultTable):
|
||||
|
||||
dependencies = []
|
||||
|
||||
def decompile(self, data, ttFont):
|
||||
dummy, rest = sstruct.unpack2(SINGFormat, data, self)
|
||||
self.uniqueName = self.decompileUniqueName(self.uniqueName)
|
||||
self.nameLength = ord(self.nameLength)
|
||||
assert len(rest) == self.nameLength
|
||||
self.baseGlyphName = rest
|
||||
|
||||
rawMETAMD5 = self.METAMD5
|
||||
self.METAMD5 = "[" + hex(ord(self.METAMD5[0]))
|
||||
for char in rawMETAMD5[1:]:
|
||||
self.METAMD5 = self.METAMD5 + ", " + hex(ord(char))
|
||||
self.METAMD5 = self.METAMD5 + "]"
|
||||
|
||||
def decompileUniqueName(self, data):
|
||||
name = ""
|
||||
for char in data:
|
||||
val = ord(char)
|
||||
if val == 0:
|
||||
break
|
||||
if (val > 31) or (val < 128):
|
||||
name = name + char
|
||||
else:
|
||||
octString = oct(val)
|
||||
if len(octString) > 3:
|
||||
octString = octString[1:] # chop off that leading zero.
|
||||
elif len(octString) < 3:
|
||||
octString.zfill(3)
|
||||
name = name + "\\" + octString
|
||||
return name
|
||||
|
||||
|
||||
def compile(self, ttFont):
|
||||
self.nameLength = chr(len(self.baseGlyphName))
|
||||
self.uniqueName = self.compilecompileUniqueName(self.uniqueName, 28)
|
||||
METAMD5List = eval(self.METAMD5)
|
||||
self.METAMD5 = ""
|
||||
for val in METAMD5List:
|
||||
self.METAMD5 = self.METAMD5 + chr(val)
|
||||
assert (len(self.METAMD5) == 16), "Failed to pack 16 byte MD5 hash in SING table"
|
||||
data = sstruct.pack(SINGFormat, self)
|
||||
data = data + self.baseGlyphName
|
||||
return data
|
||||
|
||||
def compilecompileUniqueName(self, name, length):
|
||||
nameLen = len(name)
|
||||
if length <= nameLen:
|
||||
name[:length-1] + "\000"
|
||||
else:
|
||||
name.join( (nameLen - length)* "\000")
|
||||
return name
|
||||
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
writer.comment("Most of this table will be recalculated by the compiler")
|
||||
writer.newline()
|
||||
formatstring, names, fixes = sstruct.getformat(SINGFormat)
|
||||
for name in names:
|
||||
value = getattr(self, name)
|
||||
writer.simpletag(name, value=value)
|
||||
writer.newline()
|
||||
writer.simpletag("baseGlyphName", value=self.baseGlyphName)
|
||||
writer.newline()
|
||||
|
||||
def fromXML(self, (name, attrs, content), ttFont):
|
||||
value = attrs["value"]
|
||||
if name in ["uniqueName", "METAMD5", "baseGlyphName"]:
|
||||
setattr(self, name, value)
|
||||
else:
|
||||
try:
|
||||
value = safeEval(value)
|
||||
except OverflowError:
|
||||
value = long(value)
|
||||
setattr(self, name, value)
|
@ -7,11 +7,15 @@ def _moduleFinderHint():
|
||||
import C_F_F_
|
||||
import D_S_I_G_
|
||||
import G_D_E_F_
|
||||
import G_M_A_P_
|
||||
import G_P_K_G_
|
||||
import G_P_O_S_
|
||||
import G_S_U_B_
|
||||
import J_S_T_F_
|
||||
import L_T_S_H_
|
||||
import M_E_T_A_
|
||||
import O_S_2f_2
|
||||
import S_I_N_G_
|
||||
import T_S_I_B_
|
||||
import T_S_I_D_
|
||||
import T_S_I_J_
|
||||
|
Loading…
x
Reference in New Issue
Block a user