source: mainline/uspace/lib/gfxfont/test/text.c@ 9c1cf34c

Last change on this file since 9c1cf34c was 4583015, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Add font to gfx_text_fmt_t

This is quite logical and saves us one argument that we need to pass to
all text formatting functions.

  • Property mode set to 100644
File size: 12.6 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/color.h>
30#include <gfx/context.h>
31#include <gfx/font.h>
32#include <gfx/glyph.h>
33#include <gfx/text.h>
34#include <gfx/typeface.h>
35#include <pcut/pcut.h>
36#include "../private/font.h"
37#include "../private/typeface.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(text);
42
43static errno_t testgc_set_clip_rect(void *, gfx_rect_t *);
44static errno_t testgc_set_color(void *, gfx_color_t *);
45static errno_t testgc_fill_rect(void *, gfx_rect_t *);
46static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
47 gfx_bitmap_alloc_t *, void **);
48static errno_t testgc_bitmap_destroy(void *);
49static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
50static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
51
52static gfx_context_ops_t test_ops = {
53 .set_clip_rect = testgc_set_clip_rect,
54 .set_color = testgc_set_color,
55 .fill_rect = testgc_fill_rect,
56 .bitmap_create = testgc_bitmap_create,
57 .bitmap_destroy = testgc_bitmap_destroy,
58 .bitmap_render = testgc_bitmap_render,
59 .bitmap_get_alloc = testgc_bitmap_get_alloc
60};
61
62typedef struct {
63 gfx_bitmap_params_t bm_params;
64 void *bm_pixels;
65 gfx_rect_t bm_srect;
66 gfx_coord2_t bm_offs;
67} test_gc_t;
68
69typedef struct {
70 test_gc_t *tgc;
71 gfx_bitmap_alloc_t alloc;
72 bool myalloc;
73} testgc_bitmap_t;
74
75/** Test text width computation with a dummy font */
76PCUT_TEST(dummy_text_width)
77{
78 gfx_font_props_t props;
79 gfx_font_metrics_t metrics;
80 gfx_typeface_t *tface;
81 gfx_font_t *font;
82 gfx_context_t *gc;
83 gfx_coord_t width;
84 test_gc_t tgc;
85 errno_t rc;
86
87 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
88 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
89
90 rc = gfx_typeface_create(gc, &tface);
91 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
92
93 gfx_font_props_init(&props);
94 gfx_font_metrics_init(&metrics);
95 rc = gfx_font_create(tface, &props, &metrics, &font);
96 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
97
98 width = gfx_text_width(font, "Hello world!");
99 PCUT_ASSERT_INT_EQUALS(0, width);
100
101 gfx_font_close(font);
102 gfx_typeface_destroy(tface);
103
104 rc = gfx_context_delete(gc);
105 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
106}
107
108/** Test text rendering with a dummy font */
109PCUT_TEST(dummy_puttext)
110{
111 gfx_font_props_t props;
112 gfx_font_metrics_t metrics;
113 gfx_typeface_t *tface;
114 gfx_font_t *font;
115 gfx_context_t *gc;
116 gfx_color_t *color;
117 gfx_text_fmt_t fmt;
118 gfx_coord2_t pos;
119 test_gc_t tgc;
120 errno_t rc;
121
122 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
123 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
124
125 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
126 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
127
128 rc = gfx_typeface_create(gc, &tface);
129 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
130
131 gfx_font_props_init(&props);
132 gfx_font_metrics_init(&metrics);
133 rc = gfx_font_create(tface, &props, &metrics, &font);
134 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
135
136 gfx_text_fmt_init(&fmt);
137 fmt.font = font;
138 fmt.color = color;
139 pos.x = 0;
140 pos.y = 0;
141
142 rc = gfx_puttext(&pos, &fmt, "Hello world!");
143 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
144
145 gfx_font_close(font);
146 gfx_typeface_destroy(tface);
147 gfx_color_delete(color);
148
149 rc = gfx_context_delete(gc);
150 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
151}
152
153/** gfx_text_start_pos() correctly computes text start position */
154PCUT_TEST(text_start_pos)
155{
156 gfx_font_props_t props;
157 gfx_font_metrics_t metrics;
158 gfx_typeface_t *tface;
159 gfx_font_t *font;
160 gfx_context_t *gc;
161 gfx_color_t *color;
162 gfx_text_fmt_t fmt;
163 gfx_coord2_t pos;
164 test_gc_t tgc;
165 errno_t rc;
166
167 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
168 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
169
170 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
171 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
172
173 rc = gfx_typeface_create(gc, &tface);
174 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
175
176 gfx_font_props_init(&props);
177 gfx_font_metrics_init(&metrics);
178 metrics.ascent = 10; // XXX
179 metrics.descent = 10; // XXX
180 rc = gfx_font_create(tface, &props, &metrics, &font);
181 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
182
183 gfx_text_fmt_init(&fmt);
184 fmt.font = font;
185 fmt.color = color;
186 pos.x = 0;
187 pos.y = 0;
188
189 rc = gfx_puttext(&pos, &fmt, "Hello world!");
190 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
191
192 gfx_font_close(font);
193 gfx_typeface_destroy(tface);
194 gfx_color_delete(color);
195
196 rc = gfx_context_delete(gc);
197 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
198}
199
200/** gfx_text_find_pos() finds position in text */
201PCUT_TEST(text_find_pos)
202{
203 gfx_font_props_t props;
204 gfx_font_metrics_t metrics;
205 gfx_typeface_t *tface;
206 gfx_font_t *font;
207 gfx_glyph_metrics_t gmetrics;
208 gfx_glyph_t *glyph1;
209 gfx_glyph_t *glyph2;
210 gfx_context_t *gc;
211 gfx_text_fmt_t fmt;
212 gfx_coord2_t anchor;
213 gfx_coord2_t fpos;
214 size_t off;
215 test_gc_t tgc;
216 errno_t rc;
217
218 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
219 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
220
221 rc = gfx_typeface_create(gc, &tface);
222 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
223
224 gfx_font_props_init(&props);
225 gfx_font_metrics_init(&metrics);
226 rc = gfx_font_create(tface, &props, &metrics, &font);
227 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
228
229 /* Need to create some glyphs with metrics */
230 gfx_glyph_metrics_init(&gmetrics);
231 gmetrics.advance = 10;
232
233 rc = gfx_glyph_create(font, &gmetrics, &glyph1);
234 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
235
236 rc = gfx_glyph_set_pattern(glyph1, "A");
237 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
238
239 gfx_glyph_metrics_init(&gmetrics);
240 gmetrics.advance = 1;
241
242 rc = gfx_glyph_create(font, &gmetrics, &glyph2);
243 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
244
245 rc = gfx_glyph_set_pattern(glyph2, "i");
246 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
247
248 gfx_text_fmt_init(&fmt);
249 fmt.font = font;
250 anchor.x = 10;
251 anchor.y = 0;
252
253 fpos.x = 9;
254 fpos.y = 0;
255 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
256 PCUT_ASSERT_INT_EQUALS(0, off);
257
258 fpos.x = 10;
259 fpos.y = 0;
260 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
261 PCUT_ASSERT_INT_EQUALS(0, off);
262
263 fpos.x = 11;
264 fpos.y = 0;
265 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
266 PCUT_ASSERT_INT_EQUALS(0, off);
267
268 fpos.x = 19;
269 fpos.y = 0;
270 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
271 PCUT_ASSERT_INT_EQUALS(1, off);
272
273 fpos.x = 20;
274 fpos.y = 0;
275 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
276 PCUT_ASSERT_INT_EQUALS(2, off);
277
278 fpos.x = 21;
279 fpos.y = 0;
280 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
281 PCUT_ASSERT_INT_EQUALS(3, off);
282
283 fpos.x = 22;
284 fpos.y = 0;
285 off = gfx_text_find_pos(&anchor, &fmt, "Aii", &fpos);
286 PCUT_ASSERT_INT_EQUALS(3, off);
287
288 gfx_glyph_destroy(glyph1);
289 gfx_glyph_destroy(glyph2);
290
291 gfx_font_close(font);
292 gfx_typeface_destroy(tface);
293
294 rc = gfx_context_delete(gc);
295 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
296}
297
298/** gfx_text_find_pos() finds position in text in text mode */
299PCUT_TEST(text_find_pos_text)
300{
301 gfx_typeface_t *tface;
302 gfx_font_t *font;
303 gfx_context_t *gc;
304 test_gc_t tgc;
305 size_t off;
306 gfx_text_fmt_t fmt;
307 gfx_coord2_t anchor;
308 gfx_coord2_t fpos;
309 errno_t rc;
310
311 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
312 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
313
314 rc = gfx_typeface_create(gc, &tface);
315 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
316
317 rc = gfx_font_create_textmode(tface, &font);
318 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
319
320 anchor.x = 10;
321 anchor.y = 0;
322 gfx_text_fmt_init(&fmt);
323 fmt.font = font;
324
325 fpos.x = 9;
326 fpos.y = 0;
327 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
328 PCUT_ASSERT_INT_EQUALS(0, off);
329
330 fpos.x = 10;
331 fpos.y = 0;
332 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
333 PCUT_ASSERT_INT_EQUALS(0, off);
334
335 fpos.x = 11;
336 fpos.y = 0;
337 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
338 PCUT_ASSERT_INT_EQUALS(1, off);
339
340 fpos.x = 12;
341 fpos.y = 0;
342 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
343 PCUT_ASSERT_INT_EQUALS(2, off);
344
345 fpos.x = 13;
346 fpos.y = 0;
347 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
348 PCUT_ASSERT_INT_EQUALS(3, off);
349
350 fpos.x = 14;
351 fpos.y = 0;
352 off = gfx_text_find_pos(&anchor, &fmt, "Abc", &fpos);
353 PCUT_ASSERT_INT_EQUALS(3, off);
354
355 gfx_font_close(font);
356 gfx_typeface_destroy(tface);
357
358 rc = gfx_context_delete(gc);
359 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
360}
361
362/** gfx_text_cont() produces correct continuation parameters */
363PCUT_TEST(text_cont)
364{
365 gfx_typeface_t *tface;
366 gfx_font_t *font;
367 gfx_context_t *gc;
368 gfx_color_t *color;
369 test_gc_t tgc;
370 gfx_text_fmt_t fmt;
371 gfx_coord2_t anchor;
372 gfx_coord2_t cpos;
373 gfx_text_fmt_t cfmt;
374 errno_t rc;
375
376 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
377 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
378
379 rc = gfx_typeface_create(gc, &tface);
380 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
381
382 rc = gfx_font_create_textmode(tface, &font);
383 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
384
385 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
386 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
387
388 anchor.x = 10;
389 anchor.y = 20;
390 gfx_text_fmt_init(&fmt);
391 fmt.font = font;
392 fmt.color = color;
393
394 gfx_text_cont(&anchor, &fmt, "Abc", &cpos, &cfmt);
395
396 PCUT_ASSERT_INT_EQUALS(13, cpos.x);
397 PCUT_ASSERT_INT_EQUALS(20, cpos.y);
398 PCUT_ASSERT_EQUALS(fmt.color, cfmt.color);
399 PCUT_ASSERT_EQUALS(gfx_halign_left, cfmt.halign);
400 PCUT_ASSERT_EQUALS(gfx_valign_baseline, cfmt.valign);
401
402 gfx_font_close(font);
403 gfx_typeface_destroy(tface);
404 gfx_color_delete(color);
405
406 rc = gfx_context_delete(gc);
407 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
408}
409
410/** gfx_text_rect() computes bounding rectangle */
411PCUT_TEST(text_rect)
412{
413 gfx_typeface_t *tface;
414 gfx_font_t *font;
415 gfx_context_t *gc;
416 gfx_color_t *color;
417 test_gc_t tgc;
418 gfx_text_fmt_t fmt;
419 gfx_coord2_t anchor;
420 gfx_rect_t rect;
421 errno_t rc;
422
423 rc = gfx_context_new(&test_ops, (void *)&tgc, &gc);
424 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
425
426 rc = gfx_typeface_create(gc, &tface);
427 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
428
429 rc = gfx_font_create_textmode(tface, &font);
430 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
431
432 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
433 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
434
435 anchor.x = 10;
436 anchor.y = 20;
437 gfx_text_fmt_init(&fmt);
438 fmt.font = font;
439 fmt.color = color;
440
441 gfx_text_rect(&anchor, &fmt, "Abc", &rect);
442
443 PCUT_ASSERT_INT_EQUALS(10, rect.p0.x);
444 PCUT_ASSERT_INT_EQUALS(20, rect.p0.y);
445 PCUT_ASSERT_INT_EQUALS(13, rect.p1.x);
446 PCUT_ASSERT_INT_EQUALS(21, rect.p1.y);
447
448 gfx_font_close(font);
449 gfx_typeface_destroy(tface);
450 gfx_color_delete(color);
451
452 rc = gfx_context_delete(gc);
453 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
454}
455
456static errno_t testgc_set_clip_rect(void *arg, gfx_rect_t *rect)
457{
458 return EOK;
459}
460
461static errno_t testgc_set_color(void *arg, gfx_color_t *color)
462{
463 return EOK;
464}
465
466static errno_t testgc_fill_rect(void *arg, gfx_rect_t *rect)
467{
468 return EOK;
469}
470
471static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
472 gfx_bitmap_alloc_t *alloc, void **rbm)
473{
474 test_gc_t *tgc = (test_gc_t *) arg;
475 testgc_bitmap_t *tbm;
476
477 tbm = calloc(1, sizeof(testgc_bitmap_t));
478 if (tbm == NULL)
479 return ENOMEM;
480
481 if (alloc == NULL) {
482 tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
483 sizeof(uint32_t);
484 tbm->alloc.off0 = 0;
485 tbm->alloc.pixels = calloc(sizeof(uint32_t),
486 tbm->alloc.pitch * (params->rect.p1.y - params->rect.p0.y));
487 tbm->myalloc = true;
488 if (tbm->alloc.pixels == NULL) {
489 free(tbm);
490 return ENOMEM;
491 }
492 } else {
493 tbm->alloc = *alloc;
494 }
495
496 tbm->tgc = tgc;
497 tgc->bm_params = *params;
498 tgc->bm_pixels = tbm->alloc.pixels;
499 *rbm = (void *)tbm;
500 return EOK;
501}
502
503static errno_t testgc_bitmap_destroy(void *bm)
504{
505 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
506 if (tbm->myalloc)
507 free(tbm->alloc.pixels);
508 free(tbm);
509 return EOK;
510}
511
512static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
513 gfx_coord2_t *offs)
514{
515 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
516 tbm->tgc->bm_srect = *srect;
517 tbm->tgc->bm_offs = *offs;
518 return EOK;
519}
520
521static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
522{
523 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
524 *alloc = tbm->alloc;
525 return EOK;
526}
527
528PCUT_EXPORT(text);
Note: See TracBrowser for help on using the repository browser.