def test_Slant(self, font, origin): filter_ = TransformationsFilter(Slant=45, Origin=origin) assert filter_(font) origin_height = filter_.get_origin_height(font, origin) a = font["a"] assert isclose(a[0][0].x, -origin_height) assert a[0][0].y == 0
def test_ScaleY(self, font, origin): percent = 50 filter_ = TransformationsFilter(ScaleY=percent, Origin=origin) assert filter_(font) factor = percent/100 origin_height = filter_.get_origin_height(font, origin) bottom = origin_height * factor top = bottom + 300 * factor a = font["a"] # only y coords change assert (a[0][0].x, a[0][0].y) == (0, bottom) assert (a[0][2].x, a[0][2].y) == (300, top)
def test_composite_glyphs(self, font): filter_ = TransformationsFilter(OffsetX=-10, OffsetY=51, ScaleX=50, ScaleY=50, exclude={"c"}) assert filter_(font) b = font["b"] # component 'a' #1 was not transformed, because the base glyph was already # transformed, and the component's own transformation is identity assert b.components[0].transformation == (1, 0, 0, 1, 0, 0) # component 'c' was transformed, because base glyph was not included assert b.components[1].transformation == (0.5, 0, 0, 0.5, -10, 51) # component 'a' #2 was partly transformed: the base glyph was transformed, but # the component's original transformation was not identity; thus # it was modified to compensate for the transformation already applied to # the base glyph (scale stays same, offsets are scaled) assert b.components[2].transformation == (1, 0, 0, 1, 5, -5) d = font["d"] # component 'b' was transformed as well as its base glyph, because # its original transform had a scale, so it was necessary to # compensate for the transformation applied on the base glyph assert d.components[0].transformation == (1, 0, 0, -1, 0, 102)
def test_ScaleX(self, font, origin): # different Origin heights should not affect horizontal scale filter_ = TransformationsFilter(ScaleX=50, Origin=origin) assert filter_(font) a = font["a"] assert (a[0][0].x, a[0][0].y) == (0, 0) assert (a[0][2].x, a[0][2].y) == (150, 300)
def test_OffsetXY(self, font): filter_ = TransformationsFilter(OffsetX=-10, OffsetY=51) assert filter_(font) a = font["a"] assert (a[0][0].x, a[0][0].y) == (-10, 51) assert (a.anchors[1].x, a.anchors[1].y) == (90, -149) assert font["b"].components[0].transformation[-2:] == (0, 0)
def test_OffsetX(self, font): filter_ = TransformationsFilter(OffsetX=-10) assert filter_(font) a = font["a"] assert (a[0][0].x, a[0][0].y) == (-10, 0) assert (a.anchors[1].x, a.anchors[1].y) == (90, -200) # base glyph was already transformed, component didn't change assert font["b"].components[0].transformation[-2:] == (0, 0)
def test_composite_glyphs(self, font): filter_ = TransformationsFilter( OffsetX=-10, OffsetY=51, ScaleX=50, ScaleY=50, exclude={'c'}) assert filter_(font) b = font["b"] # component 'a' was not transformed, because it doesn't have a scale # or skew and the base glyph was already included assert b.components[0].transformation == (1, 0, 0, 1, 0, 0) # component 'c' was transformed, because base glyph was not included assert b.components[1].transformation == (.5, 0, 0, .5, -10, 51) d = font["d"] # component 'b' was transformed as well as its base glyph, because # its original transform had a scale, so it was necessary to # compensate for the transformation applied on the base glyph assert d.components[0].transformation == (1, 0, 0, -1, 0, 102)
def test_Identity(self, font): filter_ = TransformationsFilter() assert not filter_(font)
def test_empty_glyph(self, font): filter_ = TransformationsFilter(OffsetY=51, include={'space'}) assert not filter_(font)
def test_invalid_origin_value(self): with pytest.raises(ValueError) as excinfo: TransformationsFilter(Origin=5) excinfo.match("is not a valid Origin")
def makeSlanted(options): font = makeDesktop(options, False) exclude = [f"u{i:X}" for i in range(0x1EE00, 0x1EEFF + 1)] exclude += [ "exclam", "period", "guillemotleft", "guillemotright", "braceleft", "bar", "braceright", "bracketleft", "bracketright", "parenleft", "parenright", "slash", "backslash", "brokenbar", "uni061F", "dot.1", "dot.2", ] skew = TransformationsFilter(Slant=-options.slant, exclude=exclude) skew(font) # fix metadata info = font.info info.italicAngle = options.slant info.postscriptFullName += " Slanted" if info.postscriptWeightName == "Bold": info.postscriptFontName = info.postscriptFontName.replace( "Bold", "BoldSlanted") info.styleName = "Bold Slanted" info.styleMapFamilyName = info.familyName info.styleMapStyleName = "bold italic" else: info.postscriptFontName = info.postscriptFontName.replace( "Regular", "Slanted") info.styleName = "Slanted" info.styleMapFamilyName = info.familyName info.styleMapStyleName = "italic" matrix = skew.context.matrix mergeLatin(font) fea = font.features.text for block in fea.statements: if isinstance(block, (ast.LookupBlock, ast.FeatureBlock)): for st in block.statements: if isinstance( st, (ast.MarkMarkPosStatement, ast.MarkBasePosStatement)): st.marks = [(transformAnchor(a, matrix), m) for a, m in st.marks] elif isinstance(st, ast.MarkClassDefinition): st.anchor = transformAnchor(st.anchor, matrix) elif isinstance(st, ast.CursivePosStatement): st.entryAnchor = transformAnchor(st.entryAnchor, matrix) st.exitAnchor = transformAnchor(st.exitAnchor, matrix) otf = generateFont(options, font) otf.save(options.output)