From 500c5f2ab2c3a49f3d3ed55fea41bc525612f6ed Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 27 Jan 2024 21:23:16 +0200 Subject: [PATCH] Test PaintFuncs Test fonts and expected results are taking verbatim from HarfBuzz tests. --- src/uharfbuzz/_draw_test_funcs.cc | 277 ++++++++++++++++++++ tests/data/expected/hand-10 | 121 +++++++++ tests/data/expected/test-10 | 22 ++ tests/data/expected/test-106 | 30 +++ tests/data/expected/test-116 | 26 ++ tests/data/expected/test-123 | 47 ++++ tests/data/expected/test-154 | 40 +++ tests/data/expected/test-165 | 22 ++ tests/data/expected/test-175 | 36 +++ tests/data/expected/test-6 | 21 ++ tests/data/expected/test-92 | 21 ++ tests/data/noto_handwriting-cff2_colr_1.otf | Bin 0 -> 4172 bytes tests/data/test_glyphs-glyf_colr_1.ttf | Bin 0 -> 16704 bytes tests/test_uharfbuzz.py | 226 ++++++++++++++++ 14 files changed, 889 insertions(+) create mode 100644 tests/data/expected/hand-10 create mode 100644 tests/data/expected/test-10 create mode 100644 tests/data/expected/test-106 create mode 100644 tests/data/expected/test-116 create mode 100644 tests/data/expected/test-123 create mode 100644 tests/data/expected/test-154 create mode 100644 tests/data/expected/test-165 create mode 100644 tests/data/expected/test-175 create mode 100644 tests/data/expected/test-6 create mode 100644 tests/data/expected/test-92 create mode 100644 tests/data/noto_handwriting-cff2_colr_1.otf create mode 100644 tests/data/test_glyphs-glyf_colr_1.ttf diff --git a/src/uharfbuzz/_draw_test_funcs.cc b/src/uharfbuzz/_draw_test_funcs.cc index a05f3d9..c676d46 100644 --- a/src/uharfbuzz/_draw_test_funcs.cc +++ b/src/uharfbuzz/_draw_test_funcs.cc @@ -1,5 +1,9 @@ #include #include +#include +#include + +#include "hb.h" #if defined (_MSC_VER) #define EXTERN __declspec (dllexport) extern @@ -68,4 +72,277 @@ _test_cubic_to (void *dfuncs, sprintf (draw_data + strlen (draw_data), "C%g,%g %g,%g %g,%g", c1_x, c1_y, c2_x, c2_y, to_x, to_y); } +typedef struct { + int level; + char *string; +} paint_data_t; + +EXTERN void* +_test_paint_data_create (size_t size) +{ + paint_data_t *data = (paint_data_t *)calloc (1, sizeof (paint_data_t)); + data->string = (char *)calloc (size, sizeof (char)); + return data; +} + +EXTERN void +_test_paint_data_destroy (void *paint_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + free (data->string); + free (data); +} + +EXTERN char * +_test_paint_data_get_string (void *paint_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + return data->string; +} + +static void +print (paint_data_t *data, + const char *format, + ...) +{ + va_list args; + + sprintf (data->string + strlen (data->string), "%*s", 2 * data->level, ""); + + va_start (args, format); + vsprintf (data->string + strlen (data->string), format, args); + va_end (args); + + sprintf (data->string + strlen (data->string), "\n"); +} + +EXTERN void +_test_push_transform (hb_paint_funcs_t *funcs, + void *paint_data, + float xx, float yx, + float xy, float yy, + float dx, float dy, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "start transform %.3g %.3g %.3g %.3g %.3g %.3g", xx, yx, xy, yy, dx, dy); + data->level++; +} + +EXTERN void +_test_pop_transform (hb_paint_funcs_t *funcs, + void *paint_data, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + data->level--; + print (data, "end transform"); +} + +EXTERN hb_bool_t +_test_paint_color_glyph (hb_paint_funcs_t *funcs, + void *paint_data, + hb_codepoint_t glyph, + hb_font_t *font, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "paint color glyph %u; acting as failed", glyph); + + return false; +} + +EXTERN void +_test_push_clip_glyph (hb_paint_funcs_t *funcs, + void *paint_data, + hb_codepoint_t glyph, + hb_font_t *font, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "start clip glyph %u", glyph); + data->level++; +} + +EXTERN void +_test_push_clip_rectangle (hb_paint_funcs_t *funcs, + void *paint_data, + float xmin, float ymin, float xmax, float ymax, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "start clip rectangle %.3g %.3g %.3g %.3g", xmin, ymin, xmax, ymax); + data->level++; +} + +EXTERN void +_test_pop_clip (hb_paint_funcs_t *funcs, + void *paint_data, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + data->level--; + print (data, "end clip"); +} + +EXTERN void +_test_paint_color (hb_paint_funcs_t *funcs, + void *paint_data, + hb_bool_t use_foreground, + hb_color_t color, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "solid %d %d %d %d", + hb_color_get_red (color), + hb_color_get_green (color), + hb_color_get_blue (color), + hb_color_get_alpha (color)); +} + +EXTERN hb_bool_t +_test_paint_image (hb_paint_funcs_t *funcs, + void *paint_data, + hb_blob_t *blob, + unsigned int width, + unsigned int height, + hb_tag_t format, + float slant, + hb_glyph_extents_t *extents, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + char buf[5] = { 0, }; + + hb_tag_to_string (format, buf); + print (data, "image type %s size %u %u slant %.3g extents %d %d %d %d\n", + buf, width, height, slant, + extents->x_bearing, extents->y_bearing, extents->width, extents->height); + + return true; +} + +static void +print_color_line (paint_data_t *data, + hb_color_line_t *color_line) +{ + hb_color_stop_t *stops; + unsigned int len; + + len = hb_color_line_get_color_stops (color_line, 0, NULL, NULL); + stops = (hb_color_stop_t *)malloc (len * sizeof (hb_color_stop_t)); + hb_color_line_get_color_stops (color_line, 0, &len, stops); + + print (data, "colors %d", hb_color_line_get_extend (color_line)); + data->level += 1; + for (unsigned int i = 0; i < len; i++) + print (data, "%.3g %d %d %d %d", + stops[i].offset, + hb_color_get_red (stops[i].color), + hb_color_get_green (stops[i].color), + hb_color_get_blue (stops[i].color), + hb_color_get_alpha (stops[i].color)); + data->level -= 1; + + free (stops); +} + +EXTERN void +_test_paint_linear_gradient (hb_paint_funcs_t *funcs, + void *paint_data, + hb_color_line_t *color_line, + float x0, float y0, + float x1, float y1, + float x2, float y2, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "linear gradient"); + data->level += 1; + print (data, "p0 %.3g %.3g", x0, y0); + print (data, "p1 %.3g %.3g", x1, y1); + print (data, "p2 %.3g %.3g", x2, y2); + + print_color_line (data, color_line); + data->level -= 1; +} + +EXTERN void +_test_paint_radial_gradient (hb_paint_funcs_t *funcs, + void *paint_data, + hb_color_line_t *color_line, + float x0, float y0, float r0, + float x1, float y1, float r1, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "radial gradient"); + data->level += 1; + print (data, "p0 %.3g %.3g radius %.3g", x0, y0, r0); + print (data, "p1 %.3g %.3g radius %.3g", x1, y1, r1); + + print_color_line (data, color_line); + data->level -= 1; +} + +EXTERN void +_test_paint_sweep_gradient (hb_paint_funcs_t *funcs, + void *paint_data, + hb_color_line_t *color_line, + float cx, float cy, + float start_angle, + float end_angle, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + + print (data, "sweep gradient"); + data->level++; + print (data, "center %.3g %.3g", cx, cy); + print (data, "angles %.3g %.3g", start_angle, end_angle); + + print_color_line (data, color_line); + data->level -= 1; +} + +EXTERN void +_test_push_group (hb_paint_funcs_t *funcs, + void *paint_data, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + print (data, "push group"); + data->level++; +} + +EXTERN void +_test_pop_group (hb_paint_funcs_t *funcs, + void *paint_data, + hb_paint_composite_mode_t mode, + void *user_data) +{ + paint_data_t *data = (paint_data_t *)paint_data; + data->level--; + print (data, "pop group mode %d", mode); +} + +EXTERN hb_bool_t +_test_custom_palette_color(hb_paint_funcs_t *funcs, + void *paint_data, + unsigned int color_index, + hb_color_t *color, + void *user_data) +{ + return false; +} + } diff --git a/tests/data/expected/hand-10 b/tests/data/expected/hand-10 new file mode 100644 index 0000000..10410e6 --- /dev/null +++ b/tests/data/expected/hand-10 @@ -0,0 +1,121 @@ +# random seed: R02Se2b1d61d9c4fd31724517ef138cff8f6 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 64 -224 1.22e+03 928 + start transform 1 0 0 1 0 0 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 13 + start transform 1 0 0 1 0 0 + start transform 1 0 0 0.977 0 0 + radial gradient + p0 280 440 radius 0 + p1 280 440 radius 467 + colors 0 + 0 186 141 104 255 + 0.449 183 138 103 255 + 0.809 173 130 100 255 + 1 164 123 98 255 + end transform + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 14 + start transform 1 0 0 1 0 0 + linear gradient + p0 231 -27 + p1 1.02e+03 -27 + p2 231 -815 + colors 0 + 0 164 123 98 255 + 1 164 123 98 255 + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 15 + start transform 1 0 0 1 0 0 + solid 145 103 77 255 + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 16 + start transform 1 0 0 1 0 0 + solid 30 136 229 255 + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 21 + start transform 1 0 0 1 0 0 + solid 145 103 77 255 + end transform + end clip + end transform + pop group mode 3 + push group + push group + start transform 1 0 -0 1 0 0 + start clip glyph 16 + start transform 1 0 0 1 0 0 + linear gradient + p0 669 776 + p1 180 -106 + p2 -212 1.26e+03 + colors 0 + 0 100 181 246 255 + 1 33 150 243 255 + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 18 + start transform 1 0 0 1 0 0 + solid 66 66 66 51 + end transform + end clip + end transform + pop group mode 3 + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 19 + start transform 1 0 0 1 0 0 + start transform 1 0 0 0.969 0 0 + radial gradient + p0 588 198 radius 0 + p1 588 198 radius 342 + colors 0 + 0 186 141 104 255 + 0.449 183 138 103 255 + 0.809 173 130 100 255 + 1 164 123 98 255 + end transform + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 20 + start transform 1 0 0 1 0 0 + solid 145 103 77 255 + end transform + end clip + end transform + pop group mode 3 + end transform +end clip diff --git a/tests/data/expected/test-10 b/tests/data/expected/test-10 new file mode 100644 index 0000000..78d3e23 --- /dev/null +++ b/tests/data/expected/test-10 @@ -0,0 +1,22 @@ +# random seed: R02S730db577e65f80492e3e3eacc21152fa +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 0 0 1e+03 1e+03 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 174 + start transform 1 0 0 1 0 0 + sweep gradient + center 500 600 + angles 0 6.28 + colors 0 + 0.25 250 240 230 255 + 0.417 0 0 255 255 + 0.583 255 0 0 255 + 0.75 47 79 79 255 + end transform + end clip + end transform + end transform +end clip diff --git a/tests/data/expected/test-106 b/tests/data/expected/test-106 new file mode 100644 index 0000000..2e04261 --- /dev/null +++ b/tests/data/expected/test-106 @@ -0,0 +1,30 @@ +# random seed: R02S33079790f9ab4f19e7151add3612840f +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 118 -22.9 750 750 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 3 + start transform 1 0 0 1 0 0 + solid 0 0 255 127 + end transform + end clip + end transform + push group + start transform 1 0 0 1 1e+03 1e+03 + start transform 1 0.364 0.176 1 0 0 + start transform 1 0 0 1 -1e+03 -1e+03 + start transform 1 0 -0 1 0 0 + start clip glyph 3 + start transform 1 0 0 1 0 0 + solid 255 165 0 178 + end transform + end clip + end transform + end transform + end transform + end transform + pop group mode 4 + end transform +end clip diff --git a/tests/data/expected/test-116 b/tests/data/expected/test-116 new file mode 100644 index 0000000..3cb18d3 --- /dev/null +++ b/tests/data/expected/test-116 @@ -0,0 +1,26 @@ +# random seed: R02S7f8abf2d360ae53f6acb756fc1d06756 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 250 250 950 950 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 3 + start transform 1 0 0 1 0 0 + solid 0 0 255 127 + end transform + end clip + end transform + push group + start transform 1 0 0 1 200 200 + start transform 1 0 -0 1 0 0 + start clip glyph 3 + start transform 1 0 0 1 0 0 + solid 255 165 0 178 + end transform + end clip + end transform + end transform + pop group mode 4 + end transform +end clip diff --git a/tests/data/expected/test-123 b/tests/data/expected/test-123 new file mode 100644 index 0000000..21f2411 --- /dev/null +++ b/tests/data/expected/test-123 @@ -0,0 +1,47 @@ +# random seed: R02Sa683270814db638bd7dc3f8fc211d03f +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 0 0 1e+03 1e+03 + start transform 1 0 0 1 0 0 + push group + start transform 1 0 -0 1 0 0 + start clip glyph 3 + start transform 1 0 0 1 0 0 + solid 0 0 0 255 + end transform + end clip + end transform + pop group mode 3 + push group + start transform 1 0 0 1 333 667 + start transform 0.5 0 0 0.5 0 0 + start transform 1 0 0 1 -333 -667 + start transform 1 0 -0 1 0 0 + start clip glyph 2 + start transform 1 0 0 1 0 0 + solid 255 220 1 255 + end transform + end clip + end transform + end transform + end transform + end transform + push group + start transform 1 0 0 1 667 333 + start transform 0.5 0 0 0.5 0 0 + start transform 1 0 0 1 -667 -333 + start transform 1 0 -0 1 0 0 + start clip glyph 2 + start transform 1 0 0 1 0 0 + solid 104 199 232 255 + end transform + end clip + end transform + end transform + end transform + end transform + pop group mode 5 + pop group mode 3 + end transform +end clip diff --git a/tests/data/expected/test-154 b/tests/data/expected/test-154 new file mode 100644 index 0000000..f108da8 --- /dev/null +++ b/tests/data/expected/test-154 @@ -0,0 +1,40 @@ +# random seed: R02S46170a7a8abc3ad07d2b70fd08efc176 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 0 500 500 1e+03 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + paint color glyph 164; acting as failed + end transform + start clip rectangle 100 100 900 900 + start transform 1 0 -0 1 0 0 + paint color glyph 93; acting as failed + end transform + start clip rectangle 0 0 1e+03 1e+03 + start transform 1 0 -0 1 0 0 + start clip glyph 2 + start transform 1 0 0 1 0 0 + radial gradient + p0 166 768 radius 0 + p1 166 768 radius 256 + colors 2 + 0 0 128 0 255 + 0.5 255 255 255 255 + 1 255 0 0 255 + end transform + end clip + end transform + end clip + end clip + push group + start transform 1 0 -0 1 0 0 + start clip glyph 159 + start transform 1 0 0 1 0 0 + solid 128 128 128 102 + end transform + end clip + end transform + pop group mode 3 + end transform +end clip diff --git a/tests/data/expected/test-165 b/tests/data/expected/test-165 new file mode 100644 index 0000000..b122f66 --- /dev/null +++ b/tests/data/expected/test-165 @@ -0,0 +1,22 @@ +# random seed: R02Sd7e42dc5034eae428f9fdf486603e319 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 100 250 1.2e+03 950 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 165 + start transform 1 0 0 1 0 0 + linear gradient + p0 100 950 + p1 2.3e+03 950 + p2 -1e+03 250 + colors 0 + 0 255 0 0 255 + 0.5 0 0 255 255 + 1 255 255 0 255 + end transform + end clip + end transform + end transform +end clip diff --git a/tests/data/expected/test-175 b/tests/data/expected/test-175 new file mode 100644 index 0000000..be14b81 --- /dev/null +++ b/tests/data/expected/test-175 @@ -0,0 +1,36 @@ +# random seed: R02Se9d7defb0878dc8a90f62d9f42a715f3 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 0 0 1e+03 1e+03 + start transform 1 0 0 1 0 0 + push group + start transform 1 0 0 1 150 0 + start transform 1 0 -0 1 0 0 + start clip glyph 174 + start transform 1 0 0 1 0 0 + solid 0 128 0 255 + end transform + end clip + end transform + end transform + pop group mode 3 + push group + start transform 1 0 0 1 -150 0 + start transform 1 0 -0 1 0 0 + start clip glyph 174 + start transform 1 0 0 1 0 0 + linear gradient + p0 500 250 + p1 500 950 + p2 600 250 + colors 1 + 0 255 0 0 255 + 1 0 0 255 255 + end transform + end clip + end transform + end transform + pop group mode 3 + end transform +end clip diff --git a/tests/data/expected/test-6 b/tests/data/expected/test-6 new file mode 100644 index 0000000..94b543e --- /dev/null +++ b/tests/data/expected/test-6 @@ -0,0 +1,21 @@ +# random seed: R02S68886e711ff0007004bb488f8b8c3904 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 100 250 900 950 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 6 + start transform 1 0 0 1 0 0 + linear gradient + p0 100 250 + p1 900 250 + p2 100 300 + colors 1 + 0 255 0 0 255 + 1 0 0 255 255 + end transform + end clip + end transform + end transform +end clip diff --git a/tests/data/expected/test-92 b/tests/data/expected/test-92 new file mode 100644 index 0000000..422e917 --- /dev/null +++ b/tests/data/expected/test-92 @@ -0,0 +1,21 @@ +# random seed: R02Se8a9546dc34a7e4d4f5c5e997ddcf0d8 +# Start of hb tests +# Start of paint tests +# Start of ot tests +start clip rectangle 0 0 1e+03 1e+03 + start transform 1 0 0 1 0 0 + start transform 1 0 -0 1 0 0 + start clip glyph 2 + start transform 1 0 0 1 0 0 + radial gradient + p0 166 768 radius 0 + p1 166 768 radius 256 + colors 1 + 0 0 128 0 255 + 0.5 255 255 255 255 + 1 255 0 0 255 + end transform + end clip + end transform + end transform +end clip diff --git a/tests/data/noto_handwriting-cff2_colr_1.otf b/tests/data/noto_handwriting-cff2_colr_1.otf new file mode 100644 index 0000000000000000000000000000000000000000..dfb30588e79ab24dfbbfd07dc98931d6cb115729 GIT binary patch literal 4172 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 CSdVZ3 literal 0 HcmV?d00001 diff --git a/tests/data/test_glyphs-glyf_colr_1.ttf b/tests/data/test_glyphs-glyf_colr_1.ttf new file mode 100644 index 0000000000000000000000000000000000000000..982ccc0a115ee9d58959eb54c27aa5a5a7491e0a GIT binary patch literal 16704 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 literal 0 HcmV?d00001 diff --git a/tests/test_uharfbuzz.py b/tests/test_uharfbuzz.py index 2a80a27..05765d7 100644 --- a/tests/test_uharfbuzz.py +++ b/tests/test_uharfbuzz.py @@ -783,6 +783,232 @@ def closePath(self): ] +class TestPaintFuncs: + @staticmethod + def setup_funcs(): + def split_color(color: int): + return color.to_bytes(4, "little") + + def push_transform_func(xx, xy, yx, yy, dx, dy, conainer): + conainer.append( + f"start transform " + f"{xx:.3g} {xy:.3g} {yx:.3g} {yy:.3g} {dx:.3g} {dy:.3g}" + ) + conainer.level += 1 + + def pop_transform_func(conainer): + conainer.level -= 1 + conainer.append(f"end transform") + + def color_glyph_func(font, gid, conainer): + conainer.append(f"paint color glyph {gid}; acting as failed") + return False + + def push_clip_glyph_func(font, gid, conainer): + conainer.append(f"start clip glyph {gid}") + conainer.level += 1 + return True + + def push_clip_rectangle_func(xmin, ymin, xmax, ymax, conainer): + conainer.append( + f"start clip rectangle " f"{xmin:.3g} {ymin:.3g} {xmax:.3g} {ymax:.3g}" + ) + conainer.level += 1 + + def pop_clip_func(conainer): + conainer.level -= 1 + conainer.append(f"end clip") + + def color_func(color, is_foreground, conainer): + a, r, g, b = split_color(color) + conainer.append(f"solid {r} {g} {b} {a}") + + def image_func(image, width, height, format, slant, extents, conainer): + conainer.append( + f"image type {format} " + f"size {width} {height} " + f"slant {slant:.3g} " + f"extents {extents.x_bearing} {extents.y_bearing} {extents.width} {extents.height}" + ) + return True + + def linear_gradient_func(color_line, x0, y0, x1, y1, x2, y2, conainer): + conainer.append(f"linear gradient") + conainer.level += 1 + conainer.append(f"p0 {x0:.3g} {y0:.3g}") + conainer.append(f"p1 {x1:.3g} {y1:.3g}") + conainer.append(f"p2 {x2:.3g} {y2:.3g}") + conainer.append_color_line(color_line) + conainer.level -= 1 + + def radial_gradient_func(color_line, x0, y0, r0, x1, y1, r1, conainer): + conainer.append(f"radial gradient") + conainer.level += 1 + conainer.append(f"p0 {x0:.3g} {y0:.3g} radius {r0:.3g}") + conainer.append(f"p1 {x1:.3g} {y1:.3g} radius {r1:.3g}") + conainer.append_color_line(color_line) + conainer.level -= 1 + + def sweep_gradient_func(color_line, cx, cy, start_angle, end_angle, conainer): + conainer.append(f"sweep gradient") + conainer.level += 1 + conainer.append(f"center {cx:.3g} {cy:.3g}") + conainer.append(f"angles {start_angle:.3g} {end_angle:.3g}") + conainer.append_color_line(color_line) + conainer.level -= 1 + + def push_group_func(conainer): + conainer.append(f"push group") + conainer.level += 1 + + def pop_group_func(mode, conainer): + conainer.level -= 1 + conainer.append(f"pop group mode {int(mode)}") + + def custom_palette_color_func(color_index, conainer): + return None + + funcs = hb.PaintFuncs() + funcs.set_push_transform_func(push_transform_func) + funcs.set_pop_transform_func(pop_transform_func) + funcs.set_color_glyph_func(color_glyph_func) + funcs.set_push_clip_glyph_func(push_clip_glyph_func) + funcs.set_push_clip_rectangle_func(push_clip_rectangle_func) + funcs.set_pop_clip_func(pop_clip_func) + funcs.set_color_func(color_func) + funcs.set_image_func(image_func) + funcs.set_linear_gradient_func(linear_gradient_func) + funcs.set_radial_gradient_func(radial_gradient_func) + funcs.set_sweep_gradient_func(sweep_gradient_func) + funcs.set_push_group_func(push_group_func) + funcs.set_pop_group_func(pop_group_func) + funcs.set_custom_palette_color_func(custom_palette_color_func) + + class Container: + def __init__(self): + self.level = 0 + self.lines = [] + + def append(self, line): + indent = " " * self.level * 2 + self.lines.append(indent + line) + + def append_color_line(self, color_line): + self.append(f"colors {int(color_line.extend)}") + + self.level += 1 + for stop in color_line.color_stops: + a, r, g, b = split_color(stop.color) + self.append(f"{stop.offset:.3g} {r} {g} {b} {a}") + self.level -= 1 + + def value(self): + return "\n".join(self.lines) + + return funcs, Container() + + @staticmethod + def setup_funcs_capsule(container_size): + import ctypes + import uharfbuzz._harfbuzz_test + + PyCapsule_New = ctypes.pythonapi.PyCapsule_New + PyCapsule_New.restype = ctypes.py_object + PyCapsule_New.argtypes = (ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) + + lib = ctypes.cdll.LoadLibrary(uharfbuzz._harfbuzz_test.__file__) + + def cap(x): + return PyCapsule_New(x, None, None) + + funcs = hb.PaintFuncs() + funcs.set_push_transform_func(cap(lib._test_push_transform)) + funcs.set_pop_transform_func(cap(lib._test_pop_transform)) + funcs.set_color_glyph_func(cap(lib._test_paint_color_glyph)) + funcs.set_push_clip_glyph_func(cap(lib._test_push_clip_glyph)) + funcs.set_push_clip_rectangle_func(cap(lib._test_push_clip_rectangle)) + funcs.set_pop_clip_func(cap(lib._test_pop_clip)) + funcs.set_color_func(cap(lib._test_paint_color)) + funcs.set_image_func(cap(lib._test_paint_image)) + funcs.set_linear_gradient_func(cap(lib._test_paint_linear_gradient)) + funcs.set_radial_gradient_func(cap(lib._test_paint_radial_gradient)) + funcs.set_sweep_gradient_func(cap(lib._test_paint_sweep_gradient)) + funcs.set_push_group_func(cap(lib._test_push_group)) + funcs.set_pop_group_func(cap(lib._test_pop_group)) + funcs.set_custom_palette_color_func(cap(lib._test_custom_palette_color)) + + class Container: + def __init__(self, size): + create = lib._test_paint_data_create + create.restype = ctypes.c_void_p + create.argtypes = (ctypes.c_size_t,) + + self.size = size + self.data = create(size) + self.cap = cap(self.data) + + def __del__(self): + destroy = lib._test_paint_data_destroy + destroy.restype = None + destroy.argtypes = (ctypes.c_void_p,) + + destroy(self.data) + + def value(self): + get_string = lib._test_paint_data_get_string + get_string.restype = ctypes.c_char_p + get_string.argtypes = (ctypes.c_void_p,) + + return get_string(self.data).decode("ascii") + + return funcs, Container(container_size) + + @pytest.mark.parametrize( + "fontpath, glyph, expectedpath, use_capsule", + [ + ("noto_handwriting-cff2_colr_1.otf", 10, "hand-10", False), + ("test_glyphs-glyf_colr_1.ttf", 6, "test-6", False), + ("test_glyphs-glyf_colr_1.ttf", 10, "test-10", False), + ("test_glyphs-glyf_colr_1.ttf", 92, "test-92", False), + ("test_glyphs-glyf_colr_1.ttf", 106, "test-106", False), + ("test_glyphs-glyf_colr_1.ttf", 116, "test-116", False), + ("test_glyphs-glyf_colr_1.ttf", 123, "test-123", False), + ("test_glyphs-glyf_colr_1.ttf", 145, "test-154", False), + ("test_glyphs-glyf_colr_1.ttf", 165, "test-165", False), + ("test_glyphs-glyf_colr_1.ttf", 175, "test-175", False), + ("noto_handwriting-cff2_colr_1.otf", 10, "hand-10", True), + ("test_glyphs-glyf_colr_1.ttf", 6, "test-6", True), + ("test_glyphs-glyf_colr_1.ttf", 10, "test-10", True), + ("test_glyphs-glyf_colr_1.ttf", 92, "test-92", True), + ("test_glyphs-glyf_colr_1.ttf", 106, "test-106", True), + ("test_glyphs-glyf_colr_1.ttf", 116, "test-116", True), + ("test_glyphs-glyf_colr_1.ttf", 123, "test-123", True), + ("test_glyphs-glyf_colr_1.ttf", 145, "test-154", True), + ("test_glyphs-glyf_colr_1.ttf", 165, "test-165", True), + ("test_glyphs-glyf_colr_1.ttf", 175, "test-175", True), + ], + ) + def test_paint(self, fontpath, glyph, expectedpath, use_capsule): + blob = hb.Blob.from_file_path(TESTDATA / fontpath) + face = hb.Face(blob) + font = hb.Font(face) + + with open(TESTDATA / "expected" / expectedpath) as f: + expected = "".join(line for line in f.readlines() if line[0] != "#") + + if use_capsule: + import ctypes + + funcs, container = self.setup_funcs_capsule(len(expected) * 2) + font.paint_glyph(glyph, funcs, container.cap) + else: + funcs, container = self.setup_funcs() + font.paint_glyph(glyph, funcs, container) + + result = container.value() + assert result.strip() == expected.strip() + + class MessageCollector: def message(self, message): pass