def test_floatToFixedToStr_precision14(self): self.assertEqual('0.8', floatToFixedToStr(0.7999878, 14)) self.assertEqual('1.0', floatToFixedToStr(1.0, 14)) self.assertEqual('1.0', floatToFixedToStr(1, 14)) self.assertEqual('-1.0', floatToFixedToStr(-1.0, 14)) self.assertEqual('-1.0', floatToFixedToStr(-1, 14)) self.assertEqual('0.0', floatToFixedToStr(0, 14))
def decompile(self, data, ttFont, version=2.0): if version >= 3.0: _, data = sstruct.unpack2(Silf_part1_format_v3, data, self) self.ruleVersion = float( floatToFixedToStr(self.ruleVersion, precisionBits=16)) _, data = sstruct.unpack2(Silf_part1_format, data, self) for jlevel in range(self.numJLevels): j, data = sstruct.unpack2(Silf_justify_format, data, _Object()) self.jLevels.append(j) _, data = sstruct.unpack2(Silf_part2_format, data, self) if self.numCritFeatures: self.critFeatures = struct.unpack_from( ('>%dH' % self.numCritFeatures), data) data = data[self.numCritFeatures * 2 + 1:] (numScriptTag, ) = struct.unpack_from('B', data) if numScriptTag: self.scriptTags = [ struct.unpack("4s", data[x:x + 4])[0].decode("ascii") for x in range(1, 1 + 4 * numScriptTag, 4) ] data = data[1 + 4 * numScriptTag:] (self.lbGID, ) = struct.unpack('>H', data[:2]) if self.numPasses: self.oPasses = struct.unpack(('>%dL' % (self.numPasses + 1)), data[2:6 + 4 * self.numPasses]) data = data[6 + 4 * self.numPasses:] (numPseudo, ) = struct.unpack(">H", data[:2]) for i in range(numPseudo): if version >= 3.0: pseudo = sstruct.unpack(Silf_pseudomap_format, data[8 + 6 * i:14 + 6 * i], _Object()) else: pseudo = sstruct.unpack(Silf_pseudomap_format_h, data[8 + 4 * i:12 + 4 * i], _Object()) self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo) data = data[8 + 6 * numPseudo:] currpos = (sstruct.calcsize(Silf_part1_format) + sstruct.calcsize(Silf_justify_format) * self.numJLevels + sstruct.calcsize(Silf_part2_format) + 2 * self.numCritFeatures + 1 + 1 + 4 * numScriptTag + 6 + 4 * self.numPasses + 8 + 6 * numPseudo) if version >= 3.0: currpos += sstruct.calcsize(Silf_part1_format_v3) self.classes = Classes() self.classes.decompile(data, ttFont, version) for i in range(self.numPasses): p = Pass() self.passes.append(p) p.decompile( data[self.oPasses[i] - currpos:self.oPasses[i + 1] - currpos], ttFont, version)
def toXML(self, writer, ttFont): writer.comment("Most of this table will be recalculated by the compiler") writer.newline() _, names, fixes = sstruct.getformat(headFormat) for name in names: value = getattr(self, name) if name in fixes: value = floatToFixedToStr(value, precisionBits=fixes[name]) elif name in ("created", "modified"): value = timestampToString(value) elif name in ("magicNumber", "checkSumAdjustment"): if value < 0: value = value + 0x100000000 value = hex(value) if value[-1:] == "L": value = value[:-1] elif name in ("macStyle", "flags"): value = num2binary(value, 16) writer.simpletag(name, value=value) writer.newline()
def decompile(self, data, ttFont): sstruct.unpack2(Glat_format_0, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) if self.version <= 1.9: decoder = partial(self.decompileAttributes12, fmt=Glat_format_1_entry) elif self.version <= 2.9: decoder = partial(self.decompileAttributes12, fmt=Glat_format_23_entry) elif self.version >= 3.0: (data, self.scheme) = grUtils.decompress(data) sstruct.unpack2(Glat_format_3, data, self) self.hasOctaboxes = (self.compression & 1) == 1 decoder = self.decompileAttributes3 gloc = ttFont['Gloc'] self.attributes = {} count = 0 for s, e in zip(gloc, gloc[1:]): self.attributes[ttFont.getGlyphName(count)] = decoder(data[s:e]) count += 1
def decompile(self, data, ttFont): sstruct.unpack2(Silf_hdr_format, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) if self.version >= 5.0: (data, self.scheme) = grUtils.decompress(data) sstruct.unpack2(Silf_hdr_format_3, data, self) base = sstruct.calcsize(Silf_hdr_format_3) elif self.version < 3.0: self.numSilf = struct.unpack('>H', data[4:6]) self.scheme = 0 self.compilerVersion = 0 base = 8 else: self.scheme = 0 sstruct.unpack2(Silf_hdr_format_3, data, self) base = sstruct.calcsize(Silf_hdr_format_3) silfoffsets = struct.unpack_from(('>%dL' % self.numSilf), data[base:]) for offset in silfoffsets: s = Silf() self.silfs.append(s) s.decompile(data[offset:], ttFont, self.version)
def decompile(self, data, ttFont): (_, data) = sstruct.unpack2(Feat_hdr_format, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) numFeats, = struct.unpack('>H', data[:2]) data = data[8:] allfeats = [] maxsetting = 0 for i in range(numFeats): if self.version >= 2.0: (fid, nums, _, offset, flags, lid) = struct.unpack(">LHHLHH", data[16 * i:16 * (i + 1)]) offset = int((offset - 12 - 16 * numFeats) / 4) else: (fid, nums, offset, flags, lid) = struct.unpack(">HHLHH", data[12 * i:12 * (i + 1)]) offset = int((offset - 12 - 12 * numFeats) / 4) allfeats.append((fid, nums, offset, flags, lid)) maxsetting = max(maxsetting, offset + nums) data = data[16 * numFeats:] allsettings = [] for i in range(maxsetting): if len(data) >= 4 * (i + 1): (val, lid) = struct.unpack(">HH", data[4 * i:4 * (i + 1)]) allsettings.append((val, lid)) for i, f in enumerate(allfeats): (fid, nums, offset, flags, lid) = f fobj = Feature() fobj.flags = flags fobj.label = lid self.features[grUtils.num2tag(fid)] = fobj fobj.settings = {} fobj.default = None fobj.index = i for i in range(offset, offset + nums): if i >= len(allsettings): continue (vid, vlid) = allsettings[i] fobj.settings[vid] = vlid if fobj.default is None: fobj.default = vid
def toXML(self, xmlWriter, ttFont=None): from fontTools.misc.textTools import num2binary if self.bytecode is not None: xmlWriter.dumphex(self.bytecode) else: index = 0 args = [] while True: token, isOperator, index = self.getToken(index) if token is None: break if isOperator: if token in ('hintmask', 'cntrmask'): hintMask, isOperator, index = self.getToken(index) bits = [] for byte in hintMask: bits.append(num2binary(byteord(byte), 8)) hintMask = strjoin(bits) line = ' '.join(args + [token, hintMask]) else: line = ' '.join(args + [token]) xmlWriter.write(line) xmlWriter.newline() args = [] else: if isinstance(token, float): token = floatToFixedToStr(token, precisionBits=16) else: token = str(token) args.append(token) if args: # NOTE: only CFF2 charstrings/subrs can have numeric arguments on # the stack after the last operator. Compiling this would fail if # this is part of CFF 1.0 table. line = ' '.join(args) xmlWriter.write(line)
def decompile(self, data, ttFont): (_, data) = sstruct.unpack2(Sill_hdr, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) numLangs, = struct.unpack('>H', data[:2]) data = data[8:] maxsetting = 0 langinfo = [] for i in range(numLangs): (langcode, numsettings, offset) = struct.unpack(">4sHH", data[i * 8:(i+1) * 8]) offset = int(offset / 8) - (numLangs + 1) langcode = langcode.replace(b'\000', b'') langinfo.append((langcode.decode("utf-8"), numsettings, offset)) maxsetting = max(maxsetting, offset + numsettings) data = data[numLangs * 8:] finfo = [] for i in range(maxsetting): (fid, val, _) = struct.unpack(">LHH", data[i * 8:(i+1) * 8]) finfo.append((fid, val)) self.langs = {} for c, n, o in langinfo: self.langs[c] = [] for i in range(o, o+n): self.langs[c].append(finfo[i])
# CONSTANTS WIDTH, HEIGHT, MARGIN, FRAMES = 2400, 1600, 125, 1 BIG_TEXT = "Estonia" AUXILIARY_FONT = "Helvetica" AUXILIARY_FONT_SIZE = 24 # Constants we will work out dynamically MY_URL = subprocess.check_output("git remote get-url origin", shell=True).decode() ttFont = TTFont(FONT_PATH) MY_FONT_NAME = ttFont["name"].getDebugName(4) FONT_VERSION = "v%s" % floatToFixedToStr(ttFont["head"].fontRevision, 16) # DRAWS A GRID def grid(): stroke(1, 0.2) strokeWidth(1) STEP_X, STEP_Y = 0, 0 INCREMENT_X, INCREMENT_Y = MARGIN / 2, MARGIN / 2 rect(MARGIN, MARGIN, WIDTH - (MARGIN * 2), HEIGHT - (MARGIN * 2)) for x in range(29): polygon((MARGIN + STEP_X, MARGIN), (MARGIN + STEP_X, HEIGHT - MARGIN)) STEP_X += INCREMENT_X for y in range(29): polygon((MARGIN, MARGIN + STEP_Y), (WIDTH - MARGIN, MARGIN + STEP_Y)) STEP_Y += INCREMENT_Y
def toXML(self, writer, ttFont, **kwargs): glyfTable = ttFont["glyf"] writer.simpletag("Version", [("value", f"0x{self.Version:08X}")]) writer.newline() writer.begintag("GlyphData") writer.newline() for glyphName, glyphData in sorted(self.GlyphData.items()): try: glyfGlyph = glyfTable[glyphName] except KeyError: print(f"WARNING: glyph {glyphName} does not exist in the VF, skipping") continue if not glyfGlyph.isComposite(): print( f"WARNING: glyph {glyphName} is not a composite in the VF, skipping" ) continue assert len(glyfGlyph.components) == len(glyphData) # TODO: Proper error writer.begintag("Glyph", [("name", glyphName)]) writer.newline() for index, (varcComponent, glyfComponent) in enumerate( zip(glyphData, glyfGlyph.components) ): writer.begintag( "Component", [("numIntBitsForScale", varcComponent.numIntBitsForScale)], ) writer.newline() writer.comment( f"component index: {index}; " f"base glyph: {glyfComponent.glyphName}; " f"offset: ({glyfComponent.x},{glyfComponent.y})" ) writer.newline() for axisName, valueDict in sorted(varcComponent.coord.items()): attrs = [ ("axis", axisName), ( "value", floatToFixedToStr(valueDict["value"], COORD_PRECISIONBITS), ), ] if "varIdx" in valueDict: outer, inner = splitVarIdx(valueDict["varIdx"]) attrs.extend([("outer", outer), ("inner", inner)]) writer.simpletag("Coord", attrs) writer.newline() scalePrecisionBits = 16 - varcComponent.numIntBitsForScale for transformFieldName, valueDict in sorted( varcComponent.transform.items() ): value = valueDict["value"] if transformFieldName in {"ScaleX", "ScaleY"}: value = floatToFixedToStr(value, scalePrecisionBits) elif transformFieldName in {"Rotation", "SkewX", "SkewY"}: value = degreestToIntToStr(value) attrs = [("value", value)] if "varIdx" in valueDict: outer, inner = splitVarIdx(valueDict["varIdx"]) attrs.extend([("outer", outer), ("inner", inner)]) writer.simpletag(transformFieldName, attrs) writer.newline() writer.endtag("Component") writer.newline() writer.endtag("Glyph") writer.newline() writer.endtag("GlyphData") writer.newline() if hasattr(self, "VarStore") and self.VarStore is not None: self.VarStore.toXML(writer, ttFont)