1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2011 Intel Corporation
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *	Chris Wilson <chris@chris-wilson.co.uk>
36
 */
37

            
38
#include "cairoint.h"
39

            
40
#include "cairo-compositor-private.h"
41
#include "cairo-damage-private.h"
42
#include "cairo-error-private.h"
43

            
44
cairo_int_status_t
45
638653
_cairo_compositor_paint (const cairo_compositor_t	*compositor,
46
			 cairo_surface_t		*surface,
47
			 cairo_operator_t		 op,
48
			 const cairo_pattern_t		*source,
49
			 const cairo_clip_t		*clip)
50
{
51
    cairo_composite_rectangles_t extents;
52
    cairo_int_status_t status;
53

            
54
    TRACE ((stderr, "%s\n", __FUNCTION__));
55
638653
    status = _cairo_composite_rectangles_init_for_paint (&extents, surface,
56
							 op, source,
57
							 clip);
58
638653
    if (unlikely (status))
59
76103
	return status;
60

            
61
    do {
62
562550
	while (compositor->paint == NULL)
63
	    compositor = compositor->delegate;
64

            
65
562550
	status = compositor->paint (compositor, &extents);
66

            
67
562550
	compositor = compositor->delegate;
68
562550
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
69

            
70
562550
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
71
	TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
72
		__FUNCTION__,
73
		extents.unbounded.x, extents.unbounded.y,
74
		extents.unbounded.width, extents.unbounded.height));
75
	surface->damage = _cairo_damage_add_rectangle (surface->damage,
76
						       &extents.unbounded);
77
    }
78

            
79
562550
    _cairo_composite_rectangles_fini (&extents);
80

            
81
562550
    return status;
82
}
83

            
84
cairo_int_status_t
85
4614
_cairo_compositor_mask (const cairo_compositor_t	*compositor,
86
			cairo_surface_t			*surface,
87
			cairo_operator_t		 op,
88
			const cairo_pattern_t		*source,
89
			const cairo_pattern_t		*mask,
90
			const cairo_clip_t		*clip)
91
{
92
    cairo_composite_rectangles_t extents;
93
    cairo_int_status_t status;
94

            
95
    TRACE ((stderr, "%s\n", __FUNCTION__));
96
4614
    status = _cairo_composite_rectangles_init_for_mask (&extents, surface,
97
							op, source, mask,
98
							clip);
99
4614
    if (unlikely (status))
100
48
	return status;
101

            
102
    do {
103
5310
	while (compositor->mask == NULL)
104
372
	    compositor = compositor->delegate;
105

            
106
4938
	status = compositor->mask (compositor, &extents);
107

            
108
4938
	compositor = compositor->delegate;
109
4938
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
110

            
111
4566
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
112
	TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
113
		__FUNCTION__,
114
		extents.unbounded.x, extents.unbounded.y,
115
		extents.unbounded.width, extents.unbounded.height));
116
	surface->damage = _cairo_damage_add_rectangle (surface->damage,
117
						       &extents.unbounded);
118
    }
119

            
120
4566
    _cairo_composite_rectangles_fini (&extents);
121

            
122
4566
    return status;
123
}
124

            
125
static cairo_int_status_t
126
40053
_cairo_compositor_stroke_impl (const cairo_compositor_t	*compositor,
127
			       cairo_surface_t		*surface,
128
			       cairo_operator_t		 op,
129
			       const cairo_pattern_t		*source,
130
			       const cairo_path_fixed_t	*path,
131
			       const cairo_stroke_style_t	*style,
132
			       const cairo_matrix_t		*ctm,
133
			       const cairo_matrix_t		*ctm_inverse,
134
			       double			 tolerance,
135
			       cairo_antialias_t		 antialias,
136
			       const cairo_clip_t		*clip)
137
{
138
    cairo_composite_rectangles_t extents;
139
    cairo_int_status_t status;
140

            
141
    TRACE ((stderr, "%s\n", __FUNCTION__));
142

            
143
40053
    if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1)
144
36
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
145

            
146
40017
    status = _cairo_composite_rectangles_init_for_stroke (&extents, surface,
147
							  op, source,
148
							  path, style, ctm,
149
							  clip);
150
40017
    if (unlikely (status))
151
51
	return status;
152

            
153
    do {
154
39978
	while (compositor->stroke == NULL)
155
	    compositor = compositor->delegate;
156

            
157
39978
	status = compositor->stroke (compositor, &extents,
158
				     path, style, ctm, ctm_inverse,
159
				     tolerance, antialias);
160

            
161
39978
	compositor = compositor->delegate;
162
39978
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
163

            
164
39966
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
165
	TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
166
		__FUNCTION__,
167
		extents.unbounded.x, extents.unbounded.y,
168
		extents.unbounded.width, extents.unbounded.height));
169
	surface->damage = _cairo_damage_add_rectangle (surface->damage,
170
						       &extents.unbounded);
171
    }
172

            
173
39966
    _cairo_composite_rectangles_fini (&extents);
