/usr/lib/python2.7/dist-packages/FontTools/fontTools/ttLib/tables/sbixStrike.py is in fonttools 3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import readHex
from .sbixGlyph import *
import struct
sbixStrikeHeaderFormat = """
>
ppem: H # The PPEM for which this strike was designed (e.g., 9,
# 12, 24)
resolution: H # The screen resolution (in dpi) for which this strike
# was designed (e.g., 72)
"""
sbixGlyphDataOffsetFormat = """
>
glyphDataOffset: L # Offset from the beginning of the strike data record
# to data for the individual glyph
"""
sbixStrikeHeaderFormatSize = sstruct.calcsize(sbixStrikeHeaderFormat)
sbixGlyphDataOffsetFormatSize = sstruct.calcsize(sbixGlyphDataOffsetFormat)
class Strike(object):
def __init__(self, rawdata=None, ppem=0, resolution=72):
self.data = rawdata
self.ppem = ppem
self.resolution = resolution
self.glyphs = {}
def decompile(self, ttFont):
if self.data is None:
from fontTools import ttLib
raise ttLib.TTLibError
if len(self.data) < sbixStrikeHeaderFormatSize:
from fontTools import ttLib
raise(ttLib.TTLibError, "Strike header too short: Expected %x, got %x.") \
% (sbixStrikeHeaderFormatSize, len(self.data))
# read Strike header from raw data
sstruct.unpack(sbixStrikeHeaderFormat, self.data[:sbixStrikeHeaderFormatSize], self)
# calculate number of glyphs
firstGlyphDataOffset, = struct.unpack(">L", \
self.data[sbixStrikeHeaderFormatSize:sbixStrikeHeaderFormatSize + sbixGlyphDataOffsetFormatSize])
self.numGlyphs = (firstGlyphDataOffset - sbixStrikeHeaderFormatSize) // sbixGlyphDataOffsetFormatSize - 1
# ^ -1 because there's one more offset than glyphs
# build offset list for single glyph data offsets
self.glyphDataOffsets = []
for i in range(self.numGlyphs + 1): # + 1 because there's one more offset than glyphs
start = i * sbixGlyphDataOffsetFormatSize + sbixStrikeHeaderFormatSize
current_offset, = struct.unpack(">L", self.data[start:start + sbixGlyphDataOffsetFormatSize])
self.glyphDataOffsets.append(current_offset)
# iterate through offset list and slice raw data into glyph data records
for i in range(self.numGlyphs):
current_glyph = Glyph(rawdata=self.data[self.glyphDataOffsets[i]:self.glyphDataOffsets[i+1]], gid=i)
current_glyph.decompile(ttFont)
self.glyphs[current_glyph.glyphName] = current_glyph
del self.glyphDataOffsets
del self.numGlyphs
del self.data
def compile(self, ttFont):
self.glyphDataOffsets = ""
self.bitmapData = ""
glyphOrder = ttFont.getGlyphOrder()
# first glyph starts right after the header
currentGlyphDataOffset = sbixStrikeHeaderFormatSize + sbixGlyphDataOffsetFormatSize * (len(glyphOrder) + 1)
for glyphName in glyphOrder:
if glyphName in self.glyphs:
# we have glyph data for this glyph
current_glyph = self.glyphs[glyphName]
else:
# must add empty glyph data record for this glyph
current_glyph = Glyph(glyphName=glyphName)
current_glyph.compile(ttFont)
current_glyph.glyphDataOffset = currentGlyphDataOffset
self.bitmapData += current_glyph.rawdata
currentGlyphDataOffset += len(current_glyph.rawdata)
self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, current_glyph)
# add last "offset", really the end address of the last glyph data record
dummy = Glyph()
dummy.glyphDataOffset = currentGlyphDataOffset
self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, dummy)
# pack header
self.data = sstruct.pack(sbixStrikeHeaderFormat, self)
# add offsets and image data after header
self.data += self.glyphDataOffsets + self.bitmapData
def toXML(self, xmlWriter, ttFont):
xmlWriter.begintag("strike")
xmlWriter.newline()
xmlWriter.simpletag("ppem", value=self.ppem)
xmlWriter.newline()
xmlWriter.simpletag("resolution", value=self.resolution)
xmlWriter.newline()
glyphOrder = ttFont.getGlyphOrder()
for i in range(len(glyphOrder)):
if glyphOrder[i] in self.glyphs:
self.glyphs[glyphOrder[i]].toXML(xmlWriter, ttFont)
# TODO: what if there are more glyph data records than (glyf table) glyphs?
xmlWriter.endtag("strike")
xmlWriter.newline()
def fromXML(self, name, attrs, content, ttFont):
if name in ["ppem", "resolution"]:
setattr(self, name, safeEval(attrs["value"]))
elif name == "glyph":
if "graphicType" in attrs:
myFormat = safeEval("'''" + attrs["graphicType"] + "'''")
else:
myFormat = None
if "glyphname" in attrs:
myGlyphName = safeEval("'''" + attrs["glyphname"] + "'''")
elif "name" in attrs:
myGlyphName = safeEval("'''" + attrs["name"] + "'''")
else:
from fontTools import ttLib
raise ttLib.TTLibError("Glyph must have a glyph name.")
if "originOffsetX" in attrs:
myOffsetX = safeEval(attrs["originOffsetX"])
else:
myOffsetX = 0
if "originOffsetY" in attrs:
myOffsetY = safeEval(attrs["originOffsetY"])
else:
myOffsetY = 0
current_glyph = Glyph(
glyphName=myGlyphName,
graphicType=myFormat,
originOffsetX=myOffsetX,
originOffsetY=myOffsetY,
)
for element in content:
if isinstance(element, tuple):
name, attrs, content = element
current_glyph.fromXML(name, attrs, content, ttFont)
current_glyph.compile(ttFont)
self.glyphs[current_glyph.glyphName] = current_glyph
else:
from fontTools import ttLib
raise ttLib.TTLibError("can't handle '%s' element" % name)
|