2 * Copyright © 2011,2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Author: Chris Wilson <chris@chris-wilson.co.uk>
27 #include "cairo-test.h"
30 #define SIZE 60 /* needs to be big to check large area effects (dithering) */
35 #define TT_FONT_SIZE 32.0
37 #define GENERATE_REF 0
39 static uint32_t data[16] = {
40 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
41 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
43 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff,
44 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff
47 static const char *png_filename = "romedalen.png";
52 cairo_set_source_rgb (cr, 0, 0, 1);
55 cairo_translate (cr, 2, 2);
56 cairo_scale (cr, 0.5, 0.5);
58 cairo_set_source_rgb (cr, 1, 0, 0);
65 paint_alpha (cairo_t *cr)
67 cairo_surface_t *surface;
69 surface = cairo_image_surface_create_for_data ((unsigned char *) data,
70 CAIRO_FORMAT_RGB24, 4, 4, 16);
72 cairo_test_paint_checkered (cr);
74 cairo_scale (cr, 4, 4);
76 cairo_set_source_surface (cr, surface, 2 , 2);
77 cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
78 cairo_paint_with_alpha (cr, 0.5);
80 cairo_surface_finish (surface); /* data will go out of scope */
81 cairo_surface_destroy (surface);
87 paint_alpha_solid_clip (cairo_t *cr)
89 cairo_test_paint_checkered (cr);
91 cairo_rectangle (cr, 2.5, 2.5, 27, 27);
94 cairo_set_source_rgb (cr, 1., 0.,0.);
95 cairo_paint_with_alpha (cr, 0.5);
101 paint_alpha_clip (cairo_t *cr)
103 cairo_surface_t *surface;
105 surface = cairo_image_surface_create_for_data ((unsigned char *) data,
106 CAIRO_FORMAT_RGB24, 4, 4, 16);
108 cairo_test_paint_checkered (cr);
110 cairo_rectangle (cr, 10.5, 10.5, 11, 11);
113 cairo_scale (cr, 4, 4);
115 cairo_set_source_surface (cr, surface, 2 , 2);
116 cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
117 cairo_paint_with_alpha (cr, 0.5);
119 cairo_surface_finish (surface); /* data will go out of scope */
120 cairo_surface_destroy (surface);
126 paint_alpha_clip_mask (cairo_t *cr)
128 cairo_surface_t *surface;
130 surface = cairo_image_surface_create_for_data ((unsigned char *) data,
131 CAIRO_FORMAT_RGB24, 4, 4, 16);
133 cairo_test_paint_checkered (cr);
135 cairo_move_to (cr, 16, 5);
136 cairo_line_to (cr, 5, 16);
137 cairo_line_to (cr, 16, 27);
138 cairo_line_to (cr, 27, 16);
141 cairo_scale (cr, 4, 4);
143 cairo_set_source_surface (cr, surface, 2 , 2);
144 cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
145 cairo_paint_with_alpha (cr, 0.5);
147 cairo_surface_finish (surface); /* data will go out of scope */
148 cairo_surface_destroy (surface);
154 select_font_face (cairo_t *cr)
156 /* We draw in the default black, so paint white first. */
157 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
160 cairo_set_source_rgb (cr, 0, 0, 0); /* black */
162 cairo_set_font_size (cr, TEXT_SIZE);
163 cairo_move_to (cr, 0, TEXT_SIZE);
165 cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Serif",
166 CAIRO_FONT_SLANT_NORMAL,
167 CAIRO_FONT_WEIGHT_NORMAL);
168 cairo_show_text (cr, "i-am-serif");
170 cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
171 CAIRO_FONT_SLANT_NORMAL,
172 CAIRO_FONT_WEIGHT_NORMAL);
173 cairo_show_text (cr, " i-am-sans");
175 cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans Mono",
176 CAIRO_FONT_SLANT_NORMAL,
177 CAIRO_FONT_WEIGHT_NORMAL);
178 cairo_show_text (cr, " i-am-mono");
184 fill_alpha (cairo_t *cr)
186 const double alpha = 1./3;
189 /* flatten to white */
190 cairo_set_source_rgb (cr, 1, 1, 1);
194 cairo_rectangle (cr, PAD, PAD, SIZE, SIZE);
195 cairo_set_source_rgba (cr, 1, 0, 0, alpha);
199 cairo_translate (cr, SIZE + 2 * PAD, 0);
200 cairo_arc (cr, PAD + SIZE / 2., PAD + SIZE / 2., SIZE / 2., 0, 2 * M_PI);
201 cairo_set_source_rgba (cr, 0, 1, 0, alpha);
205 cairo_translate (cr, 0, SIZE + 2 * PAD);
206 cairo_move_to (cr, PAD + SIZE / 2, PAD);
207 cairo_line_to (cr, PAD + SIZE, PAD + SIZE);
208 cairo_line_to (cr, PAD, PAD + SIZE);
209 cairo_set_source_rgba (cr, 0, 0, 1, alpha);
213 cairo_translate (cr, -(SIZE + 2 * PAD) + SIZE/2., SIZE/2.);
214 for (n = 0; n < 5; n++) {
216 SIZE/2 * cos (2*n * 2*M_PI / 10),
217 SIZE/2 * sin (2*n * 2*M_PI / 10));
220 SIZE/4 * cos ((2*n+1)*2*M_PI / 10),
221 SIZE/4 * sin ((2*n+1)*2*M_PI / 10));
223 cairo_set_source_rgba (cr, 0, 0, 0, alpha);
230 self_intersecting (cairo_t *cr)
232 cairo_set_source_rgb (cr, 1, 1, 1);
235 cairo_translate (cr, 1.0, 1.0);
237 cairo_set_source_rgb (cr, 1, 0, 0); /* red */
239 /* First draw the desired shape with a fill */
240 cairo_rectangle (cr, 0.5, 0.5, 4.0, 4.0);
241 cairo_rectangle (cr, 3.5, 3.5, 4.0, 4.0);
242 cairo_rectangle (cr, 3.5, 1.5, -2.0, 2.0);
243 cairo_rectangle (cr, 6.5, 4.5, -2.0, 2.0);
247 /* Then try the same thing with a stroke */
248 cairo_translate (cr, 0, 10);
249 cairo_move_to (cr, 1.0, 1.0);
250 cairo_rel_line_to (cr, 3.0, 0.0);
251 cairo_rel_line_to (cr, 0.0, 6.0);
252 cairo_rel_line_to (cr, 3.0, 0.0);
253 cairo_rel_line_to (cr, 0.0, -3.0);
254 cairo_rel_line_to (cr, -6.0, 0.0);
255 cairo_close_path (cr);
257 cairo_set_line_width (cr, 1.0);
264 draw_text_transform (cairo_t *cr)
269 cairo_matrix_init (&tm, 1, 0,
272 cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE);
273 cairo_set_font_matrix (cr, &tm);
276 cairo_move_to (cr, 50, TT_SIZE-TT_PAD);
277 cairo_show_text (cr, "A");
279 /* rotate and scale */
280 cairo_matrix_init_rotate (&tm, M_PI / 2);
281 cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE * 2.0);
282 cairo_set_font_matrix (cr, &tm);
285 cairo_move_to (cr, TT_PAD, TT_PAD + 25);
286 cairo_show_text (cr, "A");
288 cairo_matrix_init_rotate (&tm, M_PI / 2);
289 cairo_matrix_scale (&tm, TT_FONT_SIZE * 2.0, TT_FONT_SIZE);
290 cairo_set_font_matrix (cr, &tm);
293 cairo_move_to (cr, TT_PAD, TT_PAD + 50);
294 cairo_show_text (cr, "A");
298 text_transform (cairo_t *cr)
300 const cairo_test_context_t *ctx = cairo_test_get_context (cr);
301 cairo_pattern_t *pattern;
303 cairo_set_source_rgb (cr, 1., 1., 1.);
306 cairo_set_source_rgb (cr, 0., 0., 0.);
308 cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
309 CAIRO_FONT_SLANT_NORMAL,
310 CAIRO_FONT_WEIGHT_NORMAL);
312 draw_text_transform (cr);
314 cairo_translate (cr, TT_SIZE, TT_SIZE);
315 cairo_rotate (cr, M_PI);
317 pattern = cairo_test_create_pattern_from_png (ctx, png_filename);
318 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
319 cairo_set_source (cr, pattern);
320 cairo_pattern_destroy (pattern);
322 draw_text_transform (cr);
327 /* And here begins the recording and replaying... */
330 record_create (cairo_t *target)
332 cairo_surface_t *surface;
335 surface = cairo_recording_surface_create (cairo_surface_get_content (cairo_get_target (target)), NULL);
336 cr = cairo_create (surface);
337 cairo_surface_destroy (surface);
342 static cairo_surface_t *
343 record_get (cairo_t *target)
345 cairo_surface_t *surface;
347 surface = cairo_surface_reference (cairo_get_target (target));
348 cairo_destroy (target);
353 static cairo_test_status_t
354 record_replay (cairo_t *cr, cairo_t *(*func)(cairo_t *), int width, int height)
356 cairo_surface_t *surface;
361 cairo_surface_t *image;
365 surface = cairo_get_target (cr);
369 image = cairo_surface_map_to_image (surface, NULL);
371 switch (cairo_image_surface_get_format (image)) {
372 case CAIRO_FORMAT_ARGB32:
373 case CAIRO_FORMAT_RGB24:
374 case CAIRO_FORMAT_RGB30:
377 case CAIRO_FORMAT_RGB16_565:
380 case CAIRO_FORMAT_A8:
383 case CAIRO_FORMAT_A1:
384 case CAIRO_FORMAT_INVALID:
386 return CAIRO_TEST_FAILURE;
389 data = cairo_image_surface_get_data (image);
390 stride = cairo_image_surface_get_stride (image);
392 tmp = malloc (stride);
394 return CAIRO_TEST_FAILURE;
396 for (y = 0; y < height; y++) {
397 uint8_t *row = data + y * stride;
398 for (x = 0; x < width/2; x++) {
399 memcpy (tmp, row + bpp * x, bpp);
400 memcpy (row + bpp * x, row + bpp * (width - x - 1), bpp);
401 memcpy (row + bpp * (width - x - 1), tmp, bpp);
405 for (y = 0; y < height/2; y++) {
406 memcpy (tmp, data + y * stride, stride);
407 memcpy (data + y * stride, data + (height - y - 1) * stride, stride);
408 memcpy (data + (height - y - 1) * stride, tmp, stride);
413 cairo_surface_unmap_image (surface, image);
416 surface = record_get (func (record_create (cr)));
418 cairo_scale (cr, -1, -1);
419 cairo_translate (cr, -width, -height);
420 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
421 cairo_set_source_surface (cr, surface, 0, 0);
422 cairo_surface_destroy (surface);
423 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
425 for (y = 0; y < height; y += 2) {
426 for (x = 0; x < width; x += 2) {
427 cairo_rectangle (cr, x, y, 2, 2);
430 cairo_reset_clip (cr);
435 return CAIRO_TEST_SUCCESS;
438 static cairo_test_status_t
439 record_whole_replay (cairo_t *cr, cairo_t *(*func)(cairo_t *), int width, int height)
441 cairo_surface_t *surface;
445 cairo_surface_t *image;
450 surface = cairo_get_target (cr);
454 image = cairo_surface_map_to_image (surface, NULL);
456 switch (cairo_image_surface_get_format (image)) {
457 case CAIRO_FORMAT_ARGB32:
458 case CAIRO_FORMAT_RGB24:
459 case CAIRO_FORMAT_RGB30:
462 case CAIRO_FORMAT_RGB16_565:
465 case CAIRO_FORMAT_A8:
468 case CAIRO_FORMAT_A1:
469 case CAIRO_FORMAT_INVALID:
471 return CAIRO_TEST_FAILURE;
474 data = cairo_image_surface_get_data (image);
475 stride = cairo_image_surface_get_stride (image);
477 tmp = malloc (stride);
479 return CAIRO_TEST_FAILURE;
481 for (y = 0; y < height; y++) {
482 uint8_t *row = data + y * stride;
483 for (x = 0; x < width/2; x++) {
484 memcpy (tmp, row + bpp * x, bpp);
485 memcpy (row + bpp * x, row + bpp * (width - x - 1), bpp);
486 memcpy (row + bpp * (width - x - 1), tmp, bpp);
490 for (y = 0; y < height/2; y++) {
491 memcpy (tmp, data + y * stride, stride);
492 memcpy (data + y * stride, data + (height - y - 1) * stride, stride);
493 memcpy (data + (height - y - 1) * stride, tmp, stride);
498 cairo_surface_unmap_image (surface, image);
501 surface = record_get (func (record_create (cr)));
503 cairo_scale (cr, -1, -1);
504 cairo_translate (cr, -width, -height);
505 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
506 cairo_set_source_surface (cr, surface, 0, 0);
507 cairo_surface_destroy (surface);
508 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
513 return CAIRO_TEST_SUCCESS;
516 static cairo_test_status_t
517 record_paint (cairo_t *cr, int width, int height)
519 return record_replay (cr, paint, width, height);
522 static cairo_test_status_t
523 record_paint_alpha (cairo_t *cr, int width, int height)
525 return record_replay (cr, paint_alpha, width, height);
528 static cairo_test_status_t
529 record_paint_alpha_solid_clip (cairo_t *cr, int width, int height)
531 return record_replay (cr, paint_alpha_solid_clip, width, height);
534 static cairo_test_status_t
535 record_paint_alpha_clip (cairo_t *cr, int width, int height)
537 return record_replay (cr, paint_alpha_clip, width, height);
540 static cairo_test_status_t
541 record_paint_alpha_clip_mask (cairo_t *cr, int width, int height)
543 return record_replay (cr, paint_alpha_clip_mask, width, height);
546 static cairo_test_status_t
547 record_fill_alpha (cairo_t *cr, int width, int height)
549 return record_replay (cr, fill_alpha, width, height);
552 static cairo_test_status_t
553 record_self_intersecting (cairo_t *cr, int width, int height)
555 return record_replay (cr, self_intersecting, width, height);
558 static cairo_test_status_t
559 record_select_font_face (cairo_t *cr, int width, int height)
561 return record_replay (cr, select_font_face, width, height);
564 static cairo_test_status_t
565 record_text_transform (cairo_t *cr, int width, int height)
567 return record_replay (cr, text_transform, width, height);
570 static cairo_test_status_t
571 record_whole_paint (cairo_t *cr, int width, int height)
573 return record_whole_replay (cr, paint, width, height);
576 static cairo_test_status_t
577 record_whole_paint_alpha (cairo_t *cr, int width, int height)
579 return record_whole_replay (cr, paint_alpha, width, height);
582 static cairo_test_status_t
583 record_whole_paint_alpha_solid_clip (cairo_t *cr, int width, int height)
585 return record_whole_replay (cr, paint_alpha_solid_clip, width, height);
588 static cairo_test_status_t
589 record_whole_paint_alpha_clip (cairo_t *cr, int width, int height)
591 return record_whole_replay (cr, paint_alpha_clip, width, height);
594 static cairo_test_status_t
595 record_whole_paint_alpha_clip_mask (cairo_t *cr, int width, int height)
597 return record_whole_replay (cr, paint_alpha_clip_mask, width, height);
600 static cairo_test_status_t
601 record_whole_fill_alpha (cairo_t *cr, int width, int height)
603 return record_whole_replay (cr, fill_alpha, width, height);
606 static cairo_test_status_t
607 record_whole_self_intersecting (cairo_t *cr, int width, int height)
609 return record_whole_replay (cr, self_intersecting, width, height);
612 static cairo_test_status_t
613 record_whole_select_font_face (cairo_t *cr, int width, int height)
615 return record_whole_replay (cr, select_font_face, width, height);
618 static cairo_test_status_t
619 record_whole_text_transform (cairo_t *cr, int width, int height)
621 return record_whole_replay (cr, text_transform, width, height);
624 CAIRO_TEST (recordflip_whole_paint,
625 "Test replayed calls to cairo_paint",
626 "paint,record", /* keywords */
627 NULL, /* requirements */
629 NULL, record_whole_paint)
630 CAIRO_TEST (recordflip_whole_paint_alpha,
631 "Simple test of cairo_paint_with_alpha",
632 "record, paint, alpha", /* keywords */
633 NULL, /* requirements */
635 NULL, record_whole_paint_alpha)
636 CAIRO_TEST (recordflip_whole_paint_alpha_solid_clip,
637 "Simple test of cairo_paint_with_alpha+unaligned clip",
638 "record, paint, alpha, clip", /* keywords */
639 NULL, /* requirements */
641 NULL, record_whole_paint_alpha_solid_clip)
642 CAIRO_TEST (recordflip_whole_paint_alpha_clip,
643 "Simple test of cairo_paint_with_alpha+unaligned clip",
644 "record, paint, alpha, clip", /* keywords */
645 NULL, /* requirements */
647 NULL, record_whole_paint_alpha_clip)
648 CAIRO_TEST (recordflip_whole_paint_alpha_clip_mask,
649 "Simple test of cairo_paint_with_alpha+triangular clip",
650 "record, paint, alpha, clip", /* keywords */
651 NULL, /* requirements */
653 NULL, record_whole_paint_alpha_clip_mask)
654 CAIRO_TEST (recordflip_whole_fill_alpha,
655 "Tests using set_rgba();fill()",
656 "record,fill, alpha", /* keywords */
657 NULL, /* requirements */
658 (2*SIZE + 4*PAD), (2*SIZE + 4*PAD),
659 NULL, record_whole_fill_alpha)
660 CAIRO_TEST (recordflip_whole_select_font_face,
661 "Tests using cairo_select_font_face to draw text in different faces",
662 "record, font", /* keywords */
663 NULL, /* requirements */
664 192, (TEXT_SIZE + 4),
665 NULL, record_whole_select_font_face)
666 CAIRO_TEST (recordflip_whole_self_intersecting,
667 "Test strokes of self-intersecting paths",
668 "record, stroke, trap", /* keywords */
669 NULL, /* requirements */
671 NULL, record_whole_self_intersecting)
672 CAIRO_TEST (recordflip_whole_text_transform,
673 "Test various applications of the font matrix",
674 "record, text, transform", /* keywords */
675 NULL, /* requirements */
677 NULL, record_whole_text_transform)
680 CAIRO_TEST (recordflip_paint,
681 "Test replayed calls to cairo_paint",
682 "paint,record", /* keywords */
683 NULL, /* requirements */
686 CAIRO_TEST (recordflip_paint_alpha,
687 "Simple test of cairo_paint_with_alpha",
688 "record, paint, alpha", /* keywords */
689 NULL, /* requirements */
691 NULL, record_paint_alpha)
692 CAIRO_TEST (recordflip_paint_alpha_solid_clip,
693 "Simple test of cairo_paint_with_alpha+unaligned clip",
694 "record, paint, alpha, clip", /* keywords */
695 NULL, /* requirements */
697 NULL, record_paint_alpha_solid_clip)
698 CAIRO_TEST (recordflip_paint_alpha_clip,
699 "Simple test of cairo_paint_with_alpha+unaligned clip",
700 "record, paint, alpha, clip", /* keywords */
701 NULL, /* requirements */
703 NULL, record_paint_alpha_clip)
704 CAIRO_TEST (recordflip_paint_alpha_clip_mask,
705 "Simple test of cairo_paint_with_alpha+triangular clip",
706 "record, paint, alpha, clip", /* keywords */
707 NULL, /* requirements */
709 NULL, record_paint_alpha_clip_mask)
710 CAIRO_TEST (recordflip_fill_alpha,
711 "Tests using set_rgba();fill()",
712 "record,fill, alpha", /* keywords */
713 NULL, /* requirements */
714 (2*SIZE + 4*PAD), (2*SIZE + 4*PAD),
715 NULL, record_fill_alpha)
716 CAIRO_TEST (recordflip_select_font_face,
717 "Tests using cairo_select_font_face to draw text in different faces",
718 "record, font", /* keywords */
719 NULL, /* requirements */
720 192, (TEXT_SIZE + 4),
721 NULL, record_select_font_face)
722 CAIRO_TEST (recordflip_self_intersecting,
723 "Test strokes of self-intersecting paths",
724 "record, stroke, trap", /* keywords */
725 NULL, /* requirements */
727 NULL, record_self_intersecting)
728 CAIRO_TEST (recordflip_text_transform,
729 "Test various applications of the font matrix",
730 "record, text, transform", /* keywords */
731 NULL, /* requirements */
733 NULL, record_text_transform)