Esempio n. 1
0
def test_pen_roundtrip(datadir, ufo_module):
    font = classes.GSFont(str(datadir.join("PenTest.glyphs")))
    font_temp = ufo_module.Font()
    glyph_temp = font_temp.newGlyph("test")

    for glyph in font.glyphs:
        for layer in glyph.layers:
            glyph_temp.clear()
            ufo_pen = glyph_temp.getPointPen()
            layer.drawPoints(ufo_pen)

            layer_temp = classes.GSLayer()
            glyphs_pen = layer_temp.getPointPen()
            glyph_temp.drawPoints(glyphs_pen)

            assert len(layer.paths) == len(layer_temp.paths)
            for path_orig, path_temp in zip(layer.paths, layer_temp.paths):
                assert len(path_orig.nodes) == len(path_temp.nodes)
                assert path_orig.closed == path_temp.closed
                for node_orig, node_temp in zip(path_orig.nodes, path_temp.nodes):
                    assert node_orig.position.x == node_temp.position.x
                    assert node_orig.position.y == node_temp.position.y
                    assert node_orig.smooth == node_temp.smooth
                    assert node_orig.type == node_temp.type

            assert len(layer.components) == len(layer_temp.components)
            for comp_orig, comp_temp in zip(layer.components, layer_temp.components):
                assert comp_orig.name == comp_temp.name
                assert comp_orig.transform == comp_temp.transform
def test_layer_lib_in_font_user_data(ufo_module):
    font = classes.GSFont()
    font.masters.append(classes.GSFontMaster())
    font.masters.append(classes.GSFontMaster())
    glyph = classes.GSGlyph(name="a")
    font.glyphs.append(glyph)
    layer = classes.GSLayer()
    layer.layerId = font.masters[0].id
    layer.width = 0
    glyph.layers.append(layer)
    layer = classes.GSLayer()
    layer.layerId = font.masters[1].id
    layer.width = 0
    glyph.layers.append(layer)

    font.userData[GLYPHLIB_PREFIX + "layerLib.public.default"] = {
        "layerLibKey": "layerLibValue"
    }

    ufo1, ufo2 = to_ufos(font)
    assert "layerLibKey" in ufo1.layers["public.default"].lib
    assert ufo1.layers["public.default"].lib["layerLibKey"] == "layerLibValue"
    assert "layerLibKey" in ufo2.layers["public.default"].lib
    assert ufo2.layers["public.default"].lib["layerLibKey"] == "layerLibValue"
Esempio n. 3
0
    def test_write_hint(self):
        hint = classes.GSHint()
        # http://docu.glyphsapp.com/#gshint
        layer = classes.GSLayer()
        path1 = classes.GSPath()
        layer.paths.append(path1)
        node1 = classes.GSNode(Point(100, 100))
        path1.nodes.append(node1)
        hint.originNode = node1

        node2 = classes.GSNode(Point(200, 200))
        path1.nodes.append(node2)
        hint.targetNode = node2

        node3 = classes.GSNode(Point(300, 300))
        path1.nodes.append(node3)
        hint.otherNode1 = node3

        path2 = classes.GSPath()
        layer.paths.append(path2)
        node4 = classes.GSNode(Point(400, 400))
        path2.nodes.append(node4)
        hint.otherNode2 = node4

        hint.type = classes.CORNER
        hint.options = classes.TTROUND | classes.TRIPLE
        hint.horizontal = True
        # selected: not written
        hint.name = "My favourite hint"
        self.assertWrites(
            hint,
            dedent(
                """\
            {
            horizontal = 1;
            origin = "{0, 0}";
            target = "{0, 1}";
            other1 = "{0, 2}";
            other2 = "{1, 0}";
            type = 16;
            name = "My favourite hint";
            options = 128;
            }
        """
            ),
        )
