Move some methods from subset.py to 'glyf' table implementation
This commit is contained in:
parent
46d260f2a0
commit
626107c833
@ -1118,29 +1118,6 @@ def subset_glyphs(self, s):
|
|||||||
self.extraNames = [] # This seems to do it
|
self.extraNames = [] # This seems to do it
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@_add_method(ttLib.getTableModule('glyf').Glyph)
|
|
||||||
def getComponentNamesFast(self, glyfTable):
|
|
||||||
if not self.data or struct.unpack(">h", self.data[:2])[0] >= 0:
|
|
||||||
return [] # Not composite
|
|
||||||
data = self.data
|
|
||||||
i = 10
|
|
||||||
components = []
|
|
||||||
more = 1
|
|
||||||
while more:
|
|
||||||
flags, glyphID = struct.unpack(">HH", data[i:i+4])
|
|
||||||
i += 4
|
|
||||||
flags = int(flags)
|
|
||||||
components.append(glyfTable.getGlyphName(int(glyphID)))
|
|
||||||
|
|
||||||
if flags & 0x0001: i += 4 # ARG_1_AND_2_ARE_WORDS
|
|
||||||
else: i += 2
|
|
||||||
if flags & 0x0008: i += 2 # WE_HAVE_A_SCALE
|
|
||||||
elif flags & 0x0040: i += 4 # WE_HAVE_AN_X_AND_Y_SCALE
|
|
||||||
elif flags & 0x0080: i += 8 # WE_HAVE_A_TWO_BY_TWO
|
|
||||||
more = flags & 0x0020 # MORE_COMPONENTS
|
|
||||||
|
|
||||||
return components
|
|
||||||
|
|
||||||
@_add_method(ttLib.getTableModule('glyf').Glyph)
|
@_add_method(ttLib.getTableModule('glyf').Glyph)
|
||||||
def remapComponentsFast(self, indices):
|
def remapComponentsFast(self, indices):
|
||||||
if not self.data or struct.unpack(">h", self.data[:2])[0] >= 0:
|
if not self.data or struct.unpack(">h", self.data[:2])[0] >= 0:
|
||||||
@ -1167,49 +1144,6 @@ def remapComponentsFast(self, indices):
|
|||||||
|
|
||||||
self.data = data.tostring()
|
self.data = data.tostring()
|
||||||
|
|
||||||
@_add_method(ttLib.getTableModule('glyf').Glyph)
|
|
||||||
def dropInstructionsFast(self):
|
|
||||||
if not self.data:
|
|
||||||
return
|
|
||||||
numContours = struct.unpack(">h", self.data[:2])[0]
|
|
||||||
data = array.array("B", self.data)
|
|
||||||
i = 10
|
|
||||||
if numContours >= 0:
|
|
||||||
i += 2 * numContours # endPtsOfContours
|
|
||||||
instructionLen =(data[i] << 8) | data[i+1]
|
|
||||||
# Zero it
|
|
||||||
data[i] = data [i+1] = 0
|
|
||||||
i += 2
|
|
||||||
if instructionLen:
|
|
||||||
# Splice it out
|
|
||||||
data = data[:i] + data[i+instructionLen:]
|
|
||||||
else:
|
|
||||||
more = 1
|
|
||||||
while more:
|
|
||||||
flags =(data[i] << 8) | data[i+1]
|
|
||||||
# Turn instruction flag off
|
|
||||||
flags &= ~0x0100 # WE_HAVE_INSTRUCTIONS
|
|
||||||
data[i+0] = flags >> 8
|
|
||||||
data[i+1] = flags & 0xFF
|
|
||||||
i += 4
|
|
||||||
flags = int(flags)
|
|
||||||
|
|
||||||
if flags & 0x0001: i += 4 # ARG_1_AND_2_ARE_WORDS
|
|
||||||
else: i += 2
|
|
||||||
if flags & 0x0008: i += 2 # WE_HAVE_A_SCALE
|
|
||||||
elif flags & 0x0040: i += 4 # WE_HAVE_AN_X_AND_Y_SCALE
|
|
||||||
elif flags & 0x0080: i += 8 # WE_HAVE_A_TWO_BY_TWO
|
|
||||||
more = flags & 0x0020 # MORE_COMPONENTS
|
|
||||||
|
|
||||||
# Cut off
|
|
||||||
data = data[:i]
|
|
||||||
if len(data) % 4:
|
|
||||||
# add pad bytes
|
|
||||||
nPadBytes = 4 -(len(data) % 4)
|
|
||||||
for i in range(nPadBytes):
|
|
||||||
data.append(0)
|
|
||||||
self.data = data.tostring()
|
|
||||||
|
|
||||||
@_add_method(ttLib.getTableClass('glyf'))
|
@_add_method(ttLib.getTableClass('glyf'))
|
||||||
def closure_glyphs(self, s):
|
def closure_glyphs(self, s):
|
||||||
decompose = s.glyphs
|
decompose = s.glyphs
|
||||||
@ -1221,16 +1155,9 @@ def closure_glyphs(self, s):
|
|||||||
if g not in self.glyphs:
|
if g not in self.glyphs:
|
||||||
continue
|
continue
|
||||||
gl = self.glyphs[g]
|
gl = self.glyphs[g]
|
||||||
if hasattr(gl, "data"):
|
for c in gl.getComponents(self):
|
||||||
for c in gl.getComponentNamesFast(self):
|
if c not in s.glyphs:
|
||||||
if c not in s.glyphs:
|
components.add(c)
|
||||||
components.add(c)
|
|
||||||
else:
|
|
||||||
# TTX seems to expand gid0..3 always
|
|
||||||
if gl.isComposite():
|
|
||||||
for c in gl.components:
|
|
||||||
if c.glyphName not in s.glyphs:
|
|
||||||
components.add(c.glyphName)
|
|
||||||
components = set(c for c in components if c not in s.glyphs)
|
components = set(c for c in components if c not in s.glyphs)
|
||||||
if not components:
|
if not components:
|
||||||
break
|
break
|
||||||
@ -1263,11 +1190,7 @@ def subset_glyphs(self, s):
|
|||||||
def prune_post_subset(self, options):
|
def prune_post_subset(self, options):
|
||||||
if not options.hinting:
|
if not options.hinting:
|
||||||
for v in self.glyphs.itervalues():
|
for v in self.glyphs.itervalues():
|
||||||
if hasattr(v, "data"):
|
v.removeHinting()
|
||||||
v.dropInstructionsFast()
|
|
||||||
else:
|
|
||||||
v.program = ttLib.tables.ttProgram.Program()
|
|
||||||
v.program.fromBytecode([])
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@_add_method(ttLib.getTableClass('CFF '))
|
@_add_method(ttLib.getTableClass('CFF '))
|
||||||
|
@ -549,7 +549,11 @@ class Glyph:
|
|||||||
self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)
|
self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)
|
||||||
|
|
||||||
def isComposite(self):
|
def isComposite(self):
|
||||||
return self.numberOfContours == -1
|
"""Can be called on compact or expanded glyph."""
|
||||||
|
if hasattr(self, "data"):
|
||||||
|
return struct.unpack(">h", self.data[:2])[0] == -1
|
||||||
|
else:
|
||||||
|
return self.numberOfContours == -1
|
||||||
|
|
||||||
def __getitem__(self, componentIndex):
|
def __getitem__(self, componentIndex):
|
||||||
if not self.isComposite():
|
if not self.isComposite():
|
||||||
@ -601,6 +605,88 @@ class Glyph:
|
|||||||
else:
|
else:
|
||||||
return GlyphCoordinates(), [], array.array("B")
|
return GlyphCoordinates(), [], array.array("B")
|
||||||
|
|
||||||
|
def getComponents(self, glyfTable):
|
||||||
|
if not hasattr(self, "data"):
|
||||||
|
if self.isComposite():
|
||||||
|
return self.components
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Extract components without expanding glyph
|
||||||
|
|
||||||
|
if not self.data or struct.unpack(">h", self.data[:2])[0] >= 0:
|
||||||
|
return [] # Not composite
|
||||||
|
|
||||||
|
data = self.data
|
||||||
|
i = 10
|
||||||
|
components = []
|
||||||
|
more = 1
|
||||||
|
while more:
|
||||||
|
flags, glyphID = struct.unpack(">HH", data[i:i+4])
|
||||||
|
i += 4
|
||||||
|
flags = int(flags)
|
||||||
|
components.append(glyfTable.getGlyphName(int(glyphID)))
|
||||||
|
|
||||||
|
if flags & ARG_1_AND_2_ARE_WORDS: i += 4
|
||||||
|
else: i += 2
|
||||||
|
if flags & WE_HAVE_A_SCALE: i += 2
|
||||||
|
elif flags & WE_HAVE_AN_X_AND_Y_SCALE: i += 4
|
||||||
|
elif flags & WE_HAVE_A_TWO_BY_TWO: i += 8
|
||||||
|
more = flags & MORE_COMPONENTS
|
||||||
|
|
||||||
|
return components
|
||||||
|
|
||||||
|
def removeHinting(self):
|
||||||
|
if not hasattr(self, "data"):
|
||||||
|
self.program = ttLib.tables.ttProgram.Program()
|
||||||
|
self.program.fromBytecode([])
|
||||||
|
return
|
||||||
|
|
||||||
|
# Remove instructions without expanding glyph
|
||||||
|
|
||||||
|
if not self.data:
|
||||||
|
return
|
||||||
|
numContours = struct.unpack(">h", self.data[:2])[0]
|
||||||
|
data = array.array("B", self.data)
|
||||||
|
i = 10
|
||||||
|
if numContours >= 0:
|
||||||
|
i += 2 * numContours # endPtsOfContours
|
||||||
|
instructionLen = (data[i] << 8) | data[i+1]
|
||||||
|
# Zero it
|
||||||
|
data[i] = data [i+1] = 0
|
||||||
|
i += 2
|
||||||
|
if instructionLen:
|
||||||
|
# Splice it out
|
||||||
|
data = data[:i] + data[i+instructionLen:]
|
||||||
|
else:
|
||||||
|
more = 1
|
||||||
|
while more:
|
||||||
|
flags =(data[i] << 8) | data[i+1]
|
||||||
|
# Turn instruction flag off
|
||||||
|
flags &= ~WE_HAVE_INSTRUCTIONS
|
||||||
|
data[i+0] = flags >> 8
|
||||||
|
data[i+1] = flags & 0xFF
|
||||||
|
i += 4
|
||||||
|
flags = int(flags)
|
||||||
|
|
||||||
|
if flags & ARG_1_AND_2_ARE_WORDS: i += 4
|
||||||
|
else: i += 2
|
||||||
|
if flags & WE_HAVE_A_SCALE: i += 2
|
||||||
|
elif flags & WE_HAVE_AN_X_AND_Y_SCALE: i += 4
|
||||||
|
elif flags & WE_HAVE_A_TWO_BY_TWO: i += 8
|
||||||
|
more = flags & MORE_COMPONENTS
|
||||||
|
|
||||||
|
# Cut off
|
||||||
|
data = data[:i]
|
||||||
|
|
||||||
|
if len(data) % 4:
|
||||||
|
# add pad bytes
|
||||||
|
nPadBytes = 4 -(len(data) % 4)
|
||||||
|
for i in range(nPadBytes):
|
||||||
|
data.append(0)
|
||||||
|
|
||||||
|
self.data = data.tostring()
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __cmp__(self, other):
|
||||||
if type(self) != type(other) or \
|
if type(self) != type(other) or \
|
||||||
self.__class__ != other.__class__:
|
self.__class__ != other.__class__:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user