Skip to content

Commit

Permalink
Merge pull request #39 from fonttools/copy-data-from-glyph
Browse files Browse the repository at this point in the history
add methods to copy glyphs
  • Loading branch information
anthrotype authored Nov 6, 2019
2 parents 85e5764 + 9784d98 commit efdbbee
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 10 deletions.
31 changes: 31 additions & 0 deletions src/ufoLib2/objects/glyph.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import attr
from copy import deepcopy
from typing import Union, List, Any, Dict, Optional
from ufoLib2.objects.anchor import Anchor
from ufoLib2.objects.guideline import Guideline
Expand Down Expand Up @@ -145,6 +146,36 @@ def appendGuideline(self, guideline):
guideline = Guideline(**guideline)
self._guidelines.append(guideline)

def copy(self, name=None):
"""Return a new Glyph (deep) copy, optionally override the new glyph name.
"""
other = deepcopy(self)
if name is not None:
other._name = name
return other

def copyDataFromGlyph(self, glyph):
"""Deep-copy everything from the other glyph, except for the name.
Existing glyph data is overwritten.
This method was added for compatibility with the defcon API, and
it may be removed in the future.
"""
self.width = glyph.width
self.height = glyph.height
self.unicodes = list(glyph.unicodes)
self.image = deepcopy(glyph.image)
self.note = glyph.note
self.lib = deepcopy(glyph.lib)
self.anchors = deepcopy(glyph.anchors)
self.guidelines = deepcopy(glyph.guidelines)
# NOTE: defcon's copyDataFromGlyph appends instead of overwrites here,
# but we do the right thing, for consistency with the rest.
self.clearContours()
self.clearComponents()
pointPen = self.getPointPen()
glyph.drawPoints(pointPen)

# -----------
# Pen methods
# -----------
Expand Down
13 changes: 7 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import py
import pathlib
import shutil
import pytest
import ufoLib2


@pytest.fixture
def datadir(request):
return py.path.local(request.fspath.dirname).join("data")
return pathlib.Path(__file__).parent / "data"


@pytest.fixture
def ufo_UbuTestData(tmpdir, datadir):
ufo_path = tmpdir.join("UbuTestData.ufo")
datadir.join("UbuTestData.ufo").copy(ufo_path)
return ufoLib2.Font.open(str(ufo_path))
def ufo_UbuTestData(tmp_path, datadir):
ufo_path = tmp_path / "UbuTestData.ufo"
shutil.copytree(datadir / "UbuTestData.ufo", ufo_path)
return ufoLib2.Font.open(ufo_path)
72 changes: 72 additions & 0 deletions tests/objects/test_glyph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from ufoLib2.objects import Anchor, Component, Glyph, Guideline, Image


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)
8 changes: 4 additions & 4 deletions tests/test_ufoLib2.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ def test_import_version():
assert isinstance(ufoLib2.__version__, str)


def test_LayerSet_load_layers_on_iteration(tmpdir):
def test_LayerSet_load_layers_on_iteration(tmp_path):
ufo = ufoLib2.Font()
ufo.layers.newLayer("test")
ufo_save_path = str(tmpdir.join("test.ufo"))
ufo_save_path = tmp_path / "test.ufo"
ufo.save(ufo_save_path)
ufo = ufoLib2.Font.open(ufo_save_path)
for layer in ufo.layers:
assert layer is not _NOT_LOADED


def test_lazy_data_loading_saveas(ufo_UbuTestData, tmpdir):
def test_lazy_data_loading_saveas(ufo_UbuTestData, tmp_path):
ufo = ufo_UbuTestData
ufo_path = str(tmpdir.join("UbuTestData2.ufo"))
ufo_path = tmp_path / "UbuTestData2.ufo"
ufo.save(ufo_path)
assert all(v is not _NOT_LOADED for v in ufo.data._data.values())

Expand Down

0 comments on commit efdbbee

Please sign in to comment.