source: mainline/uspace/lib/gfxfont/test/font.c

Last change on this file was 1fa6292, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 5 months ago

Remove a ton of duplicated code in libui/libgfxfont tests

  • Property mode set to 100644
File size: 13.3 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <gfx/context.h>
30#include <gfx/font.h>
31#include <gfx/glyph.h>
32#include <gfx/typeface.h>
33#include <pcut/pcut.h>
34#include "../private/font.h"
35#include "../private/typeface.h"
36#include "../private/testgc.h"
37
38PCUT_INIT;
39
40PCUT_TEST_SUITE(font);
41
42/** Test creating and destroying font */
43PCUT_TEST(create_destroy)
44{
45 gfx_font_props_t props;
46 gfx_font_metrics_t metrics;
47 gfx_typeface_t *tface;
48 gfx_font_t *font;
49 gfx_context_t *gc;
50 test_gc_t tgc;
51 errno_t rc;
52
53 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
54 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
55
56 rc = gfx_typeface_create(gc, &tface);
57 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
58
59 gfx_font_props_init(&props);
60 gfx_font_metrics_init(&metrics);
61 rc = gfx_font_create(tface, &props, &metrics, &font);
62 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
63
64 gfx_font_close(font);
65 gfx_typeface_destroy(tface);
66
67 rc = gfx_context_delete(gc);
68 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
69}
70
71/** Test creating and destroying text-mode font */
72PCUT_TEST(create_textmode_destroy)
73{
74 gfx_typeface_t *tface;
75 gfx_font_t *font;
76 gfx_context_t *gc;
77 test_gc_t tgc;
78 errno_t rc;
79
80 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
81 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
82
83 rc = gfx_typeface_create(gc, &tface);
84 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
85
86 rc = gfx_font_create_textmode(tface, &font);
87 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
88
89 gfx_font_close(font);
90 gfx_typeface_destroy(tface);
91
92 rc = gfx_context_delete(gc);
93 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
94}
95
96/** Test gfx_font_get_metrics() */
97PCUT_TEST(get_metrics)
98{
99 gfx_font_props_t props;
100 gfx_font_metrics_t metrics;
101 gfx_font_metrics_t gmetrics;
102 gfx_typeface_t *tface;
103 gfx_font_t *font;
104 gfx_context_t *gc;
105 test_gc_t tgc;
106 errno_t rc;
107
108 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
109 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
110
111 gfx_font_metrics_init(&metrics);
112 metrics.ascent = 1;
113 metrics.descent = 2;
114 metrics.leading = 3;
115
116 rc = gfx_typeface_create(gc, &tface);
117 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
118
119 gfx_font_props_init(&props);
120 gfx_font_metrics_init(&metrics);
121 rc = gfx_font_create(tface, &props, &metrics, &font);
122 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
123
124 gfx_font_get_metrics(font, &gmetrics);
125 PCUT_ASSERT_INT_EQUALS(metrics.ascent, gmetrics.ascent);
126 PCUT_ASSERT_INT_EQUALS(metrics.descent, gmetrics.descent);
127 PCUT_ASSERT_INT_EQUALS(metrics.leading, gmetrics.leading);
128
129 gfx_font_close(font);
130 gfx_typeface_destroy(tface);
131 rc = gfx_context_delete(gc);
132 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
133}
134
135/** Test gfx_font_set_metrics() */
136PCUT_TEST(set_metrics)
137{
138 gfx_font_props_t props;
139 gfx_font_metrics_t metrics1;
140 gfx_font_metrics_t metrics2;
141 gfx_font_metrics_t gmetrics;
142 gfx_typeface_t *tface;
143 gfx_font_t *font;
144 gfx_context_t *gc;
145 test_gc_t tgc;
146 errno_t rc;
147
148 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
149 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
150
151 rc = gfx_typeface_create(gc, &tface);
152 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
153
154 gfx_font_props_init(&props);
155
156 gfx_font_metrics_init(&metrics1);
157 metrics1.ascent = 1;
158 metrics1.descent = 2;
159 metrics1.leading = 3;
160
161 rc = gfx_font_create(tface, &props, &metrics1, &font);
162 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
163
164 gfx_font_metrics_init(&metrics2);
165 metrics1.ascent = 4;
166 metrics1.descent = 5;
167 metrics1.leading = 6;
168
169 rc = gfx_font_set_metrics(font, &metrics2);
170 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
171
172 gfx_font_get_metrics(font, &gmetrics);
173 PCUT_ASSERT_INT_EQUALS(metrics2.ascent, gmetrics.ascent);
174 PCUT_ASSERT_INT_EQUALS(metrics2.descent, gmetrics.descent);
175 PCUT_ASSERT_INT_EQUALS(metrics2.leading, gmetrics.leading);
176
177 gfx_font_close(font);
178 gfx_typeface_destroy(tface);
179 rc = gfx_context_delete(gc);
180 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
181}
182
183/** Test gfx_font_first_glyph() */
184PCUT_TEST(first_glyph)
185{
186 gfx_font_props_t props;
187 gfx_font_metrics_t metrics;
188 gfx_glyph_metrics_t gmetrics;
189 gfx_typeface_t *tface;
190 gfx_font_t *font;
191 gfx_context_t *gc;
192 gfx_glyph_t *glyph;
193 gfx_glyph_t *gfirst;
194 test_gc_t tgc;
195 errno_t rc;
196
197 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
198 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
199
200 gfx_font_metrics_init(&metrics);
201
202 rc = gfx_typeface_create(gc, &tface);
203 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
204
205 gfx_font_props_init(&props);
206 gfx_font_metrics_init(&metrics);
207 rc = gfx_font_create(tface, &props, &metrics, &font);
208 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
209
210 /* Should get NULL since there is no glyph in the font */
211 glyph = gfx_font_first_glyph(font);
212 PCUT_ASSERT_NULL(glyph);
213
214 /* Now add one */
215 gfx_glyph_metrics_init(&gmetrics);
216 rc = gfx_glyph_create(font, &gmetrics, &glyph);
217 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
218
219 /* gfx_font_first_glyph() should return the same */
220 gfirst = gfx_font_first_glyph(font);
221 PCUT_ASSERT_EQUALS(glyph, gfirst);
222
223 gfx_glyph_destroy(glyph);
224 gfx_font_close(font);
225 gfx_typeface_destroy(tface);
226 rc = gfx_context_delete(gc);
227 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
228}
229
230/** Test gfx_font_next_glyph() */
231PCUT_TEST(next_glyph)
232{
233 gfx_font_props_t props;
234 gfx_font_metrics_t metrics;
235 gfx_glyph_metrics_t gmetrics;
236 gfx_typeface_t *tface;
237 gfx_font_t *font;
238 gfx_context_t *gc;
239 gfx_glyph_t *glyph1;
240 gfx_glyph_t *glyph2;
241 gfx_glyph_t *gfirst;
242 gfx_glyph_t *gsecond;
243 test_gc_t tgc;
244 errno_t rc;
245
246 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
247 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
248
249 gfx_font_metrics_init(&metrics);
250
251 rc = gfx_typeface_create(gc, &tface);
252 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
253
254 gfx_font_props_init(&props);
255 gfx_font_metrics_init(&metrics);
256 rc = gfx_font_create(tface, &props, &metrics, &font);
257 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
258
259 /* Add first glyph */
260 gfx_glyph_metrics_init(&gmetrics);
261 rc = gfx_glyph_create(font, &gmetrics, &glyph1);
262 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
263
264 /* Add second glyph */
265 gfx_glyph_metrics_init(&gmetrics);
266 rc = gfx_glyph_create(font, &gmetrics, &glyph2);
267 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
268
269 /* gfx_font_first_glyph() should return glyph1 */
270 gfirst = gfx_font_first_glyph(font);
271 PCUT_ASSERT_EQUALS(glyph1, gfirst);
272
273 /* gfx_font_next_glyph() should return glyph2 */
274 gsecond = gfx_font_next_glyph(gfirst);
275 PCUT_ASSERT_EQUALS(glyph2, gsecond);
276
277 gfx_glyph_destroy(glyph1);
278 gfx_glyph_destroy(glyph2);
279 gfx_font_close(font);
280 gfx_typeface_destroy(tface);
281 rc = gfx_context_delete(gc);
282 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
283}
284
285/** Test gfx_font_last_glyph() */
286PCUT_TEST(last_glyph)
287{
288 gfx_font_props_t props;
289 gfx_font_metrics_t metrics;
290 gfx_glyph_metrics_t gmetrics;
291 gfx_typeface_t *tface;
292 gfx_font_t *font;
293 gfx_context_t *gc;
294 gfx_glyph_t *glyph;
295 gfx_glyph_t *glast;
296 test_gc_t tgc;
297 errno_t rc;
298
299 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301
302 gfx_font_metrics_init(&metrics);
303
304 rc = gfx_typeface_create(gc, &tface);
305 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
306
307 gfx_font_props_init(&props);
308 gfx_font_metrics_init(&metrics);
309 rc = gfx_font_create(tface, &props, &metrics, &font);
310 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
311
312 /* Should get NULL since there is no glyph in the font */
313 glyph = gfx_font_last_glyph(font);
314 PCUT_ASSERT_NULL(glyph);
315
316 /* Now add one */
317 gfx_glyph_metrics_init(&gmetrics);
318 rc = gfx_glyph_create(font, &gmetrics, &glyph);
319 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
320
321 /* gfx_font_last_glyph() should return the same */
322 glast = gfx_font_last_glyph(font);
323 PCUT_ASSERT_EQUALS(glyph, glast);
324
325 gfx_glyph_destroy(glyph);
326 gfx_font_close(font);
327 gfx_typeface_destroy(tface);
328 rc = gfx_context_delete(gc);
329 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
330}
331
332/** Test gfx_font_prev_glyph() */
333PCUT_TEST(prev_glyph)
334{
335 gfx_font_props_t props;
336 gfx_font_metrics_t metrics;
337 gfx_glyph_metrics_t gmetrics;
338 gfx_typeface_t *tface;
339 gfx_font_t *font;
340 gfx_context_t *gc;
341 gfx_glyph_t *glyph1;
342 gfx_glyph_t *glyph2;
343 gfx_glyph_t *gfirst;
344 gfx_glyph_t *gsecond;
345 test_gc_t tgc;
346 errno_t rc;
347
348 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
349 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
350
351 gfx_font_metrics_init(&metrics);
352
353 rc = gfx_typeface_create(gc, &tface);
354 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
355
356 gfx_font_props_init(&props);
357 gfx_font_metrics_init(&metrics);
358 rc = gfx_font_create(tface, &props, &metrics, &font);
359 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
360
361 /* Add first glyph */
362 gfx_glyph_metrics_init(&gmetrics);
363 rc = gfx_glyph_create(font, &gmetrics, &glyph1);
364 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
365
366 /* Add second glyph */
367 gfx_glyph_metrics_init(&gmetrics);
368 rc = gfx_glyph_create(font, &gmetrics, &glyph2);
369 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
370
371 /* gfx_font_last_glyph() should return glyph2 */
372 gsecond = gfx_font_last_glyph(font);
373 PCUT_ASSERT_EQUALS(glyph2, gsecond);
374
375 /* gfx_font_prev_glyph() should return glyph1 */
376 gfirst = gfx_font_prev_glyph(gsecond);
377 PCUT_ASSERT_EQUALS(glyph1, gfirst);
378
379 gfx_glyph_destroy(glyph1);
380 gfx_glyph_destroy(glyph2);
381 gfx_font_close(font);
382 gfx_typeface_destroy(tface);
383 rc = gfx_context_delete(gc);
384 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
385}
386
387/** Test gfx_font_search_glyph() */
388PCUT_TEST(search_glyph)
389{
390 gfx_font_props_t props;
391 gfx_font_metrics_t metrics;
392 gfx_typeface_t *tface;
393 gfx_font_t *font;
394 gfx_context_t *gc;
395 gfx_glyph_t *glyph;
396 size_t bytes;
397 test_gc_t tgc;
398 errno_t rc;
399
400 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
401 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
402
403 gfx_font_metrics_init(&metrics);
404
405 rc = gfx_typeface_create(gc, &tface);
406 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
407
408 gfx_font_props_init(&props);
409 gfx_font_metrics_init(&metrics);
410 rc = gfx_font_create(tface, &props, &metrics, &font);
411 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
412
413 rc = gfx_font_search_glyph(font, "Hello", &glyph, &bytes);
414 PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
415
416 gfx_font_close(font);
417 gfx_typeface_destroy(tface);
418 rc = gfx_context_delete(gc);
419 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
420}
421
422/** Test gfx_font_splice_at_glyph() */
423PCUT_TEST(splice_at_glyph)
424{
425 gfx_font_props_t props;
426 gfx_font_metrics_t fmetrics;
427 gfx_typeface_t *tface;
428 gfx_font_t *font;
429 gfx_glyph_metrics_t gmetrics;
430 gfx_glyph_t *glyph;
431 gfx_context_t *gc;
432 gfx_rect_t nrect;
433 test_gc_t tgc;
434 errno_t rc;
435
436 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
437 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
438
439 rc = gfx_typeface_create(gc, &tface);
440 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
441
442 gfx_font_props_init(&props);
443 gfx_font_metrics_init(&fmetrics);
444 rc = gfx_font_create(tface, &props, &fmetrics, &font);
445 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
446
447 gfx_glyph_metrics_init(&gmetrics);
448 rc = gfx_glyph_create(font, &gmetrics, &glyph);
449 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
450
451 nrect.p0.x = -5;
452 nrect.p0.y = -5;
453 nrect.p1.x = 5;
454 nrect.p1.y = 5;
455 rc = gfx_font_splice_at_glyph(font, glyph, &nrect);
456 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
457
458 gfx_glyph_destroy(glyph);
459
460 gfx_font_close(font);
461 gfx_typeface_destroy(tface);
462 rc = gfx_context_delete(gc);
463 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
464}
465
466/** Test gfx_font_bitmap_pack() properly packs bitmap */
467PCUT_TEST(bitmap_pack)
468{
469 errno_t rc;
470 gfx_coord_t width, height;
471 gfx_coord_t i;
472 uint32_t *pixels;
473 void *data;
474 size_t size;
475 uint8_t *dp;
476
477 width = 10;
478 height = 10;
479
480 pixels = calloc(width * height, sizeof(uint32_t));
481 PCUT_ASSERT_NOT_NULL(pixels);
482
483 for (i = 0; i < 10; i++)
484 pixels[i * width + i] = PIXEL(255, 255, 255, 255);
485
486 rc = gfx_font_bitmap_pack(width, height, pixels, &data, &size);
487 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
488 PCUT_ASSERT_NOT_NULL(data);
489 PCUT_ASSERT_INT_EQUALS(20, size);
490
491 dp = data;
492
493 for (i = 0; i < 8; i++) {
494 PCUT_ASSERT_INT_EQUALS(0x80 >> i, dp[2 * i]);
495 PCUT_ASSERT_INT_EQUALS(0, dp[2 * i + 1]);
496 }
497
498 for (i = 8; i < 10; i++) {
499 PCUT_ASSERT_INT_EQUALS(0, dp[2 * i]);
500 PCUT_ASSERT_INT_EQUALS(0x80 >> (i - 8), dp[2 * i + 1]);
501 }
502}
503
504/** Test gfx_font_bitmap_unpack() properly unpacks bitmap */
505PCUT_TEST(bitmap_unpack)
506{
507 errno_t rc;
508 gfx_coord_t width, height;
509 gfx_coord_t i, j;
510 uint32_t epix;
511 uint32_t *pixels;
512 uint8_t data[20];
513
514 width = 10;
515 height = 10;
516
517 for (i = 0; i < 8; i++) {
518 data[2 * i] = 0x80 >> i;
519 data[2 * i + 1] = 0;
520 }
521
522 for (i = 8; i < 10; i++) {
523 data[2 * i] = 0;
524 data[2 * i + 1] = 0x80 >> (i - 8);
525 }
526
527 pixels = calloc(width * height, sizeof(uint32_t));
528 PCUT_ASSERT_NOT_NULL(pixels);
529
530 rc = gfx_font_bitmap_unpack(width, height, data, sizeof(data),
531 pixels);
532 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
533
534 for (j = 0; j < 10; j++) {
535 for (i = 0; i < 10; i++) {
536 epix = (i == j) ? PIXEL(255, 255, 255, 255) :
537 PIXEL(0, 0, 0, 0);
538 PCUT_ASSERT_INT_EQUALS(epix, pixels[j * width + i]);
539 }
540 }
541}
542
543PCUT_EXPORT(font);
Note: See TracBrowser for help on using the repository browser.