xref: /aosp_15_r20/external/harfbuzz_ng/test/api/test-paint.c (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2022 Matthias Clasen
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  */
24*2d1272b8SAndroid Build Coastguard Worker 
25*2d1272b8SAndroid Build Coastguard Worker #include "hb-test.h"
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #include <hb-features.h>
28*2d1272b8SAndroid Build Coastguard Worker #include <hb-ot.h>
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_FREETYPE
31*2d1272b8SAndroid Build Coastguard Worker #include <hb-ft.h>
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
34*2d1272b8SAndroid Build Coastguard Worker #include FT_COLOR_H
35*2d1272b8SAndroid Build Coastguard Worker #endif
36*2d1272b8SAndroid Build Coastguard Worker #endif
37*2d1272b8SAndroid Build Coastguard Worker 
38*2d1272b8SAndroid Build Coastguard Worker static inline hb_bool_t
have_ft_colrv1(void)39*2d1272b8SAndroid Build Coastguard Worker have_ft_colrv1 (void)
40*2d1272b8SAndroid Build Coastguard Worker {
41*2d1272b8SAndroid Build Coastguard Worker #if defined(HB_HAS_FREETYPE) && (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
42*2d1272b8SAndroid Build Coastguard Worker   return TRUE;
43*2d1272b8SAndroid Build Coastguard Worker #else
44*2d1272b8SAndroid Build Coastguard Worker   return FALSE;
45*2d1272b8SAndroid Build Coastguard Worker #endif
46*2d1272b8SAndroid Build Coastguard Worker }
47*2d1272b8SAndroid Build Coastguard Worker 
48*2d1272b8SAndroid Build Coastguard Worker /* Unit tests for hb-paint.h */
49*2d1272b8SAndroid Build Coastguard Worker 
50*2d1272b8SAndroid Build Coastguard Worker /* ---- */
51*2d1272b8SAndroid Build Coastguard Worker 
52*2d1272b8SAndroid Build Coastguard Worker typedef struct {
53*2d1272b8SAndroid Build Coastguard Worker   int level;
54*2d1272b8SAndroid Build Coastguard Worker   GString *string;
55*2d1272b8SAndroid Build Coastguard Worker } paint_data_t;
56*2d1272b8SAndroid Build Coastguard Worker 
57*2d1272b8SAndroid Build Coastguard Worker static void print (paint_data_t *data, const char *format, ...) G_GNUC_PRINTF (2, 3);
58*2d1272b8SAndroid Build Coastguard Worker 
59*2d1272b8SAndroid Build Coastguard Worker static void
print(paint_data_t * data,const char * format,...)60*2d1272b8SAndroid Build Coastguard Worker print (paint_data_t *data,
61*2d1272b8SAndroid Build Coastguard Worker        const char *format,
62*2d1272b8SAndroid Build Coastguard Worker        ...)
63*2d1272b8SAndroid Build Coastguard Worker {
64*2d1272b8SAndroid Build Coastguard Worker   va_list args;
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker   g_string_append_printf (data->string, "%*s", 2 * data->level, "");
67*2d1272b8SAndroid Build Coastguard Worker 
68*2d1272b8SAndroid Build Coastguard Worker   va_start (args, format);
69*2d1272b8SAndroid Build Coastguard Worker   g_string_append_vprintf (data->string, format, args);
70*2d1272b8SAndroid Build Coastguard Worker   va_end (args);
71*2d1272b8SAndroid Build Coastguard Worker 
72*2d1272b8SAndroid Build Coastguard Worker   g_string_append (data->string, "\n");
73*2d1272b8SAndroid Build Coastguard Worker }
74*2d1272b8SAndroid Build Coastguard Worker 
75*2d1272b8SAndroid Build Coastguard Worker static void
push_transform(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,float xx,float yx,float xy,float yy,float dx,float dy,void * user_data HB_UNUSED)76*2d1272b8SAndroid Build Coastguard Worker push_transform (hb_paint_funcs_t *funcs HB_UNUSED,
77*2d1272b8SAndroid Build Coastguard Worker                 void *paint_data,
78*2d1272b8SAndroid Build Coastguard Worker                 float xx, float yx,
79*2d1272b8SAndroid Build Coastguard Worker                 float xy, float yy,
80*2d1272b8SAndroid Build Coastguard Worker                 float dx, float dy,
81*2d1272b8SAndroid Build Coastguard Worker                 void *user_data HB_UNUSED)
82*2d1272b8SAndroid Build Coastguard Worker {
83*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
84*2d1272b8SAndroid Build Coastguard Worker 
85*2d1272b8SAndroid Build Coastguard Worker   print (data, "start transform %.3g %.3g %.3g %.3g %.3g %.3g", xx, yx, xy, yy, dx, dy);
86*2d1272b8SAndroid Build Coastguard Worker   data->level++;
87*2d1272b8SAndroid Build Coastguard Worker }
88*2d1272b8SAndroid Build Coastguard Worker 
89*2d1272b8SAndroid Build Coastguard Worker static void
pop_transform(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)90*2d1272b8SAndroid Build Coastguard Worker pop_transform (hb_paint_funcs_t *funcs HB_UNUSED,
91*2d1272b8SAndroid Build Coastguard Worker                void *paint_data,
92*2d1272b8SAndroid Build Coastguard Worker                void *user_data HB_UNUSED)
93*2d1272b8SAndroid Build Coastguard Worker {
94*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
95*2d1272b8SAndroid Build Coastguard Worker 
96*2d1272b8SAndroid Build Coastguard Worker   data->level--;
97*2d1272b8SAndroid Build Coastguard Worker   print (data, "end transform");
98*2d1272b8SAndroid Build Coastguard Worker }
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
paint_color_glyph(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_codepoint_t glyph,hb_font_t * font HB_UNUSED,void * user_data HB_UNUSED)101*2d1272b8SAndroid Build Coastguard Worker paint_color_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
102*2d1272b8SAndroid Build Coastguard Worker                    void *paint_data,
103*2d1272b8SAndroid Build Coastguard Worker                    hb_codepoint_t glyph,
104*2d1272b8SAndroid Build Coastguard Worker                    hb_font_t *font HB_UNUSED,
105*2d1272b8SAndroid Build Coastguard Worker                    void *user_data HB_UNUSED)
106*2d1272b8SAndroid Build Coastguard Worker {
107*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
108*2d1272b8SAndroid Build Coastguard Worker 
109*2d1272b8SAndroid Build Coastguard Worker   print (data, "paint color glyph %u; acting as failed", glyph);
110*2d1272b8SAndroid Build Coastguard Worker 
111*2d1272b8SAndroid Build Coastguard Worker   return FALSE;
112*2d1272b8SAndroid Build Coastguard Worker }
113*2d1272b8SAndroid Build Coastguard Worker 
114*2d1272b8SAndroid Build Coastguard Worker static void
push_clip_glyph(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_codepoint_t glyph,hb_font_t * font HB_UNUSED,void * user_data HB_UNUSED)115*2d1272b8SAndroid Build Coastguard Worker push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
116*2d1272b8SAndroid Build Coastguard Worker                  void *paint_data,
117*2d1272b8SAndroid Build Coastguard Worker                  hb_codepoint_t glyph,
118*2d1272b8SAndroid Build Coastguard Worker                  hb_font_t *font HB_UNUSED,
119*2d1272b8SAndroid Build Coastguard Worker                  void *user_data HB_UNUSED)
120*2d1272b8SAndroid Build Coastguard Worker {
121*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
122*2d1272b8SAndroid Build Coastguard Worker 
123*2d1272b8SAndroid Build Coastguard Worker   print (data, "start clip glyph %u", glyph);
124*2d1272b8SAndroid Build Coastguard Worker   data->level++;
125*2d1272b8SAndroid Build Coastguard Worker }
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker static void
push_clip_rectangle(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,float xmin,float ymin,float xmax,float ymax,void * user_data HB_UNUSED)128*2d1272b8SAndroid Build Coastguard Worker push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
129*2d1272b8SAndroid Build Coastguard Worker                      void *paint_data,
130*2d1272b8SAndroid Build Coastguard Worker                      float xmin, float ymin, float xmax, float ymax,
131*2d1272b8SAndroid Build Coastguard Worker                      void *user_data HB_UNUSED)
132*2d1272b8SAndroid Build Coastguard Worker {
133*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
134*2d1272b8SAndroid Build Coastguard Worker 
135*2d1272b8SAndroid Build Coastguard Worker   print (data, "start clip rectangle %.3g %.3g %.3g %.3g", xmin, ymin, xmax, ymax);
136*2d1272b8SAndroid Build Coastguard Worker   data->level++;
137*2d1272b8SAndroid Build Coastguard Worker }
138*2d1272b8SAndroid Build Coastguard Worker 
139*2d1272b8SAndroid Build Coastguard Worker static void
pop_clip(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)140*2d1272b8SAndroid Build Coastguard Worker pop_clip (hb_paint_funcs_t *funcs HB_UNUSED,
141*2d1272b8SAndroid Build Coastguard Worker           void *paint_data,
142*2d1272b8SAndroid Build Coastguard Worker           void *user_data HB_UNUSED)
143*2d1272b8SAndroid Build Coastguard Worker {
144*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
145*2d1272b8SAndroid Build Coastguard Worker 
146*2d1272b8SAndroid Build Coastguard Worker   data->level--;
147*2d1272b8SAndroid Build Coastguard Worker   print (data, "end clip");
148*2d1272b8SAndroid Build Coastguard Worker }
149*2d1272b8SAndroid Build Coastguard Worker 
150*2d1272b8SAndroid Build Coastguard Worker static void
paint_color(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_bool_t use_foreground HB_UNUSED,hb_color_t color,void * user_data HB_UNUSED)151*2d1272b8SAndroid Build Coastguard Worker paint_color (hb_paint_funcs_t *funcs HB_UNUSED,
152*2d1272b8SAndroid Build Coastguard Worker              void *paint_data,
153*2d1272b8SAndroid Build Coastguard Worker              hb_bool_t use_foreground HB_UNUSED,
154*2d1272b8SAndroid Build Coastguard Worker              hb_color_t color,
155*2d1272b8SAndroid Build Coastguard Worker              void *user_data HB_UNUSED)
156*2d1272b8SAndroid Build Coastguard Worker {
157*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
158*2d1272b8SAndroid Build Coastguard Worker 
159*2d1272b8SAndroid Build Coastguard Worker   print (data, "solid %d %d %d %d",
160*2d1272b8SAndroid Build Coastguard Worker          hb_color_get_red (color),
161*2d1272b8SAndroid Build Coastguard Worker          hb_color_get_green (color),
162*2d1272b8SAndroid Build Coastguard Worker          hb_color_get_blue (color),
163*2d1272b8SAndroid Build Coastguard Worker          hb_color_get_alpha (color));
164*2d1272b8SAndroid Build Coastguard Worker }
165*2d1272b8SAndroid Build Coastguard Worker 
166*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
paint_image(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_blob_t * blob HB_UNUSED,unsigned int width,unsigned int height,hb_tag_t format,float slant,hb_glyph_extents_t * extents,void * user_data HB_UNUSED)167*2d1272b8SAndroid Build Coastguard Worker paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
168*2d1272b8SAndroid Build Coastguard Worker              void *paint_data,
169*2d1272b8SAndroid Build Coastguard Worker              hb_blob_t *blob HB_UNUSED,
170*2d1272b8SAndroid Build Coastguard Worker              unsigned int width,
171*2d1272b8SAndroid Build Coastguard Worker              unsigned int height,
172*2d1272b8SAndroid Build Coastguard Worker              hb_tag_t format,
173*2d1272b8SAndroid Build Coastguard Worker              float slant,
174*2d1272b8SAndroid Build Coastguard Worker              hb_glyph_extents_t *extents,
175*2d1272b8SAndroid Build Coastguard Worker              void *user_data HB_UNUSED)
176*2d1272b8SAndroid Build Coastguard Worker {
177*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
178*2d1272b8SAndroid Build Coastguard Worker   char buf[5] = { 0, };
179*2d1272b8SAndroid Build Coastguard Worker 
180*2d1272b8SAndroid Build Coastguard Worker   hb_tag_to_string (format, buf);
181*2d1272b8SAndroid Build Coastguard Worker   print (data, "image type %s size %u %u slant %.3g extents %d %d %d %d\n",
182*2d1272b8SAndroid Build Coastguard Worker          buf, width, height, slant,
183*2d1272b8SAndroid Build Coastguard Worker          extents->x_bearing, extents->y_bearing, extents->width, extents->height);
184*2d1272b8SAndroid Build Coastguard Worker 
185*2d1272b8SAndroid Build Coastguard Worker   return TRUE;
186*2d1272b8SAndroid Build Coastguard Worker }
187*2d1272b8SAndroid Build Coastguard Worker 
188*2d1272b8SAndroid Build Coastguard Worker static void
print_color_line(paint_data_t * data,hb_color_line_t * color_line)189*2d1272b8SAndroid Build Coastguard Worker print_color_line (paint_data_t *data,
190*2d1272b8SAndroid Build Coastguard Worker                   hb_color_line_t *color_line)
191*2d1272b8SAndroid Build Coastguard Worker {
192*2d1272b8SAndroid Build Coastguard Worker   hb_color_stop_t *stops;
193*2d1272b8SAndroid Build Coastguard Worker   unsigned int len;
194*2d1272b8SAndroid Build Coastguard Worker 
195*2d1272b8SAndroid Build Coastguard Worker   len = hb_color_line_get_color_stops (color_line, 0, NULL, NULL);
196*2d1272b8SAndroid Build Coastguard Worker   stops = alloca (len * sizeof (hb_color_stop_t));
197*2d1272b8SAndroid Build Coastguard Worker   hb_color_line_get_color_stops (color_line, 0, &len, stops);
198*2d1272b8SAndroid Build Coastguard Worker 
199*2d1272b8SAndroid Build Coastguard Worker   print (data, "colors %d", hb_color_line_get_extend (color_line));
200*2d1272b8SAndroid Build Coastguard Worker   data->level += 1;
201*2d1272b8SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < len; i++)
202*2d1272b8SAndroid Build Coastguard Worker     print (data, "%.3g %d %d %d %d",
203*2d1272b8SAndroid Build Coastguard Worker            stops[i].offset,
204*2d1272b8SAndroid Build Coastguard Worker            hb_color_get_red (stops[i].color),
205*2d1272b8SAndroid Build Coastguard Worker            hb_color_get_green (stops[i].color),
206*2d1272b8SAndroid Build Coastguard Worker            hb_color_get_blue (stops[i].color),
207*2d1272b8SAndroid Build Coastguard Worker            hb_color_get_alpha (stops[i].color));
208*2d1272b8SAndroid Build Coastguard Worker   data->level -= 1;
209*2d1272b8SAndroid Build Coastguard Worker }
210*2d1272b8SAndroid Build Coastguard Worker 
211*2d1272b8SAndroid Build Coastguard Worker static void
paint_linear_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line,float x0,float y0,float x1,float y1,float x2,float y2,void * user_data HB_UNUSED)212*2d1272b8SAndroid Build Coastguard Worker paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
213*2d1272b8SAndroid Build Coastguard Worker                        void *paint_data,
214*2d1272b8SAndroid Build Coastguard Worker                        hb_color_line_t *color_line,
215*2d1272b8SAndroid Build Coastguard Worker                        float x0, float y0,
216*2d1272b8SAndroid Build Coastguard Worker                        float x1, float y1,
217*2d1272b8SAndroid Build Coastguard Worker                        float x2, float y2,
218*2d1272b8SAndroid Build Coastguard Worker                        void *user_data HB_UNUSED)
219*2d1272b8SAndroid Build Coastguard Worker {
220*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
221*2d1272b8SAndroid Build Coastguard Worker 
222*2d1272b8SAndroid Build Coastguard Worker   print (data, "linear gradient");
223*2d1272b8SAndroid Build Coastguard Worker   data->level += 1;
224*2d1272b8SAndroid Build Coastguard Worker   print (data, "p0 %.3g %.3g", x0, y0);
225*2d1272b8SAndroid Build Coastguard Worker   print (data, "p1 %.3g %.3g", x1, y1);
226*2d1272b8SAndroid Build Coastguard Worker   print (data, "p2 %.3g %.3g", x2, y2);
227*2d1272b8SAndroid Build Coastguard Worker 
228*2d1272b8SAndroid Build Coastguard Worker   print_color_line (data, color_line);
229*2d1272b8SAndroid Build Coastguard Worker   data->level -= 1;
230*2d1272b8SAndroid Build Coastguard Worker }
231*2d1272b8SAndroid Build Coastguard Worker 
232*2d1272b8SAndroid Build Coastguard Worker static void
paint_radial_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line,float x0,float y0,float r0,float x1,float y1,float r1,void * user_data HB_UNUSED)233*2d1272b8SAndroid Build Coastguard Worker paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
234*2d1272b8SAndroid Build Coastguard Worker                        void *paint_data,
235*2d1272b8SAndroid Build Coastguard Worker                        hb_color_line_t *color_line,
236*2d1272b8SAndroid Build Coastguard Worker                        float x0, float y0, float r0,
237*2d1272b8SAndroid Build Coastguard Worker                        float x1, float y1, float r1,
238*2d1272b8SAndroid Build Coastguard Worker                        void *user_data HB_UNUSED)
239*2d1272b8SAndroid Build Coastguard Worker {
240*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
241*2d1272b8SAndroid Build Coastguard Worker 
242*2d1272b8SAndroid Build Coastguard Worker   print (data, "radial gradient");
243*2d1272b8SAndroid Build Coastguard Worker   data->level += 1;
244*2d1272b8SAndroid Build Coastguard Worker   print (data, "p0 %.3g %.3g radius %.3g", x0, y0, r0);
245*2d1272b8SAndroid Build Coastguard Worker   print (data, "p1 %.3g %.3g radius %.3g", x1, y1, r1);
246*2d1272b8SAndroid Build Coastguard Worker 
247*2d1272b8SAndroid Build Coastguard Worker   print_color_line (data, color_line);
248*2d1272b8SAndroid Build Coastguard Worker   data->level -= 1;
249*2d1272b8SAndroid Build Coastguard Worker }
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker static void
paint_sweep_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line,float cx,float cy,float start_angle,float end_angle,void * user_data HB_UNUSED)252*2d1272b8SAndroid Build Coastguard Worker paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
253*2d1272b8SAndroid Build Coastguard Worker                       void *paint_data,
254*2d1272b8SAndroid Build Coastguard Worker                       hb_color_line_t *color_line,
255*2d1272b8SAndroid Build Coastguard Worker                       float cx, float cy,
256*2d1272b8SAndroid Build Coastguard Worker                       float start_angle,
257*2d1272b8SAndroid Build Coastguard Worker                       float end_angle,
258*2d1272b8SAndroid Build Coastguard Worker                       void *user_data HB_UNUSED)
259*2d1272b8SAndroid Build Coastguard Worker {
260*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
261*2d1272b8SAndroid Build Coastguard Worker 
262*2d1272b8SAndroid Build Coastguard Worker   print (data, "sweep gradient");
263*2d1272b8SAndroid Build Coastguard Worker   data->level++;
264*2d1272b8SAndroid Build Coastguard Worker   print (data, "center %.3g %.3g", cx, cy);
265*2d1272b8SAndroid Build Coastguard Worker   print (data, "angles %.3g %.3g", start_angle, end_angle);
266*2d1272b8SAndroid Build Coastguard Worker 
267*2d1272b8SAndroid Build Coastguard Worker   print_color_line (data, color_line);
268*2d1272b8SAndroid Build Coastguard Worker   data->level -= 1;
269*2d1272b8SAndroid Build Coastguard Worker }
270*2d1272b8SAndroid Build Coastguard Worker 
271*2d1272b8SAndroid Build Coastguard Worker static void
push_group(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,void * user_data HB_UNUSED)272*2d1272b8SAndroid Build Coastguard Worker push_group (hb_paint_funcs_t *funcs HB_UNUSED,
273*2d1272b8SAndroid Build Coastguard Worker             void *paint_data,
274*2d1272b8SAndroid Build Coastguard Worker             void *user_data HB_UNUSED)
275*2d1272b8SAndroid Build Coastguard Worker {
276*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
277*2d1272b8SAndroid Build Coastguard Worker   print (data, "push group");
278*2d1272b8SAndroid Build Coastguard Worker   data->level++;
279*2d1272b8SAndroid Build Coastguard Worker }
280*2d1272b8SAndroid Build Coastguard Worker 
281*2d1272b8SAndroid Build Coastguard Worker static void
pop_group(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_paint_composite_mode_t mode,void * user_data HB_UNUSED)282*2d1272b8SAndroid Build Coastguard Worker pop_group (hb_paint_funcs_t *funcs HB_UNUSED,
283*2d1272b8SAndroid Build Coastguard Worker            void *paint_data,
284*2d1272b8SAndroid Build Coastguard Worker            hb_paint_composite_mode_t mode,
285*2d1272b8SAndroid Build Coastguard Worker            void *user_data HB_UNUSED)
286*2d1272b8SAndroid Build Coastguard Worker {
287*2d1272b8SAndroid Build Coastguard Worker   paint_data_t *data = paint_data;
288*2d1272b8SAndroid Build Coastguard Worker   data->level--;
289*2d1272b8SAndroid Build Coastguard Worker   print (data, "pop group mode %d", mode);
290*2d1272b8SAndroid Build Coastguard Worker }
291*2d1272b8SAndroid Build Coastguard Worker 
292*2d1272b8SAndroid Build Coastguard Worker static hb_paint_funcs_t *
get_test_paint_funcs(void)293*2d1272b8SAndroid Build Coastguard Worker get_test_paint_funcs (void)
294*2d1272b8SAndroid Build Coastguard Worker {
295*2d1272b8SAndroid Build Coastguard Worker   static hb_paint_funcs_t *funcs = NULL;
296*2d1272b8SAndroid Build Coastguard Worker 
297*2d1272b8SAndroid Build Coastguard Worker   if (!funcs)
298*2d1272b8SAndroid Build Coastguard Worker   {
299*2d1272b8SAndroid Build Coastguard Worker     funcs = hb_paint_funcs_create ();
300*2d1272b8SAndroid Build Coastguard Worker 
301*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_push_transform_func (funcs, push_transform, NULL, NULL);
302*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_pop_transform_func (funcs, pop_transform, NULL, NULL);
303*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_color_glyph_func (funcs, paint_color_glyph, NULL, NULL);
304*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_push_clip_glyph_func (funcs, push_clip_glyph, NULL, NULL);
305*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_push_clip_rectangle_func (funcs, push_clip_rectangle, NULL, NULL);
306*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_pop_clip_func (funcs, pop_clip, NULL, NULL);
307*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_push_group_func (funcs, push_group, NULL, NULL);
308*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_pop_group_func (funcs, pop_group, NULL, NULL);
309*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_color_func (funcs, paint_color, NULL, NULL);
310*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_image_func (funcs, paint_image, NULL, NULL);
311*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_linear_gradient_func (funcs, paint_linear_gradient, NULL, NULL);
312*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_radial_gradient_func (funcs, paint_radial_gradient, NULL, NULL);
313*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_set_sweep_gradient_func (funcs, paint_sweep_gradient, NULL, NULL);
314*2d1272b8SAndroid Build Coastguard Worker 
315*2d1272b8SAndroid Build Coastguard Worker     hb_paint_funcs_make_immutable (funcs);
316*2d1272b8SAndroid Build Coastguard Worker   }
317*2d1272b8SAndroid Build Coastguard Worker 
318*2d1272b8SAndroid Build Coastguard Worker   return funcs;
319*2d1272b8SAndroid Build Coastguard Worker }
320*2d1272b8SAndroid Build Coastguard Worker 
321*2d1272b8SAndroid Build Coastguard Worker typedef struct {
322*2d1272b8SAndroid Build Coastguard Worker   const char *font_file;
323*2d1272b8SAndroid Build Coastguard Worker   float slant;
324*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t glyph;
325*2d1272b8SAndroid Build Coastguard Worker   unsigned int palette;
326*2d1272b8SAndroid Build Coastguard Worker   const char *output;
327*2d1272b8SAndroid Build Coastguard Worker } paint_test_t;
328*2d1272b8SAndroid Build Coastguard Worker 
329*2d1272b8SAndroid Build Coastguard Worker #define NOTO_HAND   "fonts/noto_handwriting-cff2_colr_1.otf"
330*2d1272b8SAndroid Build Coastguard Worker #define TEST_GLYPHS "fonts/test_glyphs-glyf_colr_1.ttf"
331*2d1272b8SAndroid Build Coastguard Worker #define TEST_GLYPHS_VF "fonts/test_glyphs-glyf_colr_1_variable.ttf"
332*2d1272b8SAndroid Build Coastguard Worker #define BAD_COLRV1  "fonts/bad_colrv1.ttf"
333*2d1272b8SAndroid Build Coastguard Worker #define ROCHER_ABC  "fonts/RocherColorGX.abc.ttf"
334*2d1272b8SAndroid Build Coastguard Worker 
335*2d1272b8SAndroid Build Coastguard Worker /* To verify the rendering visually, use
336*2d1272b8SAndroid Build Coastguard Worker  *
337*2d1272b8SAndroid Build Coastguard Worker  * hb-view --font-slant SLANT --font-palette PALETTE FONT --glyphs [gidGID=0+1000]
338*2d1272b8SAndroid Build Coastguard Worker  *
339*2d1272b8SAndroid Build Coastguard Worker  * where GID is the glyph value of the test.
340*2d1272b8SAndroid Build Coastguard Worker  */
341*2d1272b8SAndroid Build Coastguard Worker static paint_test_t paint_tests[] = {
342*2d1272b8SAndroid Build Coastguard Worker   /* COLRv1 */
343*2d1272b8SAndroid Build Coastguard Worker   { NOTO_HAND,   0.,  10,   0, "hand-10" },
344*2d1272b8SAndroid Build Coastguard Worker   { NOTO_HAND,   0.2f,10,   0, "hand-10.2" },
345*2d1272b8SAndroid Build Coastguard Worker 
346*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,    6,   0, "test-6" },   // linear gradient
347*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,   10,   0, "test-10" },  // sweep gradient
348*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,   92,   0, "test-92" },  // radial gradient
349*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  106,   0, "test-106" },
350*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  116,   0, "test-116" }, // compositing
351*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  123,   0, "test-123" },
352*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  154,   0, "test-154" },
353*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  165,   0, "test-165" }, // linear gradient
354*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS, 0,  175,   0, "test-175" }, // layers
355*2d1272b8SAndroid Build Coastguard Worker 
356*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,    6,   0, "testvf-6" },
357*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,   10,   0, "testvf-10" },
358*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,   92,   0, "testvf-92" },
359*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  106,   0, "testvf-106" },
360*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  116,   0, "testvf-116" },
361*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  123,   0, "testvf-123" },
362*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  154,   0, "testvf-154" },
363*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  165,   0, "testvf-165" },
364*2d1272b8SAndroid Build Coastguard Worker   { TEST_GLYPHS_VF, 0,  175,   0, "testvf-175" },
365*2d1272b8SAndroid Build Coastguard Worker 
366*2d1272b8SAndroid Build Coastguard Worker   { BAD_COLRV1,  0,  154,   0, "bad-154" },  // recursion
367*2d1272b8SAndroid Build Coastguard Worker 
368*2d1272b8SAndroid Build Coastguard Worker   /* COLRv0 */
369*2d1272b8SAndroid Build Coastguard Worker   { ROCHER_ABC, 0.3f, 1,   0, "rocher-1" },
370*2d1272b8SAndroid Build Coastguard Worker   { ROCHER_ABC, 0.3f, 2,   2, "rocher-2" },
371*2d1272b8SAndroid Build Coastguard Worker   { ROCHER_ABC, 0,    3, 200, "rocher-3" },
372*2d1272b8SAndroid Build Coastguard Worker };
373*2d1272b8SAndroid Build Coastguard Worker 
374*2d1272b8SAndroid Build Coastguard Worker static void
test_hb_paint(gconstpointer d,hb_bool_t use_ft HB_UNUSED)375*2d1272b8SAndroid Build Coastguard Worker test_hb_paint (gconstpointer d,
376*2d1272b8SAndroid Build Coastguard Worker                hb_bool_t     use_ft HB_UNUSED)
377*2d1272b8SAndroid Build Coastguard Worker {
378*2d1272b8SAndroid Build Coastguard Worker   const paint_test_t *test = d;
379*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face;
380*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font;
381*2d1272b8SAndroid Build Coastguard Worker   hb_paint_funcs_t *funcs;
382*2d1272b8SAndroid Build Coastguard Worker   paint_data_t data;
383*2d1272b8SAndroid Build Coastguard Worker   char *file;
384*2d1272b8SAndroid Build Coastguard Worker   char *buffer;
385*2d1272b8SAndroid Build Coastguard Worker   gsize len;
386*2d1272b8SAndroid Build Coastguard Worker   GError *error = NULL;
387*2d1272b8SAndroid Build Coastguard Worker 
388*2d1272b8SAndroid Build Coastguard Worker   face = hb_test_open_font_file (test->font_file);
389*2d1272b8SAndroid Build Coastguard Worker   font = hb_font_create (face);
390*2d1272b8SAndroid Build Coastguard Worker 
391*2d1272b8SAndroid Build Coastguard Worker   hb_font_set_synthetic_slant (font, test->slant);
392*2d1272b8SAndroid Build Coastguard Worker 
393*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_FREETYPE
394*2d1272b8SAndroid Build Coastguard Worker   if (use_ft)
395*2d1272b8SAndroid Build Coastguard Worker     hb_ft_font_set_funcs (font);
396*2d1272b8SAndroid Build Coastguard Worker #endif
397*2d1272b8SAndroid Build Coastguard Worker 
398*2d1272b8SAndroid Build Coastguard Worker   funcs = get_test_paint_funcs ();
399*2d1272b8SAndroid Build Coastguard Worker 
400*2d1272b8SAndroid Build Coastguard Worker   data.string = g_string_new ("");
401*2d1272b8SAndroid Build Coastguard Worker   data.level = 0;
402*2d1272b8SAndroid Build Coastguard Worker 
403*2d1272b8SAndroid Build Coastguard Worker   hb_font_paint_glyph (font, test->glyph, funcs, &data, 0, HB_COLOR (0, 0, 0, 255));
404*2d1272b8SAndroid Build Coastguard Worker 
405*2d1272b8SAndroid Build Coastguard Worker   /* Run
406*2d1272b8SAndroid Build Coastguard Worker    *
407*2d1272b8SAndroid Build Coastguard Worker    * GENERATE_DATA=1 G_TEST_SRCDIR=./test/api ./build/test/api/test-paint -p TESTCASE > test/api/results/OUTPUT
408*2d1272b8SAndroid Build Coastguard Worker    *
409*2d1272b8SAndroid Build Coastguard Worker    * to produce the expected results file.
410*2d1272b8SAndroid Build Coastguard Worker    */
411*2d1272b8SAndroid Build Coastguard Worker   if (getenv ("GENERATE_DATA"))
412*2d1272b8SAndroid Build Coastguard Worker     {
413*2d1272b8SAndroid Build Coastguard Worker       g_print ("%s", data.string->str);
414*2d1272b8SAndroid Build Coastguard Worker       exit (0);
415*2d1272b8SAndroid Build Coastguard Worker     }
416*2d1272b8SAndroid Build Coastguard Worker 
417*2d1272b8SAndroid Build Coastguard Worker   file = g_test_build_filename (G_TEST_DIST, "results", test->output, NULL);
418*2d1272b8SAndroid Build Coastguard Worker   if (!g_file_get_contents (file, &buffer, &len, &error))
419*2d1272b8SAndroid Build Coastguard Worker   {
420*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("File %s not found.", file);
421*2d1272b8SAndroid Build Coastguard Worker     g_test_fail ();
422*2d1272b8SAndroid Build Coastguard Worker     return;
423*2d1272b8SAndroid Build Coastguard Worker   }
424*2d1272b8SAndroid Build Coastguard Worker 
425*2d1272b8SAndroid Build Coastguard Worker   char **lines = g_strsplit (data.string->str, "\n", 0);
426*2d1272b8SAndroid Build Coastguard Worker   char **expected;
427*2d1272b8SAndroid Build Coastguard Worker   if (strstr (buffer, "\r\n"))
428*2d1272b8SAndroid Build Coastguard Worker     expected = g_strsplit (buffer, "\r\n", 0);
429*2d1272b8SAndroid Build Coastguard Worker   else
430*2d1272b8SAndroid Build Coastguard Worker     expected = g_strsplit (buffer, "\n", 0);
431*2d1272b8SAndroid Build Coastguard Worker 
432*2d1272b8SAndroid Build Coastguard Worker   /* Strip initial comments */
433*2d1272b8SAndroid Build Coastguard Worker   int i;
434*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; expected[i]; i++)
435*2d1272b8SAndroid Build Coastguard Worker     {
436*2d1272b8SAndroid Build Coastguard Worker       if (expected[i][0] != '#')
437*2d1272b8SAndroid Build Coastguard Worker         {
438*2d1272b8SAndroid Build Coastguard Worker           if (i > 0)
439*2d1272b8SAndroid Build Coastguard Worker             {
440*2d1272b8SAndroid Build Coastguard Worker               char **tmp = g_strdupv (expected + i);
441*2d1272b8SAndroid Build Coastguard Worker               g_strfreev (expected);
442*2d1272b8SAndroid Build Coastguard Worker               expected = tmp;
443*2d1272b8SAndroid Build Coastguard Worker             }
444*2d1272b8SAndroid Build Coastguard Worker           break;
445*2d1272b8SAndroid Build Coastguard Worker         }
446*2d1272b8SAndroid Build Coastguard Worker     }
447*2d1272b8SAndroid Build Coastguard Worker 
448*2d1272b8SAndroid Build Coastguard Worker   if (g_strv_length (lines) != g_strv_length (expected))
449*2d1272b8SAndroid Build Coastguard Worker   {
450*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("Unexpected number of lines in output (%d instead of %d):\n%s", g_strv_length (lines), g_strv_length (expected), data.string->str);
451*2d1272b8SAndroid Build Coastguard Worker     g_test_fail ();
452*2d1272b8SAndroid Build Coastguard Worker   }
453*2d1272b8SAndroid Build Coastguard Worker   else
454*2d1272b8SAndroid Build Coastguard Worker   {
455*2d1272b8SAndroid Build Coastguard Worker     unsigned int length = g_strv_length (lines);
456*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < length; i++)
457*2d1272b8SAndroid Build Coastguard Worker     {
458*2d1272b8SAndroid Build Coastguard Worker       if (strcmp (lines[i], expected[i]) != 0)
459*2d1272b8SAndroid Build Coastguard Worker       {
460*2d1272b8SAndroid Build Coastguard Worker         int pos;
461*2d1272b8SAndroid Build Coastguard Worker         for (pos = 0; lines[i][pos]; pos++)
462*2d1272b8SAndroid Build Coastguard Worker           if (lines[i][pos] != expected[i][pos])
463*2d1272b8SAndroid Build Coastguard Worker             break;
464*2d1272b8SAndroid Build Coastguard Worker 
465*2d1272b8SAndroid Build Coastguard Worker         g_test_message ("Unexpected output at %d:%d (%c instead of %c):\n%s", i, pos, lines[i][pos], expected[i][pos], data.string->str);
466*2d1272b8SAndroid Build Coastguard Worker         g_test_fail ();
467*2d1272b8SAndroid Build Coastguard Worker       }
468*2d1272b8SAndroid Build Coastguard Worker     }
469*2d1272b8SAndroid Build Coastguard Worker   }
470*2d1272b8SAndroid Build Coastguard Worker 
471*2d1272b8SAndroid Build Coastguard Worker   g_strfreev (lines);
472*2d1272b8SAndroid Build Coastguard Worker   g_strfreev (expected);
473*2d1272b8SAndroid Build Coastguard Worker 
474*2d1272b8SAndroid Build Coastguard Worker   g_free (buffer);
475*2d1272b8SAndroid Build Coastguard Worker   g_free (file);
476*2d1272b8SAndroid Build Coastguard Worker 
477*2d1272b8SAndroid Build Coastguard Worker   g_string_free (data.string, TRUE);
478*2d1272b8SAndroid Build Coastguard Worker 
479*2d1272b8SAndroid Build Coastguard Worker   hb_font_destroy (font);
480*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
481*2d1272b8SAndroid Build Coastguard Worker }
482*2d1272b8SAndroid Build Coastguard Worker 
483*2d1272b8SAndroid Build Coastguard Worker static void
test_compare_ot_ft(const char * file,hb_codepoint_t glyph)484*2d1272b8SAndroid Build Coastguard Worker test_compare_ot_ft (const char *file, hb_codepoint_t glyph)
485*2d1272b8SAndroid Build Coastguard Worker {
486*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face;
487*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font;
488*2d1272b8SAndroid Build Coastguard Worker   hb_paint_funcs_t *funcs;
489*2d1272b8SAndroid Build Coastguard Worker   GString *ot_str;
490*2d1272b8SAndroid Build Coastguard Worker   paint_data_t data;
491*2d1272b8SAndroid Build Coastguard Worker 
492*2d1272b8SAndroid Build Coastguard Worker   face = hb_test_open_font_file (file);
493*2d1272b8SAndroid Build Coastguard Worker   font = hb_font_create (face);
494*2d1272b8SAndroid Build Coastguard Worker 
495*2d1272b8SAndroid Build Coastguard Worker   funcs = get_test_paint_funcs ();
496*2d1272b8SAndroid Build Coastguard Worker 
497*2d1272b8SAndroid Build Coastguard Worker   data.string = g_string_new ("");
498*2d1272b8SAndroid Build Coastguard Worker   data.level = 0;
499*2d1272b8SAndroid Build Coastguard Worker 
500*2d1272b8SAndroid Build Coastguard Worker   hb_font_paint_glyph (font, glyph, funcs, &data, 0, HB_COLOR (0, 0, 0, 255));
501*2d1272b8SAndroid Build Coastguard Worker 
502*2d1272b8SAndroid Build Coastguard Worker   g_assert_true (data.level == 0);
503*2d1272b8SAndroid Build Coastguard Worker 
504*2d1272b8SAndroid Build Coastguard Worker   ot_str = data.string;
505*2d1272b8SAndroid Build Coastguard Worker 
506*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_FREETYPE
507*2d1272b8SAndroid Build Coastguard Worker   hb_ft_font_set_funcs (font);
508*2d1272b8SAndroid Build Coastguard Worker #endif
509*2d1272b8SAndroid Build Coastguard Worker 
510*2d1272b8SAndroid Build Coastguard Worker   data.string = g_string_new ("");
511*2d1272b8SAndroid Build Coastguard Worker   data.level = 0;
512*2d1272b8SAndroid Build Coastguard Worker 
513*2d1272b8SAndroid Build Coastguard Worker   hb_font_paint_glyph (font, glyph, funcs, &data, 0, HB_COLOR (0, 0, 0, 255));
514*2d1272b8SAndroid Build Coastguard Worker 
515*2d1272b8SAndroid Build Coastguard Worker   g_assert_true (data.level == 0);
516*2d1272b8SAndroid Build Coastguard Worker 
517*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpstr (ot_str->str, ==, data.string->str);
518*2d1272b8SAndroid Build Coastguard Worker 
519*2d1272b8SAndroid Build Coastguard Worker   g_string_free (data.string, TRUE);
520*2d1272b8SAndroid Build Coastguard Worker   hb_font_destroy (font);
521*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
522*2d1272b8SAndroid Build Coastguard Worker 
523*2d1272b8SAndroid Build Coastguard Worker   g_string_free (ot_str, TRUE);
524*2d1272b8SAndroid Build Coastguard Worker }
525*2d1272b8SAndroid Build Coastguard Worker 
526*2d1272b8SAndroid Build Coastguard Worker static void
test_hb_paint_ot(gconstpointer data)527*2d1272b8SAndroid Build Coastguard Worker test_hb_paint_ot (gconstpointer data)
528*2d1272b8SAndroid Build Coastguard Worker {
529*2d1272b8SAndroid Build Coastguard Worker   test_hb_paint (data, 0);
530*2d1272b8SAndroid Build Coastguard Worker }
531*2d1272b8SAndroid Build Coastguard Worker 
532*2d1272b8SAndroid Build Coastguard Worker static void
test_hb_paint_ft(gconstpointer data)533*2d1272b8SAndroid Build Coastguard Worker test_hb_paint_ft (gconstpointer data)
534*2d1272b8SAndroid Build Coastguard Worker {
535*2d1272b8SAndroid Build Coastguard Worker   if (have_ft_colrv1 ())
536*2d1272b8SAndroid Build Coastguard Worker     test_hb_paint (data, 1);
537*2d1272b8SAndroid Build Coastguard Worker   else
538*2d1272b8SAndroid Build Coastguard Worker     g_test_skip ("FreeType COLRv1 support not present");
539*2d1272b8SAndroid Build Coastguard Worker }
540*2d1272b8SAndroid Build Coastguard Worker 
541*2d1272b8SAndroid Build Coastguard Worker static void
test_compare_ot_ft_novf(gconstpointer d)542*2d1272b8SAndroid Build Coastguard Worker test_compare_ot_ft_novf (gconstpointer d)
543*2d1272b8SAndroid Build Coastguard Worker {
544*2d1272b8SAndroid Build Coastguard Worker   if (have_ft_colrv1 ())
545*2d1272b8SAndroid Build Coastguard Worker     test_compare_ot_ft (TEST_GLYPHS, GPOINTER_TO_UINT (d));
546*2d1272b8SAndroid Build Coastguard Worker   else
547*2d1272b8SAndroid Build Coastguard Worker     g_test_skip ("FreeType COLRv1 support not present");
548*2d1272b8SAndroid Build Coastguard Worker }
549*2d1272b8SAndroid Build Coastguard Worker 
550*2d1272b8SAndroid Build Coastguard Worker static void
test_compare_ot_ft_vf(gconstpointer d)551*2d1272b8SAndroid Build Coastguard Worker test_compare_ot_ft_vf (gconstpointer d)
552*2d1272b8SAndroid Build Coastguard Worker {
553*2d1272b8SAndroid Build Coastguard Worker   if (have_ft_colrv1 ())
554*2d1272b8SAndroid Build Coastguard Worker     test_compare_ot_ft (TEST_GLYPHS_VF, GPOINTER_TO_UINT (d));
555*2d1272b8SAndroid Build Coastguard Worker   else
556*2d1272b8SAndroid Build Coastguard Worker     g_test_skip ("FreeType COLRv1 support not present");
557*2d1272b8SAndroid Build Coastguard Worker }
558*2d1272b8SAndroid Build Coastguard Worker 
559*2d1272b8SAndroid Build Coastguard Worker static void
scrutinize_linear_gradient(hb_paint_funcs_t * funcs HB_UNUSED,void * paint_data,hb_color_line_t * color_line,float x0 HB_UNUSED,float y0 HB_UNUSED,float x1 HB_UNUSED,float y1 HB_UNUSED,float x2 HB_UNUSED,float y2 HB_UNUSED,void * user_data HB_UNUSED)560*2d1272b8SAndroid Build Coastguard Worker scrutinize_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
561*2d1272b8SAndroid Build Coastguard Worker                             void *paint_data,
562*2d1272b8SAndroid Build Coastguard Worker                             hb_color_line_t *color_line,
563*2d1272b8SAndroid Build Coastguard Worker                             float x0 HB_UNUSED, float y0 HB_UNUSED,
564*2d1272b8SAndroid Build Coastguard Worker                             float x1 HB_UNUSED, float y1 HB_UNUSED,
565*2d1272b8SAndroid Build Coastguard Worker                             float x2 HB_UNUSED, float y2 HB_UNUSED,
566*2d1272b8SAndroid Build Coastguard Worker                             void *user_data HB_UNUSED)
567*2d1272b8SAndroid Build Coastguard Worker {
568*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t *result = paint_data;
569*2d1272b8SAndroid Build Coastguard Worker   hb_color_stop_t *stops;
570*2d1272b8SAndroid Build Coastguard Worker   unsigned int len;
571*2d1272b8SAndroid Build Coastguard Worker   hb_color_stop_t *stops2;
572*2d1272b8SAndroid Build Coastguard Worker   unsigned int len2;
573*2d1272b8SAndroid Build Coastguard Worker 
574*2d1272b8SAndroid Build Coastguard Worker   *result = FALSE;
575*2d1272b8SAndroid Build Coastguard Worker 
576*2d1272b8SAndroid Build Coastguard Worker   len = hb_color_line_get_color_stops (color_line, 0, NULL, NULL);
577*2d1272b8SAndroid Build Coastguard Worker   if (len == 0)
578*2d1272b8SAndroid Build Coastguard Worker     return;
579*2d1272b8SAndroid Build Coastguard Worker 
580*2d1272b8SAndroid Build Coastguard Worker   stops = malloc (len * sizeof (hb_color_stop_t));
581*2d1272b8SAndroid Build Coastguard Worker   stops2 = malloc (len * sizeof (hb_color_stop_t));
582*2d1272b8SAndroid Build Coastguard Worker 
583*2d1272b8SAndroid Build Coastguard Worker   hb_color_line_get_color_stops (color_line, 0, &len, stops);
584*2d1272b8SAndroid Build Coastguard Worker   hb_color_line_get_color_stops (color_line, 0, &len, stops2);
585*2d1272b8SAndroid Build Coastguard Worker 
586*2d1272b8SAndroid Build Coastguard Worker   // check that we can get stops twice
587*2d1272b8SAndroid Build Coastguard Worker   if (memcmp (stops, stops2, len * sizeof (hb_color_stop_t)) != 0)
588*2d1272b8SAndroid Build Coastguard Worker   {
589*2d1272b8SAndroid Build Coastguard Worker     free (stops);
590*2d1272b8SAndroid Build Coastguard Worker     free (stops2);
591*2d1272b8SAndroid Build Coastguard Worker     return;
592*2d1272b8SAndroid Build Coastguard Worker   }
593*2d1272b8SAndroid Build Coastguard Worker 
594*2d1272b8SAndroid Build Coastguard Worker   // check that we can get a single stop in the middle
595*2d1272b8SAndroid Build Coastguard Worker   len2 = 1;
596*2d1272b8SAndroid Build Coastguard Worker   hb_color_line_get_color_stops (color_line, len - 1, &len2, stops2);
597*2d1272b8SAndroid Build Coastguard Worker   if (memcmp (&stops[len - 1], stops2, sizeof (hb_color_stop_t)) != 0)
598*2d1272b8SAndroid Build Coastguard Worker   {
599*2d1272b8SAndroid Build Coastguard Worker     free (stops);
600*2d1272b8SAndroid Build Coastguard Worker     free (stops2);
601*2d1272b8SAndroid Build Coastguard Worker     return;
602*2d1272b8SAndroid Build Coastguard Worker   }
603*2d1272b8SAndroid Build Coastguard Worker 
604*2d1272b8SAndroid Build Coastguard Worker   free (stops);
605*2d1272b8SAndroid Build Coastguard Worker   free (stops2);
606*2d1272b8SAndroid Build Coastguard Worker 
607*2d1272b8SAndroid Build Coastguard Worker   *result = TRUE;
608*2d1272b8SAndroid Build Coastguard Worker }
609*2d1272b8SAndroid Build Coastguard Worker 
610*2d1272b8SAndroid Build Coastguard Worker static void
test_color_stops(hb_bool_t use_ft HB_UNUSED)611*2d1272b8SAndroid Build Coastguard Worker test_color_stops (hb_bool_t use_ft HB_UNUSED)
612*2d1272b8SAndroid Build Coastguard Worker {
613*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face;
614*2d1272b8SAndroid Build Coastguard Worker   hb_font_t *font;
615*2d1272b8SAndroid Build Coastguard Worker   hb_paint_funcs_t *funcs;
616*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t result = FALSE;
617*2d1272b8SAndroid Build Coastguard Worker 
618*2d1272b8SAndroid Build Coastguard Worker   face = hb_test_open_font_file (NOTO_HAND);
619*2d1272b8SAndroid Build Coastguard Worker   font = hb_font_create (face);
620*2d1272b8SAndroid Build Coastguard Worker 
621*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_FREETYPE
622*2d1272b8SAndroid Build Coastguard Worker   if (use_ft)
623*2d1272b8SAndroid Build Coastguard Worker     hb_ft_font_set_funcs (font);
624*2d1272b8SAndroid Build Coastguard Worker #endif
625*2d1272b8SAndroid Build Coastguard Worker 
626*2d1272b8SAndroid Build Coastguard Worker   funcs = hb_paint_funcs_create ();
627*2d1272b8SAndroid Build Coastguard Worker   hb_paint_funcs_set_linear_gradient_func (funcs, scrutinize_linear_gradient, NULL, NULL);
628*2d1272b8SAndroid Build Coastguard Worker 
629*2d1272b8SAndroid Build Coastguard Worker   hb_font_paint_glyph (font, 10, funcs, &result, 0, HB_COLOR (0, 0, 0, 255));
630*2d1272b8SAndroid Build Coastguard Worker 
631*2d1272b8SAndroid Build Coastguard Worker   g_assert_true (result);
632*2d1272b8SAndroid Build Coastguard Worker 
633*2d1272b8SAndroid Build Coastguard Worker   hb_paint_funcs_destroy (funcs);
634*2d1272b8SAndroid Build Coastguard Worker   hb_font_destroy (font);
635*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
636*2d1272b8SAndroid Build Coastguard Worker }
637*2d1272b8SAndroid Build Coastguard Worker 
638*2d1272b8SAndroid Build Coastguard Worker static void
test_color_stops_ot(void)639*2d1272b8SAndroid Build Coastguard Worker test_color_stops_ot (void)
640*2d1272b8SAndroid Build Coastguard Worker {
641*2d1272b8SAndroid Build Coastguard Worker   test_color_stops (0);
642*2d1272b8SAndroid Build Coastguard Worker }
643*2d1272b8SAndroid Build Coastguard Worker 
644*2d1272b8SAndroid Build Coastguard Worker static void
test_color_stops_ft(void)645*2d1272b8SAndroid Build Coastguard Worker test_color_stops_ft (void)
646*2d1272b8SAndroid Build Coastguard Worker {
647*2d1272b8SAndroid Build Coastguard Worker   if (have_ft_colrv1 ())
648*2d1272b8SAndroid Build Coastguard Worker     test_color_stops (1);
649*2d1272b8SAndroid Build Coastguard Worker   else
650*2d1272b8SAndroid Build Coastguard Worker     g_test_skip ("FreeType COLRv1 support not present");
651*2d1272b8SAndroid Build Coastguard Worker }
652*2d1272b8SAndroid Build Coastguard Worker 
653*2d1272b8SAndroid Build Coastguard Worker int
main(int argc,char ** argv)654*2d1272b8SAndroid Build Coastguard Worker main (int argc, char **argv)
655*2d1272b8SAndroid Build Coastguard Worker {
656*2d1272b8SAndroid Build Coastguard Worker   int status = 0;
657*2d1272b8SAndroid Build Coastguard Worker 
658*2d1272b8SAndroid Build Coastguard Worker   hb_test_init (&argc, &argv);
659*2d1272b8SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < G_N_ELEMENTS (paint_tests); i++)
660*2d1272b8SAndroid Build Coastguard Worker   {
661*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_data_flavor (&paint_tests[i], paint_tests[i].output, test_hb_paint_ot);
662*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_data_flavor (&paint_tests[i], paint_tests[i].output, test_hb_paint_ft);
663*2d1272b8SAndroid Build Coastguard Worker   }
664*2d1272b8SAndroid Build Coastguard Worker 
665*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face = hb_test_open_font_file (TEST_GLYPHS);
666*2d1272b8SAndroid Build Coastguard Worker   unsigned glyph_count = hb_face_get_glyph_count (face);
667*2d1272b8SAndroid Build Coastguard Worker   for (unsigned int i = 1; i < glyph_count; i++)
668*2d1272b8SAndroid Build Coastguard Worker   {
669*2d1272b8SAndroid Build Coastguard Worker     char buf[20];
670*2d1272b8SAndroid Build Coastguard Worker     snprintf (buf, 20, "test-%u", i);
671*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_data_flavor (GUINT_TO_POINTER (i), buf, test_compare_ot_ft_novf);
672*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_data_flavor (GUINT_TO_POINTER (i), buf, test_compare_ot_ft_vf);
673*2d1272b8SAndroid Build Coastguard Worker   }
674*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
675*2d1272b8SAndroid Build Coastguard Worker 
676*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_color_stops_ot);
677*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_color_stops_ft);
678*2d1272b8SAndroid Build Coastguard Worker 
679*2d1272b8SAndroid Build Coastguard Worker   status = hb_test_run();
680*2d1272b8SAndroid Build Coastguard Worker 
681*2d1272b8SAndroid Build Coastguard Worker   return status;
682*2d1272b8SAndroid Build Coastguard Worker }
683