def test_node_user_data_into_glif_lib():
    font = classes.GSFont()
    master = classes.GSFontMaster()
    master.id = "M1"
    font.masters.append(master)
    glyph = classes.GSGlyph("a")
    layer = classes.GSLayer()
    layer.layerId = "M1"
    layer.associatedMasterId = "M1"
    glyph.layers.append(layer)
    font.glyphs.append(glyph)
    path = classes.GSPath()
    layer.paths.append(path)
    node1 = classes.GSNode()
    node1.userData["nodeUserDataKey1"] = "nodeUserDataValue1"
    node1.name = "node1"
    node2 = classes.GSNode()
    node2.userData["nodeUserDataKey2"] = "nodeUserDataValue2"
    node2.name = "node2"
    path.nodes.append(classes.GSNode())
    path.nodes.append(node1)
    path.nodes.append(classes.GSNode())
    path.nodes.append(classes.GSNode())
    path.nodes.append(node2)

    (ufo, ) = to_ufos(font, minimize_glyphs_diffs=True)

    assert ufo["a"].lib[GLYPHLIB_PREFIX + "nodeUserData.0.1"] == {
        "nodeUserDataKey1": "nodeUserDataValue1"
    }
    assert ufo["a"][0][2].name == "node1"
    assert ufo["a"].lib[GLYPHLIB_PREFIX + "nodeUserData.0.4"] == {
        "nodeUserDataKey2": "nodeUserDataValue2"
    }
    assert ufo["a"][0][0].name == "node2"

    font = to_glyphs([ufo])

    path = font.glyphs["a"].layers["M1"].paths[0]
    assert path.nodes[1].userData["nodeUserDataKey1"] == "nodeUserDataValue1"
    assert path.nodes[1].name == "node1"
    assert path.nodes[4].userData["nodeUserDataKey2"] == "nodeUserDataValue2"
    assert path.nodes[4].name == "node2"
def test_glyph_user_data_into_ufo_lib():
    font = classes.GSFont()
    font.masters.append(classes.GSFontMaster())
    glyph = classes.GSGlyph('a')
    glyph.userData['glyphUserDataKey'] = 'glyphUserDataValue'
    font.glyphs.append(glyph)
    layer = classes.GSLayer()
    layer.layerId = font.masters[0].id
    glyph.layers.append(layer)

    ufo, = to_ufos(font)

    assert ufo.lib[GLYPHLIB_PREFIX + 'glyphUserData.a'] == {
        'glyphUserDataKey': 'glyphUserDataValue'
    }

    font = to_glyphs([ufo])

    assert font.glyphs['a'].userData[
        'glyphUserDataKey'] == 'glyphUserDataValue'
def test_glyph_user_data_into_ufo_lib():
    font = classes.GSFont()
    font.masters.append(classes.GSFontMaster())
    glyph = classes.GSGlyph("a")
    glyph.userData["glyphUserDataKey"] = "glyphUserDataValue"
    font.glyphs.append(glyph)
    layer = classes.GSLayer()
    layer.layerId = font.masters[0].id
    glyph.layers.append(layer)

    (ufo, ) = to_ufos(font)

    assert ufo.lib[GLYPHLIB_PREFIX + "glyphUserData.a"] == {
        "glyphUserDataKey": "glyphUserDataValue"
    }

    font = to_glyphs([ufo])

    assert font.glyphs["a"].userData[
        "glyphUserDataKey"] == "glyphUserDataValue"
