1 /*
2  * Copyright (c) 2018-2019 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #include <inttypes.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22 
23 #include <d2tk/core.h>
24 #include <d2tk/hash.h>
25 #include "mock.h"
26 
27 static void
_test_hash()28 _test_hash()
29 {
30 	const uint32_t bar = 12;
31 	const char *foo = "barbarbarbar";
32 
33 	const uint64_t hash1 = d2tk_hash(&bar, sizeof(bar));
34 	const uint64_t hash2 = d2tk_hash(foo, strlen(foo));
35 
36 	assert(hash1 != hash2);
37 }
38 
39 static void
_test_hash_foreach()40 _test_hash_foreach()
41 {
42 	const uint32_t bar = 12;
43 	const char *foo = "foofoofoofoo";
44 
45 	const d2tk_hash_dict_t dict [] = {
46 		{ foo, strlen(foo) },
47 		{ &bar, sizeof(bar) },
48 		{ NULL, 0 }
49 	};
50 
51 	const uint64_t hash1 = d2tk_hash_dict(dict);
52 
53 	const uint64_t hash2 = d2tk_hash_foreach(foo, strlen(foo),
54 		&bar, sizeof(bar),
55 		NULL);
56 
57 	assert(hash1 == hash2);
58 }
59 
60 static void
_test_rect_shrink()61 _test_rect_shrink()
62 {
63 	d2tk_rect_t dst;
64 
65 	// initialization
66 	const d2tk_rect_t src = D2TK_RECT(1, 2, 3, 4);
67 	assert(src.x == 1);
68 	assert(src.y == 2);
69 	assert(src.w == 3);
70 	assert(src.h == 4);
71 
72 	// shrink on x-axis
73 	memset(&dst, 0x0, sizeof(dst));
74 	d2tk_rect_shrink_x(&dst, &src, 1);
75 	assert(dst.x == 1 + 1);
76 	assert(dst.y == 2);
77 	assert(dst.w == 3 - 2*1);
78 	assert(dst.h == 4);
79 
80 	// shrink on y-axis
81 	memset(&dst, 0x0, sizeof(dst));
82 	d2tk_rect_shrink_y(&dst, &src, 1);
83 	assert(dst.x == 1);
84 	assert(dst.y == 2 + 1);
85 	assert(dst.w == 3);
86 	assert(dst.h == 4 - 2*1);
87 
88 	// shrink on x/y-axes
89 	memset(&dst, 0x0, sizeof(dst));
90 	d2tk_rect_shrink(&dst, &src, 1);
91 	assert(dst.x == 1 + 1);
92 	assert(dst.y == 2 + 1);
93 	assert(dst.w == 3 - 2*1);
94 	assert(dst.h == 4 - 2*1);
95 }
96 
97 static void
_test_point()98 _test_point()
99 {
100 	// initialization
101 	const d2tk_point_t src = D2TK_POINT(11, 22);
102 	assert(src.x == 11);
103 	assert(src.y == 22);
104 }
105 
106 static void
_test_dimensions()107 _test_dimensions()
108 {
109 	d2tk_coord_t w;
110 	d2tk_coord_t h;
111 
112 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, NULL);
113 	assert(core);
114 
115 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
116 
117 	w = 0;
118 	h = 0;
119 	d2tk_core_get_dimensions(core, &w, &h);
120 	assert(w == DIM_W);
121 	assert(h == DIM_H);
122 
123 	w = 0;
124 	h = 0;
125 	d2tk_core_get_dimensions(core, NULL, NULL);
126 	assert(w == 0);
127 	assert(h == 0);
128 
129 	d2tk_core_free(core);
130 }
131 
132 #define BG_COLOR 0x222222ff
133 
134 static void
_test_bg_color()135 _test_bg_color()
136 {
137 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, NULL);
138 	assert(core);
139 
140 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
141 
142 	d2tk_core_set_bg_color(core, BG_COLOR);
143 	assert(BG_COLOR == d2tk_core_get_bg_color(core));
144 
145 	d2tk_core_free(core);
146 }
147 
148 #undef BG_COLOR
149 
150 #define MOVE_TO_X 10
151 #define MOVE_TO_Y 20
152 
153 static void
_check_move_to(const d2tk_com_t * com,const d2tk_clip_t * clip)154 _check_move_to(const d2tk_com_t *com, const d2tk_clip_t *clip)
155 {
156 	assert(clip->x0 == CLIP_X);
157 	assert(clip->y0 == CLIP_Y);
158 	assert(clip->x1 == CLIP_X + CLIP_W);
159 	assert(clip->y1 == CLIP_Y + CLIP_H);
160 	assert(clip->w == CLIP_W);
161 	assert(clip->h == CLIP_H);
162 
163 	assert(com->size == sizeof(d2tk_body_move_to_t));
164 	assert(com->instr == D2TK_INSTR_MOVE_TO);
165 	assert(com->body->move_to.x == MOVE_TO_X - CLIP_X);
166 	assert(com->body->move_to.y == MOVE_TO_Y - CLIP_Y);
167 }
168 
169 static void
_test_move_to()170 _test_move_to()
171 {
172 	d2tk_mock_ctx_t ctx = {
173 		.check = _check_move_to
174 	};
175 
176 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
177 	assert(core);
178 
179 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
180 
181 	d2tk_core_pre(core, NULL);
182 	const ssize_t ref = d2tk_core_bbox_push(core, true,
183 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
184 	assert(ref >= 0);
185 
186 	d2tk_core_move_to(core, MOVE_TO_X, MOVE_TO_Y);
187 
188 	d2tk_core_bbox_pop(core, ref);
189 	d2tk_core_post(core);
190 
191 	// trigger garbage collector
192 	for(unsigned i = 0; i < 0x400; i++)
193 	{
194 		d2tk_core_pre(core, NULL);
195 		d2tk_core_post(core);
196 	}
197 
198 	d2tk_core_free(core);
199 }
200 
201 #undef MOVE_TO_X
202 #undef MOVE_TO_Y
203 
204 #define LINE_TO_X 10
205 #define LINE_TO_Y 20
206 
207 static void
_check_line_to(const d2tk_com_t * com,const d2tk_clip_t * clip)208 _check_line_to(const d2tk_com_t *com, const d2tk_clip_t *clip)
209 {
210 	assert(clip->x0 == CLIP_X);
211 	assert(clip->y0 == CLIP_Y);
212 	assert(clip->x1 == CLIP_X + CLIP_W);
213 	assert(clip->y1 == CLIP_Y + CLIP_H);
214 	assert(clip->w == CLIP_W);
215 	assert(clip->h == CLIP_H);
216 
217 	assert(com->size == sizeof(d2tk_body_line_to_t));
218 	assert(com->instr == D2TK_INSTR_LINE_TO);
219 	assert(com->body->line_to.x == LINE_TO_X - CLIP_X);
220 	assert(com->body->line_to.y == LINE_TO_Y - CLIP_Y);
221 }
222 
223 static void
_test_line_to()224 _test_line_to()
225 {
226 	d2tk_mock_ctx_t ctx = {
227 		.check = _check_line_to
228 	};
229 
230 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
231 	assert(core);
232 
233 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
234 
235 	d2tk_core_pre(core, NULL);
236 	const ssize_t ref = d2tk_core_bbox_push(core, true,
237 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
238 	assert(ref >= 0);
239 
240 	d2tk_core_line_to(core, LINE_TO_X, LINE_TO_Y);
241 
242 	d2tk_core_bbox_pop(core, ref);
243 	d2tk_core_post(core);
244 	d2tk_core_free(core);
245 }
246 
247 #undef LINE_TO_X
248 #undef LINE_TO_Y
249 
250 #define RECT_X 10
251 #define RECT_Y 20
252 #define RECT_W 30
253 #define RECT_H 40
254 
255 static void
_check_rect(const d2tk_com_t * com,const d2tk_clip_t * clip)256 _check_rect(const d2tk_com_t *com, const d2tk_clip_t *clip)
257 {
258 	assert(clip->x0 == CLIP_X);
259 	assert(clip->y0 == CLIP_Y);
260 	assert(clip->x1 == CLIP_X + CLIP_W);
261 	assert(clip->y1 == CLIP_Y + CLIP_H);
262 	assert(clip->w == CLIP_W);
263 	assert(clip->h == CLIP_H);
264 
265 	assert(com->size == sizeof(d2tk_body_rect_t));
266 	assert(com->instr == D2TK_INSTR_RECT);
267 	assert(com->body->rect.x == RECT_X - CLIP_X);
268 	assert(com->body->rect.y == RECT_Y - CLIP_Y);
269 	assert(com->body->rect.w == RECT_W);
270 	assert(com->body->rect.h == RECT_H);
271 }
272 
273 static void
_test_rect()274 _test_rect()
275 {
276 	d2tk_mock_ctx_t ctx = {
277 		.check = _check_rect
278 	};
279 
280 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
281 	assert(core);
282 
283 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
284 
285 	d2tk_core_pre(core, NULL);
286 	const ssize_t ref = d2tk_core_bbox_push(core, true,
287 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
288 	assert(ref >= 0);
289 
290 	d2tk_core_rect(core, &D2TK_RECT(RECT_X, RECT_Y, RECT_W, RECT_H));
291 
292 	d2tk_core_bbox_pop(core, ref);
293 	d2tk_core_post(core);
294 	d2tk_core_free(core);
295 }
296 
297 #undef RECT_X
298 #undef RECT_Y
299 #undef RECT_W
300 #undef RECT_H
301 
302 #define ROUNDED_RECT_X 10
303 #define ROUNDED_RECT_Y 20
304 #define ROUNDED_RECT_W 30
305 #define ROUNDED_RECT_H 40
306 #define ROUNDED_RECT_R 5
307 
308 static void
_check_rounded_rect(const d2tk_com_t * com,const d2tk_clip_t * clip)309 _check_rounded_rect(const d2tk_com_t *com, const d2tk_clip_t *clip)
310 {
311 	assert(clip->x0 == CLIP_X);
312 	assert(clip->y0 == CLIP_Y);
313 	assert(clip->x1 == CLIP_X + CLIP_W);
314 	assert(clip->y1 == CLIP_Y + CLIP_H);
315 	assert(clip->w == CLIP_W);
316 	assert(clip->h == CLIP_H);
317 
318 	assert(com->size == sizeof(d2tk_body_rounded_rect_t));
319 	assert(com->instr == D2TK_INSTR_ROUNDED_RECT);
320 	assert(com->body->rounded_rect.x == ROUNDED_RECT_X - CLIP_X);
321 	assert(com->body->rounded_rect.y == ROUNDED_RECT_Y - CLIP_Y);
322 	assert(com->body->rounded_rect.w == ROUNDED_RECT_W);
323 	assert(com->body->rounded_rect.h == ROUNDED_RECT_H);
324 	assert(com->body->rounded_rect.r == ROUNDED_RECT_R);
325 }
326 
327 static void
_test_rounded_rect()328 _test_rounded_rect()
329 {
330 	d2tk_mock_ctx_t ctx = {
331 		.check = _check_rounded_rect
332 	};
333 
334 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
335 	assert(core);
336 
337 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
338 
339 	d2tk_core_pre(core, NULL);
340 	const ssize_t ref = d2tk_core_bbox_push(core, true,
341 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
342 	assert(ref >= 0);
343 
344 	d2tk_core_rounded_rect(core,
345 		&D2TK_RECT(ROUNDED_RECT_X, ROUNDED_RECT_Y, ROUNDED_RECT_W, ROUNDED_RECT_H),
346 		ROUNDED_RECT_R);
347 
348 	d2tk_core_bbox_pop(core, ref);
349 	d2tk_core_post(core);
350 	d2tk_core_free(core);
351 }
352 
353 #undef ROUNDED_RECT_X
354 #undef ROUNDED_RECT_Y
355 #undef ROUNDED_RECT_W
356 #undef ROUNDED_RECT_H
357 #undef ROUNDED_RECT_R
358 
359 #define ARC_X 10
360 #define ARC_Y 20
361 #define ARC_R 5
362 #define ARC_A 30
363 #define ARC_B 60
364 #define ARC_CW true
365 
366 static void
_check_arc(const d2tk_com_t * com,const d2tk_clip_t * clip)367 _check_arc(const d2tk_com_t *com, const d2tk_clip_t *clip)
368 {
369 	assert(clip->x0 == CLIP_X);
370 	assert(clip->y0 == CLIP_Y);
371 	assert(clip->x1 == CLIP_X + CLIP_W);
372 	assert(clip->y1 == CLIP_Y + CLIP_H);
373 	assert(clip->w == CLIP_W);
374 	assert(clip->h == CLIP_H);
375 
376 	assert(com->size == sizeof(d2tk_body_arc_t));
377 	assert(com->instr == D2TK_INSTR_ARC);
378 	assert(com->body->arc.x == ARC_X - CLIP_X);
379 	assert(com->body->arc.y == ARC_Y - CLIP_Y);
380 	assert(com->body->arc.r == ARC_R);
381 	assert(com->body->arc.a == ARC_A);
382 	assert(com->body->arc.b == ARC_B);
383 	assert(com->body->arc.cw == ARC_CW);
384 }
385 
386 static void
_test_arc()387 _test_arc()
388 {
389 	d2tk_mock_ctx_t ctx = {
390 		.check = _check_arc
391 	};
392 
393 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
394 	assert(core);
395 
396 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
397 
398 	d2tk_core_pre(core, NULL);
399 	const ssize_t ref = d2tk_core_bbox_push(core, true,
400 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
401 	assert(ref >= 0);
402 
403 	d2tk_core_arc(core, ARC_X, ARC_Y, ARC_R, ARC_A, ARC_B, ARC_CW);
404 
405 	d2tk_core_bbox_pop(core, ref);
406 	d2tk_core_post(core);
407 	d2tk_core_free(core);
408 }
409 
410 #undef ARC_X
411 #undef ARC_Y
412 #undef ARC_R
413 #undef ARC_A
414 #undef ARC_B
415 #undef ARC_CW
416 
417 #define CURVE_TO_X1 10
418 #define CURVE_TO_Y1 10
419 #define CURVE_TO_X2 20
420 #define CURVE_TO_Y2 20
421 #define CURVE_TO_X3 30
422 #define CURVE_TO_Y3 30
423 
424 static void
_check_curve_to(const d2tk_com_t * com,const d2tk_clip_t * clip)425 _check_curve_to(const d2tk_com_t *com, const d2tk_clip_t *clip)
426 {
427 	assert(clip->x0 == CLIP_X);
428 	assert(clip->y0 == CLIP_Y);
429 	assert(clip->x1 == CLIP_X + CLIP_W);
430 	assert(clip->y1 == CLIP_Y + CLIP_H);
431 	assert(clip->w == CLIP_W);
432 	assert(clip->h == CLIP_H);
433 
434 	assert(com->size == sizeof(d2tk_body_curve_to_t));
435 	assert(com->instr == D2TK_INSTR_CURVE_TO);
436 	assert(com->body->curve_to.x1 == CURVE_TO_X1 - CLIP_X);
437 	assert(com->body->curve_to.y1 == CURVE_TO_Y1 - CLIP_Y);
438 	assert(com->body->curve_to.x2 == CURVE_TO_X2 - CLIP_X);
439 	assert(com->body->curve_to.y2 == CURVE_TO_Y2 - CLIP_Y);
440 	assert(com->body->curve_to.x3 == CURVE_TO_X3 - CLIP_X);
441 	assert(com->body->curve_to.y3 == CURVE_TO_Y3 - CLIP_Y);
442 }
443 
444 static void
_test_curve_to()445 _test_curve_to()
446 {
447 	d2tk_mock_ctx_t ctx = {
448 		.check = _check_curve_to
449 	};
450 
451 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
452 	assert(core);
453 
454 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
455 
456 	d2tk_core_pre(core, NULL);
457 	const ssize_t ref = d2tk_core_bbox_push(core, true,
458 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
459 	assert(ref >= 0);
460 
461 	d2tk_core_curve_to(core, CURVE_TO_X1, CURVE_TO_Y1, CURVE_TO_X2, CURVE_TO_Y2,
462 		CURVE_TO_X3, CURVE_TO_Y3);
463 
464 	d2tk_core_bbox_pop(core, ref);
465 	d2tk_core_post(core);
466 	d2tk_core_free(core);
467 }
468 
469 #undef CURVE_TO_X1
470 #undef CURVE_TO_Y1
471 #undef CURVE_TO_X2
472 #undef CURVE_TO_Y2
473 #undef CURVE_TO_X3
474 #undef CURVE_TO_Y3
475 
476 #define COLOR_RGBA 0xff00ff00
477 
478 static void
_check_color(const d2tk_com_t * com,const d2tk_clip_t * clip)479 _check_color(const d2tk_com_t *com, const d2tk_clip_t *clip)
480 {
481 	assert(clip->x0 == CLIP_X);
482 	assert(clip->y0 == CLIP_Y);
483 	assert(clip->x1 == CLIP_X + CLIP_W);
484 	assert(clip->y1 == CLIP_Y + CLIP_H);
485 	assert(clip->w == CLIP_W);
486 	assert(clip->h == CLIP_H);
487 
488 	assert(com->size == sizeof(d2tk_body_color_t));
489 	assert(com->instr == D2TK_INSTR_COLOR);
490 	assert(com->body->color.rgba == COLOR_RGBA);
491 }
492 
493 static void
_test_color()494 _test_color()
495 {
496 	d2tk_mock_ctx_t ctx = {
497 		.check = _check_color
498 	};
499 
500 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
501 	assert(core);
502 
503 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
504 
505 	d2tk_core_pre(core, NULL);
506 	const ssize_t ref = d2tk_core_bbox_push(core, true,
507 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
508 	assert(ref >= 0);
509 
510 	d2tk_core_color(core, COLOR_RGBA);
511 
512 	d2tk_core_bbox_pop(core, ref);
513 	d2tk_core_post(core);
514 	d2tk_core_free(core);
515 }
516 
517 #undef COLOR_RGBA
518 
519 #define LINEAR_GRADIENT_X_0 10
520 #define LINEAR_GRADIENT_Y_0 20
521 #define LINEAR_GRADIENT_X_1 30
522 #define LINEAR_GRADIENT_Y_1 40
523 #define LINEAR_GRADIENT_RGBA_0 0xff00ff00
524 #define LINEAR_GRADIENT_RGBA_1 0xffff00ff
525 
526 static void
_check_linear_gradient(const d2tk_com_t * com,const d2tk_clip_t * clip)527 _check_linear_gradient(const d2tk_com_t *com, const d2tk_clip_t *clip)
528 {
529 	assert(clip->x0 == CLIP_X);
530 	assert(clip->y0 == CLIP_Y);
531 	assert(clip->x1 == CLIP_X + CLIP_W);
532 	assert(clip->y1 == CLIP_Y + CLIP_H);
533 	assert(clip->w == CLIP_W);
534 	assert(clip->h == CLIP_H);
535 
536 	assert(com->size == sizeof(d2tk_body_linear_gradient_t));
537 	assert(com->instr == D2TK_INSTR_LINEAR_GRADIENT);
538 	assert(com->body->linear_gradient.p[0].x == LINEAR_GRADIENT_X_0 - CLIP_X);
539 	assert(com->body->linear_gradient.p[0].y == LINEAR_GRADIENT_Y_0 - CLIP_Y);
540 	assert(com->body->linear_gradient.p[1].x == LINEAR_GRADIENT_X_1 - CLIP_X);
541 	assert(com->body->linear_gradient.p[1].y == LINEAR_GRADIENT_Y_1 - CLIP_Y);
542 	assert(com->body->linear_gradient.rgba[0] == LINEAR_GRADIENT_RGBA_0);
543 	assert(com->body->linear_gradient.rgba[1] == LINEAR_GRADIENT_RGBA_1);
544 }
545 
546 static void
_test_linear_gradient()547 _test_linear_gradient()
548 {
549 	d2tk_mock_ctx_t ctx = {
550 		.check = _check_linear_gradient
551 	};
552 
553 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
554 	assert(core);
555 
556 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
557 
558 	d2tk_core_pre(core, NULL);
559 	const ssize_t ref = d2tk_core_bbox_push(core, true,
560 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
561 	assert(ref >= 0);
562 
563 	const d2tk_point_t p [2] = {
564 		D2TK_POINT(LINEAR_GRADIENT_X_0, LINEAR_GRADIENT_Y_0),
565 		D2TK_POINT(LINEAR_GRADIENT_X_1, LINEAR_GRADIENT_Y_1)
566 	};
567 	const uint32_t rgba [2] = {
568 		LINEAR_GRADIENT_RGBA_0,
569 		LINEAR_GRADIENT_RGBA_1
570 	};
571 	d2tk_core_linear_gradient(core, p, rgba);
572 
573 	d2tk_core_bbox_pop(core, ref);
574 	d2tk_core_post(core);
575 	d2tk_core_free(core);
576 }
577 
578 #undef LINEAR_GRADIENT_X_0
579 #undef LINEAR_GRADIENT_Y_0
580 #undef LINEAR_GRADIENT_X_1
581 #undef LINEAR_GRADIENT_Y_1
582 #undef LINEAR_GRADIENT_RGBA_0
583 #undef LINEAR_GRADIENT_RGBA_1
584 
585 static void
_check_stroke(const d2tk_com_t * com,const d2tk_clip_t * clip)586 _check_stroke(const d2tk_com_t *com, const d2tk_clip_t *clip)
587 {
588 	assert(clip->x0 == CLIP_X);
589 	assert(clip->y0 == CLIP_Y);
590 	assert(clip->x1 == CLIP_X + CLIP_W);
591 	assert(clip->y1 == CLIP_Y + CLIP_H);
592 	assert(clip->w == CLIP_W);
593 	assert(clip->h == CLIP_H);
594 
595 	assert(com->size == 0);
596 	assert(com->instr == D2TK_INSTR_STROKE);
597 }
598 
599 static void
_test_stroke()600 _test_stroke()
601 {
602 	d2tk_mock_ctx_t ctx = {
603 		.check = _check_stroke
604 	};
605 
606 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
607 	assert(core);
608 
609 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
610 
611 	d2tk_core_pre(core, NULL);
612 	const ssize_t ref = d2tk_core_bbox_push(core, true,
613 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
614 	assert(ref >= 0);
615 
616 	d2tk_core_stroke(core);
617 
618 	d2tk_core_bbox_pop(core, ref);
619 	d2tk_core_post(core);
620 	d2tk_core_free(core);
621 }
622 
623 static void
_check_fill(const d2tk_com_t * com,const d2tk_clip_t * clip)624 _check_fill(const d2tk_com_t *com, const d2tk_clip_t *clip)
625 {
626 	assert(clip->x0 == CLIP_X);
627 	assert(clip->y0 == CLIP_Y);
628 	assert(clip->x1 == CLIP_X + CLIP_W);
629 	assert(clip->y1 == CLIP_Y + CLIP_H);
630 	assert(clip->w == CLIP_W);
631 	assert(clip->h == CLIP_H);
632 
633 	assert(com->size == 0);
634 	assert(com->instr == D2TK_INSTR_FILL);
635 }
636 
637 static void
_test_fill()638 _test_fill()
639 {
640 	d2tk_mock_ctx_t ctx = {
641 		.check = _check_fill
642 	};
643 
644 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
645 	assert(core);
646 
647 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
648 
649 	d2tk_core_pre(core, NULL);
650 	const ssize_t ref = d2tk_core_bbox_push(core, true,
651 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
652 	assert(ref >= 0);
653 
654 	d2tk_core_fill(core);
655 
656 	d2tk_core_bbox_pop(core, ref);
657 	d2tk_core_post(core);
658 	d2tk_core_free(core);
659 }
660 
661 static void
_check_save(const d2tk_com_t * com,const d2tk_clip_t * clip)662 _check_save(const d2tk_com_t *com, const d2tk_clip_t *clip)
663 {
664 	assert(clip->x0 == CLIP_X);
665 	assert(clip->y0 == CLIP_Y);
666 	assert(clip->x1 == CLIP_X + CLIP_W);
667 	assert(clip->y1 == CLIP_Y + CLIP_H);
668 	assert(clip->w == CLIP_W);
669 	assert(clip->h == CLIP_H);
670 
671 	assert(com->size == 0);
672 	assert(com->instr == D2TK_INSTR_SAVE);
673 }
674 
675 static void
_test_save()676 _test_save()
677 {
678 	d2tk_mock_ctx_t ctx = {
679 		.check = _check_save
680 	};
681 
682 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
683 	assert(core);
684 
685 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
686 
687 	d2tk_core_pre(core, NULL);
688 	const ssize_t ref = d2tk_core_bbox_push(core, true,
689 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
690 	assert(ref >= 0);
691 
692 	d2tk_core_save(core);
693 
694 	d2tk_core_bbox_pop(core, ref);
695 	d2tk_core_post(core);
696 	d2tk_core_free(core);
697 }
698 
699 static void
_check_restore(const d2tk_com_t * com,const d2tk_clip_t * clip)700 _check_restore(const d2tk_com_t *com, const d2tk_clip_t *clip)
701 {
702 	assert(clip->x0 == CLIP_X);
703 	assert(clip->y0 == CLIP_Y);
704 	assert(clip->x1 == CLIP_X + CLIP_W);
705 	assert(clip->y1 == CLIP_Y + CLIP_H);
706 	assert(clip->w == CLIP_W);
707 	assert(clip->h == CLIP_H);
708 
709 	assert(com->size == 0);
710 	assert(com->instr == D2TK_INSTR_RESTORE);
711 }
712 
713 static void
_test_restore()714 _test_restore()
715 {
716 	d2tk_mock_ctx_t ctx = {
717 		.check = _check_restore
718 	};
719 
720 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
721 	assert(core);
722 
723 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
724 
725 	d2tk_core_pre(core, NULL);
726 	const ssize_t ref = d2tk_core_bbox_push(core, true,
727 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
728 	assert(ref >= 0);
729 
730 	d2tk_core_restore(core);
731 
732 	d2tk_core_bbox_pop(core, ref);
733 	d2tk_core_post(core);
734 	d2tk_core_free(core);
735 }
736 
737 #define ROTATE_DEG 45
738 
739 static void
_check_rotate(const d2tk_com_t * com,const d2tk_clip_t * clip)740 _check_rotate(const d2tk_com_t *com, const d2tk_clip_t *clip)
741 {
742 	assert(clip->x0 == CLIP_X);
743 	assert(clip->y0 == CLIP_Y);
744 	assert(clip->x1 == CLIP_X + CLIP_W);
745 	assert(clip->y1 == CLIP_Y + CLIP_H);
746 	assert(clip->w == CLIP_W);
747 	assert(clip->h == CLIP_H);
748 
749 	assert(com->size == sizeof(d2tk_body_rotate_t));
750 	assert(com->instr == D2TK_INSTR_ROTATE);
751 	assert(com->body->rotate.deg == ROTATE_DEG);
752 }
753 
754 static void
_test_rotate()755 _test_rotate()
756 {
757 	d2tk_mock_ctx_t ctx = {
758 		.check = _check_rotate
759 	};
760 
761 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
762 	assert(core);
763 
764 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
765 
766 	d2tk_core_pre(core, NULL);
767 	const ssize_t ref = d2tk_core_bbox_push(core, true,
768 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
769 	assert(ref >= 0);
770 
771 	d2tk_core_rotate(core, ROTATE_DEG);
772 
773 	d2tk_core_bbox_pop(core, ref);
774 	d2tk_core_post(core);
775 	d2tk_core_free(core);
776 }
777 
778 #undef ROTATE_DEG
779 
780 static void
_check_begin_path(const d2tk_com_t * com,const d2tk_clip_t * clip)781 _check_begin_path(const d2tk_com_t *com, const d2tk_clip_t *clip)
782 {
783 	assert(clip->x0 == CLIP_X);
784 	assert(clip->y0 == CLIP_Y);
785 	assert(clip->x1 == CLIP_X + CLIP_W);
786 	assert(clip->y1 == CLIP_Y + CLIP_H);
787 	assert(clip->w == CLIP_W);
788 	assert(clip->h == CLIP_H);
789 
790 	assert(com->size == 0);
791 	assert(com->instr == D2TK_INSTR_BEGIN_PATH);
792 }
793 
794 static void
_test_begin_path()795 _test_begin_path()
796 {
797 	d2tk_mock_ctx_t ctx = {
798 		.check = _check_begin_path
799 	};
800 
801 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
802 	assert(core);
803 
804 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
805 
806 	d2tk_core_pre(core, NULL);
807 	const ssize_t ref = d2tk_core_bbox_push(core, true,
808 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
809 	assert(ref >= 0);
810 
811 	d2tk_core_begin_path(core);
812 
813 	d2tk_core_bbox_pop(core, ref);
814 	d2tk_core_post(core);
815 	d2tk_core_free(core);
816 }
817 
818 static void
_check_close_path(const d2tk_com_t * com,const d2tk_clip_t * clip)819 _check_close_path(const d2tk_com_t *com, const d2tk_clip_t *clip)
820 {
821 	assert(clip->x0 == CLIP_X);
822 	assert(clip->y0 == CLIP_Y);
823 	assert(clip->x1 == CLIP_X + CLIP_W);
824 	assert(clip->y1 == CLIP_Y + CLIP_H);
825 	assert(clip->w == CLIP_W);
826 	assert(clip->h == CLIP_H);
827 
828 	assert(com->size == 0);
829 	assert(com->instr == D2TK_INSTR_CLOSE_PATH);
830 }
831 
832 static void
_test_close_path()833 _test_close_path()
834 {
835 	d2tk_mock_ctx_t ctx = {
836 		.check = _check_close_path
837 	};
838 
839 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
840 	assert(core);
841 
842 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
843 
844 	d2tk_core_pre(core, NULL);
845 	const ssize_t ref = d2tk_core_bbox_push(core, true,
846 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
847 	assert(ref >= 0);
848 
849 	d2tk_core_close_path(core);
850 
851 	d2tk_core_bbox_pop(core, ref);
852 	d2tk_core_post(core);
853 	d2tk_core_free(core);
854 }
855 
856 #define SCISSOR_X 10
857 #define SCISSOR_Y 20
858 #define SCISSOR_W 30
859 #define SCISSOR_H 40
860 
861 static void
_check_scissor(const d2tk_com_t * com,const d2tk_clip_t * clip)862 _check_scissor(const d2tk_com_t *com, const d2tk_clip_t *clip)
863 {
864 	assert(clip->x0 == CLIP_X);
865 	assert(clip->y0 == CLIP_Y);
866 	assert(clip->x1 == CLIP_X + CLIP_W);
867 	assert(clip->y1 == CLIP_Y + CLIP_H);
868 	assert(clip->w == CLIP_W);
869 	assert(clip->h == CLIP_H);
870 
871 	assert(com->size == sizeof(d2tk_body_scissor_t));
872 	assert(com->instr == D2TK_INSTR_SCISSOR);
873 	assert(com->body->scissor.x == SCISSOR_X - CLIP_X);
874 	assert(com->body->scissor.y == SCISSOR_Y - CLIP_Y);
875 	assert(com->body->scissor.w == SCISSOR_W);
876 	assert(com->body->scissor.h == SCISSOR_H);
877 }
878 
879 static void
_test_scissor()880 _test_scissor()
881 {
882 	d2tk_mock_ctx_t ctx = {
883 		.check = _check_scissor
884 	};
885 
886 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
887 	assert(core);
888 
889 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
890 
891 	d2tk_core_pre(core, NULL);
892 	const ssize_t ref = d2tk_core_bbox_push(core, true,
893 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
894 	assert(ref >= 0);
895 
896 	d2tk_core_scissor(core, &D2TK_RECT(SCISSOR_X, SCISSOR_Y, SCISSOR_W, SCISSOR_H));
897 
898 	d2tk_core_bbox_pop(core, ref);
899 	d2tk_core_post(core);
900 	d2tk_core_free(core);
901 }
902 
903 #undef SCISSOR_X
904 #undef SCISSOR_Y
905 #undef SCISSOR_W
906 #undef SCISSOR_H
907 
908 static void
_check_reset_scissor(const d2tk_com_t * com,const d2tk_clip_t * clip)909 _check_reset_scissor(const d2tk_com_t *com, const d2tk_clip_t *clip)
910 {
911 	assert(clip->x0 == CLIP_X);
912 	assert(clip->y0 == CLIP_Y);
913 	assert(clip->x1 == CLIP_X + CLIP_W);
914 	assert(clip->y1 == CLIP_Y + CLIP_H);
915 	assert(clip->w == CLIP_W);
916 	assert(clip->h == CLIP_H);
917 
918 	assert(com->size == 0);
919 	assert(com->instr == D2TK_INSTR_RESET_SCISSOR);
920 }
921 
922 static void
_test_reset_scissor()923 _test_reset_scissor()
924 {
925 	d2tk_mock_ctx_t ctx = {
926 		.check = _check_reset_scissor
927 	};
928 
929 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
930 	assert(core);
931 
932 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
933 
934 	d2tk_core_pre(core, NULL);
935 	const ssize_t ref = d2tk_core_bbox_push(core, true,
936 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
937 	assert(ref >= 0);
938 
939 	d2tk_core_reset_scissor(core);
940 
941 	d2tk_core_bbox_pop(core, ref);
942 	d2tk_core_post(core);
943 	d2tk_core_free(core);
944 }
945 
946 #define FONT_SIZE 11
947 
948 static void
_check_font_size(const d2tk_com_t * com,const d2tk_clip_t * clip)949 _check_font_size(const d2tk_com_t *com, const d2tk_clip_t *clip)
950 {
951 	assert(clip->x0 == CLIP_X);
952 	assert(clip->y0 == CLIP_Y);
953 	assert(clip->x1 == CLIP_X + CLIP_W);
954 	assert(clip->y1 == CLIP_Y + CLIP_H);
955 	assert(clip->w == CLIP_W);
956 	assert(clip->h == CLIP_H);
957 
958 	assert(com->size == sizeof(d2tk_body_font_size_t));
959 	assert(com->instr == D2TK_INSTR_FONT_SIZE);
960 	assert(com->body->font_size.size == FONT_SIZE);
961 }
962 
963 static void
_test_font_size()964 _test_font_size()
965 {
966 	d2tk_mock_ctx_t ctx = {
967 		.check = _check_font_size
968 	};
969 
970 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
971 	assert(core);
972 
973 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
974 
975 	d2tk_core_pre(core, NULL);
976 	const ssize_t ref = d2tk_core_bbox_push(core, true,
977 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
978 	assert(ref >= 0);
979 
980 	d2tk_core_font_size(core, FONT_SIZE);
981 
982 	d2tk_core_bbox_pop(core, ref);
983 	d2tk_core_post(core);
984 	d2tk_core_free(core);
985 }
986 
987 #undef FONT_SIZE
988 
989 #define FONT_FACE "Monospace"
990 
991 static void
_check_font_face(const d2tk_com_t * com,const d2tk_clip_t * clip)992 _check_font_face(const d2tk_com_t *com, const d2tk_clip_t *clip)
993 {
994 	assert(clip->x0 == CLIP_X);
995 	assert(clip->y0 == CLIP_Y);
996 	assert(clip->x1 == CLIP_X + CLIP_W);
997 	assert(clip->y1 == CLIP_Y + CLIP_H);
998 	assert(clip->w == CLIP_W);
999 	assert(clip->h == CLIP_H);
1000 
1001 	assert(com->size == sizeof(d2tk_body_font_face_t) + strlen(FONT_FACE));
1002 	assert(com->instr == D2TK_INSTR_FONT_FACE);
1003 	assert(strcmp(com->body->font_face.face, FONT_FACE) == 0);
1004 }
1005 
1006 static void
_test_font_face()1007 _test_font_face()
1008 {
1009 	d2tk_mock_ctx_t ctx = {
1010 		.check = _check_font_face
1011 	};
1012 
1013 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1014 	assert(core);
1015 
1016 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1017 
1018 	d2tk_core_pre(core, NULL);
1019 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1020 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1021 	assert(ref >= 0);
1022 
1023 	d2tk_core_font_face(core, strlen(FONT_FACE), FONT_FACE);
1024 
1025 	d2tk_core_bbox_pop(core, ref);
1026 	d2tk_core_post(core);
1027 	d2tk_core_free(core);
1028 }
1029 
1030 #undef FONT_FACE
1031 
1032 #define TEXT_X 10
1033 #define TEXT_Y 20
1034 #define TEXT_W 30
1035 #define TEXT_H 40
1036 #define TEXT_TEXT "Text" "времени" "äöäÄÖÄ"
1037 #define TEXT_ALIGN D2TK_ALIGN_LEFT
1038 
1039 static void
_check_text(const d2tk_com_t * com,const d2tk_clip_t * clip)1040 _check_text(const d2tk_com_t *com, const d2tk_clip_t *clip)
1041 {
1042 	assert(clip->x0 == CLIP_X);
1043 	assert(clip->y0 == CLIP_Y);
1044 	assert(clip->x1 == CLIP_X + CLIP_W);
1045 	assert(clip->y1 == CLIP_Y + CLIP_H);
1046 	assert(clip->w == CLIP_W);
1047 	assert(clip->h == CLIP_H);
1048 
1049 	assert(com->size == sizeof(d2tk_body_text_t) + strlen(TEXT_TEXT));
1050 	assert(com->instr == D2TK_INSTR_TEXT);
1051 	assert(com->body->text.x == TEXT_X - CLIP_X);
1052 	assert(com->body->text.y == TEXT_Y - CLIP_Y);
1053 	assert(com->body->text.w == TEXT_W);
1054 	assert(com->body->text.h == TEXT_H);
1055 	assert(strcmp(com->body->text.text, TEXT_TEXT) == 0);
1056 	assert(com->body->text.align == TEXT_ALIGN);
1057 }
1058 
1059 static void
_test_text()1060 _test_text()
1061 {
1062 	d2tk_mock_ctx_t ctx = {
1063 		.check = _check_text
1064 	};
1065 
1066 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1067 	assert(core);
1068 
1069 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1070 
1071 	d2tk_core_pre(core, NULL);
1072 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1073 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1074 	assert(ref >= 0);
1075 
1076 	d2tk_core_text(core, &D2TK_RECT(TEXT_X, TEXT_Y, TEXT_W, TEXT_H),
1077 		strlen(TEXT_TEXT), TEXT_TEXT, TEXT_ALIGN);
1078 
1079 	d2tk_core_bbox_pop(core, ref);
1080 	d2tk_core_post(core);
1081 	d2tk_core_free(core);
1082 }
1083 
1084 #undef TEXT_X
1085 #undef TEXT_Y
1086 #undef TEXT_W
1087 #undef TEXT_H
1088 #undef TEXT_TEXT
1089 #undef TEXT_ALIGN
1090 
1091 #define IMAGE_X 10
1092 #define IMAGE_Y 20
1093 #define IMAGE_W 30
1094 #define IMAGE_H 40
1095 #define IMAGE_PATH "./libre-sugar-skull.png"
1096 #define IMAGE_ALIGN D2TK_ALIGN_LEFT
1097 
1098 static void
_check_image(const d2tk_com_t * com,const d2tk_clip_t * clip)1099 _check_image(const d2tk_com_t *com, const d2tk_clip_t *clip)
1100 {
1101 	assert(clip->x0 == CLIP_X);
1102 	assert(clip->y0 == CLIP_Y);
1103 	assert(clip->x1 == CLIP_X + CLIP_W);
1104 	assert(clip->y1 == CLIP_Y + CLIP_H);
1105 	assert(clip->w == CLIP_W);
1106 	assert(clip->h == CLIP_H);
1107 
1108 	assert(com->size == sizeof(d2tk_body_image_t) + strlen(IMAGE_PATH));
1109 	assert(com->instr == D2TK_INSTR_IMAGE);
1110 	assert(com->body->image.x == IMAGE_X - CLIP_X);
1111 	assert(com->body->image.y == IMAGE_Y - CLIP_Y);
1112 	assert(com->body->image.w == IMAGE_W);
1113 	assert(com->body->image.h == IMAGE_H);
1114 	assert(strcmp(com->body->image.path , IMAGE_PATH) == 0);
1115 	assert(com->body->image.align == IMAGE_ALIGN);
1116 }
1117 
1118 static void
_test_image()1119 _test_image()
1120 {
1121 	d2tk_mock_ctx_t ctx = {
1122 		.check = _check_image
1123 	};
1124 
1125 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1126 	assert(core);
1127 
1128 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1129 
1130 	d2tk_core_pre(core, NULL);
1131 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1132 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1133 	assert(ref >= 0);
1134 
1135 	d2tk_core_image(core, &D2TK_RECT(IMAGE_X, IMAGE_Y, IMAGE_W, IMAGE_H),
1136 		strlen(IMAGE_PATH), IMAGE_PATH, IMAGE_ALIGN);
1137 
1138 	d2tk_core_bbox_pop(core, ref);
1139 	d2tk_core_post(core);
1140 	d2tk_core_free(core);
1141 }
1142 
1143 #undef IMAGE_X
1144 #undef IMAGE_Y
1145 #undef IMAGE_W
1146 #undef IMAGE_H
1147 #undef IMAGE_PATH
1148 #undef IMAGE_ALIGN
1149 
1150 #define BITMAP_X 10
1151 #define BITMAP_Y 20
1152 #define BITMAP_W 30
1153 #define BITMAP_H 40
1154 #define BITMAP_WIDTH 24
1155 #define BITMAP_HEIGHT 24
1156 #define BITMAP_STRIDE 32*sizeof(uint32_t)
1157 #define BITMAP_ALIGN D2TK_ALIGN_LEFT
1158 
1159 static void
_check_bitmap(const d2tk_com_t * com,const d2tk_clip_t * clip)1160 _check_bitmap(const d2tk_com_t *com, const d2tk_clip_t *clip)
1161 {
1162 	assert(clip->x0 == CLIP_X);
1163 	assert(clip->y0 == CLIP_Y);
1164 	assert(clip->x1 == CLIP_X + CLIP_W);
1165 	assert(clip->y1 == CLIP_Y + CLIP_H);
1166 	assert(clip->w == CLIP_W);
1167 	assert(clip->h == CLIP_H);
1168 
1169 	assert(com->size == sizeof(d2tk_body_bitmap_t));
1170 	assert(com->instr == D2TK_INSTR_BITMAP);
1171 	assert(com->body->bitmap.x == BITMAP_X - CLIP_X);
1172 	assert(com->body->bitmap.y == BITMAP_Y - CLIP_Y);
1173 	assert(com->body->bitmap.w == BITMAP_W);
1174 	assert(com->body->bitmap.h == BITMAP_H);
1175 	assert(com->body->bitmap.align == BITMAP_ALIGN);
1176 	assert(com->body->bitmap.surf.w == BITMAP_WIDTH);
1177 	assert(com->body->bitmap.surf.h == BITMAP_HEIGHT);
1178 	assert(com->body->bitmap.surf.stride == BITMAP_STRIDE);
1179 	for(unsigned y = 0, o = 0;
1180 		y < com->body->bitmap.surf.h;
1181 		y++, o += com->body->bitmap.surf.stride/sizeof(uint32_t))
1182 	{
1183 		for(unsigned x = 0; x < com->body->bitmap.surf.w; x++)
1184 		{
1185 			const unsigned idx = o + x;
1186 
1187 			assert(com->body->bitmap.surf.argb[idx] == 999 - idx);
1188 		}
1189 	}
1190 }
1191 
1192 static void
_test_bitmap()1193 _test_bitmap()
1194 {
1195 	d2tk_mock_ctx_t ctx = {
1196 		.check = _check_bitmap
1197 	};
1198 
1199 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1200 	assert(core);
1201 
1202 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1203 
1204 	d2tk_core_pre(core, NULL);
1205 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1206 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1207 	assert(ref >= 0);
1208 
1209 	uint32_t surf [BITMAP_STRIDE/sizeof(uint32_t)*BITMAP_HEIGHT];
1210 	for(unsigned y = 0, o = 0;
1211 		y < BITMAP_HEIGHT;
1212 		y++, o += BITMAP_STRIDE/sizeof(uint32_t))
1213 	{
1214 		for(unsigned x = 0; x < BITMAP_WIDTH; x++)
1215 		{
1216 			const unsigned idx = o + x;
1217 
1218 			surf[idx] = 999 - idx;
1219 		}
1220 	}
1221 
1222 	const uint64_t rev = 0;
1223 
1224 	d2tk_core_bitmap(core, &D2TK_RECT(BITMAP_X, BITMAP_Y, BITMAP_W, BITMAP_H),
1225 		BITMAP_WIDTH, BITMAP_HEIGHT, BITMAP_STRIDE, surf, rev, BITMAP_ALIGN);
1226 
1227 	d2tk_core_bbox_pop(core, ref);
1228 	d2tk_core_post(core);
1229 	d2tk_core_free(core);
1230 }
1231 
1232 #undef BITMAP_X
1233 #undef BITMAP_Y
1234 #undef BITMAP_W
1235 #undef BITMAP_H
1236 #undef BITMAP_WIDTH
1237 #undef BITMAP_HEIGHT
1238 #undef BITMAP_STRIDE
1239 #undef BITMAP_ALIGN
1240 
1241 #define CUSTOM_X 10
1242 #define CUSTOM_Y 20
1243 #define CUSTOM_W 30
1244 #define CUSTOM_H 40
1245 static const uint32_t _data = 12;
1246 #define CUSTOM_DATA (&_data)
1247 
1248 static void
_custom(void * ctx,const d2tk_rect_t * rect,const void * data)1249 _custom(void *ctx, const d2tk_rect_t *rect, const void *data)
1250 {
1251 	assert(ctx == NULL);
1252 	assert(rect != NULL);
1253 	assert(rect->x == CUSTOM_X);
1254 	assert(rect->y == CUSTOM_Y);
1255 	assert(rect->w == CUSTOM_W);
1256 	assert(rect->h == CUSTOM_H);
1257 	assert(data == CUSTOM_DATA);
1258 }
1259 
1260 static void
_check_custom(const d2tk_com_t * com,const d2tk_clip_t * clip)1261 _check_custom(const d2tk_com_t *com, const d2tk_clip_t *clip)
1262 {
1263 	assert(clip->x0 == CLIP_X);
1264 	assert(clip->y0 == CLIP_Y);
1265 	assert(clip->x1 == CLIP_X + CLIP_W);
1266 	assert(clip->y1 == CLIP_Y + CLIP_H);
1267 	assert(clip->w == CLIP_W);
1268 	assert(clip->h == CLIP_H);
1269 
1270 	const uint64_t dhash = d2tk_hash(CUSTOM_DATA, sizeof(uint32_t));
1271 
1272 	assert(com->size == sizeof(d2tk_body_custom_t));
1273 	assert(com->instr == D2TK_INSTR_CUSTOM);
1274 	assert(com->body->custom.x == CUSTOM_X - CLIP_X);
1275 	assert(com->body->custom.y == CUSTOM_Y - CLIP_Y);
1276 	assert(com->body->custom.w == CUSTOM_W);
1277 	assert(com->body->custom.h == CUSTOM_H);
1278 	assert(com->body->custom.dhash == dhash);
1279 	assert(com->body->custom.data == CUSTOM_DATA);
1280 	assert(com->body->custom.custom == _custom);
1281 }
1282 
1283 static void
_test_custom()1284 _test_custom()
1285 {
1286 	d2tk_mock_ctx_t ctx = {
1287 		.check = _check_custom
1288 	};
1289 
1290 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1291 	assert(core);
1292 
1293 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1294 
1295 	d2tk_core_pre(core, NULL);
1296 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1297 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1298 	assert(ref >= 0);
1299 
1300 	const uint64_t dhash = d2tk_hash(CUSTOM_DATA, sizeof(uint32_t));
1301 
1302 	d2tk_core_custom(core, &D2TK_RECT(CUSTOM_X, CUSTOM_Y, CUSTOM_W, CUSTOM_H),
1303 		dhash, CUSTOM_DATA, _custom);
1304 
1305 	d2tk_core_bbox_pop(core, ref);
1306 	d2tk_core_post(core);
1307 	d2tk_core_free(core);
1308 }
1309 
1310 #undef CUSTOM_X
1311 #undef CUSTOM_Y
1312 #undef CUSTOM_W
1313 #undef CUSTOM_H
1314 #undef CUSTOM_SIZE
1315 #undef CUSTOM_DATA
1316 
1317 #define STROKE_WIDTH 2
1318 
1319 static void
_check_stroke_width(const d2tk_com_t * com,const d2tk_clip_t * clip)1320 _check_stroke_width(const d2tk_com_t *com, const d2tk_clip_t *clip)
1321 {
1322 	assert(clip->x0 == CLIP_X);
1323 	assert(clip->y0 == CLIP_Y);
1324 	assert(clip->x1 == CLIP_X + CLIP_W);
1325 	assert(clip->y1 == CLIP_Y + CLIP_H);
1326 	assert(clip->w == CLIP_W);
1327 	assert(clip->h == CLIP_H);
1328 
1329 	assert(com->size == sizeof(d2tk_body_stroke_width_t));
1330 	assert(com->instr == D2TK_INSTR_STROKE_WIDTH);
1331 	assert(com->body->stroke_width.width == STROKE_WIDTH);
1332 }
1333 
1334 static void
_test_stroke_width()1335 _test_stroke_width()
1336 {
1337 	d2tk_mock_ctx_t ctx = {
1338 		.check = _check_stroke_width
1339 	};
1340 
1341 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver, &ctx);
1342 	assert(core);
1343 
1344 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1345 
1346 	d2tk_core_pre(core, NULL);
1347 	const ssize_t ref = d2tk_core_bbox_push(core, true,
1348 		&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1349 	assert(ref >= 0);
1350 
1351 	d2tk_core_stroke_width(core, STROKE_WIDTH);
1352 
1353 	d2tk_core_bbox_pop(core, ref);
1354 	d2tk_core_post(core);
1355 	d2tk_core_free(core);
1356 }
1357 
1358 #undef STROKE_WIDTH
1359 
1360 static void
_check_triple(const d2tk_com_t * com,const d2tk_clip_t * clip)1361 _check_triple(const d2tk_com_t *com, const d2tk_clip_t *clip)
1362 {
1363 	assert(clip->x0 == CLIP_X);
1364 	assert(clip->y0 == CLIP_Y);
1365 	assert(clip->x1 == CLIP_X + CLIP_W);
1366 	assert(clip->y1 == CLIP_Y + CLIP_H);
1367 	assert(clip->w == CLIP_W);
1368 	assert(clip->h == CLIP_H);
1369 
1370 	(void)com; //FIXME
1371 }
1372 
1373 static void
_test_triple()1374 _test_triple()
1375 {
1376 	d2tk_mock_ctx_t ctx = {
1377 		.check = _check_triple
1378 	};
1379 
1380 	d2tk_core_t *core = d2tk_core_new(&d2tk_mock_driver_triple, &ctx);
1381 	assert(core);
1382 
1383 	d2tk_core_set_dimensions(core, DIM_W, DIM_H);
1384 
1385 	for(unsigned i = 0; i < 3; i++)
1386 	{
1387 		d2tk_core_pre(core, NULL);
1388 
1389 		if(i != 0)
1390 		{
1391 			const ssize_t ref = d2tk_core_bbox_push(core, true,
1392 				&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1393 			assert(ref >= 0);
1394 
1395 			d2tk_core_rect(core, &D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1396 
1397 			d2tk_core_bbox_pop(core, ref);
1398 		}
1399 
1400 		if(i != 1)
1401 		{
1402 			const ssize_t ref = d2tk_core_bbox_push(core, true,
1403 				&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1404 			assert(ref >= 0);
1405 
1406 			d2tk_core_rect(core, &D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W/2, CLIP_H));
1407 
1408 			d2tk_core_bbox_pop(core, ref);
1409 		}
1410 
1411 		if(i != 2)
1412 		{
1413 			const ssize_t ref = d2tk_core_bbox_push(core, true,
1414 				&D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H));
1415 			assert(ref >= 0);
1416 
1417 			d2tk_core_rect(core, &D2TK_RECT(CLIP_X, CLIP_Y, CLIP_W, CLIP_H/2));
1418 
1419 			d2tk_core_bbox_pop(core, ref);
1420 		}
1421 
1422 		d2tk_core_post(core);
1423 	}
1424 
1425 	d2tk_core_free(core);
1426 }
1427 
1428 int
main(int argc,char ** argv)1429 main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
1430 {
1431 	_test_hash();
1432 	_test_hash_foreach();
1433 	_test_rect_shrink();
1434 	_test_point();
1435 	_test_dimensions();
1436 	_test_bg_color();
1437 
1438 	_test_move_to();
1439 	_test_line_to();
1440 	_test_rect();
1441 	_test_rounded_rect();
1442 	_test_arc();
1443 	_test_curve_to();
1444 	_test_color();
1445 	_test_linear_gradient();
1446 	_test_stroke();
1447 	_test_fill();
1448 	_test_save();
1449 	_test_restore();
1450 	_test_rotate();
1451 	_test_begin_path();
1452 	_test_close_path();
1453 	_test_scissor();
1454 	_test_reset_scissor();
1455 	_test_font_size();
1456 	_test_font_face();
1457 	_test_text();
1458 	_test_image();
1459 	_test_bitmap();
1460 	_test_custom();
1461 	_test_stroke_width();
1462 
1463 	_test_triple();
1464 
1465 	return EXIT_SUCCESS;
1466 }
1467