source: mainline/uspace/lib/gfxfont/test/glyph_bmp.c@ 0ee3157

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0ee3157 was 313ac8e, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Make negative quadrants actually work

  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*
2 * Copyright (c) 2020 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
36PCUT_INIT;
37
38PCUT_TEST_SUITE(glyph_bmp);
39
40static errno_t testgc_set_color(void *, gfx_color_t *);
41static errno_t testgc_fill_rect(void *, gfx_rect_t *);
42static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
43 gfx_bitmap_alloc_t *, void **);
44static errno_t testgc_bitmap_destroy(void *);
45static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
46static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
47
48static gfx_context_ops_t test_ops = {
49 .set_color = testgc_set_color,
50 .fill_rect = testgc_fill_rect,
51 .bitmap_create = testgc_bitmap_create,
52 .bitmap_destroy = testgc_bitmap_destroy,
53 .bitmap_render = testgc_bitmap_render,
54 .bitmap_get_alloc = testgc_bitmap_get_alloc
55};
56
57typedef struct {
58 gfx_bitmap_params_t bm_params;
59 void *bm_pixels;
60 gfx_rect_t bm_srect;
61 gfx_coord2_t bm_offs;
62} test_gc_t;
63
64typedef struct {
65 test_gc_t *tgc;
66 gfx_bitmap_alloc_t alloc;
67 bool myalloc;
68} testgc_bitmap_t;
69
70/** Test opening and closing glyph bitmap */
71PCUT_TEST(open_close)
72{
73 gfx_font_props_t fprops;
74 gfx_font_metrics_t fmetrics;
75 gfx_typeface_t *tface;
76 gfx_font_t *font;
77 gfx_glyph_metrics_t gmetrics;
78 gfx_glyph_t *glyph;
79 gfx_context_t *gc;
80 gfx_glyph_bmp_t *bmp;
81 test_gc_t tgc;
82 errno_t rc;
83
84 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
85 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
86
87 rc = gfx_typeface_create(gc, &tface);
88 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
89
90 gfx_font_props_init(&fprops);
91 gfx_font_metrics_init(&fmetrics);
92 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
93 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
94
95 gfx_glyph_metrics_init(&gmetrics);
96 gmetrics.advance = 1;
97
98 rc = gfx_glyph_create(font, &gmetrics, &glyph);
99 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
100
101 bmp = NULL;
102
103 rc = gfx_glyph_bmp_open(glyph, &bmp);
104 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
105 PCUT_ASSERT_NOT_NULL(bmp);
106
107 gfx_glyph_bmp_close(bmp);
108
109 gfx_glyph_destroy(glyph);
110
111 gfx_font_close(font);
112 gfx_typeface_destroy(tface);
113 rc = gfx_context_delete(gc);
114 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
115}
116
117/** Test glyph_bmp_save() */
118PCUT_TEST(save)
119{
120 gfx_font_props_t fprops;
121 gfx_font_metrics_t fmetrics;
122 gfx_typeface_t *tface;
123 gfx_font_t *font;
124 gfx_glyph_metrics_t gmetrics;
125 gfx_glyph_t *glyph;
126 gfx_context_t *gc;
127 gfx_glyph_bmp_t *bmp;
128 int pix;
129 test_gc_t tgc;
130 errno_t rc;
131
132 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
133 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
134
135 rc = gfx_typeface_create(gc, &tface);
136 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
137
138 gfx_font_props_init(&fprops);
139 gfx_font_metrics_init(&fmetrics);
140 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
141 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
142
143 gfx_glyph_metrics_init(&gmetrics);
144 gmetrics.advance = 1;
145
146 rc = gfx_glyph_create(font, &gmetrics, &glyph);
147 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
148
149 bmp = NULL;
150
151 /* Open bitmap and set some pixels */
152
153 rc = gfx_glyph_bmp_open(glyph, &bmp);
154 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
155 PCUT_ASSERT_NOT_NULL(bmp);
156
157 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
158 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
159
160 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
161 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
162
163 rc = gfx_glyph_bmp_save(bmp);
164 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
165
166 gfx_glyph_bmp_close(bmp);
167 bmp = NULL;
168
169 /* Re-open the saved bimap and verify pixel values were preserved */
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 /* ... */
188
189 rc = gfx_glyph_bmp_setpix(bmp, 1, -1, 1);
190 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
191
192 rc = gfx_glyph_bmp_save(bmp);
193 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
194
195 gfx_glyph_bmp_close(bmp);
196
197 /* Once again */
198
199 rc = gfx_glyph_bmp_open(glyph, &bmp);
200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
201 PCUT_ASSERT_NOT_NULL(bmp);
202
203 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
204 PCUT_ASSERT_INT_EQUALS(1, pix);
205
206 pix = gfx_glyph_bmp_getpix(bmp, 1, 1);
207 PCUT_ASSERT_INT_EQUALS(1, pix);
208
209 pix = gfx_glyph_bmp_getpix(bmp, 1, 0);
210 PCUT_ASSERT_INT_EQUALS(0, pix);
211
212 pix = gfx_glyph_bmp_getpix(bmp, 0, 1);
213 PCUT_ASSERT_INT_EQUALS(0, pix);
214
215 pix = gfx_glyph_bmp_getpix(bmp, 1, -1);
216 PCUT_ASSERT_INT_EQUALS(1, pix);
217
218 pix = gfx_glyph_bmp_getpix(bmp, 0, -1);
219 PCUT_ASSERT_INT_EQUALS(0, pix);
220
221 gfx_glyph_destroy(glyph);
222
223 gfx_font_close(font);
224 gfx_typeface_destroy(tface);
225 rc = gfx_context_delete(gc);
226 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
227}
228
229/** Test glyph_bmp_getpix() */
230PCUT_TEST(getpix)
231{
232 gfx_font_props_t fprops;
233 gfx_font_metrics_t fmetrics;
234 gfx_typeface_t *tface;
235 gfx_font_t *font;
236 gfx_glyph_metrics_t gmetrics;
237 gfx_glyph_t *glyph;
238 gfx_context_t *gc;
239 gfx_glyph_bmp_t *bmp;
240 test_gc_t tgc;
241 int pix;
242 errno_t rc;
243
244 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
245 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
246
247 rc = gfx_typeface_create(gc, &tface);
248 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
249
250 gfx_font_props_init(&fprops);
251 gfx_font_metrics_init(&fmetrics);
252 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
253 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
254
255 gfx_glyph_metrics_init(&gmetrics);
256 gmetrics.advance = 1;
257
258 rc = gfx_glyph_create(font, &gmetrics, &glyph);
259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
260
261 bmp = NULL;
262
263 rc = gfx_glyph_bmp_open(glyph, &bmp);
264 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
265 PCUT_ASSERT_NOT_NULL(bmp);
266
267 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
268 PCUT_ASSERT_INT_EQUALS(0, pix);
269
270 gfx_glyph_bmp_close(bmp);
271
272 gfx_glyph_destroy(glyph);
273
274 gfx_font_close(font);
275 gfx_typeface_destroy(tface);
276 rc = gfx_context_delete(gc);
277 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
278}
279
280/** Test glyph_bmp_setpix() can flip pixel value both ways */
281PCUT_TEST(setpix_flip)
282{
283 gfx_font_props_t fprops;
284 gfx_font_metrics_t fmetrics;
285 gfx_typeface_t *tface;
286 gfx_font_t *font;
287 gfx_glyph_metrics_t gmetrics;
288 gfx_glyph_t *glyph;
289 gfx_context_t *gc;
290 gfx_glyph_bmp_t *bmp;
291 test_gc_t tgc;
292 int pix;
293 errno_t rc;
294
295 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
296 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
297
298 rc = gfx_typeface_create(gc, &tface);
299 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
300
301 gfx_font_props_init(&fprops);
302 gfx_font_metrics_init(&fmetrics);
303 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
304 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
305
306 gfx_glyph_metrics_init(&gmetrics);
307 gmetrics.advance = 1;
308
309 rc = gfx_glyph_create(font, &gmetrics, &glyph);
310 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
311
312 bmp = NULL;
313
314 rc = gfx_glyph_bmp_open(glyph, &bmp);
315 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
316 PCUT_ASSERT_NOT_NULL(bmp);
317
318 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
319 PCUT_ASSERT_INT_EQUALS(0, pix);
320
321 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
322 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
323
324 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
325 PCUT_ASSERT_INT_EQUALS(1, pix);
326
327 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 0);
328 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
329
330 pix = gfx_glyph_bmp_getpix(bmp, 0, 0);
331 PCUT_ASSERT_INT_EQUALS(0, pix);
332
333 gfx_glyph_bmp_close(bmp);
334
335 gfx_glyph_destroy(glyph);
336
337 gfx_font_close(font);
338 gfx_typeface_destroy(tface);
339 rc = gfx_context_delete(gc);
340 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
341}
342
343/** Test glyph_bmp_setpix() properly extends pixel array */
344PCUT_TEST(setpix_externd)
345{
346 gfx_font_props_t fprops;
347 gfx_font_metrics_t fmetrics;
348 gfx_typeface_t *tface;
349 gfx_font_t *font;
350 gfx_glyph_metrics_t gmetrics;
351 gfx_glyph_t *glyph;
352 gfx_context_t *gc;
353 gfx_glyph_bmp_t *bmp;
354 gfx_coord_t x, y;
355 test_gc_t tgc;
356 int pix;
357 errno_t rc;
358
359 rc = gfx_context_new(&test_ops, (void *) &tgc, &gc);
360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361
362 rc = gfx_typeface_create(gc, &tface);
363 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
364
365 gfx_font_props_init(&fprops);
366 gfx_font_metrics_init(&fmetrics);
367 rc = gfx_font_create(tface, &fprops, &fmetrics, &font);
368 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
369
370 gfx_glyph_metrics_init(&gmetrics);
371 gmetrics.advance = 1;
372
373 rc = gfx_glyph_create(font, &gmetrics, &glyph);
374 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
375
376 bmp = NULL;
377
378 rc = gfx_glyph_bmp_open(glyph, &bmp);
379 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
380 PCUT_ASSERT_NOT_NULL(bmp);
381
382 /*
383 * Fill the rectangle [0, 0]..[3, 3] with alternating pixel pattern
384 * and then check it.
385 */
386
387 rc = gfx_glyph_bmp_setpix(bmp, 0, 0, 1);
388 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
389
390 rc = gfx_glyph_bmp_setpix(bmp, 1, 1, 1);
391 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
392
393 rc = gfx_glyph_bmp_setpix(bmp, 2, 0, 1);
394 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
395
396 rc = gfx_glyph_bmp_setpix(bmp, 0, 2, 1);
397 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
398
399 rc = gfx_glyph_bmp_setpix(bmp, 2, 2, 1);
400 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
401
402 for (y = 0; y <= 2; y++) {
403 for (x = 0; x <= 2; x++) {
404 pix = gfx_glyph_bmp_getpix(bmp, x, y);
405 PCUT_ASSERT_INT_EQUALS((x & 1) ^ (y & 1) ^ 1, pix);
406 }
407 }
408
409 gfx_glyph_bmp_close(bmp);
410
411 gfx_glyph_destroy(glyph);
412
413 gfx_font_close(font);
414 gfx_typeface_destroy(tface);
415 rc = gfx_context_delete(gc);
416 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
417}
418
419static errno_t testgc_set_color(void *arg, gfx_color_t *color)
420{
421 return EOK;
422}
423
424static errno_t testgc_fill_rect(void *arg, gfx_rect_t *rect)
425{
426 return EOK;
427}
428
429static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
430 gfx_bitmap_alloc_t *alloc, void **rbm)
431{
432 test_gc_t *tgc = (test_gc_t *) arg;
433 testgc_bitmap_t *tbm;
434
435 tbm = calloc(1, sizeof(testgc_bitmap_t));
436 if (tbm == NULL)
437 return ENOMEM;
438
439 if (alloc == NULL) {
440 tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
441 sizeof(uint32_t);
442 tbm->alloc.off0 = 0;
443 tbm->alloc.pixels = calloc(sizeof(uint32_t),
444 tbm->alloc.pitch * (params->rect.p1.y - params->rect.p0.y));
445 tbm->myalloc = true;
446 if (tbm->alloc.pixels == NULL) {
447 free(tbm);
448 return ENOMEM;
449 }
450 } else {
451 tbm->alloc = *alloc;
452 }
453
454 tbm->tgc = tgc;
455 tgc->bm_params = *params;
456 tgc->bm_pixels = tbm->alloc.pixels;
457 *rbm = (void *)tbm;
458 return EOK;
459}
460
461static errno_t testgc_bitmap_destroy(void *bm)
462{
463 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
464 if (tbm->myalloc)
465 free(tbm->alloc.pixels);
466 free(tbm);
467 return EOK;
468}
469
470static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
471 gfx_coord2_t *offs)
472{
473 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
474 tbm->tgc->bm_srect = *srect;
475 tbm->tgc->bm_offs = *offs;
476 return EOK;
477}
478
479static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
480{
481 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
482 *alloc = tbm->alloc;
483 return EOK;
484}
485
486PCUT_EXPORT(glyph_bmp);
Note: See TracBrowser for help on using the repository browser.