fa16f72f056e4bbfe77645c06c7ea3929ef5430d
[platform/core/graphics/cairo.git] / test / finer-grained-fallbacks.c
1 /*
2  * Copyright © 2008 Adrian Johnson
3  *
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:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
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
22  * SOFTWARE.
23  *
24  * Author: Adrian Johnson <ajohnson@redneon.com>
25  */
26
27 #include "cairo-test.h"
28
29 #define CIRCLE_SIZE 10
30 #define PAD 2
31 #define WIDTH (CIRCLE_SIZE*6.5 + PAD)
32 #define HEIGHT (CIRCLE_SIZE*7.0 + PAD)
33
34 static void
35 draw_circle (cairo_t *cr, double x, double y)
36 {
37     cairo_save (cr);
38     cairo_translate (cr, x, y);
39     cairo_arc (cr, 0, 0, CIRCLE_SIZE / 2, 0., 2. * M_PI);
40     cairo_fill (cr);
41     cairo_restore (cr);
42 }
43
44 static void
45 draw_image_circle (cairo_t *cr, cairo_surface_t *source, double x, double y)
46 {
47     cairo_save (cr);
48
49     cairo_set_source_surface (cr, source, x, y);
50     cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REFLECT);
51     cairo_rectangle (cr, x, y, CIRCLE_SIZE, CIRCLE_SIZE);
52     cairo_fill (cr);
53
54     cairo_restore (cr);
55 }
56
57 static void
58 draw_circles (cairo_t *cr)
59 {
60     draw_circle (cr, 0,               -CIRCLE_SIZE*0.1);
61     draw_circle (cr, CIRCLE_SIZE*0.4,  CIRCLE_SIZE*0.25);
62
63     draw_circle (cr, CIRCLE_SIZE*2, 0);
64     draw_circle (cr, CIRCLE_SIZE*4, 0);
65     draw_circle (cr, CIRCLE_SIZE*6, 0);
66 }
67
68 static void
69 draw_image_circles (cairo_t *cr, cairo_surface_t *source)
70 {
71     draw_image_circle (cr, source, 0,               -CIRCLE_SIZE*0.1);
72     draw_image_circle (cr, source, CIRCLE_SIZE*0.4,  CIRCLE_SIZE*0.25);
73
74     draw_image_circle (cr, source, CIRCLE_SIZE*2, 0);
75     draw_image_circle (cr, source, CIRCLE_SIZE*4, 0);
76     draw_image_circle (cr, source, CIRCLE_SIZE*6, 0);
77 }
78
79 /* For each of circle and fallback_circle we draw:
80  *  - two overlapping
81  *  - one isolated
82  *  - one off the page
83  *  - one overlapping the edge of the page.
84  *
85  * We also draw a circle and fallback_circle overlapping each other.
86  *
87  * Circles are drawn in green. An opaque color and CAIRO_OPERATOR_OVER
88  * is used to ensure they will be emitted as a vectors in PS/PDF.
89  *
90  * Fallback circles are drawn in red. CAIRO_OPERATOR_ADD is used to
91  * ensure they will be emitted as a fallback image in PS/PDF.
92  *
93  * In order to trigger a fallback for SVG, we need to use a surface with
94  * REFLECT.
95  */
96 static cairo_surface_t *
97 surface_create (cairo_t *target)
98 {
99     cairo_surface_t *surface;
100     cairo_t *cr;
101
102     surface = cairo_surface_create_similar (cairo_get_target (target),
103                                             CAIRO_CONTENT_COLOR_ALPHA,
104                                             CIRCLE_SIZE, CIRCLE_SIZE);
105     cr = cairo_create (surface);
106     cairo_surface_destroy (surface);
107
108     cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
109     draw_circle (cr, CIRCLE_SIZE/2, CIRCLE_SIZE/2);
110
111     surface = cairo_surface_reference (cairo_get_target (cr));
112     cairo_destroy (cr);
113
114     return surface;
115 }
116
117 static cairo_test_status_t
118 draw (cairo_t *cr, int width, int height)
119 {
120     cairo_surface_t *surface;
121
122     cairo_translate (cr, PAD, PAD);
123
124     cairo_save (cr);
125
126     /* Draw overlapping circle and fallback circle */
127     cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
128     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
129     draw_circle (cr, CIRCLE_SIZE*0.5,  CIRCLE_SIZE*1.5);
130
131     cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
132     cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
133     draw_circle (cr, CIRCLE_SIZE*0.75, CIRCLE_SIZE*1.75);
134
135     /* Draw circles */
136     cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
137     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
138     cairo_translate (cr, CIRCLE_SIZE*2.5, CIRCLE_SIZE*0.6);
139     draw_circles (cr);
140
141     /* Draw fallback circles */
142     cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
143     cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
144     cairo_translate (cr, 0, CIRCLE_SIZE*2);
145     draw_circles (cr);
146
147     cairo_restore (cr);
148     cairo_translate (cr, 0, CIRCLE_SIZE * 3.5);
149
150     /* Draw using fallback surface */
151     surface = surface_create (cr);
152
153     cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
154     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
155     draw_circle (cr, CIRCLE_SIZE*0.5,  CIRCLE_SIZE*1.5);
156
157     cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
158     draw_image_circle (cr, surface, CIRCLE_SIZE/4, CIRCLE_SIZE + CIRCLE_SIZE/4);
159
160     /* Draw circles */
161     cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
162     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
163     cairo_translate (cr, CIRCLE_SIZE*2.5, CIRCLE_SIZE*0.6);
164     draw_circles (cr);
165
166     cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
167     cairo_translate (cr, -CIRCLE_SIZE/2, CIRCLE_SIZE*1.5);
168     draw_image_circles (cr, surface);
169
170     cairo_surface_destroy (surface);
171
172     return CAIRO_TEST_SUCCESS;
173 }
174
175 CAIRO_TEST (finer_grained_fallbacks,
176             "Test that multiple PS/PDF fallback images in various locations are correct",
177             "fallbacks", /* keywords */
178             NULL, /* requirements */
179             WIDTH, HEIGHT,
180             NULL, draw)