source: mainline/uspace/lib/gfxfont/test/glyph_bmp.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.2 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/glyph_bmp.h>
33#include <gfx/typeface.h>
34#include <pcut/pcut.h>
35#include "../private/glyph_bmp.h"
36#include "../private/testgc.h"
37
38PCUT_INIT;
39
40PCUT_TEST_SUITE(glyph_bmp);
41
42/** Test opening and closing glyph bitmap */
43PCUT_TEST(open_close)
44{
45 gfx_font_props_t fprops;
46 gfx_font_metrics_t fmetrics;
47 gfx_typeface_t *tface;
48 gfx_font_t *font;
49 gfx_glyph_metrics_t gmetrics;
50 gfx_glyph_t *glyph;
51 gfx_context_t *gc;
52 gfx_glyph_bmp_t *bmp;
53 test_gc_t tgc;
54 errno_t rc;
55
56 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
57 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
58
59 rc = gfx_typeface_create(gc, &tface);
60 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
61
62 gfx_font_props_init(&fprops);
63 gfx_font_metrics_init(&fmetrics);
64 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
65 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
66
67 gfx_glyph_metrics_init(&gmetrics);
68 gmetrics.advance = 1;
69
70 rc = gfx_glyph_create(font, &gmetrics, &glyph);
71 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
72
73 bmp = NULL;
74
75 rc = gfx_glyph_bmp_open(glyph, &bmp);
76 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
77 PCUT_ASSERT_NOT_NULL(bmp);
78
79 gfx_glyph_bmp_close(bmp);
80
81 gfx_glyph_destroy(glyph);
82
83 gfx_font_close(font);
84 gfx_typeface_destroy(tface);
85 rc = gfx_context_delete(gc);
86 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
87}
88
89/** Test glyph_bmp_save() */
90PCUT_TEST(save)
91{
92 gfx_font_props_t fprops;
93 gfx_font_metrics_t fmetrics;
94 gfx_typeface_t *tface;
95 gfx_font_t *font;
96 gfx_glyph_metrics_t gmetrics;
97 gfx_glyph_t *glyph;
98 gfx_context_t *gc;
99 gfx_glyph_bmp_t *bmp;
100 int pix;
101 test_gc_t tgc;
102 errno_t rc;
103
104 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106
107 rc = gfx_typeface_create(gc, &tface);
108 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
109
110 gfx_font_props_init(&fprops);
111 gfx_font_metrics_init(&fmetrics);
112 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
113 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
114
115 gfx_glyph_metrics_init(&gmetrics);
116 gmetrics.advance = 1;
117
118 rc = gfx_glyph_create(font, &gmetrics, &glyph);
119 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
120
121 bmp = NULL;
122
123 /* Open bitmap and set some pixels */
124
125 rc = gfx_glyph_bmp_open(glyph, &bmp);
126 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
127 PCUT_ASSERT_NOT_NULL(bmp);
128
129 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
130 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
131
132 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
133 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
134
135 rc = gfx_glyph_bmp_save(bmp);
136 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
137
138 gfx_glyph_bmp_close(bmp);
139 bmp = NULL;
140
141 /* Re-open the saved bimap and verify pixel values were preserved */
142
143 rc = gfx_glyph_bmp_open(glyph, &bmp);
144 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
145 PCUT_ASSERT_NOT_NULL(bmp);
146
147 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
148 PCUT_ASSERT_INT_EQUALS(1, pix);
149
150 pix = gfx_glyph_bmp_getpix(bmp, 1, 1);
151 PCUT_ASSERT_INT_EQUALS(1, pix);
152
153 pix = gfx_glyph_bmp_getpix(bmp, 1, 0);
154 PCUT_ASSERT_INT_EQUALS(0, pix);
155
156 pix = gfx_glyph_bmp_getpix(bmp, 0, 1);
157 PCUT_ASSERT_INT_EQUALS(0, pix);
158
159 /* ... */
160
161 rc = gfx_glyph_bmp_setpix(bmp, 1, -1, 1);
162 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
163
164 rc = gfx_glyph_bmp_save(bmp);
165 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
166
167 gfx_glyph_bmp_close(bmp);
168
169 /* Once again */
170
171 rc = gfx_glyph_bmp_open(glyph, &bmp);
172 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
173 PCUT_ASSERT_NOT_NULL(bmp);
174
175 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
176 PCUT_ASSERT_INT_EQUALS(1, pix);
177
178 pix = gfx_glyph_bmp_getpix(bmp, 1, 1);
179 PCUT_ASSERT_INT_EQUALS(1, pix);
180
181 pix = gfx_glyph_bmp_getpix(bmp, 1, 0);
182 PCUT_ASSERT_INT_EQUALS(0, pix);
183
184 pix = gfx_glyph_bmp_getpix(bmp, 0, 1);
185 PCUT_ASSERT_INT_EQUALS(0, pix);
186
187 pix = gfx_glyph_bmp_getpix(bmp, 1, -1);
188 PCUT_ASSERT_INT_EQUALS(1, pix);
189
190 pix = gfx_glyph_bmp_getpix(bmp, 0, -1);
191 PCUT_ASSERT_INT_EQUALS(0, pix);
192
193 gfx_glyph_destroy(glyph);
194
195 gfx_font_close(font);
196 gfx_typeface_destroy(tface);
197 rc = gfx_context_delete(gc);
198 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
199}
200
201/** Test glyph_bmp_getpix() */
202PCUT_TEST(getpix)
203{
204 gfx_font_props_t fprops;
205 gfx_font_metrics_t fmetrics;
206 gfx_typeface_t *tface;
207 gfx_font_t *font;
208 gfx_glyph_metrics_t gmetrics;
209 gfx_glyph_t *glyph;
210 gfx_context_t *gc;
211 gfx_glyph_bmp_t *bmp;
212 test_gc_t tgc;
213 int pix;
214 errno_t rc;
215
216 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
217 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
218
219 rc = gfx_typeface_create(gc, &tface);
220 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
221
222 gfx_font_props_init(&fprops);
223 gfx_font_metrics_init(&fmetrics);
224 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
225 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
226
227 gfx_glyph_metrics_init(&gmetrics);
228 gmetrics.advance = 1;
229
230 rc = gfx_glyph_create(font, &gmetrics, &glyph);
231 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
232
233 bmp = NULL;
234
235 rc = gfx_glyph_bmp_open(glyph, &bmp);
236 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
237 PCUT_ASSERT_NOT_NULL(bmp);
238
239 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
240 PCUT_ASSERT_INT_EQUALS(0, pix);
241
242 gfx_glyph_bmp_close(bmp);
243
244 gfx_glyph_destroy(glyph);
245
246 gfx_font_close(font);
247 gfx_typeface_destroy(tface);
248 rc = gfx_context_delete(gc);
249 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
250}
251
252/** Test glyph_bmp_setpix() can flip pixel value both ways */
253PCUT_TEST(setpix_flip)
254{
255 gfx_font_props_t fprops;
256 gfx_font_metrics_t fmetrics;
257 gfx_typeface_t *tface;
258 gfx_font_t *font;
259 gfx_glyph_metrics_t gmetrics;
260 gfx_glyph_t *glyph;
261 gfx_context_t *gc;
262 gfx_glyph_bmp_t *bmp;
263 test_gc_t tgc;
264 int pix;
265 errno_t rc;
266
267 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
268 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
269
270 rc = gfx_typeface_create(gc, &tface);
271 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
272
273 gfx_font_props_init(&fprops);
274 gfx_font_metrics_init(&fmetrics);
275 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
276 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
277
278 gfx_glyph_metrics_init(&gmetrics);
279 gmetrics.advance = 1;
280
281 rc = gfx_glyph_create(font, &gmetrics, &glyph);
282 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
283
284 bmp = NULL;
285
286 rc = gfx_glyph_bmp_open(glyph, &bmp);
287 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
288 PCUT_ASSERT_NOT_NULL(bmp);
289
290 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
291 PCUT_ASSERT_INT_EQUALS(0, pix);
292
293 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
294 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
295
296 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
297 PCUT_ASSERT_INT_EQUALS(1, pix);
298
299 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 0);
300 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
301
302 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
303 PCUT_ASSERT_INT_EQUALS(0, pix);
304
305 gfx_glyph_bmp_close(bmp);
306
307 gfx_glyph_destroy(glyph);
308
309 gfx_font_close(font);
310 gfx_typeface_destroy(tface);
311 rc = gfx_context_delete(gc);
312 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
313}
314
315/** Test glyph_bmp_setpix() properly extends pixel array */
316PCUT_TEST(setpix_extend)
317{
318 gfx_font_props_t fprops;
319 gfx_font_metrics_t fmetrics;
320 gfx_typeface_t *tface;
321 gfx_font_t *font;
322 gfx_glyph_metrics_t gmetrics;
323 gfx_glyph_t *glyph;
324 gfx_context_t *gc;
325 gfx_glyph_bmp_t *bmp;
326 gfx_coord_t x, y;
327 test_gc_t tgc;
328 int pix;
329 errno_t rc;
330
331 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
332 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
333
334 rc = gfx_typeface_create(gc, &tface);
335 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
336
337 gfx_font_props_init(&fprops);
338 gfx_font_metrics_init(&fmetrics);
339 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
340 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
341
342 gfx_glyph_metrics_init(&gmetrics);
343 gmetrics.advance = 1;
344
345 rc = gfx_glyph_create(font, &gmetrics, &glyph);
346 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
347
348 bmp = NULL;
349
350 rc = gfx_glyph_bmp_open(glyph, &bmp);
351 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
352 PCUT_ASSERT_NOT_NULL(bmp);
353
354 /*
355 * Fill the rectangle [0, 0]..[3, 3] with alternating pixel pattern
356 * and then check it.
357 */
358
359 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361
362 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
363 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
364
365 rc = gfx_glyph_bmp_setpix(bmp, 2, 0, 1);
366 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
367
368 rc = gfx_glyph_bmp_setpix(bmp, 0, 2, 1);
369 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
370
371 rc = gfx_glyph_bmp_setpix(bmp, 2, 2, 1);
372 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
373
374 for (y = 0; y <= 2; y++) {
375 for (x = 0; x <= 2; x++) {
376 pix = gfx_glyph_bmp_getpix(bmp, x, y);
377 PCUT_ASSERT_INT_EQUALS((x & 1) ^ (y & 1) ^ 1, pix);
378 }
379 }
380
381 gfx_glyph_bmp_close(bmp);
382
383 gfx_glyph_destroy(glyph);
384
385 gfx_font_close(font);
386 gfx_typeface_destroy(tface);
387 rc = gfx_context_delete(gc);
388 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
389}
390
391/** Test glyph_bmp_clear() properly clears bitmap */
392PCUT_TEST(clear)
393{
394 gfx_font_props_t fprops;
395 gfx_font_metrics_t fmetrics;
396 gfx_typeface_t *tface;
397 gfx_font_t *font;
398 gfx_glyph_metrics_t gmetrics;
399 gfx_glyph_t *glyph;
400 gfx_context_t *gc;
401 gfx_glyph_bmp_t *bmp;
402 gfx_rect_t rect;
403 test_gc_t tgc;
404 int pix;
405 errno_t rc;
406
407 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
408 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
409
410 rc = gfx_typeface_create(gc, &tface);
411 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
412
413 gfx_font_props_init(&fprops);
414 gfx_font_metrics_init(&fmetrics);
415 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
416 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
417
418 gfx_glyph_metrics_init(&gmetrics);
419 gmetrics.advance = 1;
420
421 rc = gfx_glyph_create(font, &gmetrics, &glyph);
422 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
423
424 bmp = NULL;
425
426 rc = gfx_glyph_bmp_open(glyph, &bmp);
427 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
428 PCUT_ASSERT_NOT_NULL(bmp);
429
430 /* Set some pixels */
431
432 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
433 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
434
435 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
436 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
437
438 /* Clear the bitmap and check */
439 gfx_glyph_bmp_clear(bmp);
440
441 gfx_glyph_bmp_get_rect(bmp, &rect);
442 PCUT_ASSERT_INT_EQUALS(0, rect.p0.x);
443 PCUT_ASSERT_INT_EQUALS(0, rect.p0.y);
444 PCUT_ASSERT_INT_EQUALS(0, rect.p1.x);
445 PCUT_ASSERT_INT_EQUALS(0, rect.p1.y);
446
447 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
448 PCUT_ASSERT_INT_EQUALS(0, pix);
449 pix = gfx_glyph_bmp_getpix(bmp, 1, 1);
450 PCUT_ASSERT_INT_EQUALS(0, pix);
451
452 gfx_glyph_bmp_close(bmp);
453
454 gfx_glyph_destroy(glyph);
455
456 gfx_font_close(font);
457 gfx_typeface_destroy(tface);
458 rc = gfx_context_delete(gc);
459 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
460}
461
462/** Test glyph_bmp_find_used_rect() find minimum used rectangle */
463PCUT_TEST(find_used_rect)
464{
465 gfx_font_props_t fprops;
466 gfx_font_metrics_t fmetrics;
467 gfx_typeface_t *tface;
468 gfx_font_t *font;
469 gfx_glyph_metrics_t gmetrics;
470 gfx_glyph_t *glyph;
471 gfx_context_t *gc;
472 gfx_glyph_bmp_t *bmp;
473 gfx_rect_t rect;
474 test_gc_t tgc;
475 errno_t rc;
476
477 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
478 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
479
480 rc = gfx_typeface_create(gc, &tface);
481 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
482
483 gfx_font_props_init(&fprops);
484 gfx_font_metrics_init(&fmetrics);
485 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
486 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
487
488 gfx_glyph_metrics_init(&gmetrics);
489 gmetrics.advance = 1;
490
491 rc = gfx_glyph_create(font, &gmetrics, &glyph);
492 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
493
494 bmp = NULL;
495
496 rc = gfx_glyph_bmp_open(glyph, &bmp);
497 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
498 PCUT_ASSERT_NOT_NULL(bmp);
499
500 /* Check used rectangle */
501
502 gfx_glyph_bmp_find_used_rect(bmp, &rect);
503 PCUT_ASSERT_INT_EQUALS(0, rect.p0.x);
504 PCUT_ASSERT_INT_EQUALS(0, rect.p0.y);
505 PCUT_ASSERT_INT_EQUALS(0, rect.p1.x);
506 PCUT_ASSERT_INT_EQUALS(0, rect.p1.y);
507
508 /* Set some pixels */
509
510 rc = gfx_glyph_bmp_setpix(bmp, -4, -5, 1);
511 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
512
513 rc = gfx_glyph_bmp_setpix(bmp, -2, -1, 1);
514 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
515
516 rc = gfx_glyph_bmp_setpix(bmp, 3, 4, 1);
517 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
518
519 rc = gfx_glyph_bmp_setpix(bmp, 7, 6, 1);
520 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
521
522 /* Check used rectangle */
523
524 gfx_glyph_bmp_find_used_rect(bmp, &rect);
525 PCUT_ASSERT_INT_EQUALS(-4, rect.p0.x);
526 PCUT_ASSERT_INT_EQUALS(-5, rect.p0.y);
527 PCUT_ASSERT_INT_EQUALS(8, rect.p1.x);
528 PCUT_ASSERT_INT_EQUALS(7, rect.p1.y);
529
530 /* Clear the corner pixels */
531
532 rc = gfx_glyph_bmp_setpix(bmp, -4, -5, 0);
533 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
534
535 rc = gfx_glyph_bmp_setpix(bmp, 7, 6, 0);
536 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
537
538 /* Check used rectangle got smaller */
539
540 gfx_glyph_bmp_find_used_rect(bmp, &rect);
541 PCUT_ASSERT_INT_EQUALS(-2, rect.p0.x);
542 PCUT_ASSERT_INT_EQUALS(-1, rect.p0.y);
543 PCUT_ASSERT_INT_EQUALS(4, rect.p1.x);
544 PCUT_ASSERT_INT_EQUALS(5, rect.p1.y);
545
546 gfx_glyph_bmp_close(bmp);
547
548 gfx_glyph_destroy(glyph);
549
550 gfx_font_close(font);
551 gfx_typeface_destroy(tface);
552 rc = gfx_context_delete(gc);
553 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
554}
555
556PCUT_EXPORT(glyph_bmp);
Note: See TracBrowser for help on using the repository browser.