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

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

Remove a ton of duplicated code in libui/libgfxfont tests

  • Property mode set to 100644
File size: 13.7 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/bitmap.h>
30#include <gfx/context.h>
31#include <gfx/font.h>
32#include <gfx/glyph.h>
33#include <gfx/glyph_bmp.h>
34#include <gfx/typeface.h>
35#include <io/pixelmap.h>
36#include <pcut/pcut.h>
37#include <stdbool.h>
38#include <str.h>
39#include "../private/glyph.h"
40#include "../private/testgc.h"
41
42PCUT_INIT;
43
44PCUT_TEST_SUITE(glyph);
45
46/** Test creating and destroying glyph */
47PCUT_TEST(create_destroy)
48{
49 gfx_font_props_t fprops;
50 gfx_font_metrics_t fmetrics;
51 gfx_typeface_t *tface;
52 gfx_font_t *font;
53 gfx_glyph_metrics_t gmetrics;
54 gfx_glyph_t *glyph;
55 gfx_context_t *gc;
56 test_gc_t tgc;
57 errno_t rc;
58
59 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
60 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
61
62 rc = gfx_typeface_create(gc, &tface);
63 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
64
65 gfx_font_props_init(&fprops);
66 gfx_font_metrics_init(&fmetrics);
67 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
68 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
69
70 gfx_glyph_metrics_init(&gmetrics);
71 rc = gfx_glyph_create(font, &gmetrics, &glyph);
72 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
73
74 gfx_glyph_destroy(glyph);
75
76 gfx_font_close(font);
77 gfx_typeface_destroy(tface);
78 rc = gfx_context_delete(gc);
79 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
80}
81
82/** Test gfx_glyph_get_metrics() */
83PCUT_TEST(get_metrics)
84{
85 gfx_font_props_t fprops;
86 gfx_font_metrics_t fmetrics;
87 gfx_typeface_t *tface;
88 gfx_font_t *font;
89 gfx_glyph_metrics_t gmetrics;
90 gfx_glyph_t *glyph;
91 gfx_glyph_metrics_t rmetrics;
92 gfx_context_t *gc;
93 test_gc_t tgc;
94 errno_t rc;
95
96 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
97 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
98
99 rc = gfx_typeface_create(gc, &tface);
100 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
101
102 gfx_font_props_init(&fprops);
103 gfx_font_metrics_init(&fmetrics);
104 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106
107 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
108
109 gfx_glyph_metrics_init(&gmetrics);
110 gmetrics.advance = 42;
111
112 rc = gfx_glyph_create(font, &gmetrics, &glyph);
113 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
114
115 gfx_glyph_get_metrics(glyph, &rmetrics);
116 PCUT_ASSERT_INT_EQUALS(gmetrics.advance, rmetrics.advance);
117
118 gfx_glyph_destroy(glyph);
119
120 gfx_font_close(font);
121 gfx_typeface_destroy(tface);
122 rc = gfx_context_delete(gc);
123 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
124}
125
126/** Test gfx_glyph_set_metrics() */
127PCUT_TEST(set_metrics)
128{
129 gfx_font_props_t fprops;
130 gfx_font_metrics_t fmetrics;
131 gfx_typeface_t *tface;
132 gfx_font_t *font;
133 gfx_glyph_metrics_t gmetrics1;
134 gfx_glyph_metrics_t gmetrics2;
135 gfx_glyph_t *glyph;
136 gfx_glyph_metrics_t rmetrics;
137 gfx_context_t *gc;
138 test_gc_t tgc;
139 errno_t rc;
140
141 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
142 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
143
144 rc = gfx_typeface_create(gc, &tface);
145 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
146
147 gfx_font_props_init(&fprops);
148 gfx_font_metrics_init(&fmetrics);
149 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
150 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
151
152 gfx_glyph_metrics_init(&gmetrics1);
153 gmetrics1.advance = 1;
154
155 rc = gfx_glyph_create(font, &gmetrics1, &glyph);
156 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
157
158 gfx_glyph_metrics_init(&gmetrics2);
159 gmetrics2.advance = 2;
160
161 gfx_glyph_set_metrics(glyph, &gmetrics2);
162
163 gfx_glyph_get_metrics(glyph, &rmetrics);
164 PCUT_ASSERT_INT_EQUALS(gmetrics2.advance, rmetrics.advance);
165
166 gfx_glyph_destroy(glyph);
167
168 gfx_font_close(font);
169 gfx_typeface_destroy(tface);
170 rc = gfx_context_delete(gc);
171 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
172}
173
174/** Test gfx_glyph_set_pattern() */
175PCUT_TEST(set_pattern)
176{
177 gfx_font_props_t fprops;
178 gfx_font_metrics_t fmetrics;
179 gfx_typeface_t *tface;
180 gfx_font_t *font;
181 gfx_glyph_metrics_t gmetrics;
182 gfx_glyph_t *glyph;
183 gfx_context_t *gc;
184 test_gc_t tgc;
185 errno_t rc;
186
187 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
188 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
189
190 rc = gfx_typeface_create(gc, &tface);
191 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
192
193 gfx_font_props_init(&fprops);
194 gfx_font_metrics_init(&fmetrics);
195 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
196 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
197
198 gfx_glyph_metrics_init(&gmetrics);
199 gmetrics.advance = 1;
200
201 rc = gfx_glyph_create(font, &gmetrics, &glyph);
202 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
203
204 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
205
206 /* Set a pattern */
207 rc = gfx_glyph_set_pattern(glyph, "A");
208 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
209 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
210
211 /* Setting the same pattern again should be OK */
212 rc = gfx_glyph_set_pattern(glyph, "A");
213 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
214 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
215
216 gfx_glyph_destroy(glyph);
217
218 gfx_font_close(font);
219 gfx_typeface_destroy(tface);
220 rc = gfx_context_delete(gc);
221 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
222}
223
224/** Test gfx_glyph_clear_pattern() */
225PCUT_TEST(clear_pattern)
226{
227 gfx_font_props_t fprops;
228 gfx_font_metrics_t fmetrics;
229 gfx_typeface_t *tface;
230 gfx_font_t *font;
231 gfx_glyph_metrics_t gmetrics;
232 gfx_glyph_t *glyph;
233 gfx_context_t *gc;
234 test_gc_t tgc;
235 errno_t rc;
236
237 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
238 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
239
240 rc = gfx_typeface_create(gc, &tface);
241 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
242
243 gfx_font_props_init(&fprops);
244 gfx_font_metrics_init(&fmetrics);
245 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
246 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
247
248 gfx_glyph_metrics_init(&gmetrics);
249 gmetrics.advance = 1;
250
251 rc = gfx_glyph_create(font, &gmetrics, &glyph);
252 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
253
254 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
255
256 /* Set a pattern */
257 rc = gfx_glyph_set_pattern(glyph, "A");
258 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
259 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
260
261 /* Now clear a different pattern - should be OK */
262 gfx_glyph_clear_pattern(glyph, "AA");
263 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
264
265 /* Now clear the pattern which has been set */
266 gfx_glyph_clear_pattern(glyph, "A");
267 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
268
269 gfx_glyph_destroy(glyph);
270
271 gfx_font_close(font);
272 gfx_typeface_destroy(tface);
273 rc = gfx_context_delete(gc);
274 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
275}
276
277/** Test gfx_glyph_matches() */
278PCUT_TEST(matches)
279{
280 gfx_font_props_t fprops;
281 gfx_font_metrics_t fmetrics;
282 gfx_typeface_t *tface;
283 gfx_font_t *font;
284 gfx_glyph_metrics_t gmetrics;
285 gfx_glyph_t *glyph;
286 gfx_context_t *gc;
287 test_gc_t tgc;
288 bool match;
289 size_t msize;
290 errno_t rc;
291
292 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
293 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
294
295 rc = gfx_typeface_create(gc, &tface);
296 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
297
298 gfx_font_props_init(&fprops);
299 gfx_font_metrics_init(&fmetrics);
300 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
301 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
302
303 gfx_glyph_metrics_init(&gmetrics);
304 gmetrics.advance = 1;
305
306 rc = gfx_glyph_create(font, &gmetrics, &glyph);
307 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
308
309 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
310
311 /* Set a pattern */
312 rc = gfx_glyph_set_pattern(glyph, "AB");
313 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
314 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
315
316 match = gfx_glyph_matches(glyph, "A", &msize);
317 PCUT_ASSERT_FALSE(match);
318
319 match = gfx_glyph_matches(glyph, "AB", &msize);
320 PCUT_ASSERT_TRUE(match);
321 PCUT_ASSERT_INT_EQUALS(2, msize);
322
323 match = gfx_glyph_matches(glyph, "ABC", &msize);
324 PCUT_ASSERT_TRUE(match);
325 PCUT_ASSERT_INT_EQUALS(2, msize);
326
327 match = gfx_glyph_matches(glyph, "BAB", &msize);
328 PCUT_ASSERT_FALSE(match);
329
330 gfx_glyph_destroy(glyph);
331
332 gfx_font_close(font);
333 gfx_typeface_destroy(tface);
334 rc = gfx_context_delete(gc);
335 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
336}
337
338/** Test gfx_glyph_first_pattern(), gfx_glyph_next_pattern() */
339PCUT_TEST(first_next_pattern)
340{
341 gfx_font_props_t fprops;
342 gfx_font_metrics_t fmetrics;
343 gfx_typeface_t *tface;
344 gfx_font_t *font;
345 gfx_glyph_metrics_t gmetrics;
346 gfx_glyph_t *glyph;
347 gfx_context_t *gc;
348 test_gc_t tgc;
349 gfx_glyph_pattern_t *pat;
350 errno_t rc;
351
352 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
353 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
354
355 rc = gfx_typeface_create(gc, &tface);
356 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
357
358 gfx_font_props_init(&fprops);
359 gfx_font_metrics_init(&fmetrics);
360 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
361 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
362
363 gfx_glyph_metrics_init(&gmetrics);
364 gmetrics.advance = 1;
365
366 rc = gfx_glyph_create(font, &gmetrics, &glyph);
367 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
368
369 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
370
371 /* Set a pattern */
372 rc = gfx_glyph_set_pattern(glyph, "A");
373 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
374 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
375
376 pat = gfx_glyph_first_pattern(glyph);
377 PCUT_ASSERT_NOT_NULL(pat);
378
379 pat = gfx_glyph_next_pattern(pat);
380 PCUT_ASSERT_NULL(pat);
381
382 gfx_glyph_destroy(glyph);
383
384 gfx_font_close(font);
385 gfx_typeface_destroy(tface);
386 rc = gfx_context_delete(gc);
387 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
388}
389
390/** Test gfx_glyph_pattern_str() */
391PCUT_TEST(pattern_str)
392{
393 gfx_font_props_t fprops;
394 gfx_font_metrics_t fmetrics;
395 gfx_typeface_t *tface;
396 gfx_font_t *font;
397 gfx_glyph_metrics_t gmetrics;
398 gfx_glyph_t *glyph;
399 gfx_context_t *gc;
400 test_gc_t tgc;
401 gfx_glyph_pattern_t *pat;
402 const char *pstr;
403 errno_t rc;
404
405 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
406 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
407
408 rc = gfx_typeface_create(gc, &tface);
409 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
410
411 gfx_font_props_init(&fprops);
412 gfx_font_metrics_init(&fmetrics);
413 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
414 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
415
416 gfx_glyph_metrics_init(&gmetrics);
417 gmetrics.advance = 1;
418
419 rc = gfx_glyph_create(font, &gmetrics, &glyph);
420 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
421
422 PCUT_ASSERT_NULL(gfx_glyph_first_pattern(glyph));
423
424 /* Set a pattern */
425 rc = gfx_glyph_set_pattern(glyph, "A");
426 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
427 PCUT_ASSERT_NOT_NULL(gfx_glyph_first_pattern(glyph));
428
429 pat = gfx_glyph_first_pattern(glyph);
430 PCUT_ASSERT_NOT_NULL(pat);
431
432 pstr = gfx_glyph_pattern_str(pat);
433 PCUT_ASSERT_INT_EQUALS(0, str_cmp("A", pstr));
434
435 gfx_glyph_destroy(glyph);
436
437 gfx_font_close(font);
438 gfx_typeface_destroy(tface);
439 rc = gfx_context_delete(gc);
440 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
441}
442
443/** Test gfx_glyph_transfer() */
444PCUT_TEST(transfer)
445{
446 gfx_font_props_t fprops;
447 gfx_font_metrics_t fmetrics;
448 gfx_typeface_t *tface;
449 gfx_font_t *font;
450 gfx_glyph_metrics_t gmetrics;
451 gfx_glyph_t *glyph;
452 gfx_context_t *gc;
453 gfx_bitmap_t *bitmap;
454 gfx_bitmap_params_t params;
455 gfx_bitmap_alloc_t alloc;
456 gfx_glyph_bmp_t *bmp;
457 pixelmap_t pmap;
458 pixel_t pixel;
459 test_gc_t tgc;
460 errno_t rc;
461
462 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
463 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
464
465 rc = gfx_typeface_create(gc, &tface);
466 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
467
468 gfx_font_props_init(&fprops);
469 gfx_font_metrics_init(&fmetrics);
470 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
471 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
472
473 gfx_glyph_metrics_init(&gmetrics);
474 gmetrics.advance = 1;
475
476 rc = gfx_glyph_create(font, &gmetrics, &glyph);
477 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
478
479 /*
480 * We need to fill some pixels of the glyph.
481 * We'll use the glyph bitmap for that.
482 * That means this test won't pass unless glyph
483 * bitmap works.
484 */
485
486 rc = gfx_glyph_bmp_open(glyph, &bmp);
487 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
488 PCUT_ASSERT_NOT_NULL(bmp);
489
490 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
491 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
492
493 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
494 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
495
496 rc = gfx_glyph_bmp_save(bmp);
497 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
498 gfx_glyph_bmp_close(bmp);
499
500 /* Now create a new bitmap */
501
502 gfx_bitmap_params_init(&params);
503 params.rect.p0.x = 0;
504 params.rect.p0.y = 0;
505 params.rect.p1.x = 10;
506 params.rect.p1.y = 10;
507 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
508 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
509
510 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
511 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
512
513 /* Transfer the glyph to new bitmap */
514 rc = gfx_glyph_transfer(glyph, 0, bitmap, &params.rect);
515 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
516
517 /* Now let's read pixels from the new bitmap */
518 pmap.width = params.rect.p1.x;
519 pmap.height = params.rect.p1.y;
520 pmap.data = alloc.pixels;
521
522 pixel = pixelmap_get_pixel(&pmap, 0, 0);
523 PCUT_ASSERT_INT_EQUALS(PIXEL(255, 255, 255, 255), pixel);
524
525 pixel = pixelmap_get_pixel(&pmap, 1, 1);
526 PCUT_ASSERT_INT_EQUALS(PIXEL(255, 255, 255, 255), pixel);
527
528 pixel = pixelmap_get_pixel(&pmap, 1, 0);
529 PCUT_ASSERT_INT_EQUALS(PIXEL(0, 0, 0, 0), pixel);
530
531 pixel = pixelmap_get_pixel(&pmap, 0, 1);
532 PCUT_ASSERT_INT_EQUALS(PIXEL(0, 0, 0, 0), pixel);
533
534 gfx_glyph_destroy(glyph);
535
536 gfx_font_close(font);
537 gfx_typeface_destroy(tface);
538 rc = gfx_context_delete(gc);
539 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
540}
541
542PCUT_EXPORT(glyph);
Note: See TracBrowser for help on using the repository browser.