aboutsummaryrefslogtreecommitdiff
path: root/Tests/colorLib/builder_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/colorLib/builder_test.py')
-rw-r--r--Tests/colorLib/builder_test.py167
1 files changed, 166 insertions, 1 deletions
diff --git a/Tests/colorLib/builder_test.py b/Tests/colorLib/builder_test.py
index d1e94df9..43ec96a4 100644
--- a/Tests/colorLib/builder_test.py
+++ b/Tests/colorLib/builder_test.py
@@ -1,7 +1,8 @@
from fontTools.ttLib import newTable
from fontTools.ttLib.tables import otTables as ot
from fontTools.colorLib import builder
-from fontTools.colorLib.builder import LayerV1ListBuilder
+from fontTools.colorLib.geometry import round_start_circle_stable_containment, Circle
+from fontTools.colorLib.builder import LayerV1ListBuilder, _build_n_ary_tree
from fontTools.colorLib.errors import ColorLibError
import pytest
from typing import List
@@ -673,6 +674,43 @@ def test_buildColrV1():
assert baseGlyphs.BaseGlyphV1Record[2].BaseGlyph == "g"
+def test_buildColrV1_more_than_255_paints():
+ num_paints = 364
+ colorGlyphs = {
+ "a": [
+ {
+ "format": 5, # PaintGlyph
+ "paint": 0,
+ "glyph": name,
+ }
+ for name in (f"glyph{i}" for i in range(num_paints))
+ ],
+ }
+ layers, baseGlyphs = builder.buildColrV1(colorGlyphs)
+ paints = layers.Paint
+
+ assert len(paints) == num_paints + 1
+
+ assert all(paints[i].Format == ot.Paint.Format.PaintGlyph for i in range(255))
+
+ assert paints[255].Format == ot.Paint.Format.PaintColrLayers
+ assert paints[255].FirstLayerIndex == 0
+ assert paints[255].NumLayers == 255
+
+ assert all(
+ paints[i].Format == ot.Paint.Format.PaintGlyph
+ for i in range(256, num_paints + 1)
+ )
+
+ assert baseGlyphs.BaseGlyphCount == len(colorGlyphs)
+ assert baseGlyphs.BaseGlyphV1Record[0].BaseGlyph == "a"
+ assert (
+ baseGlyphs.BaseGlyphV1Record[0].Paint.Format == ot.Paint.Format.PaintColrLayers
+ )
+ assert baseGlyphs.BaseGlyphV1Record[0].Paint.FirstLayerIndex == 255
+ assert baseGlyphs.BaseGlyphV1Record[0].Paint.NumLayers == num_paints + 1 - 255
+
+
def test_split_color_glyphs_by_version():
layerBuilder = LayerV1ListBuilder()
colorGlyphs = {
@@ -1055,3 +1093,130 @@ class BuildCOLRTest(object):
assert hasattr(colr, "table")
assert isinstance(colr.table, ot.COLR)
assert colr.table.VarStore is None
+
+
+class TrickyRadialGradientTest:
+ @staticmethod
+ def circle_inside_circle(c0, r0, c1, r1, rounded=False):
+ if rounded:
+ return Circle(c0, r0).round().inside(Circle(c1, r1).round())
+ else:
+ return Circle(c0, r0).inside(Circle(c1, r1))
+
+ def round_start_circle(self, c0, r0, c1, r1, inside=True):
+ assert self.circle_inside_circle(c0, r0, c1, r1) is inside
+ assert self.circle_inside_circle(c0, r0, c1, r1, rounded=True) is not inside
+ r = round_start_circle_stable_containment(c0, r0, c1, r1)
+ assert (
+ self.circle_inside_circle(r.centre, r.radius, c1, r1, rounded=True)
+ is inside
+ )
+ return r.centre, r.radius
+
+ def test_noto_emoji_mosquito_u1f99f(self):
+ # https://github.com/googlefonts/picosvg/issues/158
+ c0 = (385.23508, 70.56727999999998)
+ r0 = 0
+ c1 = (642.99108, 104.70327999999995)
+ r1 = 260.0072
+ assert self.round_start_circle(c0, r0, c1, r1, inside=True) == ((386, 71), 0)
+
+ @pytest.mark.parametrize(
+ "c0, r0, c1, r1, inside, expected",
+ [
+ # inside before round, outside after round
+ ((1.4, 0), 0, (2.6, 0), 1.3, True, ((2, 0), 0)),
+ ((1, 0), 0.6, (2.8, 0), 2.45, True, ((2, 0), 1)),
+ ((6.49, 6.49), 0, (0.49, 0.49), 8.49, True, ((5, 5), 0)),
+ # outside before round, inside after round
+ ((0, 0), 0, (2, 0), 1.5, False, ((-1, 0), 0)),
+ ((0, -0.5), 0, (0, -2.5), 1.5, False, ((0, 1), 0)),
+ # the following ones require two nudges to round correctly
+ ((0.5, 0), 0, (9.4, 0), 8.8, False, ((-1, 0), 0)),
+ ((1.5, 1.5), 0, (0.49, 0.49), 1.49, True, ((0, 0), 0)),
+ # limit case when circle almost exactly overlap
+ ((0.5000001, 0), 0.5000001, (0.499999, 0), 0.4999999, True, ((0, 0), 0)),
+ # concentrical circles, r0 > r1
+ ((0, 0), 1.49, (0, 0), 1, False, ((0, 0), 2)),
+ ],
+ )
+ def test_nudge_start_circle_position(self, c0, r0, c1, r1, inside, expected):
+ assert self.round_start_circle(c0, r0, c1, r1, inside) == expected
+
+
+@pytest.mark.parametrize(
+ "lst, n, expected",
+ [
+ ([0], 2, [0]),
+ ([0, 1], 2, [0, 1]),
+ ([0, 1, 2], 2, [[0, 1], 2]),
+ ([0, 1, 2], 3, [0, 1, 2]),
+ ([0, 1, 2, 3], 2, [[0, 1], [2, 3]]),
+ ([0, 1, 2, 3], 3, [[0, 1, 2], 3]),
+ ([0, 1, 2, 3, 4], 3, [[0, 1, 2], 3, 4]),
+ ([0, 1, 2, 3, 4, 5], 3, [[0, 1, 2], [3, 4, 5]]),
+ (list(range(7)), 3, [[0, 1, 2], [3, 4, 5], 6]),
+ (list(range(8)), 3, [[0, 1, 2], [3, 4, 5], [6, 7]]),
+ (list(range(9)), 3, [[0, 1, 2], [3, 4, 5], [6, 7, 8]]),
+ (list(range(10)), 3, [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], 9]),
+ (list(range(11)), 3, [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], 9, 10]),
+ (list(range(12)), 3, [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [9, 10, 11]]),
+ (list(range(13)), 3, [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [9, 10, 11], 12]),
+ (
+ list(range(14)),
+ 3,
+ [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [[9, 10, 11], 12, 13]],
+ ),
+ (
+ list(range(15)),
+ 3,
+ [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [9, 10, 11], [12, 13, 14]],
+ ),
+ (
+ list(range(16)),
+ 3,
+ [[[0, 1, 2], [3, 4, 5], [6, 7, 8]], [[9, 10, 11], [12, 13, 14], 15]],
+ ),
+ (
+ list(range(23)),
+ 3,
+ [
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
+ [[9, 10, 11], [12, 13, 14], [15, 16, 17]],
+ [[18, 19, 20], 21, 22],
+ ],
+ ),
+ (
+ list(range(27)),
+ 3,
+ [
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
+ [[9, 10, 11], [12, 13, 14], [15, 16, 17]],
+ [[18, 19, 20], [21, 22, 23], [24, 25, 26]],
+ ],
+ ),
+ (
+ list(range(28)),
+ 3,
+ [
+ [
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
+ [[9, 10, 11], [12, 13, 14], [15, 16, 17]],
+ [[18, 19, 20], [21, 22, 23], [24, 25, 26]],
+ ],
+ 27,
+ ],
+ ),
+ (list(range(257)), 256, [list(range(256)), 256]),
+ (list(range(258)), 256, [list(range(256)), 256, 257]),
+ (list(range(512)), 256, [list(range(256)), list(range(256, 512))]),
+ (list(range(512 + 1)), 256, [list(range(256)), list(range(256, 512)), 512]),
+ (
+ list(range(256 ** 2)),
+ 256,
+ [list(range(k * 256, k * 256 + 256)) for k in range(256)],
+ ),
+ ],
+)
+def test_build_n_ary_tree(lst, n, expected):
+ assert _build_n_ary_tree(lst, n) == expected