_g_l_y_f: use floatToFixedToStr and strToFixedToFloat in GlyphComponent toXML/fromXML
This commit is contained in:
parent
8791caf3b8
commit
c60512de0e
@ -11,6 +11,8 @@ from fontTools.misc.bezierTools import calcQuadraticBounds
|
|||||||
from fontTools.misc.fixedTools import (
|
from fontTools.misc.fixedTools import (
|
||||||
fixedToFloat as fi2fl,
|
fixedToFloat as fi2fl,
|
||||||
floatToFixed as fl2fi,
|
floatToFixed as fl2fi,
|
||||||
|
floatToFixedToStr as fl2str,
|
||||||
|
strToFixedToFloat as str2fl,
|
||||||
otRound,
|
otRound,
|
||||||
)
|
)
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
@ -1365,15 +1367,18 @@ class GlyphComponent(object):
|
|||||||
transform = self.transform
|
transform = self.transform
|
||||||
if transform[0][1] or transform[1][0]:
|
if transform[0][1] or transform[1][0]:
|
||||||
attrs = attrs + [
|
attrs = attrs + [
|
||||||
("scalex", transform[0][0]), ("scale01", transform[0][1]),
|
("scalex", fl2str(transform[0][0], 14)),
|
||||||
("scale10", transform[1][0]), ("scaley", transform[1][1]),
|
("scale01", fl2str(transform[0][1], 14)),
|
||||||
]
|
("scale10", fl2str(transform[1][0], 14)),
|
||||||
|
("scaley", fl2str(transform[1][1], 14)),
|
||||||
|
]
|
||||||
elif transform[0][0] != transform[1][1]:
|
elif transform[0][0] != transform[1][1]:
|
||||||
attrs = attrs + [
|
attrs = attrs + [
|
||||||
("scalex", transform[0][0]), ("scaley", transform[1][1]),
|
("scalex", fl2str(transform[0][0], 14)),
|
||||||
]
|
("scaley", fl2str(transform[1][1], 14)),
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
attrs = attrs + [("scale", transform[0][0])]
|
attrs = attrs + [("scale", fl2str(transform[0][0], 14))]
|
||||||
attrs = attrs + [("flags", hex(self.flags))]
|
attrs = attrs + [("flags", hex(self.flags))]
|
||||||
writer.simpletag("component", attrs)
|
writer.simpletag("component", attrs)
|
||||||
writer.newline()
|
writer.newline()
|
||||||
@ -1387,17 +1392,17 @@ class GlyphComponent(object):
|
|||||||
self.x = safeEval(attrs["x"])
|
self.x = safeEval(attrs["x"])
|
||||||
self.y = safeEval(attrs["y"])
|
self.y = safeEval(attrs["y"])
|
||||||
if "scale01" in attrs:
|
if "scale01" in attrs:
|
||||||
scalex = safeEval(attrs["scalex"])
|
scalex = str2fl(attrs["scalex"], 14)
|
||||||
scale01 = safeEval(attrs["scale01"])
|
scale01 = str2fl(attrs["scale01"], 14)
|
||||||
scale10 = safeEval(attrs["scale10"])
|
scale10 = str2fl(attrs["scale10"], 14)
|
||||||
scaley = safeEval(attrs["scaley"])
|
scaley = str2fl(attrs["scaley"], 14)
|
||||||
self.transform = [[scalex, scale01], [scale10, scaley]]
|
self.transform = [[scalex, scale01], [scale10, scaley]]
|
||||||
elif "scalex" in attrs:
|
elif "scalex" in attrs:
|
||||||
scalex = safeEval(attrs["scalex"])
|
scalex = str2fl(attrs["scalex"], 14)
|
||||||
scaley = safeEval(attrs["scaley"])
|
scaley = str2fl(attrs["scaley"], 14)
|
||||||
self.transform = [[scalex, 0], [0, scaley]]
|
self.transform = [[scalex, 0], [0, scaley]]
|
||||||
elif "scale" in attrs:
|
elif "scale" in attrs:
|
||||||
scale = safeEval(attrs["scale"])
|
scale = str2fl(attrs["scale"], 14)
|
||||||
self.transform = [[scale, 0], [0, scale]]
|
self.transform = [[scale, 0], [0, scale]]
|
||||||
self.flags = safeEval(attrs["flags"])
|
self.flags = safeEval(attrs["flags"])
|
||||||
|
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
from fontTools.misc.py23 import *
|
from fontTools.misc.py23 import *
|
||||||
from fontTools.misc.fixedTools import otRound
|
from fontTools.misc.fixedTools import otRound
|
||||||
|
from fontTools.misc.testTools import getXML, parseXML
|
||||||
from fontTools.pens.ttGlyphPen import TTGlyphPen
|
from fontTools.pens.ttGlyphPen import TTGlyphPen
|
||||||
from fontTools.ttLib import TTFont, newTable, TTLibError
|
from fontTools.ttLib import TTFont, newTable, TTLibError
|
||||||
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
|
from fontTools.ttLib.tables._g_l_y_f import (
|
||||||
|
GlyphCoordinates,
|
||||||
|
GlyphComponent,
|
||||||
|
ARGS_ARE_XY_VALUES,
|
||||||
|
WE_HAVE_A_SCALE,
|
||||||
|
WE_HAVE_A_TWO_BY_TWO,
|
||||||
|
WE_HAVE_AN_X_AND_Y_SCALE,
|
||||||
|
)
|
||||||
from fontTools.ttLib.tables import ttProgram
|
from fontTools.ttLib.tables import ttProgram
|
||||||
import sys
|
import sys
|
||||||
import array
|
import array
|
||||||
|
import itertools
|
||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
@ -276,6 +285,124 @@ class glyfTableTest(unittest.TestCase):
|
|||||||
composite.compact(glyfTable)
|
composite.compact(glyfTable)
|
||||||
|
|
||||||
|
|
||||||
|
class GlyphComponentTest:
|
||||||
|
|
||||||
|
def test_toXML_no_transform(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
comp.glyphName = "a"
|
||||||
|
comp.flags = ARGS_ARE_XY_VALUES
|
||||||
|
comp.x, comp.y = 1, 2
|
||||||
|
|
||||||
|
assert getXML(comp.toXML) == [
|
||||||
|
'<component glyphName="a" x="1" y="2" flags="0x2"/>'
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_toXML_transform_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
comp.glyphName = "a"
|
||||||
|
comp.flags = ARGS_ARE_XY_VALUES | WE_HAVE_A_SCALE
|
||||||
|
comp.x, comp.y = 1, 2
|
||||||
|
|
||||||
|
comp.transform = [[0.2999878, 0], [0, 0.2999878]]
|
||||||
|
assert getXML(comp.toXML) == [
|
||||||
|
'<component glyphName="a" x="1" y="2" scale="0.3" flags="0xa"/>'
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_toXML_transform_xy_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
comp.glyphName = "a"
|
||||||
|
comp.flags = ARGS_ARE_XY_VALUES | WE_HAVE_AN_X_AND_Y_SCALE
|
||||||
|
comp.x, comp.y = 1, 2
|
||||||
|
|
||||||
|
comp.transform = [[0.5999756, 0], [0, 0.2999878]]
|
||||||
|
assert getXML(comp.toXML) == [
|
||||||
|
'<component glyphName="a" x="1" y="2" scalex="0.6" '
|
||||||
|
'scaley="0.3" flags="0x42"/>'
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_toXML_transform_2x2_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
comp.glyphName = "a"
|
||||||
|
comp.flags = ARGS_ARE_XY_VALUES | WE_HAVE_A_TWO_BY_TWO
|
||||||
|
comp.x, comp.y = 1, 2
|
||||||
|
|
||||||
|
comp.transform = [[0.5999756, -0.2000122], [0.2000122, 0.2999878]]
|
||||||
|
assert getXML(comp.toXML) == [
|
||||||
|
'<component glyphName="a" x="1" y="2" scalex="0.6" scale01="-0.2" '
|
||||||
|
'scale10="0.2" scaley="0.3" flags="0x82"/>'
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_fromXML_no_transform(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
for name, attrs, content in parseXML(
|
||||||
|
['<component glyphName="a" x="1" y="2" flags="0x2"/>']
|
||||||
|
):
|
||||||
|
comp.fromXML(name, attrs, content, ttFont=None)
|
||||||
|
|
||||||
|
assert comp.glyphName == "a"
|
||||||
|
assert comp.flags & ARGS_ARE_XY_VALUES != 0
|
||||||
|
assert (comp.x, comp.y) == (1, 2)
|
||||||
|
assert not hasattr(comp, "transform")
|
||||||
|
|
||||||
|
def test_fromXML_transform_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
for name, attrs, content in parseXML(
|
||||||
|
['<component glyphName="a" x="1" y="2" scale="0.3" flags="0xa"/>']
|
||||||
|
):
|
||||||
|
comp.fromXML(name, attrs, content, ttFont=None)
|
||||||
|
|
||||||
|
assert comp.glyphName == "a"
|
||||||
|
assert comp.flags & ARGS_ARE_XY_VALUES != 0
|
||||||
|
assert comp.flags & WE_HAVE_A_SCALE != 0
|
||||||
|
assert (comp.x, comp.y) == (1, 2)
|
||||||
|
assert hasattr(comp, "transform")
|
||||||
|
for value, expected in zip(
|
||||||
|
itertools.chain(*comp.transform), [0.2999878, 0, 0, 0.2999878]
|
||||||
|
):
|
||||||
|
assert value == pytest.approx(expected)
|
||||||
|
|
||||||
|
def test_fromXML_transform_xy_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
for name, attrs, content in parseXML(
|
||||||
|
[
|
||||||
|
'<component glyphName="a" x="1" y="2" scalex="0.6" '
|
||||||
|
'scaley="0.3" flags="0x42"/>'
|
||||||
|
]
|
||||||
|
):
|
||||||
|
comp.fromXML(name, attrs, content, ttFont=None)
|
||||||
|
|
||||||
|
assert comp.glyphName == "a"
|
||||||
|
assert comp.flags & ARGS_ARE_XY_VALUES != 0
|
||||||
|
assert comp.flags & WE_HAVE_AN_X_AND_Y_SCALE != 0
|
||||||
|
assert (comp.x, comp.y) == (1, 2)
|
||||||
|
assert hasattr(comp, "transform")
|
||||||
|
for value, expected in zip(
|
||||||
|
itertools.chain(*comp.transform), [0.5999756, 0, 0, 0.2999878]
|
||||||
|
):
|
||||||
|
assert value == pytest.approx(expected)
|
||||||
|
|
||||||
|
def test_fromXML_transform_2x2_scale(self):
|
||||||
|
comp = GlyphComponent()
|
||||||
|
for name, attrs, content in parseXML(
|
||||||
|
[
|
||||||
|
'<component glyphName="a" x="1" y="2" scalex="0.6" scale01="-0.2" '
|
||||||
|
'scale10="0.2" scaley="0.3" flags="0x82"/>'
|
||||||
|
]
|
||||||
|
):
|
||||||
|
comp.fromXML(name, attrs, content, ttFont=None)
|
||||||
|
|
||||||
|
assert comp.glyphName == "a"
|
||||||
|
assert comp.flags & ARGS_ARE_XY_VALUES != 0
|
||||||
|
assert comp.flags & WE_HAVE_A_TWO_BY_TWO != 0
|
||||||
|
assert (comp.x, comp.y) == (1, 2)
|
||||||
|
assert hasattr(comp, "transform")
|
||||||
|
for value, expected in zip(
|
||||||
|
itertools.chain(*comp.transform),
|
||||||
|
[0.5999756, -0.2000122, 0.2000122, 0.2999878]
|
||||||
|
):
|
||||||
|
assert value == pytest.approx(expected)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
sys.exit(unittest.main())
|
sys.exit(unittest.main())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user