Merge pull request #2884 from fonttools/woff2-overlap-simple
[woff2] Support encoding/decoding OVERLAP_SIMPLE glyf flags
This commit is contained in:
commit
3585641248
@ -523,7 +523,8 @@ woff2TransformedTableTags = ('glyf', 'loca')
|
|||||||
|
|
||||||
woff2GlyfTableFormat = """
|
woff2GlyfTableFormat = """
|
||||||
> # big endian
|
> # big endian
|
||||||
version: L # = 0x00000000
|
version: H # = 0x0000
|
||||||
|
optionFlags: H # Bit 0: we have overlapSimpleBitmap[], Bits 1-15: reserved
|
||||||
numGlyphs: H # Number of glyphs
|
numGlyphs: H # Number of glyphs
|
||||||
indexFormat: H # Offset format for loca table
|
indexFormat: H # Offset format for loca table
|
||||||
nContourStreamSize: L # Size of nContour stream
|
nContourStreamSize: L # Size of nContour stream
|
||||||
@ -545,6 +546,8 @@ bboxFormat = """
|
|||||||
yMax: h
|
yMax: h
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
woff2OverlapSimpleBitmapFlag = 0x0001
|
||||||
|
|
||||||
|
|
||||||
def getKnownTagIndex(tag):
|
def getKnownTagIndex(tag):
|
||||||
"""Return index of 'tag' in woff2KnownTags list. Return 63 if not found."""
|
"""Return index of 'tag' in woff2KnownTags list. Return 63 if not found."""
|
||||||
@ -690,6 +693,13 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
data = data[size:]
|
data = data[size:]
|
||||||
offset += size
|
offset += size
|
||||||
|
|
||||||
|
hasOverlapSimpleBitmap = self.optionFlags & woff2OverlapSimpleBitmapFlag
|
||||||
|
self.overlapSimpleBitmap = None
|
||||||
|
if hasOverlapSimpleBitmap:
|
||||||
|
overlapSimpleBitmapSize = (self.numGlyphs + 7) >> 3
|
||||||
|
self.overlapSimpleBitmap = array.array('B', data[:overlapSimpleBitmapSize])
|
||||||
|
offset += overlapSimpleBitmapSize
|
||||||
|
|
||||||
if offset != inputDataSize:
|
if offset != inputDataSize:
|
||||||
raise TTLibError(
|
raise TTLibError(
|
||||||
"incorrect size of transformed 'glyf' table: expected %d, received %d bytes"
|
"incorrect size of transformed 'glyf' table: expected %d, received %d bytes"
|
||||||
@ -737,15 +747,22 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
bboxBitmapSize = ((self.numGlyphs + 31) >> 5) << 2
|
bboxBitmapSize = ((self.numGlyphs + 31) >> 5) << 2
|
||||||
self.bboxBitmap = array.array('B', [0]*bboxBitmapSize)
|
self.bboxBitmap = array.array('B', [0]*bboxBitmapSize)
|
||||||
|
|
||||||
|
self.overlapSimpleBitmap = array.array('B', [0]*((self.numGlyphs + 7) >> 3))
|
||||||
for glyphID in range(self.numGlyphs):
|
for glyphID in range(self.numGlyphs):
|
||||||
self._encodeGlyph(glyphID)
|
self._encodeGlyph(glyphID)
|
||||||
|
hasOverlapSimpleBitmap = any(self.overlapSimpleBitmap)
|
||||||
|
|
||||||
self.bboxStream = self.bboxBitmap.tobytes() + self.bboxStream
|
self.bboxStream = self.bboxBitmap.tobytes() + self.bboxStream
|
||||||
for stream in self.subStreams:
|
for stream in self.subStreams:
|
||||||
setattr(self, stream + 'Size', len(getattr(self, stream)))
|
setattr(self, stream + 'Size', len(getattr(self, stream)))
|
||||||
self.version = 0
|
self.version = 0
|
||||||
|
self.optionFlags = 0
|
||||||
|
if hasOverlapSimpleBitmap:
|
||||||
|
self.optionFlags |= woff2OverlapSimpleBitmapFlag
|
||||||
data = sstruct.pack(woff2GlyfTableFormat, self)
|
data = sstruct.pack(woff2GlyfTableFormat, self)
|
||||||
data += bytesjoin([getattr(self, s) for s in self.subStreams])
|
data += bytesjoin([getattr(self, s) for s in self.subStreams])
|
||||||
|
if hasOverlapSimpleBitmap:
|
||||||
|
data += self.overlapSimpleBitmap.tobytes()
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _decodeGlyph(self, glyphID):
|
def _decodeGlyph(self, glyphID):
|
||||||
@ -757,6 +774,7 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
self._decodeComponents(glyph)
|
self._decodeComponents(glyph)
|
||||||
else:
|
else:
|
||||||
self._decodeCoordinates(glyph)
|
self._decodeCoordinates(glyph)
|
||||||
|
self._decodeOverlapSimpleFlag(glyph, glyphID)
|
||||||
self._decodeBBox(glyphID, glyph)
|
self._decodeBBox(glyphID, glyph)
|
||||||
return glyph
|
return glyph
|
||||||
|
|
||||||
@ -787,6 +805,14 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
self._decodeTriplets(glyph)
|
self._decodeTriplets(glyph)
|
||||||
self._decodeInstructions(glyph)
|
self._decodeInstructions(glyph)
|
||||||
|
|
||||||
|
def _decodeOverlapSimpleFlag(self, glyph, glyphID):
|
||||||
|
if self.overlapSimpleBitmap is None or glyph.numberOfContours <= 0:
|
||||||
|
return
|
||||||
|
byte = glyphID >> 3
|
||||||
|
bit = glyphID & 7
|
||||||
|
if self.overlapSimpleBitmap[byte] & (0x80 >> bit):
|
||||||
|
glyph.flags[0] |= _g_l_y_f.flagOverlapSimple
|
||||||
|
|
||||||
def _decodeInstructions(self, glyph):
|
def _decodeInstructions(self, glyph):
|
||||||
glyphStream = self.glyphStream
|
glyphStream = self.glyphStream
|
||||||
instructionStream = self.instructionStream
|
instructionStream = self.instructionStream
|
||||||
@ -885,6 +911,7 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
self._encodeComponents(glyph)
|
self._encodeComponents(glyph)
|
||||||
else:
|
else:
|
||||||
self._encodeCoordinates(glyph)
|
self._encodeCoordinates(glyph)
|
||||||
|
self._encodeOverlapSimpleFlag(glyph, glyphID)
|
||||||
self._encodeBBox(glyphID, glyph)
|
self._encodeBBox(glyphID, glyph)
|
||||||
|
|
||||||
def _encodeComponents(self, glyph):
|
def _encodeComponents(self, glyph):
|
||||||
@ -909,6 +936,14 @@ class WOFF2GlyfTable(getTableClass('glyf')):
|
|||||||
self._encodeTriplets(glyph)
|
self._encodeTriplets(glyph)
|
||||||
self._encodeInstructions(glyph)
|
self._encodeInstructions(glyph)
|
||||||
|
|
||||||
|
def _encodeOverlapSimpleFlag(self, glyph, glyphID):
|
||||||
|
if glyph.numberOfContours <= 0:
|
||||||
|
return
|
||||||
|
if glyph.flags[0] & _g_l_y_f.flagOverlapSimple:
|
||||||
|
byte = glyphID >> 3
|
||||||
|
bit = glyphID & 7
|
||||||
|
self.overlapSimpleBitmap[byte] |= 0x80 >> bit
|
||||||
|
|
||||||
def _encodeInstructions(self, glyph):
|
def _encodeInstructions(self, glyph):
|
||||||
instructions = glyph.program.getBytecode()
|
instructions = glyph.program.getBytecode()
|
||||||
self.glyphStream += pack255UShort(len(instructions))
|
self.glyphStream += pack255UShort(len(instructions))
|
||||||
|
@ -1239,7 +1239,10 @@ class WOFF2RoundtripTest(object):
|
|||||||
|
|
||||||
_, ttFont2 = self.roundtrip(tmp)
|
_, ttFont2 = self.roundtrip(tmp)
|
||||||
assert ttFont2.flavor == "woff2"
|
assert ttFont2.flavor == "woff2"
|
||||||
assert ttFont2["glyf"]["A"].flags[0] == 0
|
# check that the off-curve point is still there
|
||||||
|
assert ttFont2["glyf"]["A"].flags[0] & _g_l_y_f.flagOnCurve == 0
|
||||||
|
# check that the overlap bit is still there
|
||||||
|
assert ttFont2["glyf"]["A"].flags[0] & _g_l_y_f.flagOverlapSimple != 0
|
||||||
|
|
||||||
class MainTest(object):
|
class MainTest(object):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user