174

            
175
39966
    return status;
176
}
177

            
178
cairo_int_status_t
179
40053
_cairo_compositor_stroke (const cairo_compositor_t	*compositor,
180
			  cairo_surface_t		*surface,
181
			  cairo_operator_t		 op,
182
			  const cairo_pattern_t	*source,
183
			  const cairo_path_fixed_t	*path,
184
			  const cairo_stroke_style_t	*style,
185
			  const cairo_matrix_t		*ctm,
186
			  const cairo_matrix_t		*ctm_inverse,
187
			  double			 tolerance,
188
			  cairo_antialias_t		 antialias,
189
			  const cairo_clip_t		*clip)
190
{
191
40053
    if (!style->is_hairline)
192
40023
	return _cairo_compositor_stroke_impl (compositor, surface,
193
				              op, source, path,
194
					      style, ctm, ctm_inverse,
195
					      tolerance, antialias, clip);
196
    else {
197
	cairo_stroke_style_t hairline_style;
198
	cairo_status_t status;
199
	cairo_matrix_t identity;
200

            
201
30
	status = _cairo_stroke_style_init_copy (&hairline_style, style);
202
30
	if (unlikely (status))
203
	    return status;
204
	
205
30
	hairline_style.line_width = 1.0;
206

            
207
30
	cairo_matrix_init_identity (&identity);
208

            
209
30
	status = _cairo_compositor_stroke_impl (compositor, surface,
210
					        op, source, path,
211
					        &hairline_style, &identity, &identity,
212
					        tolerance, antialias, clip);
213

            
214
30
	_cairo_stroke_style_fini (&hairline_style);
215

            
216
30
	return status;
217
    }
218
}
219

            
220
cairo_int_status_t
221
498678
_cairo_compositor_fill (const cairo_compositor_t	*compositor,
222
			cairo_surface_t			*surface,
223
			cairo_operator_t		 op,
224
			const cairo_pattern_t		*source,
225
			const cairo_path_fixed_t	*path,
226
			cairo_fill_rule_t		 fill_rule,
227
			double				 tolerance,
228
			cairo_antialias_t		 antialias,
229
			const cairo_clip_t		*clip)
230
{
231
    cairo_composite_rectangles_t extents;
232
    cairo_int_status_t status;
233

            
234
    TRACE ((stderr, "%s\n", __FUNCTION__));
235
498678
    status = _cairo_composite_rectangles_init_for_fill (&extents, surface,
236
							op, source, path,
237
							clip);
238
498678
    if (unlikely (status))
239
666
	return status;
240

            
241
    do {
242
498396
	while (compositor->fill == NULL)
243
	    compositor = compositor->delegate;
244

            
245
498396
	status = compositor->fill (compositor, &extents,
246
				   path, fill_rule, tolerance, antialias);
247

            
248
498396
	compositor = compositor->delegate;
249
498396
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
250

            
251
498012
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
252
	TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
253
		__FUNCTION__,
254
		extents.unbounded.x, extents.unbounded.y,
255
		extents.unbounded.width, extents.unbounded.height));
256
	surface->damage = _cairo_damage_add_rectangle (surface->damage,
257
						       &extents.unbounded);
258
    }
259

            
260
498012
    _cairo_composite_rectangles_fini (&extents);
261

            
262
498012
    return status;
263
}
264

            
265
cairo_int_status_t
266
69792
_cairo_compositor_glyphs (const cairo_compositor_t		*compositor,
267
			  cairo_surface_t			*surface,
268
			  cairo_operator_t			 op,
269
			  const cairo_pattern_t			*source,
270
			  cairo_glyph_t				*glyphs,
271
			  int					 num_glyphs,
272
			  cairo_scaled_font_t			*scaled_font,
273
			  const cairo_clip_t			*clip)
274
{
275
    cairo_composite_rectangles_t extents;
276
    cairo_bool_t overlap;
277
    cairo_int_status_t status;
278

            
279
    TRACE ((stderr, "%s\n", __FUNCTION__));
280
69792
    status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
281
							  op, source,
282
							  scaled_font,
283
							  glyphs, num_glyphs,
284
							  clip, &overlap);
285
69792
    if (unlikely (status))
286
1185
	return status;
287

            
288
    do {
289
205821
	while (compositor->glyphs == NULL)
290
137214
	    compositor = compositor->delegate;
291

            
292
68607
	status = compositor->glyphs (compositor, &extents,
293
				     scaled_font, glyphs, num_glyphs, overlap);
294

            
295
68607
	compositor = compositor->delegate;
296
68607
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
297

            
298
68607
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
299
	TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
300
		__FUNCTION__,
301
		extents.unbounded.x, extents.unbounded.y,
302
		extents.unbounded.width, extents.unbounded.height));
303
	surface->damage = _cairo_damage_add_rectangle (surface->damage,
304
						       &extents.unbounded);
305
    }
306

            
307
68607
    _cairo_composite_rectangles_fini (&extents);
308

            
309
68607
    return status;
310
}