def test_node_user_data_into_glif_lib():
    font = classes.GSFont()
    master = classes.GSFontMaster()
    master.id = "M1"
    font.masters.append(master)
    glyph = classes.GSGlyph('a')
    layer = classes.GSLayer()
    layer.layerId = "M1"
    layer.associatedMasterId = "M1"
    glyph.layers.append(layer)
    font.glyphs.append(glyph)
    path = classes.GSPath()
    layer.paths.append(path)
    node1 = classes.GSNode()
    node1.userData['nodeUserDataKey1'] = 'nodeUserDataValue1'
    node2 = classes.GSNode()
    node2.userData['nodeUserDataKey2'] = 'nodeUserDataValue2'
    path.nodes.append(classes.GSNode())
    path.nodes.append(node1)
    path.nodes.append(classes.GSNode())
    path.nodes.append(classes.GSNode())
    path.nodes.append(node2)

    ufo, = to_ufos(font, minimize_glyphs_diffs=True)

    assert ufo['a'].lib[GLYPHLIB_PREFIX + 'nodeUserData.0.1'] == {
        'nodeUserDataKey1': 'nodeUserDataValue1'
    }
    assert ufo['a'].lib[GLYPHLIB_PREFIX + 'nodeUserData.0.4'] == {
        'nodeUserDataKey2': 'nodeUserDataValue2'
    }

    font = to_glyphs([ufo])

    path = font.glyphs['a'].layers['M1'].paths[0]
    assert path.nodes[1].userData['nodeUserDataKey1'] == 'nodeUserDataValue1'
    assert path.nodes[4].userData['nodeUserDataKey2'] == 'nodeUserDataValue2'
Esempio n. 8
0
    def test_write_layer(self):
        layer = classes.GSLayer()
        # http://docu.glyphsapp.com/#gslayer
        # parent: not written
        # name
        layer.name = '{125, 100}'
        # associatedMasterId
        layer.associatedMasterId = 'M1'
        # layerId
        layer.layerId = 'L1'
        # color
        layer.color = 2  # brown
        # colorObject: read-only, computed
        # components
        component = classes.GSComponent(glyph='glyphName')
        layer.components.append(component)
        # guides
        guide = classes.GSGuideLine()
        guide.name = 'xheight'
        layer.guides.append(guide)
        # annotations
        annotation = classes.GSAnnotation()
        annotation.type = classes.TEXT
        annotation.text = 'F**k, this curve is ugly!'
        layer.annotations.append(annotation)
        # hints
        hint = classes.GSHint()
        hint.name = 'hintName'
        layer.hints.append(hint)
        # anchors
        anchor = classes.GSAnchor()
        anchor.name = 'top'
        layer.anchors['top'] = anchor
        # paths
        path = classes.GSPath()
        layer.paths.append(path)
        # selection: read-only
        # LSB, RSB, TSB, BSB: not written
        # width
        layer.width = 890.4
        # leftMetricsKey
        layer.leftMetricsKey = "A"
        # rightMetricsKey
        layer.rightMetricsKey = "A"
        # widthMetricsKey
        layer.widthMetricsKey = "A"
        # bounds: read-only, computed
        # selectionBounds: read-only, computed
        # background
        # FIXME: (jany) why not use a GSLayer like the official doc suggests?
        background_layer = classes.GSBackgroundLayer()
        layer.background = background_layer
        # backgroundImage
        image = classes.GSBackgroundImage('/path/to/file.jpg')
        layer.backgroundImage = image
        # bezierPath: read-only, objective-c
        # openBezierPath: read-only, objective-c
        # completeOpenBezierPath: read-only, objective-c
        # isAligned
        # FIXME: (jany) is this read-only?
        #   is this computed from each component's alignment?
        # layer.isAligned = False
        # userData
        layer.userData['rememberToMakeCoffe'] = True
        # smartComponentPoleMapping
        layer.smartComponentPoleMapping['crotchDepth'] = 2  # Top pole
        layer.smartComponentPoleMapping['shoulderWidth'] = 1  # Bottom pole
        self.assertWrites(layer, dedent("""\
            {
            anchors = (
            {
            name = top;
            }
            );
            annotations = (
            {
            position = ;
            text = "F**k, this curve is ugly!";
            type = 1;
            }
            );
            associatedMasterId = M1;
            background = {
            };
            backgroundImage = {
            crop = "{{0, 0}, {0, 0}}";
            imagePath = "/path/to/file.jpg";
            };
            color = 2;
            components = (
            {
            name = glyphName;
            }
            );
            guideLines = (
            {
            name = xheight;
            }
            );
            hints = (
            {
            name = hintName;
            }
            );
            layerId = L1;
            leftMetricsKey = A;
            widthMetricsKey = A;
            rightMetricsKey = A;
            name = "{125, 100}";
            paths = (
            {
            }
            );
            userData = {
            PartSelection = {
            crotchDepth = 2;
            shoulderWidth = 1;
            };
            rememberToMakeCoffe = 1;
            };
            width = 890.4;
            }
        """))

        # Don't write a blank layer name
        layer.name = ""
        written = test_helpers.write_to_lines(layer)
        self.assertNotIn('name = "";', written)
