Esempio n. 1
0
def test_component_getBounds(layer: Layer) -> None:
    assert Component("a",
                     (1, 0, 0, 1, 0, 0)).getBounds(layer) == (0, 0, 7.5, 20)
    assert Component("a",
                     (1, 0, 0, 1, -5, 0)).getBounds(layer) == (-5, 0, 2.5, 20)
    assert Component("a",
                     (1, 0, 0, 1, 0, 5)).getBounds(layer) == (0, 5, 7.5, 25)
Esempio n. 2
0
def test_component_getControlBounds(layer):
    assert Component("a",
                     (1, 0, 0, 1, 0, 0)).getControlBounds(layer) == (0, 0, 10,
                                                                     20)
    assert Component("a",
                     (1, 0, 0, 1, -5, 0)).getControlBounds(layer) == (-5, 0, 5,
                                                                      20)
    assert Component("a",
                     (1, 0, 0, 1, 0, 5)).getControlBounds(layer) == (0, 5, 10,
                                                                     25)
Esempio n. 3
0
def _glyf_ufo(ufo, color_glyphs):
    # glyphs by reuse_key
    glyphs = {}
    for color_glyph in color_glyphs:
        logging.debug(
            "%s %s %s",
            ufo.info.familyName,
            color_glyph.glyph_name,
            color_glyph.transform_for_font_space(),
        )
        parent_glyph = ufo.get(color_glyph.glyph_name)
        for painted_layer in color_glyph.as_painted_layers():
            # if we've seen this shape before reuse it
            reuse_key = _inter_glyph_reuse_key(painted_layer)
            if reuse_key not in glyphs:
                glyph = _create_glyph(color_glyph, painted_layer)
                glyphs[reuse_key] = glyph
            else:
                glyph = glyphs[reuse_key]
            parent_glyph.components.append(Component(baseGlyph=glyph.name))

        # No great reason to keep single-component glyphs around
        if len(parent_glyph.components) == 1:
            component = ufo[parent_glyph.components[0].baseGlyph]
            del ufo[component.name]
            ufo[color_glyph.glyph_name] = component
            assert component.name == color_glyph.glyph_name
Esempio n. 4
0
def _create_transformed_glyph(color_glyph: ColorGlyph, paint: PaintGlyph,
                              transform: Affine2D) -> Glyph:
    glyph = _init_glyph(color_glyph)
    glyph.components.append(
        Component(baseGlyph=paint.glyph, transformation=transform))
    color_glyph.ufo.glyphOrder += [glyph.name]
    return glyph
Esempio n. 5
0
def test_glyph_get_bounds():
    a = Glyph("a")
    pen = a.getPen()
    pen.moveTo((0, 0))
    pen.curveTo((10, 10), (10, 20), (0, 20))
    pen.closePath()

    b = Glyph("b", components=[Component("a", (1, 0, 0, 1, -50, 100))])

    layer = Layer(glyphs=[a, b])

    assert a.getBounds(layer) == BoundingBox(xMin=0, yMin=0, xMax=7.5, yMax=20)

    assert a.getControlBounds(layer) == BoundingBox(xMin=0,
                                                    yMin=0,
                                                    xMax=10,
                                                    yMax=20)

    with pytest.raises(
            TypeError,
            match="layer is required to compute bounds of components"):
        b.getBounds()
    with pytest.raises(
            TypeError,
            match="layer is required to compute bounds of components"):
        b.getControlBounds()

    assert b.getBounds(layer) == (-50, 100, -42.5, 120
                                  )  # namedtuple is a tuple
    assert b.getControlBounds(layer) == (-50, 100, -40, 120)
Esempio n. 6
0
def _create_glyph(color_glyph: ColorGlyph,
                  painted_layer: PaintedLayer) -> Glyph:
    ufo = color_glyph.ufo

    glyph = ufo.newGlyph(
        _next_name(ufo, lambda i: f"{color_glyph.glyph_name}.{i}"))
    glyph_names = [glyph.name]
    glyph.width = ufo.info.unitsPerEm

    svg_units_to_font_units = color_glyph.transform_for_font_space()

    if painted_layer.reuses:
        # Shape repeats, form a composite
        base_glyph = ufo.newGlyph(
            _next_name(ufo, lambda i: f"{glyph.name}.component.{i}"))
        glyph_names.append(base_glyph.name)

        draw_svg_path(painted_layer.path, base_glyph.getPen(),
                      svg_units_to_font_units)

        glyph.components.append(
            Component(baseGlyph=base_glyph.name,
                      transformation=Affine2D.identity()))

        for transform in painted_layer.reuses:
            # We already redrew the component into font space, don't redo it
            # scale x/y translation and flip y movement to match font space
            transform = transform._replace(
                e=transform.e * svg_units_to_font_units.a,
                f=transform.f * svg_units_to_font_units.d,
            )
            glyph.components.append(
                Component(baseGlyph=base_glyph.name, transformation=transform))
    else:
        # Not a composite, just draw directly on the glyph
        draw_svg_path(painted_layer.path, glyph.getPen(),
                      svg_units_to_font_units)

    ufo.glyphOrder += glyph_names

    return glyph
Esempio n. 7
0
def layer() -> Layer:
    a = Glyph("a")
    pen = a.getPen()
    pen.moveTo((8, 0))
    pen.lineTo((18, 0))
    pen.lineTo((18, 20))
    pen.lineTo((8, 20))
    pen.closePath()
    a.width = 30
    a.appendAnchor({"x": 10, "y": 30, "name": "top"})

    b = Glyph("b", width=a.width, components=[Component("a", (1, 0, 0, 1, 2, -5))])

    layer = Layer(glyphs=[a, b])
    return layer
