• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import struct
2
3from fontTools.misc import etree
4from fontTools.misc.testTools import getXML, parseXML
5from fontTools.ttLib import TTFont
6from fontTools.ttLib.tables.S_V_G_ import table_S_V_G_
7
8import pytest
9
10
11def dump(table, ttFont=None):
12    print("\n".join(getXML(table.toXML, ttFont)))
13
14
15def strip_xml_whitespace(xml_string):
16    def strip_or_none(text):
17        text = text.strip() if text else None
18        return text if text else None
19
20    tree = etree.fromstring(xml_string)
21    for e in tree.iter("*"):
22        e.text = strip_or_none(e.text)
23        e.tail = strip_or_none(e.tail)
24    return etree.tostring(tree, encoding="utf-8")
25
26
27SVG_DOCS = [
28    strip_xml_whitespace(svg)
29    for svg in (
30        b"""\
31        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
32          <defs>
33            <rect x="100" y="-200" width="300" height="400" id="p1"/>
34          </defs>
35          <g id="glyph1">
36            <use xlink:href="#p1" fill="#red"/>
37          </g>
38          <g id="glyph2">
39            <use xlink:href="#p1" fill="#blue"/>
40          </g>
41          <g id="glyph4">
42            <use xlink:href="#p1" fill="#green"/>
43          </g>
44        </svg>""",
45        b"""\
46        <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
47          <g id="glyph3">
48            <path d="M0,0 L100,0 L50,100 Z"/>
49          </g>
50        </svg>""",
51    )
52]
53
54
55OTSVG_DATA = b"".join(
56    [
57        # SVG table header
58        b"\x00\x00"  # version (0)
59        b"\x00\x00\x00\x0a"  # offset to SVGDocumentList (10)
60        b"\x00\x00\x00\x00"  # reserved (0)
61        #  SVGDocumentList
62        b"\x00\x03"  # number of SVGDocumentRecords (3)
63        # SVGDocumentRecord[0]
64        b"\x00\x01"  # startGlyphID (1)
65        b"\x00\x02"  # endGlyphID (2)
66        b"\x00\x00\x00\x26"  # svgDocOffset (2 + 12*3 == 38 == 0x26)
67        + struct.pack(">L", len(SVG_DOCS[0]))  # svgDocLength
68        # SVGDocumentRecord[1]
69        + b"\x00\x03"  # startGlyphID (3)
70        b"\x00\x03"  # endGlyphID (3)
71        + struct.pack(">L", 0x26 + len(SVG_DOCS[0]))  # svgDocOffset
72        + struct.pack(">L", len(SVG_DOCS[1]))  # svgDocLength
73        # SVGDocumentRecord[2]
74        + b"\x00\x04"  # startGlyphID (4)
75        b"\x00\x04"  # endGlyphID (4)
76        b"\x00\x00\x00\x26"  # svgDocOffset (38); records 0 and 2 point to same SVG doc
77        + struct.pack(">L", len(SVG_DOCS[0]))  # svgDocLength
78    ]
79    + SVG_DOCS
80)
81
82OTSVG_TTX = [
83    '<svgDoc endGlyphID="2" startGlyphID="1">',
84    f"  <![CDATA[{SVG_DOCS[0].decode()}]]>",
85    "</svgDoc>",
86    '<svgDoc endGlyphID="3" startGlyphID="3">',
87    f"  <![CDATA[{SVG_DOCS[1].decode()}]]>",
88    "</svgDoc>",
89    '<svgDoc endGlyphID="4" startGlyphID="4">',
90    f"  <![CDATA[{SVG_DOCS[0].decode()}]]>",
91    "</svgDoc>",
92]
93
94
95@pytest.fixture
96def font():
97    font = TTFont()
98    font.setGlyphOrder([".notdef"] + ["glyph%05d" % i for i in range(1, 30)])
99    return font
100
101
102def test_decompile_and_compile(font):
103    table = table_S_V_G_()
104    table.decompile(OTSVG_DATA, font)
105    assert table.compile(font) == OTSVG_DATA
106
107
108def test_decompile_and_dump_ttx(font):
109    table = table_S_V_G_()
110    table.decompile(OTSVG_DATA, font)
111
112    dump(table, font)
113    assert getXML(table.toXML, font) == OTSVG_TTX
114
115
116def test_load_from_ttx_and_compile(font):
117    table = table_S_V_G_()
118    for name, attrs, content in parseXML(OTSVG_TTX):
119        table.fromXML(name, attrs, content, font)
120    assert table.compile(font) == OTSVG_DATA
121
122
123def test_round_trip_ttx(font):
124    table = table_S_V_G_()
125    for name, attrs, content in parseXML(OTSVG_TTX):
126        table.fromXML(name, attrs, content, font)
127    compiled = table.compile(font)
128
129    table = table_S_V_G_()
130    table.decompile(compiled, font)
131    assert getXML(table.toXML, font) == OTSVG_TTX
132