xref: /aosp_15_r20/external/harfbuzz_ng/test/api/test-draw-varc.c (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1 /*
2  * Copyright © 2024  Behdad Esfahbod
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  */
24 
25 #include "hb-test.h"
26 #include <math.h>
27 
28 #include <hb.h>
29 
30 typedef struct draw_data_t
31 {
32   unsigned move_to_count;
33   unsigned line_to_count;
34   unsigned quad_to_count;
35   unsigned cubic_to_count;
36   unsigned close_path_count;
37 } draw_data_t;
38 
39 /* Our modified itoa, why not using libc's? it is going to be used
40    in harfbuzzjs where libc isn't available */
_hb_reverse(char * buf,unsigned int len)41 static void _hb_reverse (char *buf, unsigned int len)
42 {
43   unsigned start = 0, end = len - 1;
44   while (start < end)
45   {
46     char c = buf[end];
47     buf[end] = buf[start];
48     buf[start] = c;
49     start++; end--;
50   }
51 }
_hb_itoa(float fnum,char * buf)52 static unsigned _hb_itoa (float fnum, char *buf)
53 {
54   int32_t num = (int32_t) floorf (fnum + .5f);
55   unsigned int i = 0;
56   hb_bool_t is_negative = num < 0;
57   if (is_negative) num = -num;
58   do
59   {
60     buf[i++] = '0' + num % 10;
61     num /= 10;
62   } while (num);
63   if (is_negative) buf[i++] = '-';
64   _hb_reverse (buf, i);
65   buf[i] = '\0';
66   return i;
67 }
68 
69 #define ITOA_BUF_SIZE 12 // 10 digits in int32, 1 for negative sign, 1 for \0
70 
71 static void
test_itoa(void)72 test_itoa (void)
73 {
74   char s[] = "12345";
75   _hb_reverse (s, 5);
76   g_assert_cmpmem (s, 5, "54321", 5);
77 
78   {
79     unsigned num = 12345;
80     char buf[ITOA_BUF_SIZE];
81     unsigned len = _hb_itoa (num, buf);
82     g_assert_cmpmem (buf, len, "12345", 5);
83   }
84 
85   {
86     unsigned num = 3152;
87     char buf[ITOA_BUF_SIZE];
88     unsigned len = _hb_itoa (num, buf);
89     g_assert_cmpmem (buf, len, "3152", 4);
90   }
91 
92   {
93     int num = -6457;
94     char buf[ITOA_BUF_SIZE];
95     unsigned len = _hb_itoa (num, buf);
96     g_assert_cmpmem (buf, len, "-6457", 5);
97   }
98 }
99 
100 static void
move_to(HB_UNUSED hb_draw_funcs_t * dfuncs,draw_data_t * draw_data,HB_UNUSED hb_draw_state_t * st,HB_UNUSED float to_x,HB_UNUSED float to_y,HB_UNUSED void * user_data)101 move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
102 	 HB_UNUSED hb_draw_state_t *st,
103 	 HB_UNUSED float to_x, HB_UNUSED float to_y,
104 	 HB_UNUSED void *user_data)
105 {
106   draw_data->move_to_count++;
107 }
108 
109 static void
line_to(HB_UNUSED hb_draw_funcs_t * dfuncs,draw_data_t * draw_data,HB_UNUSED hb_draw_state_t * st,HB_UNUSED float to_x,HB_UNUSED float to_y,HB_UNUSED void * user_data)110 line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
111 	 HB_UNUSED hb_draw_state_t *st,
112 	 HB_UNUSED float to_x, HB_UNUSED float to_y,
113 	 HB_UNUSED void *user_data)
114 {
115   draw_data->line_to_count++;
116 }
117 
118 static void
quadratic_to(HB_UNUSED hb_draw_funcs_t * dfuncs,draw_data_t * draw_data,HB_UNUSED hb_draw_state_t * st,HB_UNUSED float control_x,HB_UNUSED float control_y,HB_UNUSED float to_x,HB_UNUSED float to_y,HB_UNUSED void * user_data)119 quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
120 	      HB_UNUSED hb_draw_state_t *st,
121 	      HB_UNUSED float control_x, HB_UNUSED float control_y,
122 	      HB_UNUSED float to_x, HB_UNUSED float to_y,
123 	      HB_UNUSED void *user_data)
124 {
125   draw_data->quad_to_count++;
126 }
127 
128 static void
cubic_to(HB_UNUSED hb_draw_funcs_t * dfuncs,draw_data_t * draw_data,HB_UNUSED hb_draw_state_t * st,HB_UNUSED float control1_x,HB_UNUSED float control1_y,HB_UNUSED float control2_x,HB_UNUSED float control2_y,HB_UNUSED float to_x,HB_UNUSED float to_y,HB_UNUSED void * user_data)129 cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
130 	  HB_UNUSED hb_draw_state_t *st,
131 	  HB_UNUSED float control1_x, HB_UNUSED float control1_y,
132 	  HB_UNUSED float control2_x, HB_UNUSED float control2_y,
133 	  HB_UNUSED float to_x, HB_UNUSED float to_y,
134 	  HB_UNUSED void *user_data)
135 {
136   draw_data->cubic_to_count++;
137 }
138 
139 static void
close_path(HB_UNUSED hb_draw_funcs_t * dfuncs,draw_data_t * draw_data,HB_UNUSED hb_draw_state_t * st,HB_UNUSED void * user_data)140 close_path (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
141 	    HB_UNUSED hb_draw_state_t *st,
142 	    HB_UNUSED void *user_data)
143 {
144   draw_data->close_path_count++;
145 }
146 
147 static hb_draw_funcs_t *funcs;
148 
149 #ifdef HB_EXPERIMENTAL_API
150 static void
test_hb_draw_varc_simple_hangul(void)151 test_hb_draw_varc_simple_hangul (void)
152 {
153   hb_face_t *face = hb_test_open_font_file ("fonts/varc-ac00-ac01.ttf");
154   hb_font_t *font = hb_font_create (face);
155   hb_face_destroy (face);
156 
157   draw_data_t draw_data0 = {0};
158   draw_data_t draw_data;;
159   unsigned gid = 0;
160 
161   hb_font_get_nominal_glyph (font, 0xAC00u, &gid);
162   draw_data = draw_data0;
163   hb_font_draw_glyph (font, gid, funcs, &draw_data);
164   g_assert_cmpuint (draw_data.move_to_count, ==, 3);
165 
166   hb_font_get_nominal_glyph (font, 0xAC01u, &gid);
167   draw_data = draw_data0;
168   hb_font_draw_glyph (font, gid, funcs, &draw_data);
169   g_assert_cmpuint (draw_data.move_to_count, ==, 4);
170 
171   hb_variation_t var;
172   var.tag = HB_TAG ('w','g','h','t');
173   var.value = 800;
174   hb_font_set_variations (font, &var, 1);
175 
176   hb_font_get_nominal_glyph (font, 0xAC00u, &gid);
177   draw_data = draw_data0;
178   hb_font_draw_glyph (font, gid, funcs, &draw_data);
179   g_assert_cmpuint (draw_data.move_to_count, ==, 3);
180 
181   hb_font_get_nominal_glyph (font, 0xAC01u, &gid);
182   draw_data = draw_data0;
183   hb_font_draw_glyph (font, gid, funcs, &draw_data);
184   g_assert_cmpuint (draw_data.move_to_count, ==, 4);
185 
186   hb_font_destroy (font);
187 }
188 
189 static void
test_hb_draw_varc_simple_hanzi(void)190 test_hb_draw_varc_simple_hanzi (void)
191 {
192   hb_face_t *face = hb_test_open_font_file ("fonts/varc-6868.ttf");
193   hb_font_t *font = hb_font_create (face);
194   hb_face_destroy (face);
195 
196   draw_data_t draw_data0 = {0};
197   draw_data_t draw_data;;
198   unsigned gid = 0;
199 
200   hb_font_get_nominal_glyph (font, 0x6868u, &gid);
201   draw_data = draw_data0;
202   hb_font_draw_glyph (font, gid, funcs, &draw_data);
203   g_assert_cmpuint (draw_data.move_to_count, ==, 11);
204 
205   hb_variation_t var;
206   var.tag = HB_TAG ('w','g','h','t');
207   var.value = 800;
208   hb_font_set_variations (font, &var, 1);
209 
210   hb_font_get_nominal_glyph (font, 0x6868u, &gid);
211   draw_data = draw_data0;
212   hb_font_draw_glyph (font, gid, funcs, &draw_data);
213   g_assert_cmpuint (draw_data.move_to_count, ==, 11);
214 
215   hb_font_destroy (font);
216 }
217 
218 static void
test_hb_draw_varc_conditional(void)219 test_hb_draw_varc_conditional (void)
220 {
221   hb_face_t *face = hb_test_open_font_file ("fonts/varc-ac01-conditional.ttf");
222   hb_font_t *font = hb_font_create (face);
223   hb_face_destroy (face);
224 
225   draw_data_t draw_data0 = {0};
226   draw_data_t draw_data;;
227   unsigned gid = 0;
228 
229   hb_font_get_nominal_glyph (font, 0xAC01u, &gid);
230   draw_data = draw_data0;
231   hb_font_draw_glyph (font, gid, funcs, &draw_data);
232   g_assert_cmpuint (draw_data.move_to_count, ==, 2);
233 
234   hb_variation_t var;
235   var.tag = HB_TAG ('w','g','h','t');
236   var.value = 800;
237   hb_font_set_variations (font, &var, 1);
238 
239   hb_font_get_nominal_glyph (font, 0xAC01u, &gid);
240   draw_data = draw_data0;
241   hb_font_draw_glyph (font, gid, funcs, &draw_data);
242   g_assert_cmpuint (draw_data.move_to_count, ==, 4);
243 
244   hb_font_destroy (font);
245 }
246 #endif
247 
248 int
main(int argc,char ** argv)249 main (int argc, char **argv)
250 {
251   funcs = hb_draw_funcs_create ();
252   hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
253   hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
254   hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, NULL, NULL);
255   hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
256   hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
257   hb_draw_funcs_make_immutable (funcs);
258 
259   hb_test_init (&argc, &argv);
260   hb_test_add (test_itoa);
261 #ifdef HB_EXPERIMENTAL_API
262   hb_test_add (test_hb_draw_varc_simple_hangul);
263   hb_test_add (test_hb_draw_varc_simple_hanzi);
264   hb_test_add (test_hb_draw_varc_conditional);
265 #endif
266   unsigned result = hb_test_run ();
267 
268   hb_draw_funcs_destroy (funcs);
269   return result;
270 }
271