def test_setupTable_CFF_all_blues_defined(self, testufo): testufo.info.postscriptBlueFuzz = 2 testufo.info.postscriptBlueShift = 8 testufo.info.postscriptBlueScale = 0.049736 testufo.info.postscriptForceBold = False testufo.info.postscriptBlueValues = [-12, 0, 486, 498, 712, 724] testufo.info.postscriptOtherBlues = [-217, -205] testufo.info.postscriptFamilyBlues = [-12, 0, 486, 498, 712, 724] testufo.info.postscriptFamilyOtherBlues = [-217, -205] compiler = OutlineOTFCompiler(testufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private assert private.BlueFuzz == 2 assert private.BlueShift == 8 assert private.BlueScale == 0.049736 assert private.ForceBold == 0 assert private.BlueValues == [-12, 0, 486, 498, 712, 724] assert private.OtherBlues == [-217, -205] assert private.FamilyBlues == [-12, 0, 486, 498, 712, 724] assert private.FamilyOtherBlues == [-217, -205]
def test_setupTable_CFF_no_blues_defined(self, testufo): # no blue values defined testufo.info.postscriptBlueValues = [] testufo.info.postscriptOtherBlues = [] testufo.info.postscriptFamilyBlues = [] testufo.info.postscriptFamilyOtherBlues = [] # the following attributes have no effect testufo.info.postscriptBlueFuzz = 2 testufo.info.postscriptBlueShift = 8 testufo.info.postscriptBlueScale = 0.049736 testufo.info.postscriptForceBold = False compiler = OutlineOTFCompiler(testufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private # expect default values as defined in fontTools' cffLib.py assert private.BlueFuzz == 1 assert private.BlueShift == 7 assert private.BlueScale == 0.039625 assert private.ForceBold == 0 # CFF PrivateDict has no blues attributes assert not hasattr(private, "BlueValues") assert not hasattr(private, "OtherBlues") assert not hasattr(private, "FamilyBlues") assert not hasattr(private, "FamilyOtherBlues")
def test_setupTable_CFF_all_blues_defined(self): self.ufo.info.postscriptBlueFuzz = 2 self.ufo.info.postscriptBlueShift = 8 self.ufo.info.postscriptBlueScale = 0.049736 self.ufo.info.postscriptForceBold = False self.ufo.info.postscriptBlueValues = [-12, 0, 486, 498, 712, 724] self.ufo.info.postscriptOtherBlues = [-217, -205] self.ufo.info.postscriptFamilyBlues = [-12, 0, 486, 498, 712, 724] self.ufo.info.postscriptFamilyOtherBlues = [-217, -205] compiler = OutlineOTFCompiler(self.ufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private self.assertEqual(private.BlueFuzz, 2) self.assertEqual(private.BlueShift, 8) self.assertEqual(private.BlueScale, 0.049736) self.assertEqual(private.ForceBold, False) self.assertEqual(private.BlueValues, [-12, 0, 486, 498, 712, 724]) self.assertEqual(private.OtherBlues, [-217, -205]) self.assertEqual(private.FamilyBlues, [-12, 0, 486, 498, 712, 724]) self.assertEqual(private.FamilyOtherBlues, [-217, -205])
def test_setupTable_CFF_round_some(self, testufo): # only floats 'close enough' are rounded to integer compiler = OutlineOTFCompiler(testufo, roundTolerance=0.34) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() program = self.get_charstring_program(otf, "d") self.assertProgramEqual( program, [ -26, 150.66, 197, "rmoveto", -33.66, -27, -27, -33, -33, 27, -27, 33.66, 33.34, 26.65, 27, 33, 33, -26.65, 27, -33.34, "hvcurveto", "endchar", ], )
def test_setupTable_CFF_round_none(self, testufo): # roundTolerance=0 means 'don't round, keep all floats' compiler = OutlineOTFCompiler(testufo, roundTolerance=0) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() program = self.get_charstring_program(otf, "d") self.assertProgramEqual( program, [ -26, 150.66, 197.32, "rmoveto", -33.66, -26.67, -26.99, -33.33, -33.33, 26.67, -26.66, 33.66, 33.33, 26.66, 26.66, 33.33, 33.33, -26.66, 26.99, -33.33, "hvcurveto", "endchar", ], )
def test_importTTX(self): compiler = OutlineOTFCompiler(self.ufo) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.importTTX() self.assertIn("CUST", otf) self.assertEqual(otf["CUST"].data, b"\x00\x01\xbe\xef") self.assertEqual(otf.sfntVersion, "OTTO")
def test_importTTX(self, testufo): compiler = OutlineOTFCompiler(testufo) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.importTTX() assert "CUST" in otf assert otf["CUST"].data == b"\x00\x01\xbe\xef" assert otf.sfntVersion == "OTTO"
def test_setupTable_CFF_no_blues_defined(self): # no blue values defined self.ufo.info.postscriptBlueValues = [] self.ufo.info.postscriptOtherBlues = [] self.ufo.info.postscriptFamilyBlues = [] self.ufo.info.postscriptFamilyOtherBlues = [] # the following attributes have no effect self.ufo.info.postscriptBlueFuzz = 2 self.ufo.info.postscriptBlueShift = 8 self.ufo.info.postscriptBlueScale = 0.049736 self.ufo.info.postscriptForceBold = False compiler = OutlineOTFCompiler(self.ufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private # expect default values as defined in fontTools' cffLib.py self.assertEqual(private.BlueFuzz, 1) self.assertEqual(private.BlueShift, 7) self.assertEqual(private.BlueScale, 0.039625) self.assertEqual(private.ForceBold, False) # CFF PrivateDict has no blues attributes self.assertFalse(hasattr(private, "BlueValues")) self.assertFalse(hasattr(private, "OtherBlues")) self.assertFalse(hasattr(private, "FamilyBlues")) self.assertFalse(hasattr(private, "FamilyOtherBlues"))
def test_no_contour_glyphs(self): for glyph in self.ufo: glyph.clearContours() compiler = OutlineOTFCompiler(self.ufo) compiler.compile() self.assertEqual(compiler.otf['hhea'].advanceWidthMax, 600) self.assertEqual(compiler.otf['hhea'].minLeftSideBearing, 0) self.assertEqual(compiler.otf['hhea'].minRightSideBearing, 0) self.assertEqual(compiler.otf['hhea'].xMaxExtent, 0)
def test_no_contour_glyphs(self, testufo): for glyph in testufo: glyph.clearContours() compiler = OutlineOTFCompiler(testufo) compiler.compile() assert compiler.otf["hhea"].advanceWidthMax == 600 assert compiler.otf["hhea"].minLeftSideBearing == 0 assert compiler.otf["hhea"].minRightSideBearing == 0 assert compiler.otf["hhea"].xMaxExtent == 0
def test_setupTable_CFF_no_optimize(self, testufo): compiler = OutlineOTFCompiler(testufo, optimizeCFF=False) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() program = self.get_charstring_program(otf, "a") self.assertProgramEqual( program, [-12, 66, 0, "rmoveto", 256, 0, "rlineto", -128, 510, "rlineto", "endchar"], )
def test_setupTable_CFF_round_all(self): # by default all floats are rounded to integer compiler = OutlineOTFCompiler(self.ufo) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() # glyph 'd' in TestFont.ufo contains float coordinates program = self.get_charstring_program(otf, "d") self.assertProgramEqual(program, [ -26, 151, 197, 'rmoveto', -34, -27, -27, -33, -33, 27, -27, 34, 33, 27, 27, 33, 33, -27, 27, -33, 'hvcurveto', 'endchar' ])
def test_calcCodePageRanges(emptyufo, unicodes, expected): font = emptyufo for i, c in enumerate(unicodes): font.newGlyph("glyph%d" % i).unicode = ord(c) compiler = OutlineOTFCompiler(font) compiler.compile() assert compiler.otf["OS/2"].ulCodePageRange1 == intListToNum(expected, start=0, length=32) assert compiler.otf["OS/2"].ulCodePageRange2 == intListToNum(expected, start=32, length=32)
def test_cmap_nonBMP_with_UVS(self, testufo): u1F170 = testufo.newGlyph("u1F170") u1F170.unicode = 0x1F170 testufo.newGlyph("u1F170.text") testufo.lib["public.unicodeVariationSequences"] = { "FE0E": { "1F170": "u1F170.text", }, "FE0F": { "1F170": "u1F170", }, } compiler = OutlineOTFCompiler(testufo) otf = compiler.compile() assert "cmap" in otf cmap = otf["cmap"] cmap.compile(otf) assert len(cmap.tables) == 5 cmap4_0_3 = cmap.tables[0] cmap12_0_4 = cmap.tables[1] cmap14_0_5 = cmap.tables[2] cmap4_3_1 = cmap.tables[3] cmap12_3_10 = cmap.tables[4] assert (cmap4_0_3.platformID, cmap4_0_3.platEncID) == (0, 3) assert (cmap4_3_1.platformID, cmap4_3_1.platEncID) == (3, 1) assert cmap4_0_3.language == cmap4_3_1.language assert cmap4_0_3.language == 0 mapping = {c: chr(c) for c in range(0x61, 0x6D)} mapping[0x20] = "space" assert cmap4_0_3.cmap == cmap4_3_1.cmap assert cmap4_0_3.cmap == mapping assert (cmap12_0_4.platformID, cmap12_0_4.platEncID) == (0, 4) assert (cmap12_3_10.platformID, cmap12_3_10.platEncID) == (3, 10) assert cmap12_0_4.language == cmap12_3_10.language assert cmap12_0_4.language == 0 mapping[0x1F170] = "u1F170" assert cmap12_0_4.cmap == cmap12_3_10.cmap assert cmap12_0_4.cmap == mapping assert (cmap14_0_5.platformID, cmap14_0_5.platEncID) == (0, 5) assert cmap14_0_5.language == 0 assert cmap14_0_5.uvsDict == { 0xFE0E: [(0x1F170, "u1F170.text")], 0xFE0F: [(0x1F170, None)], }
def test_setupTable_CFF_round_some(self): # only floats 'close enough' are rounded to integer compiler = OutlineOTFCompiler(self.ufo, roundTolerance=0.1) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() program = self.get_charstring_program(otf, "d") # e.g., 26.99 becomes 27, but 150.66 stays as it is self.assertProgramEqual(program, [ -26, 150.66, 197.32, 'rmoveto', -33.66, 0, -26.67, -27, 0, -33.33, 'rrcurveto', 0, -33.33, 26.67, -26.67, 33.66, 0, 'rrcurveto', 33.34, 0, 26.65, 26.67, 0, 33.33, 'rrcurveto', 0, 33.33, -26.65, 27, -33.34, 0, 'rrcurveto', 'endchar'])
def test_makeGlyphsBoundingBoxes(self): # the call to 'makeGlyphsBoundingBoxes' happen in the __init__ method compiler = OutlineOTFCompiler(self.ufo) # with default roundTolerance, all coordinates and hence the bounding # box values are rounded with round() self.assertEqual(compiler.glyphBoundingBoxes['d'], (90, 77, 211, 197))
def test_makeGlyphsBoundingBoxes_floats(self): # specifying a custom roundTolerance affects which coordinates are # rounded; in this case, the top-most Y coordinate stays a float # (197.32), hence the bbox.yMax (198) is rounded using math.ceiling() compiler = OutlineOTFCompiler(self.ufo, roundTolerance=0.1) self.assertEqual(compiler.glyphBoundingBoxes['d'], (90, 77, 211, 198))
def test_cmap_BMP(self, testufo): compiler = OutlineOTFCompiler(testufo) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_cmap() assert "cmap" in otf cmap = otf["cmap"] assert len(cmap.tables) == 2 cmap4_0_3 = cmap.tables[0] cmap4_3_1 = cmap.tables[1] assert (cmap4_0_3.platformID, cmap4_0_3.platEncID) == (0, 3) assert (cmap4_3_1.platformID, cmap4_3_1.platEncID) == (3, 1) assert cmap4_0_3.language == cmap4_3_1.language assert cmap4_0_3.language == 0 mapping = {c: chr(c) for c in range(0x61, 0x6D)} mapping[0x20] = "space" assert cmap4_0_3.cmap == cmap4_3_1.cmap assert cmap4_0_3.cmap == mapping
def test_setupTable_CFF_optimize(self, testufo): compiler = OutlineOTFCompiler(testufo, optimizeCFF=True) otf = compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() program = self.get_charstring_program(otf, "a") self.assertProgramEqual( program, [ -12, 66, 'hmoveto', 256, 'hlineto', -128, 510, 'rlineto', 'endchar' ] )
def test_setupTable_CFF_some_blues_defined(self): self.ufo.info.postscriptBlueFuzz = 2 self.ufo.info.postscriptForceBold = True self.ufo.info.postscriptBlueValues = [] self.ufo.info.postscriptOtherBlues = [-217, -205] self.ufo.info.postscriptFamilyBlues = [] self.ufo.info.postscriptFamilyOtherBlues = [] compiler = OutlineOTFCompiler(self.ufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private self.assertEqual(private.BlueFuzz, 2) self.assertEqual(private.BlueShift, 7) # default self.assertEqual(private.BlueScale, 0.039625) # default self.assertEqual(private.ForceBold, True) self.assertFalse(hasattr(private, "BlueValues")) self.assertEqual(private.OtherBlues, [-217, -205]) self.assertFalse(hasattr(private, "FamilyBlues")) self.assertFalse(hasattr(private, "FamilyOtherBlues"))
def test_setupTable_CFF_some_blues_defined(self, testufo): testufo.info.postscriptBlueFuzz = 2 testufo.info.postscriptForceBold = True testufo.info.postscriptBlueValues = [] testufo.info.postscriptOtherBlues = [-217, -205] testufo.info.postscriptFamilyBlues = [] testufo.info.postscriptFamilyOtherBlues = [] compiler = OutlineOTFCompiler(testufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff private = cff[list(cff.keys())[0]].Private assert private.BlueFuzz == 2 assert private.BlueShift == 7 # default assert private.BlueScale == 0.039625 # default assert private.ForceBold is True assert not hasattr(private, "BlueValues") assert private.OtherBlues == [-217, -205] assert not hasattr(private, "FamilyBlues") assert not hasattr(private, "FamilyOtherBlues")
def test_optimized_default_and_nominal_widths(self, FontClass): ufo = FontClass() ufo.info.unitsPerEm = 1000 for glyphName, width in ( (".notdef", 500), ("space", 250), ("a", 388), ("b", 410), ("c", 374), ("d", 374), ("e", 388), ("f", 410), ("g", 388), ("h", 410), ("i", 600), ("j", 600), ("k", 600), ("l", 600), ): glyph = ufo.newGlyph(glyphName) glyph.width = width compiler = OutlineOTFCompiler(ufo) compiler.otf = TTFont(sfntVersion="OTTO") compiler.setupTable_hmtx() compiler.setupTable_CFF() cff = compiler.otf["CFF "].cff topDict = cff[list(cff.keys())[0]] private = topDict.Private assert private.defaultWidthX == 600 assert private.nominalWidthX == 303 charStrings = topDict.CharStrings # the following have width == defaultWidthX, so it's omitted for g in ("i", "j", "k", "l"): assert charStrings.getItemAndSelector(g)[0].program == ["endchar"] # 'space' has width 250, so the width encoded in its charstring is: # 250 - nominalWidthX assert charStrings.getItemAndSelector("space")[0].program == [ -53, "endchar" ]
def test_makeGlyphsBoundingBoxes(self, testufo): compiler = OutlineOTFCompiler(testufo) # with default roundTolerance, all coordinates and hence the bounding # box values are rounded with otRound() assert compiler.glyphBoundingBoxes["d"] == (90, 77, 211, 197)