Esempio n. 8
0
def _glyf_ufo(config: FontConfig, ufo: ufoLib2.Font,
              color_glyphs: Tuple[ColorGlyph, ...]):
    # We want to mutate our view of color_glyphs
    color_glyphs = list(color_glyphs)

    # glyphs by reuse_key
    glyph_cache = GlyphReuseCache(config.reuse_tolerance)
    glyph_uses = Counter()
    for i, color_glyph in enumerate(color_glyphs):
        logging.debug(
            "%s %s %s",
            ufo.info.familyName,
            color_glyph.glyph_name,
            color_glyph.transform_for_font_space(),
        )
        parent_glyph = ufo[color_glyph.glyph_name]

        # generate glyphs for PaintGlyph's and assign glyph names
        color_glyphs[i] = color_glyph = _migrate_paths_to_ufo_glyphs(
            color_glyph, glyph_cache)

        for root in color_glyph.painted_layers:
            for context in root.breadth_first():
                # For 'glyf' just dump anything that isn't a PaintGlyph
                if not isinstance(context.paint, PaintGlyph):
                    continue
                paint_glyph = cast(PaintGlyph, context.paint)
                glyph = ufo.get(paint_glyph.glyph)
                parent_glyph.components.append(
                    Component(baseGlyph=glyph.name,
                              transformation=context.transform))
                glyph_uses[glyph.name] += 1

    # No great reason to keep single-component glyphs around (unless reused)
    for color_glyph in color_glyphs:
        parent_glyph = ufo[color_glyph.glyph_name]
        if (len(parent_glyph.components) == 1
                and glyph_uses[parent_glyph.components[0].baseGlyph] == 1):
            component = ufo[parent_glyph.components[0].baseGlyph]
            del ufo[component.name]
            component.unicode = parent_glyph.unicode
            ufo[color_glyph.glyph_name] = component
            assert component.name == color_glyph.glyph_name
Esempio n. 9
0
 (Point(0, 0), {
     "x": 0,
     "y": 0
 }),
 (
     Point(1.5, -2.1, "qcurve", True, "foobar", "12345"),
     {
         "x": 1.5,
         "y": -2.1,
         "type": "qcurve",
         "smooth": True,
         "name": "foobar",
         "identifier": "12345",
     },
 ),
 (Component("a"), {
     "baseGlyph": "a"
 }),
 (
     Component("b", Transform(1, 0, 0, 0.5, 10, 20), "abcd1234"),
     {
         "baseGlyph": "b",
         "transformation": (1, 0, 0, 0.5, 10, 20),
         "identifier": "abcd1234",
     },
 ),
 (Contour(), {}),
 (
     Contour([Point(0, 0), Point(1, 2)], "zzzz"),
     {
         "points": [{
Esempio n. 10
0
def test_copyDataFromGlyph(ufo_UbuTestData):
    font = ufo_UbuTestData

    a = font["a"]
    a.height = 500
    a.image = Image("a.png")
    a.note = "a note"
    a.lib = {"bar": [3, 2, 1]}
    a.anchors = [Anchor(250, 0, "bottom")]
    a.guidelines = [Guideline(y=500)]
    a.components = [Component("A")]

    b = Glyph("b")
    b.width = 350
    b.height = 1000
    b.image = Image("b.png")
    b.note = "b note"
    b.lib = {"foo": [1, 2, 3]}
    b.anchors = [Anchor(350, 800, "top")]
    b.guidelines = [Guideline(x=50)]

    assert b.name != a.name
    assert b.width != a.width
    assert b.height != a.height
    assert b.unicodes != a.unicodes
    assert b.image != a.image
    assert b.note != a.note
    assert b.lib != a.lib
    assert b.anchors != a.anchors
    assert b.guidelines != a.guidelines
    assert b.contours != a.contours
    assert b.components != a.components

    def _assert_equal_but_distinct_objects(glyph1, glyph2):
        assert glyph1.width == glyph2.width
        assert glyph1.height == glyph2.height
        assert glyph1.unicodes == glyph2.unicodes
        assert glyph1.unicodes is not glyph2.unicodes
        assert glyph1.image == glyph2.image
        assert glyph1.image is not glyph2.image
        assert glyph1.note == glyph2.note
        assert glyph1.lib == glyph2.lib
        assert glyph1.lib is not glyph2.lib
        assert glyph1.lib["bar"] == glyph2.lib["bar"]
        assert glyph1.lib["bar"] is not glyph2.lib["bar"]
        assert glyph1.anchors == glyph2.anchors
        assert glyph1.anchors is not glyph2.anchors
        assert glyph1.anchors[0] is not glyph2.anchors[0]
        assert glyph1.guidelines == glyph2.guidelines
        assert glyph1.guidelines is not glyph2.guidelines
        assert glyph1.guidelines[0] is not glyph2.guidelines[0]
        assert glyph1.contours == glyph2.contours
        assert glyph1.contours is not glyph2.contours
        assert glyph1.contours[0] is not glyph2.contours[0]
        assert glyph1.components == glyph2.components
        assert glyph1.components is not glyph2.components
        assert glyph1.components[0] is not glyph2.components[0]

    b.copyDataFromGlyph(a)
    assert b.name != a.name
    _assert_equal_but_distinct_objects(b, a)

    c = a.copy()
    assert c.name == a.name
    _assert_equal_but_distinct_objects(c, a)

    d = a.copy(name="d")
    assert d.name == "d"
    _assert_equal_but_distinct_objects(d, a)
Esempio n. 11
0
def test_component_not_in_layer(layer: Layer) -> None:
    with pytest.raises(KeyError, match="b"):
        Component("b", (1, 0, 0, 1, 0, 0)).getBounds(layer)
    with pytest.raises(KeyError, match="b"):
        Component("b", (1, 0, 0, 1, 0, 0)).getControlBounds(layer)