Esempio n. 9
0
    def test_write_glyph(self):
        glyph = classes.GSGlyph()
        # https://docu.glyphsapp.com/#gsglyph
        # parent: not written
        # layers
        # Put the glyph in a font with at least one master for the magic in
        # `glyph.layers.append()` to work.
        font = classes.GSFont()
        master = classes.GSFontMaster()
        master.id = "MASTER-ID"
        font.masters.insert(0, master)
        font.glyphs.append(glyph)
        layer = classes.GSLayer()
        layer.layerId = "LAYER-ID"
        layer.name = "L1"
        glyph.layers.insert(0, layer)
        # name
        glyph.name = "Aacute"
        # unicode
        glyph.unicode = "00C1"
        # string: not written
        # id: not written
        # category
        glyph.category = "Letter"
        # subCategory
        glyph.subCategory = "Uppercase"
        # script
        glyph.script = "latin"
        # productionName
        glyph.productionName = "Aacute.prod"
        # glyphInfo: not written
        # leftKerningGroup
        glyph.leftKerningGroup = "A"
        # rightKerningGroup
        glyph.rightKerningGroup = "A"
        # leftKerningKey: not written
        # rightKerningKey: not written
        # leftMetricsKey
        glyph.leftMetricsKey = "A"
        # rightMetricsKey
        glyph.rightMetricsKey = "A"
        # widthMetricsKey
        glyph.widthMetricsKey = "A"
        # export
        glyph.export = False
        # color
        glyph.color = 11
        # colorObject: not written
        # note
        glyph.note = "Stunning one-bedroom A with renovated acute accent"
        # selected: not written
        # mastersCompatible: not stored
        # userData
        glyph.userData['rememberToMakeCoffe'] = True
        # Check that empty collections are written
        glyph.userData['com.someoneelse.coolsoftware.customdata'] = [
            OrderedDict([
                ('zero', 0),
                ('emptyList', []),
                ('emptyDict', {}),
                ('emptyString', ""),
            ]),
            [],
            {},
            "",
            "hey",
            0,
            1,
        ]
        # smartComponentAxes
        axis = classes.GSSmartComponentAxis()
        axis.name = "crotchDepth"
        glyph.smartComponentAxes.append(axis)
        # lastChange
        glyph.lastChange = glyphs_datetime('2017-10-03 07:35:46 +0000')
        self.assertWrites(glyph, dedent("""\
            {
            color = 11;
            export = 0;
            glyphname = Aacute;
            lastChange = "2017-10-03 07:35:46 +0000";
            layers = (
            {
            associatedMasterId = "MASTER-ID";
            layerId = "LAYER-ID";
            name = L1;
            width = 0;
            }
            );
            leftKerningGroup = A;
            leftMetricsKey = A;
            widthMetricsKey = A;
            note = "Stunning one-bedroom A with renovated acute accent";
            rightKerningGroup = A;
            rightMetricsKey = A;
            unicode = 00C1;
            script = latin;
            category = Letter;
            subCategory = Uppercase;
            userData = {
            com.someoneelse.coolsoftware.customdata = (
            {
            zero = 0;
            emptyList = (
            );
            emptyDict = {
            };
            emptyString = "";
            },
            (
            ),
            {
            },
            "",
            hey,
            0,
            1
            );
            rememberToMakeCoffe = 1;
            };
            partsSettings = (
            {
            name = crotchDepth;
            bottomValue = 0;
            topValue = 0;
            }
            );
            }
        """))

        # Write the script even when it's an empty string
        # Same for category and subCategory
        glyph.script = ""
        glyph.category = ""
        glyph.subCategory = ""
        written = test_helpers.write_to_lines(glyph)
        self.assertIn('script = "";', written)
        self.assertIn('category = "";', written)
        self.assertIn('subCategory = "";', written)
Esempio n. 10
0
    def test_write_layer(self):
        layer = classes.GSLayer()
        # http://docu.glyphsapp.com/#gslayer
        # parent: not written
        # name
        layer.name = "{125, 100}"
        # associatedMasterId
        layer.associatedMasterId = "M1"
        # layerId
        layer.layerId = "L1"
        # color
        layer.color = (1, 2, 3, 4)
        # colorObject: read-only, computed
        # components
        component = classes.GSComponent(glyph="glyphName")
        layer.components.append(component)
        # guides
        guide = classes.GSGuideLine()
        guide.name = "xheight"
        layer.guides.append(guide)
        # annotations
        annotation = classes.GSAnnotation()
        annotation.type = classes.TEXT
        annotation.text = "F**k, this curve is ugly!"
        layer.annotations.append(annotation)
        # hints
        hint = classes.GSHint()
        hint.name = "hintName"
        layer.hints.append(hint)
        # anchors
        anchor = classes.GSAnchor()
        anchor.name = "top"
        layer.anchors["top"] = anchor
        # paths
        path = classes.GSPath()
        layer.paths.append(path)
        # selection: read-only
        # LSB, RSB, TSB, BSB: not written
        # width
        layer.width = 890.4
        # leftMetricsKey
        layer.leftMetricsKey = "A"
        # rightMetricsKey
        layer.rightMetricsKey = "A"
        # widthMetricsKey
        layer.widthMetricsKey = "A"
        # bounds: read-only, computed
        # selectionBounds: read-only, computed
        # background
        # XXX bg is unused?
        bg = layer.background  # noqa: F841
        # backgroundImage
        image = classes.GSBackgroundImage("/path/to/file.jpg")
        layer.backgroundImage = image
        # bezierPath: read-only, objective-c
        # openBezierPath: read-only, objective-c
        # completeOpenBezierPath: read-only, objective-c
        # isAligned
        # FIXME: (jany) is this read-only?
        #   is this computed from each component's alignment?
        # layer.isAligned = False
        # userData
        layer.userData["rememberToMakeCoffe"] = True
        # smartComponentPoleMapping
        layer.smartComponentPoleMapping["crotchDepth"] = 2  # Top pole
        layer.smartComponentPoleMapping["shoulderWidth"] = 1  # Bottom pole
        self.assertWrites(
            layer,
            dedent("""\
            {
            anchors = (
            {
            name = top;
            position = "{0, 0}";
            }
            );
            annotations = (
            {
            text = "F**k, this curve is ugly!";
            type = 1;
            }
            );
            associatedMasterId = M1;
            background = {
            };
            backgroundImage = {
            crop = "{{0, 0}, {0, 0}}";
            imagePath = "/path/to/file.jpg";
            };
            color = (1, 2, 3, 4);
            components = (
            {
            name = glyphName;
            }
            );
            guideLines = (
            {
            name = xheight;
            }
            );
            hints = (
            {
            name = hintName;
            }
            );
            layerId = L1;
            leftMetricsKey = A;
            widthMetricsKey = A;
            rightMetricsKey = A;
            name = "{125, 100}";
            paths = (
            {
            closed = 1;
            }
            );
            userData = {
            PartSelection = {
            crotchDepth = 2;
            shoulderWidth = 1;
            };
            rememberToMakeCoffe = 1;
            };
            width = 890.4;
            }
        """),
        )

        # Don't write a blank layer name
        layer.name = ""
        written = test_helpers.write_to_lines(layer)
        self.assertNotIn('name = "";', written)

        # Write the width even if 0
        layer.width = 0
        written = test_helpers.write_to_lines(layer)
        self.assertIn("width = 0;", written)