Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 1... Line 1...
1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
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
2
/* cairo - a vector graphics library with display and print output
3
 *
3
 *
4
 * Copyright © 2002 University of Southern California
4
 * Copyright © 2002 University of Southern California
5
 * Copyright © 2005 Red Hat, Inc.
5
 * Copyright © 2005 Red Hat, Inc.
-
 
6
 * Copyright © 2011 Intel Corporation
6
 *
7
 *
7
 * This library is free software; you can redistribute it and/or
8
 * This library is free software; you can redistribute it and/or
8
 * modify it either under the terms of the GNU Lesser General Public
9
 * modify it either under the terms of the GNU Lesser General Public
9
 * License version 2.1 as published by the Free Software Foundation
10
 * License version 2.1 as published by the Free Software Foundation
10
 * (the "LGPL") or, at your option, under the terms of the Mozilla
11
 * (the "LGPL") or, at your option, under the terms of the Mozilla
Line 38... Line 39...
38
 *	Chris Wilson 
39
 *	Chris Wilson 
39
 */
40
 */
Line 40... Line 41...
40
 
41
 
Line 41... Line -...
41
#include "cairoint.h"
-
 
42
 
-
 
43
#include "cairo-boxes-private.h"
-
 
44
#include "cairo-clip-private.h"
-
 
45
#include "cairo-composite-rectangles-private.h"
42
#include "cairoint.h"
46
#include "cairo-error-private.h"
-
 
47
#include "cairo-region-private.h"
43
 
Line 48... Line -...
48
#include "cairo-spans-private.h"
-
 
49
#include "cairo-surface-fallback-private.h"
-
 
50
 
-
 
51
typedef struct {
-
 
52
    cairo_surface_t *dst;
-
 
53
    cairo_rectangle_int_t extents;
-
 
54
    cairo_image_surface_t *image;
-
 
55
    cairo_rectangle_int_t image_rect;
-
 
56
    void *image_extra;
-
 
57
} fallback_state_t;
-
 
58
 
-
 
59
/**
-
 
60
 * _fallback_init:
-
 
61
 *
-
 
62
 * Acquire destination image surface needed for an image-based
-
 
63
 * fallback.
-
 
64
 *
-
 
65
 * Return value: %CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not
-
 
66
 * visible, %CAIRO_STATUS_SUCCESS if some portion is visible and all
-
 
67
 * went well, or some error status otherwise.
-
 
68
 **/
-
 
69
static cairo_int_status_t
-
 
70
_fallback_init (fallback_state_t *state,
-
 
71
		cairo_surface_t  *dst,
-
 
72
		int               x,
-
 
73
		int               y,
-
 
74
		int               width,
-
 
75
		int               height)
-
 
76
{
-
 
77
    cairo_status_t status;
-
 
78
 
-
 
79
    state->extents.x = x;
-
 
80
    state->extents.y = y;
-
 
81
    state->extents.width = width;
-
 
82
    state->extents.height = height;
-
 
83
 
-
 
84
    state->dst = dst;
-
 
85
 
-
 
86
    status = _cairo_surface_acquire_dest_image (dst, &state->extents,
-
 
87
						&state->image, &state->image_rect,
-
 
88
						&state->image_extra);
-
 
89
    if (unlikely (status))
-
 
90
	return status;
-
 
91
 
-
 
92
 
-
 
93
    /* XXX: This NULL value tucked away in state->image is a rather
-
 
94
     * ugly interface. Cleaner would be to push the
-
 
95
     * CAIRO_INT_STATUS_NOTHING_TO_DO value down into
-
 
96
     * _cairo_surface_acquire_dest_image and its backend
-
 
97
     * counterparts. */
-
 
98
    assert (state->image != NULL);
-
 
99
 
-
 
100
    return CAIRO_STATUS_SUCCESS;
-
 
101
}
-
 
102
 
-
 
103
static void
-
 
104
_fallback_fini (fallback_state_t *state)
-
 
105
{
-
 
106
    _cairo_surface_release_dest_image (state->dst, &state->extents,
-
 
107
				       state->image, &state->image_rect,
-
 
108
				       state->image_extra);
-
 
109
}
-
 
110
 
-
 
111
typedef cairo_status_t
-
 
112
(*cairo_draw_func_t) (void                          *closure,
-
 
113
		      cairo_operator_t               op,
-
 
114
		      const cairo_pattern_t         *src,
-
 
115
		      cairo_surface_t               *dst,
-
 
116
		      int                            dst_x,
-
 
117
		      int                            dst_y,
-
 
118
		      const cairo_rectangle_int_t   *extents,
-
 
119
		      cairo_region_t		    *clip_region);
-
 
120
 
-
 
121
static cairo_status_t
-
 
122
_create_composite_mask_pattern (cairo_surface_pattern_t       *mask_pattern,
-
 
123
				cairo_clip_t                  *clip,
-
 
124
				cairo_draw_func_t              draw_func,
-
 
125
				void                          *draw_closure,
-
 
126
				cairo_surface_t               *dst,
-
 
127
				const cairo_rectangle_int_t   *extents)
-
 
128
{
-
 
129
    cairo_surface_t *mask;
-
 
130
    cairo_region_t *clip_region = NULL, *fallback_region = NULL;
-
 
131
    cairo_status_t status;
-
 
132
    cairo_bool_t clip_surface = FALSE;
-
 
133
 
-
 
134
    if (clip != NULL) {
-
 
135
	status = _cairo_clip_get_region (clip, &clip_region);
-
 
136
	if (unlikely (_cairo_status_is_error (status) ||
-
 
137
		      status == CAIRO_INT_STATUS_NOTHING_TO_DO))
-
 
138
	{
-
 
139
	    return status;
-
 
140
	}
-
 
141
 
-
 
142
	clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
 
143
    }
-
 
144
 
-
 
145
    /* We need to use solid here, because to use CAIRO_OPERATOR_SOURCE with
-
 
146
     * a mask (as called via _cairo_surface_mask) triggers assertion failures.
-
 
147
     */
-
 
148
    mask = _cairo_surface_create_similar_solid (dst,
-
 
149
						CAIRO_CONTENT_ALPHA,
-
 
150
						extents->width,
-
 
151
						extents->height,
-
 
152
						CAIRO_COLOR_TRANSPARENT,
-
 
153
						TRUE);
-
 
154
    if (unlikely (mask->status))
-
 
155
	return mask->status;
-
 
156
 
-
 
157
    if (clip_region && (extents->x || extents->y)) {
-
 
158
	fallback_region = cairo_region_copy (clip_region);
-
 
159
	status = fallback_region->status;
-
 
160
	if (unlikely (status))
-
 
161
	    goto CLEANUP_SURFACE;
-
 
162
 
-
 
163
	cairo_region_translate (fallback_region,
-
 
164
				-extents->x,
-
 
165
				-extents->y);
-
 
166
	clip_region = fallback_region;
-
 
167
    }
-
 
168
 
-
 
169
    status = draw_func (draw_closure, CAIRO_OPERATOR_ADD,
-
 
170
			&_cairo_pattern_white.base, mask,
-
 
171
			extents->x, extents->y,
-
 
172
			extents,
-
 
173
			clip_region);
-
 
174
    if (unlikely (status))
-
 
175
	goto CLEANUP_SURFACE;
-
 
176
 
-
 
177
    if (clip_surface)
-
 
178
	status = _cairo_clip_combine_with_surface (clip, mask, extents->x, extents->y);
-
 
179
 
-
 
180
    _cairo_pattern_init_for_surface (mask_pattern, mask);
-
 
181
 
-
 
182
 CLEANUP_SURFACE:
-
 
183
    if (fallback_region)
-
 
184
        cairo_region_destroy (fallback_region);
-
 
185
    cairo_surface_destroy (mask);
-
 
186
 
-
 
187
    return status;
-
 
188
}
-
 
189
 
-
 
190
/* Handles compositing with a clip surface when the operator allows
-
 
191
 * us to combine the clip with the mask
-
 
192
 */
-
 
193
static cairo_status_t
-
 
194
_clip_and_composite_with_mask (cairo_clip_t                  *clip,
-
 
195
			       cairo_operator_t               op,
-
 
196
			       const cairo_pattern_t         *src,
-
 
197
			       cairo_draw_func_t              draw_func,
-
 
198
			       void                          *draw_closure,
-
 
199
			       cairo_surface_t               *dst,
-
 
200
			       const cairo_rectangle_int_t   *extents)
-
 
201
{
-
 
202
    cairo_surface_pattern_t mask_pattern;
-
 
203
    cairo_status_t status;
-
 
204
 
-
 
205
    status = _create_composite_mask_pattern (&mask_pattern,
-
 
206
					     clip,
-
 
207
					     draw_func, draw_closure,
-
 
208
					     dst, extents);
-
 
209
    if (likely (status == CAIRO_STATUS_SUCCESS)) {
-
 
210
	status = _cairo_surface_composite (op,
-
 
211
					   src, &mask_pattern.base, dst,
-
 
212
					   extents->x,     extents->y,
-
 
213
					   0,              0,
-
 
214
					   extents->x,     extents->y,
-
 
215
					   extents->width, extents->height,
-
 
216
					   NULL);
-
 
217
 
-
 
218
	_cairo_pattern_fini (&mask_pattern.base);
-
 
219
    }
-
 
220
 
-
 
221
    return status;
-
 
222
}
-
 
223
 
-
 
224
/* Handles compositing with a clip surface when we have to do the operation
-
 
225
 * in two pieces and combine them together.
-
 
226
 */
-
 
227
static cairo_status_t
-
 
228
_clip_and_composite_combine (cairo_clip_t                  *clip,
-
 
229
			     cairo_operator_t               op,
-
 
230
			     const cairo_pattern_t         *src,
-
 
231
			     cairo_draw_func_t              draw_func,
-
 
232
			     void                          *draw_closure,
-
 
233
			     cairo_surface_t               *dst,
-
 
234
			     const cairo_rectangle_int_t   *extents)
-
 
235
{
-
 
236
    cairo_surface_t *intermediate;
-
 
237
    cairo_surface_pattern_t pattern;
-
 
238
    cairo_surface_pattern_t clip_pattern;
-
 
239
    cairo_surface_t *clip_surface;
-
 
240
    int clip_x, clip_y;
-
 
241
    cairo_status_t status;
-
 
242
 
-
 
243
    /* We'd be better off here creating a surface identical in format
-
 
244
     * to dst, but we have no way of getting that information. Instead
-
 
245
     * we ask the backend to create a similar surface of identical content,
-
 
246
     * in the belief that the backend will do something useful - like use
-
 
247
     * an identical format. For example, the xlib backend will endeavor to
-
 
248
     * use a compatible depth to enable core protocol routines.
-
 
249
     */
-
 
250
    intermediate =
-
 
251
	_cairo_surface_create_similar_scratch (dst, dst->content,
-
 
252
					       extents->width,
-
 
253
					       extents->height);
-
 
254
    if (intermediate == NULL) {
-
 
255
	intermediate =
-
 
256
	    _cairo_image_surface_create_with_content (dst->content,
-
 
257
						      extents->width,
-
 
258
						      extents->width);
-
 
259
    }
-
 
260
    if (unlikely (intermediate->status))
-
 
261
	return intermediate->status;
-
 
262
 
-
 
263
    /* Initialize the intermediate surface from the destination surface */
-
 
264
    _cairo_pattern_init_for_surface (&pattern, dst);
-
 
265
    status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
-
 
266
				       &pattern.base, NULL, intermediate,
-
 
267
				       extents->x,     extents->y,
-
 
268
				       0,              0,
-
 
269
				       0,              0,
-
 
270
				       extents->width, extents->height,
-
 
271
				       NULL);
-
 
272
    _cairo_pattern_fini (&pattern.base);
-
 
273
    if (unlikely (status))
-
 
274
	goto CLEANUP_SURFACE;
-
 
275
 
-
 
276
    status = (*draw_func) (draw_closure, op,
-
 
277
			   src, intermediate,
-
 
278
			   extents->x, extents->y,
-
 
279
			   extents,
-
 
280
			   NULL);
-
 
281
    if (unlikely (status))
-
 
282
	goto CLEANUP_SURFACE;
-
 
283
 
-
 
284
    assert (clip->path != NULL);
-
 
285
    clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y);
-
 
286
    if (unlikely (clip_surface->status))
-
 
287
	goto CLEANUP_SURFACE;
-
 
288
 
-
 
289
    _cairo_pattern_init_for_surface (&clip_pattern, clip_surface);
-
 
290
 
-
 
291
    /* Combine that with the clip */
-
 
292
    status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_IN,
-
 
293
				       &clip_pattern.base, NULL, intermediate,
-
 
294
				       extents->x - clip_x,
-
 
295
				       extents->y - clip_y,
-
 
296
				       0, 0,
-
 
297
				       0, 0,
-
 
298
				       extents->width, extents->height,
-
 
299
				       NULL);
-
 
300
    if (unlikely (status))
-
 
301
	goto CLEANUP_CLIP;
-
 
302
 
-
 
303
    /* Punch the clip out of the destination */
-
 
304
    status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
-
 
305
				       &clip_pattern.base, NULL, dst,
-
 
306
				       extents->x - clip_x,
-
 
307
				       extents->y - clip_y,
-
 
308
				       0, 0,
-
 
309
				       extents->x, extents->y,
-
 
310
				       extents->width, extents->height,
-
 
311
				       NULL);
-
 
312
    if (unlikely (status))
-
 
313
	goto CLEANUP_CLIP;
-
 
314
 
-
 
315
    /* Now add the two results together */
-
 
316
    _cairo_pattern_init_for_surface (&pattern, intermediate);
-
 
317
    status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
-
 
318
				       &pattern.base, NULL, dst,
-
 
319
				       0,              0,
-
 
320
				       0,              0,
-
 
321
				       extents->x,     extents->y,
-
 
322
				       extents->width, extents->height,
-
 
323
				       NULL);
-
 
324
    _cairo_pattern_fini (&pattern.base);
-
 
325
 
-
 
326
 CLEANUP_CLIP:
-
 
327
    _cairo_pattern_fini (&clip_pattern.base);
-
 
328
 CLEANUP_SURFACE:
-
 
329
    cairo_surface_destroy (intermediate);
-
 
330
 
-
 
331
    return status;
-
 
332
}
-
 
333
 
-
 
334
/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
-
 
335
 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
-
 
336
 */
-
 
337
static cairo_status_t
-
 
338
_clip_and_composite_source (cairo_clip_t                  *clip,
-
 
339
			    const cairo_pattern_t         *src,
-
 
340
			    cairo_draw_func_t              draw_func,
-
 
341
			    void                          *draw_closure,
-
 
342
			    cairo_surface_t               *dst,
-
 
343
			    const cairo_rectangle_int_t   *extents)
-
 
344
{
-
 
345
    cairo_surface_pattern_t mask_pattern;
-
 
346
    cairo_region_t *clip_region = NULL;
-
 
347
    cairo_status_t status;
-
 
348
 
-
 
349
    if (clip != NULL) {
-
 
350
	status = _cairo_clip_get_region (clip, &clip_region);
-
 
351
	if (unlikely (_cairo_status_is_error (status) ||
-
 
352
		      status == CAIRO_INT_STATUS_NOTHING_TO_DO))
-
 
353
	{
-
 
354
	    return status;
-
 
355
	}
-
 
356
    }
-
 
357
 
-
 
358
    /* Create a surface that is mask IN clip */
-
 
359
    status = _create_composite_mask_pattern (&mask_pattern,
-
 
360
					     clip,
-
 
361
					     draw_func, draw_closure,
-
 
362
					     dst, extents);
-
 
363
    if (unlikely (status))
-
 
364
	return status;
-
 
365
 
-
 
366
    /* Compute dest' = dest OUT (mask IN clip) */
-
 
367
    status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
-
 
368
				       &mask_pattern.base, NULL, dst,
-
 
369
				       0,              0,
-
 
370
				       0,              0,
-
 
371
				       extents->x,     extents->y,
-
 
372
				       extents->width, extents->height,
-
 
373
				       clip_region);
-
 
374
 
-
 
375
    if (unlikely (status))
-
 
376
	goto CLEANUP_MASK_PATTERN;
-
 
377
 
-
 
378
    /* Now compute (src IN (mask IN clip)) ADD dest' */
-
 
379
    status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
-
 
380
				       src, &mask_pattern.base, dst,
-
 
381
				       extents->x,     extents->y,
-
 
382
				       0,              0,
-
 
383
				       extents->x,     extents->y,
-
 
384
				       extents->width, extents->height,
-
 
385
				       clip_region);
-
 
386
 
-
 
387
 CLEANUP_MASK_PATTERN:
-
 
388
    _cairo_pattern_fini (&mask_pattern.base);
-
 
389
    return status;
-
 
390
}
-
 
391
 
-
 
392
static int
-
 
393
_cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
-
 
394
{
-
 
395
    return rect->width == 0 || rect->height == 0;
-
 
396
}
-
 
397
 
-
 
398
/**
-
 
399
 * _clip_and_composite:
-
 
400
 * @clip: a #cairo_clip_t
-
 
401
 * @op: the operator to draw with
-
 
402
 * @src: source pattern
-
 
403
 * @draw_func: function that can be called to draw with the mask onto a surface.
-
 
404
 * @draw_closure: data to pass to @draw_func.
-
 
405
 * @dst: destination surface
-
 
406
 * @extents: rectangle holding a bounding box for the operation; this
-
 
407
 *           rectangle will be used as the size for the temporary
-
 
408
 *           surface.
-
 
409
 *
-
 
410
 * When there is a surface clip, we typically need to create an intermediate
-
 
411
 * surface. This function handles the logic of creating a temporary surface
-
 
412
 * drawing to it, then compositing the result onto the target surface.
-
 
413
 *
-
 
414
 * @draw_func is to called to draw the mask; it will be called no more
-
 
415
 * than once.
-
 
416
 *
-
 
417
 * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
-
 
418
 **/
-
 
419
static cairo_status_t
-
 
420
_clip_and_composite (cairo_clip_t                  *clip,
-
 
421
		     cairo_operator_t               op,
-
 
422
		     const cairo_pattern_t         *src,
-
 
423
		     cairo_draw_func_t              draw_func,
-
 
424
		     void                          *draw_closure,
-
 
425
		     cairo_surface_t               *dst,
-
 
426
		     const cairo_rectangle_int_t   *extents)
-
 
427
{
-
 
428
    cairo_status_t status;
-
 
429
 
-
 
430
    if (_cairo_rectangle_empty (extents))
-
 
431
	/* Nothing to do */
-
 
432
	return CAIRO_STATUS_SUCCESS;
-
 
433
 
-
 
434
    if (op == CAIRO_OPERATOR_CLEAR) {
-
 
435
	src = &_cairo_pattern_white.base;
-
 
436
	op = CAIRO_OPERATOR_DEST_OUT;
-
 
437
    }
-
 
438
 
-
 
439
    if (op == CAIRO_OPERATOR_SOURCE) {
-
 
440
	status = _clip_and_composite_source (clip,
-
 
441
					     src,
-
 
442
					     draw_func, draw_closure,
-
 
443
					     dst, extents);
-
 
444
    } else {
-
 
445
	cairo_bool_t clip_surface = FALSE;
-
 
446
	cairo_region_t *clip_region = NULL;
-
 
447
 
-
 
448
	if (clip != NULL) {
-
 
449
	    status = _cairo_clip_get_region (clip, &clip_region);
-
 
450
	    if (unlikely (_cairo_status_is_error (status) ||
-
 
451
			  status == CAIRO_INT_STATUS_NOTHING_TO_DO))
-
 
452
	    {
-
 
453
		return status;
-
 
454
	    }
-
 
455
 
-
 
456
	    clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
 
457
	}
-
 
458
 
-
 
459
	if (clip_surface) {
-
 
460
	    if (_cairo_operator_bounded_by_mask (op)) {
-
 
461
		status = _clip_and_composite_with_mask (clip, op,
-
 
462
							src,
-
 
463
							draw_func, draw_closure,
-
 
464
							dst, extents);
-
 
465
	    } else {
-
 
466
		status = _clip_and_composite_combine (clip, op,
-
 
467
						      src,
-
 
468
						      draw_func, draw_closure,
-
 
469
						      dst, extents);
-
 
470
	    }
-
 
471
	} else {
-
 
472
	    status = draw_func (draw_closure, op,
-
 
473
				src, dst,
-
 
474
				0, 0,
-
 
475
				extents,
-
 
476
				clip_region);
-
 
477
	}
-
 
478
    }
-
 
479
 
-
 
480
    return status;
-
 
481
}
-
 
482
 
-
 
483
/* Composites a region representing a set of trapezoids.
-
 
484
 */
-
 
485
static cairo_status_t
-
 
486
_composite_trap_region (cairo_clip_t            *clip,
-
 
487
			const cairo_pattern_t	*src,
-
 
488
			cairo_operator_t         op,
-
 
489
			cairo_surface_t         *dst,
-
 
490
			cairo_region_t          *trap_region,
-
 
491
			const cairo_rectangle_int_t   *extents)
-
 
492
{
-
 
493
    cairo_status_t status;
-
 
494
    cairo_surface_pattern_t mask_pattern;
-
 
495
    cairo_pattern_t *mask = NULL;
-
 
496
    int mask_x = 0, mask_y =0;
-
 
497
 
-
 
498
    if (clip != NULL) {
-
 
499
	cairo_surface_t *clip_surface = NULL;
-
 
500
	int clip_x, clip_y;
-
 
501
 
-
 
502
	clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y);
-
 
503
	if (unlikely (clip_surface->status))
-
 
504
	    return clip_surface->status;
-
 
505
 
-
 
506
	if (op == CAIRO_OPERATOR_CLEAR) {
-
 
507
	    src = &_cairo_pattern_white.base;
-
 
508
	    op = CAIRO_OPERATOR_DEST_OUT;
-
 
509
	}
-
 
510
 
-
 
511
	_cairo_pattern_init_for_surface (&mask_pattern, clip_surface);
-
 
512
	mask_x = extents->x - clip_x;
-
 
513
	mask_y = extents->y - clip_y;
-
 
514
	mask = &mask_pattern.base;
-
 
515
    }
-
 
516
 
-
 
517
    status = _cairo_surface_composite (op, src, mask, dst,
-
 
518
				       extents->x, extents->y,
-
 
519
				       mask_x, mask_y,
-
 
520
				       extents->x, extents->y,
-
 
521
				       extents->width, extents->height,
-
 
522
				       trap_region);
-
 
523
 
-
 
524
    if (mask != NULL)
-
 
525
      _cairo_pattern_fini (mask);
-
 
526
 
-
 
527
    return status;
-
 
528
}
-
 
529
 
-
 
530
typedef struct {
-
 
531
    cairo_traps_t *traps;
-
 
532
    cairo_antialias_t antialias;
-
 
533
} cairo_composite_traps_info_t;
-
 
534
 
-
 
535
static cairo_status_t
-
 
536
_composite_traps_draw_func (void                          *closure,
-
 
537
			    cairo_operator_t               op,
-
 
538
			    const cairo_pattern_t         *src,
-
 
539
			    cairo_surface_t               *dst,
-
 
540
			    int                            dst_x,
-
 
541
			    int                            dst_y,
-
 
542
			    const cairo_rectangle_int_t   *extents,
-
 
543
			    cairo_region_t		  *clip_region)
-
 
544
{
-
 
545
    cairo_composite_traps_info_t *info = closure;
-
 
546
    cairo_status_t status;
-
 
547
    cairo_region_t *extents_region = NULL;
-
 
548
 
-
 
549
    if (dst_x != 0 || dst_y != 0)
-
 
550
	_cairo_traps_translate (info->traps, - dst_x, - dst_y);
-
 
551
 
-
 
552
    if (clip_region == NULL &&
-
 
553
        !_cairo_operator_bounded_by_source (op)) {
-
 
554
        extents_region = cairo_region_create_rectangle (extents);
-
 
555
        if (unlikely (extents_region->status))
-
 
556
            return extents_region->status;
-
 
557
        cairo_region_translate (extents_region, -dst_x, -dst_y);
-
 
558
        clip_region = extents_region;
-
 
559
    }
-
 
560
 
-
 
561
    status = _cairo_surface_composite_trapezoids (op,
-
 
562
                                                  src, dst, info->antialias,
-
 
563
                                                  extents->x,         extents->y,
-
 
564
                                                  extents->x - dst_x, extents->y - dst_y,
-
 
565
                                                  extents->width,     extents->height,
-
 
566
                                                  info->traps->traps,
-
 
567
                                                  info->traps->num_traps,
-
 
568
                                                  clip_region);
-
 
569
 
-
 
570
    if (extents_region)
-
 
571
        cairo_region_destroy (extents_region);
-
 
572
 
-
 
573
    return status;
-
 
574
}
-
 
575
 
-
 
576
enum {
-
 
577
    HAS_CLEAR_REGION = 0x1,
-
 
578
};
-
 
579
 
-
 
580
static cairo_status_t
-
 
581
_clip_and_composite_region (const cairo_pattern_t *src,
-
 
582
			    cairo_operator_t op,
-
 
583
			    cairo_surface_t *dst,
-
 
584
			    cairo_region_t *trap_region,
-
 
585
			    cairo_clip_t *clip,
-
 
586
			    cairo_rectangle_int_t *extents)
-
 
587
{
-
 
588
    cairo_region_t clear_region;
-
 
589
    unsigned int has_region = 0;
-
 
590
    cairo_status_t status;
-
 
591
 
-
 
592
    if (! _cairo_operator_bounded_by_mask (op) && clip == NULL) {
-
 
593
	/* If we optimize drawing with an unbounded operator to
-
 
594
	 * _cairo_surface_fill_rectangles() or to drawing with a
-
 
595
	 * clip region, then we have an additional region to clear.
-
 
596
	 */
-
 
597
	_cairo_region_init_rectangle (&clear_region, extents);
-
 
598
	status = cairo_region_subtract (&clear_region, trap_region);
-
 
599
	if (unlikely (status))
-
 
600
	    return status;
-
 
601
 
-
 
602
	if (! cairo_region_is_empty (&clear_region))
-
 
603
	    has_region |= HAS_CLEAR_REGION;
-
 
604
    }
-
 
605
 
-
 
606
    if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
-
 
607
	clip == NULL)
-
 
608
    {
-
 
609
	const cairo_color_t *color;
-
 
610
 
-
 
611
	if (op == CAIRO_OPERATOR_CLEAR)
-
 
612
	    color = CAIRO_COLOR_TRANSPARENT;
-
 
613
	else
-
 
614
	    color = &((cairo_solid_pattern_t *)src)->color;
-
 
615
 
-
 
616
	/* Solid rectangles special case */
-
 
617
	status = _cairo_surface_fill_region (dst, op, color, trap_region);
-
 
618
    } else {
-
 
619
	/* For a simple rectangle, we can just use composite(), for more
-
 
620
	 * rectangles, we have to set a clip region. The cost of rasterizing
-
 
621
	 * trapezoids is pretty high for most backends currently, so it's
-
 
622
	 * worthwhile even if a region is needed.
-
 
623
	 *
-
 
624
	 * If we have a clip surface, we set it as the mask; this only works
-
 
625
	 * for bounded operators other than SOURCE; for unbounded operators,
-
 
626
	 * clip and mask cannot be interchanged. For SOURCE, the operator
-
 
627
	 * as implemented by the backends is different in its handling
-
 
628
	 * of the mask then what we want.
-
 
629
	 *
-
 
630
	 * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
-
 
631
	 * more than rectangle and the destination doesn't support clip
-
 
632
	 * regions. In that case, we fall through.
-
 
633
	 */
-
 
634
	status = _composite_trap_region (clip, src, op, dst,
-
 
635
					 trap_region, extents);
-
 
636
    }
-
 
637
 
-
 
638
    if (has_region & HAS_CLEAR_REGION) {
-
 
639
	if (status == CAIRO_STATUS_SUCCESS) {
-
 
640
	    status = _cairo_surface_fill_region (dst,
-
 
641
						 CAIRO_OPERATOR_CLEAR,
-
 
642
						 CAIRO_COLOR_TRANSPARENT,
-
 
643
						 &clear_region);
-
 
644
	}
-
 
645
	_cairo_region_fini (&clear_region);
-
 
646
    }
-
 
647
 
-
 
648
    return status;
-
 
649
}
-
 
650
 
-
 
651
/* avoid using region code to re-validate boxes */
-
 
652
static cairo_status_t
-
 
653
_fill_rectangles (cairo_surface_t *dst,
-
 
654
		  cairo_operator_t op,
-
 
655
		  const cairo_pattern_t *src,
-
 
656
		  cairo_traps_t *traps,
-
 
657
		  cairo_clip_t *clip)
-
 
658
{
-
 
659
    const cairo_color_t *color;
-
 
660
    cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
-
 
661
    cairo_rectangle_int_t *rects = stack_rects;
-
 
662
    cairo_status_t status;
-
 
663
    int i;
-
 
664
 
-
 
665
    if (! traps->is_rectilinear || ! traps->maybe_region)
-
 
666
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
667
 
-
 
668
    /* XXX: convert clip region to geometric boxes? */
-
 
669
    if (clip != NULL)
-
 
670
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
671
 
-
 
672
    /* XXX: fallback for the region_subtract() operation */
-
 
673
    if (! _cairo_operator_bounded_by_mask (op))
-
 
674
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
675
 
-
 
676
    if (! (src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR))
-
 
677
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
678
 
-
 
679
    if (traps->has_intersections) {
-
 
680
	if (traps->is_rectangular) {
-
 
681
	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
-
 
682
	} else {
-
 
683
	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
-
 
684
	}
-
 
685
	if (unlikely (status))
-
 
686
	    return status;
-
 
687
    }
-
 
688
 
-
 
689
    for (i = 0; i < traps->num_traps; i++) {
-
 
690
	if (! _cairo_fixed_is_integer (traps->traps[i].top)          ||
-
 
691
	    ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
-
 
692
	    ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
-
 
693
	    ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
-
 
694
	{
-
 
695
	    traps->maybe_region = FALSE;
-
 
696
	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
697
	}
-
 
698
    }
-
 
699
 
-
 
700
    if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
-
 
701
	rects = _cairo_malloc_ab (traps->num_traps,
-
 
702
				  sizeof (cairo_rectangle_int_t));
-
 
703
	if (unlikely (rects == NULL))
-
 
704
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
705
    }
-
 
706
 
-
 
707
    for (i = 0; i < traps->num_traps; i++) {
-
 
708
	int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
-
 
709
	int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
-
 
710
	int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
-
 
711
	int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
-
 
712
 
-
 
713
	rects[i].x = x1;
-
 
714
	rects[i].y = y1;
-
 
715
	rects[i].width = x2 - x1;
-
 
716
	rects[i].height = y2 - y1;
-
 
717
    }
-
 
718
 
-
 
719
    if (op == CAIRO_OPERATOR_CLEAR)
-
 
720
	color = CAIRO_COLOR_TRANSPARENT;
-
 
721
    else
-
 
722
	color = &((cairo_solid_pattern_t *)src)->color;
-
 
723
 
-
 
724
    status =  _cairo_surface_fill_rectangles (dst, op, color, rects, i);
-
 
725
 
-
 
726
    if (rects != stack_rects)
-
 
727
	free (rects);
-
 
728
 
-
 
729
    return status;
-
 
730
}
-
 
731
 
-
 
732
/* fast-path for very common composite of a single rectangle */
-
 
733
static cairo_status_t
-
 
734
_composite_rectangle (cairo_surface_t *dst,
-
 
735
		      cairo_operator_t op,
-
 
736
		      const cairo_pattern_t *src,
-
 
737
		      cairo_traps_t *traps,
-
 
738
		      cairo_clip_t *clip)
-
 
739
{
-
 
740
    cairo_rectangle_int_t rect;
-
 
741
 
-
 
742
    if (clip != NULL)
-
 
743
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
744
 
-
 
745
    if (traps->num_traps > 1 || ! traps->is_rectilinear || ! traps->maybe_region)
-
 
746
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
747
 
-
 
748
    if (! _cairo_fixed_is_integer (traps->traps[0].top)          ||
-
 
749
	! _cairo_fixed_is_integer (traps->traps[0].bottom)       ||
-
 
750
	! _cairo_fixed_is_integer (traps->traps[0].left.p1.x)    ||
-
 
751
	! _cairo_fixed_is_integer (traps->traps[0].right.p1.x))
-
 
752
    {
-
 
753
	traps->maybe_region = FALSE;
-
 
754
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
755
    }
-
 
756
 
-
 
757
    rect.x = _cairo_fixed_integer_part (traps->traps[0].left.p1.x);
-
 
758
    rect.y = _cairo_fixed_integer_part (traps->traps[0].top);
-
 
759
    rect.width  = _cairo_fixed_integer_part (traps->traps[0].right.p1.x) - rect.x;
-
 
760
    rect.height = _cairo_fixed_integer_part (traps->traps[0].bottom) - rect.y;
-
 
761
 
-
 
762
    return _cairo_surface_composite (op, src, NULL, dst,
-
 
763
				     rect.x, rect.y,
-
 
764
				     0, 0,
-
 
765
				     rect.x, rect.y,
-
 
766
				     rect.width, rect.height,
-
 
767
				     NULL);
-
 
768
}
-
 
769
 
-
 
770
/* Warning: This call modifies the coordinates of traps */
-
 
771
static cairo_status_t
-
 
772
_clip_and_composite_trapezoids (const cairo_pattern_t *src,
-
 
773
				cairo_operator_t op,
-
 
774
				cairo_surface_t *dst,
-
 
775
				cairo_traps_t *traps,
-
 
776
				cairo_antialias_t antialias,
-
 
777
				cairo_clip_t *clip,
-
 
778
				cairo_rectangle_int_t *extents)
-
 
779
{
-
 
780
    cairo_composite_traps_info_t traps_info;
-
 
781
    cairo_region_t *clip_region = NULL;
-
 
782
    cairo_bool_t clip_surface = FALSE;
-
 
783
    cairo_status_t status;
-
 
784
 
-
 
785
    if (traps->num_traps == 0 && _cairo_operator_bounded_by_mask (op))
-
 
786
	return CAIRO_STATUS_SUCCESS;
-
 
787
 
-
 
788
    if (clip != NULL) {
-
 
789
	status = _cairo_clip_get_region (clip, &clip_region);
-
 
790
	if (unlikely (_cairo_status_is_error (status)))
-
 
791
	    return status;
-
 
792
	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
-
 
793
	    return CAIRO_STATUS_SUCCESS;
-
 
794
 
-
 
795
	clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
 
796
    }
-
 
797
 
-
 
798
    /* Use a fast path if the trapezoids consist of a simple region,
-
 
799
     * but we can only do this if we do not have a clip surface, or can
-
 
800
     * substitute the mask with the clip.
-
 
801
     */
-
 
802
    if (! clip_surface ||
-
 
803
	(_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE))
-
 
804
    {
-
 
805
	cairo_region_t *trap_region = NULL;
-
 
806
 
-
 
807
        if (_cairo_operator_bounded_by_source (op)) {
-
 
808
            status = _fill_rectangles (dst, op, src, traps, clip);
-
 
809
            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-
 
810
                return status;
-
 
811
 
-
 
812
            status = _composite_rectangle (dst, op, src, traps, clip);
-
 
813
            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-
 
814
                return status;
-
 
815
        }
-
 
816
 
-
 
817
	status = _cairo_traps_extract_region (traps, &trap_region);
-
 
818
	if (unlikely (_cairo_status_is_error (status)))
-
 
819
	    return status;
-
 
820
 
-
 
821
	if (trap_region != NULL) {
-
 
822
	    status = cairo_region_intersect_rectangle (trap_region, extents);
-
 
823
	    if (unlikely (status)) {
-
 
824
		cairo_region_destroy (trap_region);
-
 
825
		return status;
-
 
826
	    }
-
 
827
 
-
 
828
	    if (clip_region != NULL) {
-
 
829
		status = cairo_region_intersect (trap_region, clip_region);
-
 
830
		if (unlikely (status)) {
-
 
831
		    cairo_region_destroy (trap_region);
-
 
832
		    return status;
-
 
833
		}
-
 
834
	    }
-
 
835
 
-
 
836
	    if (_cairo_operator_bounded_by_mask (op)) {
-
 
837
		cairo_rectangle_int_t trap_extents;
-
 
838
 
-
 
839
		cairo_region_get_extents (trap_region, &trap_extents);
-
 
840
		if (! _cairo_rectangle_intersect (extents, &trap_extents)) {
-
 
841
		    cairo_region_destroy (trap_region);
-
 
842
		    return CAIRO_STATUS_SUCCESS;
-
 
843
		}
-
 
844
	    }
-
 
845
 
-
 
846
	    status = _clip_and_composite_region (src, op, dst,
-
 
847
						 trap_region,
-
 
848
						 clip_surface ? clip : NULL,
-
 
849
						 extents);
-
 
850
	    cairo_region_destroy (trap_region);
-
 
851
 
-
 
852
	    if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
-
 
853
		return status;
-
 
854
	}
-
 
855
    }
-
 
856
 
-
 
857
    /* No fast path, exclude self-intersections and clip trapezoids. */
-
 
858
    if (traps->has_intersections) {
-
 
859
	if (traps->is_rectangular)
-
 
860
	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
-
 
861
	else if (traps->is_rectilinear)
-
 
862
	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
-
 
863
	else
-
 
864
	    status = _cairo_bentley_ottmann_tessellate_traps (traps, CAIRO_FILL_RULE_WINDING);
-
 
865
	if (unlikely (status))
-
 
866
	    return status;
-
 
867
    }
-
 
868
 
-
 
869
    /* Otherwise render the trapezoids to a mask and composite in the usual
-
 
870
     * fashion.
-
 
871
     */
-
 
872
    traps_info.traps = traps;
-
 
873
    traps_info.antialias = antialias;
-
 
874
 
-
 
875
    return _clip_and_composite (clip, op, src,
-
 
876
				_composite_traps_draw_func,
-
 
877
				&traps_info, dst, extents);
44
#include "cairo-compositor-private.h"
878
}
45
#include "cairo-surface-fallback-private.h"
879
 
46
 
880
cairo_status_t
47
cairo_int_status_t
881
_cairo_surface_fallback_paint (cairo_surface_t		*surface,
48
_cairo_surface_fallback_paint (void			*surface,
882
			       cairo_operator_t		 op,
49
			       cairo_operator_t		 op,
883
			       const cairo_pattern_t	*source,
-
 
884
			       cairo_clip_t		*clip)
-
 
885
{
-
 
886
    cairo_composite_rectangles_t extents;
-
 
887
    cairo_rectangle_int_t rect;
-
 
888
    cairo_clip_path_t *clip_path = clip ? clip->path : NULL;
-
 
889
    cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
-
 
890
    cairo_boxes_t  boxes;
-
 
891
    int num_boxes = ARRAY_LENGTH (boxes_stack);
-
 
892
    cairo_status_t status;
-
 
893
    cairo_traps_t traps;
-
 
894
 
-
 
895
    if (!_cairo_surface_get_extents (surface, &rect))
50
			       const cairo_pattern_t	*source,
896
        ASSERT_NOT_REACHED;
-
 
897
 
-
 
898
    status = _cairo_composite_rectangles_init_for_paint (&extents,
51
			       const cairo_clip_t	*clip)
899
							 rect.width,
-
 
900
							 rect.height,
-
 
901
							 op, source,
-
 
902
							 clip);
-
 
903
    if (unlikely (status))
-
 
904
	return status;
-
 
905
 
-
 
906
    if (_cairo_clip_contains_extents (clip, &extents))
-
 
907
	clip = NULL;
-
 
908
 
-
 
909
    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
-
 
910
    if (unlikely (status))
-
 
911
	return status;
-
 
912
 
-
 
913
    /* If the clip cannot be reduced to a set of boxes, we will need to
-
 
914
     * use a clipmask. Paint is special as it is the only operation that
-
 
915
     * does not implicitly use a mask, so we may be able to reduce this
-
 
916
     * operation to a fill...
-
 
917
     */
-
 
918
    if (clip != NULL && clip_path->prev == NULL &&
-
 
919
	_cairo_operator_bounded_by_mask (op))
-
 
920
    {
-
 
921
	return _cairo_surface_fill (surface, op, source,
-
 
922
				    &clip_path->path,
-
 
923
				    clip_path->fill_rule,
-
 
924
				    clip_path->tolerance,
-
 
925
				    clip_path->antialias,
-
 
926
				    NULL);
-
 
927
    }
-
 
928
 
-
 
929
    /* meh, surface-fallback is dying anyway... */
-
 
930
    _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
-
 
931
    status = _cairo_traps_init_boxes (&traps, &boxes);
-
 
932
    if (unlikely (status))
-
 
933
	goto CLEANUP_BOXES;
-
 
934
 
-
 
935
    status = _clip_and_composite_trapezoids (source, op, surface,
-
 
936
					     &traps, CAIRO_ANTIALIAS_DEFAULT,
-
 
937
					     clip,
-
 
938
                                             extents.is_bounded ? &extents.bounded : &extents.unbounded);
-
 
939
    _cairo_traps_fini (&traps);
-
 
940
 
-
 
941
CLEANUP_BOXES:
-
 
942
    if (clip_boxes != boxes_stack)
-
 
943
	free (clip_boxes);
-
 
944
 
-
 
945
    return status;
-
 
946
}
-
 
947
 
-
 
948
static cairo_status_t
-
 
949
_cairo_surface_mask_draw_func (void                        *closure,
-
 
950
			       cairo_operator_t             op,
-
 
951
			       const cairo_pattern_t       *src,
-
 
952
			       cairo_surface_t             *dst,
-
 
953
			       int                          dst_x,
-
 
954
			       int                          dst_y,
-
 
955
			       const cairo_rectangle_int_t *extents,
-
 
956
			       cairo_region_t		   *clip_region)
-
 
957
{
-
 
958
    cairo_pattern_t *mask = closure;
-
 
959
    cairo_status_t status;
-
 
960
    cairo_region_t *extents_region = NULL;
-
 
961
 
-
 
962
    if (clip_region == NULL &&
-
 
963
        !_cairo_operator_bounded_by_source (op)) {
-
 
964
        extents_region = cairo_region_create_rectangle (extents);
-
 
965
        if (unlikely (extents_region->status))
-
 
966
            return extents_region->status;
-
 
967
        cairo_region_translate (extents_region, -dst_x, -dst_y);
-
 
968
        clip_region = extents_region;
-
 
969
    }
-
 
970
 
-
 
971
    if (src) {
-
 
972
	status = _cairo_surface_composite (op,
-
 
973
                                           src, mask, dst,
-
 
974
                                           extents->x,         extents->y,
-
 
975
                                           extents->x,         extents->y,
-
 
976
                                           extents->x - dst_x, extents->y - dst_y,
-
 
977
                                           extents->width,     extents->height,
-
 
978
                                           clip_region);
-
 
979
    } else {
-
 
980
	status = _cairo_surface_composite (op,
-
 
981
                                           mask, NULL, dst,
-
 
982
                                           extents->x,         extents->y,
-
 
983
                                           0,                  0, /* unused */
-
 
984
                                           extents->x - dst_x, extents->y - dst_y,
-
 
985
                                           extents->width,     extents->height,
-
 
986
                                           clip_region);
-
 
987
    }
-
 
988
 
-
 
989
    if (extents_region)
-
 
990
        cairo_region_destroy (extents_region);
52
{
Line 991... Line 53...
991
 
53
    return _cairo_compositor_paint (&_cairo_fallback_compositor,
992
    return status;
54
				    surface, op, source, clip);
993
}
55
}
994
 
56
 
995
cairo_status_t
57
cairo_int_status_t
996
_cairo_surface_fallback_mask (cairo_surface_t		*surface,
58
_cairo_surface_fallback_mask (void			*surface,
997
			      cairo_operator_t		 op,
59
			      cairo_operator_t		 op,
998
			      const cairo_pattern_t	*source,
-
 
999
			      const cairo_pattern_t	*mask,
-
 
1000
			      cairo_clip_t		*clip)
-
 
1001
{
-
 
1002
    cairo_composite_rectangles_t extents;
-
 
1003
    cairo_rectangle_int_t rect;
-
 
1004
    cairo_status_t status;
-
 
1005
 
60
			      const cairo_pattern_t	*source,
1006
    if (!_cairo_surface_get_extents (surface, &rect))
-
 
1007
        ASSERT_NOT_REACHED;
61
			      const cairo_pattern_t	*mask,
1008
 
-
 
1009
    status = _cairo_composite_rectangles_init_for_mask (&extents,
-
 
1010
							rect.width, rect.height,
-
 
1011
							op, source, mask, clip);
-
 
1012
    if (unlikely (status))
-
 
1013
	return status;
-
 
1014
 
-
 
1015
    if (_cairo_clip_contains_extents (clip, &extents))
-
 
1016
	clip = NULL;
-
 
1017
 
-
 
1018
    if (clip != NULL && extents.is_bounded) {
-
 
1019
	status = _cairo_clip_rectangle (clip, &extents.bounded);
-
 
1020
	if (unlikely (status))
-
 
1021
	    return status;
-
 
1022
    }
-
 
1023
 
-
 
1024
    return _clip_and_composite (clip, op, source,
-
 
1025
				_cairo_surface_mask_draw_func,
62
			      const cairo_clip_t	*clip)
Line 1026... Line 63...
1026
				(void *) mask,
63
{
1027
				surface,
64
    return _cairo_compositor_mask (&_cairo_fallback_compositor,
1028
                                extents.is_bounded ? &extents.bounded : &extents.unbounded);
65
				   surface, op, source, mask, clip);
1029
}
66
}
1030
 
67
 
1031
cairo_status_t
68
cairo_int_status_t
1032
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
69
_cairo_surface_fallback_stroke (void			*surface,
1033
				cairo_operator_t	 op,
70
				cairo_operator_t	 op,
1034
				const cairo_pattern_t	*source,
71
				const cairo_pattern_t	*source,
1035
				cairo_path_fixed_t	*path,
72
				const cairo_path_fixed_t*path,
1036
				const cairo_stroke_style_t	*stroke_style,
73
				const cairo_stroke_style_t*style,
1037
				const cairo_matrix_t		*ctm,
74
				const cairo_matrix_t	*ctm,
1038
				const cairo_matrix_t		*ctm_inverse,
-
 
1039
				double			 tolerance,
-
 
1040
				cairo_antialias_t	 antialias,
-
 
1041
				cairo_clip_t		*clip)
-
 
1042
{
-
 
1043
    cairo_polygon_t polygon;
-
 
1044
    cairo_traps_t traps;
-
 
1045
    cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
-
 
1046
    int num_boxes = ARRAY_LENGTH (boxes_stack);
-
 
1047
    cairo_composite_rectangles_t extents;
-
 
1048
    cairo_rectangle_int_t rect;
-
 
1049
    cairo_status_t status;
75
				const cairo_matrix_t	*ctm_inverse,
1050
 
-
 
1051
    if (!_cairo_surface_get_extents (surface, &rect))
-
 
1052
        ASSERT_NOT_REACHED;
76
				double			 tolerance,
1053
 
-
 
1054
    status = _cairo_composite_rectangles_init_for_stroke (&extents,
-
 
1055
							  rect.width,
-
 
1056
							  rect.height,
-
 
1057
							  op, source,
-
 
1058
							  path, stroke_style, ctm,
-
 
1059
							  clip);
-
 
1060
    if (unlikely (status))
-
 
1061
	return status;
-
 
1062
 
-
 
1063
    if (_cairo_clip_contains_extents (clip, &extents))
-
 
1064
	clip = NULL;
-
 
1065
 
-
 
1066
    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
-
 
1067
    if (unlikely (status))
-
 
1068
	return status;
-
 
1069
 
-
 
1070
    _cairo_polygon_init (&polygon);
-
 
1071
    _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
-
 
1072
 
-
 
1073
    _cairo_traps_init (&traps);
-
 
1074
    _cairo_traps_limit (&traps, clip_boxes, num_boxes);
-
 
1075
 
-
 
1076
    if (path->is_rectilinear) {
-
 
1077
	status = _cairo_path_fixed_stroke_rectilinear_to_traps (path,
-
 
1078
								stroke_style,
-
 
1079
								ctm,
-
 
1080
								&traps);
-
 
1081
	if (likely (status == CAIRO_STATUS_SUCCESS))
-
 
1082
	    goto DO_TRAPS;
-
 
1083
 
-
 
1084
	if (_cairo_status_is_error (status))
-
 
1085
	    goto CLEANUP;
77
				cairo_antialias_t	 antialias,
1086
    }
-
 
1087
 
-
 
1088
    status = _cairo_path_fixed_stroke_to_polygon (path,
-
 
1089
						  stroke_style,
-
 
1090
						  ctm, ctm_inverse,
-
 
1091
						  tolerance,
-
 
1092
						  &polygon);
-
 
1093
    if (unlikely (status))
-
 
1094
	goto CLEANUP;
-
 
1095
 
-
 
1096
    if (polygon.num_edges == 0)
-
 
1097
	goto DO_TRAPS;
-
 
1098
 
-
 
1099
    if (_cairo_operator_bounded_by_mask (op)) {
-
 
1100
	_cairo_box_round_to_rectangle (&polygon.extents, &extents.mask);
-
 
1101
	if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
-
 
1102
	    goto CLEANUP;
-
 
1103
    }
-
 
1104
 
-
 
1105
    /* Fall back to trapezoid fills. */
-
 
1106
    status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
-
 
1107
							&polygon,
-
 
1108
							CAIRO_FILL_RULE_WINDING);
-
 
1109
    if (unlikely (status))
78
				const cairo_clip_t	*clip)
1110
	goto CLEANUP;
-
 
1111
 
-
 
1112
  DO_TRAPS:
-
 
1113
    status = _clip_and_composite_trapezoids (source, op, surface,
-
 
1114
					     &traps, antialias,
-
 
1115
					     clip,
-
 
1116
                                             extents.is_bounded ? &extents.bounded : &extents.unbounded);
-
 
1117
  CLEANUP:
-
 
1118
    _cairo_traps_fini (&traps);
-
 
1119
    _cairo_polygon_fini (&polygon);
79
{
Line 1120... Line 80...
1120
    if (clip_boxes != boxes_stack)
80
    return _cairo_compositor_stroke (&_cairo_fallback_compositor,
1121
	free (clip_boxes);
81
				     surface, op, source, path,
1122
 
82
				     style, ctm,ctm_inverse,
1123
    return status;
83
				     tolerance, antialias, clip);
1124
}
84
}
1125
 
85
 
1126
cairo_status_t
86
cairo_int_status_t
1127
_cairo_surface_fallback_fill (cairo_surface_t		*surface,
87
_cairo_surface_fallback_fill (void			*surface,
1128
			      cairo_operator_t		 op,
88
			     cairo_operator_t		 op,
1129
			      const cairo_pattern_t	*source,
89
			     const cairo_pattern_t	*source,
1130
			      cairo_path_fixed_t	*path,
-
 
1131
			      cairo_fill_rule_t		 fill_rule,
-
 
1132
			      double			 tolerance,
-
 
1133
			      cairo_antialias_t		 antialias,
-
 
1134
			      cairo_clip_t		*clip)
-
 
1135
{
-
 
1136
    cairo_polygon_t polygon;
-
 
1137
    cairo_traps_t traps;
-
 
1138
    cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
-
 
1139
    int num_boxes = ARRAY_LENGTH (boxes_stack);
-
 
1140
    cairo_bool_t is_rectilinear;
-
 
1141
    cairo_composite_rectangles_t extents;
-
 
1142
    cairo_rectangle_int_t rect;
90
			     const cairo_path_fixed_t	*path,
1143
    cairo_status_t status;
91
			     cairo_fill_rule_t		 fill_rule,
1144
 
-
 
1145
    if (!_cairo_surface_get_extents (surface, &rect))
92
			     double			 tolerance,
1146
        ASSERT_NOT_REACHED;
93
			     cairo_antialias_t		 antialias,
1147
 
-
 
1148
    status = _cairo_composite_rectangles_init_for_fill (&extents,
-
 
1149
							rect.width,
-
 
1150
							rect.height,
-
 
1151
							op, source, path,
-
 
1152
							clip);
-
 
1153
    if (unlikely (status))
-
 
1154
	return status;
-
 
1155
 
-
 
1156
    if (_cairo_clip_contains_extents (clip, &extents))
-
 
1157
	clip = NULL;
-
 
1158
 
-
 
1159
    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
-
 
1160
    if (unlikely (status))
-
 
1161
	return status;
-
 
1162
 
-
 
1163
    _cairo_traps_init (&traps);
-
 
1164
    _cairo_traps_limit (&traps, clip_boxes, num_boxes);
-
 
1165
 
-
 
1166
    _cairo_polygon_init (&polygon);
-
 
1167
    _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
-
 
1168
 
-
 
1169
    if (path->is_empty_fill)
-
 
1170
	goto DO_TRAPS;
-
 
1171
 
-
 
1172
    is_rectilinear = _cairo_path_fixed_is_rectilinear_fill (path);
-
 
1173
    if (is_rectilinear) {
-
 
1174
	status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
-
 
1175
							      fill_rule,
-
 
1176
							      &traps);
-
 
1177
	if (likely (status == CAIRO_STATUS_SUCCESS))
-
 
1178
	    goto DO_TRAPS;
-
 
1179
 
-
 
1180
	if (_cairo_status_is_error (status))
-
 
1181
	    goto CLEANUP;
-
 
1182
    }
-
 
1183
 
-
 
1184
    status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
-
 
1185
    if (unlikely (status))
-
 
1186
	goto CLEANUP;
-
 
1187
 
-
 
1188
    if (polygon.num_edges == 0)
-
 
1189
	goto DO_TRAPS;
-
 
1190
 
-
 
1191
    if (_cairo_operator_bounded_by_mask (op)) {
-
 
1192
	_cairo_box_round_to_rectangle (&polygon.extents, &extents.mask);
-
 
1193
	if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
-
 
1194
	    goto CLEANUP;
-
 
1195
    }
-
 
1196
 
-
 
1197
    if (is_rectilinear) {
-
 
1198
	status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
-
 
1199
									&polygon,
-
 
1200
									fill_rule);
-
 
1201
	if (likely (status == CAIRO_STATUS_SUCCESS))
-
 
1202
	    goto DO_TRAPS;
-
 
1203
 
-
 
1204
	if (unlikely (_cairo_status_is_error (status)))
-
 
1205
	    goto CLEANUP;
-
 
1206
    }
-
 
1207
 
-
 
1208
    /* Fall back to trapezoid fills. */
-
 
1209
    status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
-
 
1210
							&polygon,
-
 
1211
							fill_rule);
-
 
1212
    if (unlikely (status))
-
 
1213
	goto CLEANUP;
-
 
1214
 
-
 
1215
  DO_TRAPS:
-
 
1216
    status = _clip_and_composite_trapezoids (source, op, surface,
-
 
1217
					     &traps, antialias,
-
 
1218
					     clip,
-
 
1219
                                             extents.is_bounded ? &extents.bounded : &extents.unbounded);
-
 
1220
  CLEANUP:
-
 
1221
    _cairo_traps_fini (&traps);
-
 
1222
    _cairo_polygon_fini (&polygon);
-
 
1223
    if (clip_boxes != boxes_stack)
-
 
1224
	free (clip_boxes);
-
 
1225
 
-
 
1226
    return status;
-
 
1227
}
-
 
1228
 
-
 
1229
typedef struct {
-
 
1230
    cairo_scaled_font_t *font;
-
 
1231
    cairo_glyph_t *glyphs;
-
 
1232
    int num_glyphs;
-
 
1233
} cairo_show_glyphs_info_t;
-
 
1234
 
-
 
1235
static cairo_status_t
-
 
1236
_cairo_surface_old_show_glyphs_draw_func (void                          *closure,
-
 
1237
					  cairo_operator_t               op,
-
 
1238
					  const cairo_pattern_t         *src,
-
 
1239
					  cairo_surface_t               *dst,
-
 
1240
					  int                            dst_x,
-
 
1241
					  int                            dst_y,
-
 
1242
					  const cairo_rectangle_int_t	*extents,
-
 
1243
					  cairo_region_t		*clip_region)
-
 
1244
{
-
 
1245
    cairo_show_glyphs_info_t *glyph_info = closure;
-
 
1246
    cairo_status_t status;
-
 
1247
    cairo_region_t *extents_region = NULL;
-
 
1248
 
-
 
1249
    if (clip_region == NULL &&
-
 
1250
        !_cairo_operator_bounded_by_source (op)) {
-
 
1251
        extents_region = cairo_region_create_rectangle (extents);
-
 
1252
        if (unlikely (extents_region->status))
-
 
1253
            return extents_region->status;
-
 
1254
        cairo_region_translate (extents_region, -dst_x, -dst_y);
-
 
1255
        clip_region = extents_region;
-
 
1256
    }
-
 
1257
 
-
 
1258
    /* Modifying the glyph array is fine because we know that this function
-
 
1259
     * will be called only once, and we've already made a copy of the
-
 
1260
     * glyphs in the wrapper.
-
 
1261
     */
-
 
1262
    if (dst_x != 0 || dst_y != 0) {
-
 
1263
	int i;
-
 
1264
 
-
 
1265
	for (i = 0; i < glyph_info->num_glyphs; ++i) {
-
 
1266
	    ((cairo_glyph_t *) glyph_info->glyphs)[i].x -= dst_x;
-
 
1267
	    ((cairo_glyph_t *) glyph_info->glyphs)[i].y -= dst_y;
-
 
1268
	}
-
 
1269
    }
-
 
1270
 
-
 
1271
    status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src,
-
 
1272
					     dst,
-
 
1273
					     extents->x, extents->y,
-
 
1274
					     extents->x - dst_x,
-
 
1275
					     extents->y - dst_y,
-
 
1276
					     extents->width,
-
 
1277
					     extents->height,
-
 
1278
					     glyph_info->glyphs,
-
 
1279
					     glyph_info->num_glyphs,
-
 
1280
					     clip_region);
-
 
1281
 
-
 
1282
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-
 
1283
	status = _cairo_scaled_font_show_glyphs (glyph_info->font,
-
 
1284
                                                 op,
-
 
1285
                                                 src, dst,
-
 
1286
                                                 extents->x,         extents->y,
-
 
1287
                                                 extents->x - dst_x,
-
 
1288
                                                 extents->y - dst_y,
-
 
1289
                                                 extents->width,     extents->height,
-
 
1290
                                                 glyph_info->glyphs,
-
 
1291
                                                 glyph_info->num_glyphs,
-
 
1292
                                                 clip_region);
-
 
1293
    }
94
			     const cairo_clip_t		*clip)
Line 1294... Line 95...
1294
 
95
{
1295
    if (extents_region)
96
    return _cairo_compositor_fill (&_cairo_fallback_compositor,
1296
        cairo_region_destroy (extents_region);
97
				   surface, op, source, path,
1297
 
98
				   fill_rule, tolerance, antialias,
1298
    return status;
99
				   clip);
1299
}
100
}
1300
 
101
 
1301
cairo_status_t
102
cairo_int_status_t
1302
_cairo_surface_fallback_show_glyphs (cairo_surface_t		*surface,
-
 
1303
				     cairo_operator_t		 op,
-
 
1304
				     const cairo_pattern_t	*source,
-
 
1305
				     cairo_glyph_t		*glyphs,
-
 
1306
				     int			 num_glyphs,
-
 
1307
				     cairo_scaled_font_t	*scaled_font,
-
 
1308
				     cairo_clip_t		*clip)
-
 
1309
{
-
 
1310
    cairo_show_glyphs_info_t glyph_info;
-
 
1311
    cairo_composite_rectangles_t extents;
-
 
1312
    cairo_rectangle_int_t rect;
-
 
1313
    cairo_status_t status;
-
 
1314
 
-
 
1315
    if (!_cairo_surface_get_extents (surface, &rect))
-
 
1316
        ASSERT_NOT_REACHED;
-
 
1317
 
-
 
1318
    status = _cairo_composite_rectangles_init_for_glyphs (&extents,
-
 
1319
							  rect.width,
-
 
1320
							  rect.height,
-
 
1321
							  op, source,
-
 
1322
							  scaled_font,
-
 
1323
							  glyphs, num_glyphs,
-
 
1324
							  clip,
-
 
1325
							  NULL);
-
 
1326
    if (unlikely (status))
-
 
1327
	return status;
-
 
1328
 
-
 
1329
    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
-
 
1330
	clip = NULL;
-
 
1331
 
-
 
1332
    if (clip != NULL && extents.is_bounded) {
-
 
1333
	status = _cairo_clip_rectangle (clip, &extents.bounded);
-
 
1334
	if (unlikely (status))
-
 
1335
	    return status;
-
 
1336
    }
-
 
1337
 
-
 
1338
    glyph_info.font = scaled_font;
-
 
1339
    glyph_info.glyphs = glyphs;
-
 
1340
    glyph_info.num_glyphs = num_glyphs;
-
 
1341
 
-
 
1342
    return _clip_and_composite (clip, op, source,
-
 
1343
				_cairo_surface_old_show_glyphs_draw_func,
-
 
1344
				&glyph_info,
-
 
1345
				surface,
-
 
1346
                                extents.is_bounded ? &extents.bounded : &extents.unbounded);
-
 
1347
}
-
 
1348
 
-
 
1349
cairo_surface_t *
-
 
1350
_cairo_surface_fallback_snapshot (cairo_surface_t *surface)
-
 
1351
{
-
 
1352
    cairo_surface_t *snapshot;
-
 
1353
    cairo_status_t status;
-
 
1354
    cairo_format_t format;
-
 
1355
    cairo_surface_pattern_t pattern;
-
 
1356
    cairo_image_surface_t *image;
-
 
1357
    void *image_extra;
-
 
1358
 
-
 
1359
    status = _cairo_surface_acquire_source_image (surface,
-
 
1360
						  &image, &image_extra);
-
 
1361
    if (unlikely (status))
-
 
1362
	return _cairo_surface_create_in_error (status);
-
 
1363
 
-
 
1364
    format = image->format;
-
 
1365
    if (format == CAIRO_FORMAT_INVALID) {
-
 
1366
	/* Non-standard images formats can be generated when retrieving
-
 
1367
	 * images from unusual xservers, for example.
-
 
1368
	 */
-
 
1369
	format = _cairo_format_from_content (image->base.content);
-
 
1370
    }
-
 
1371
    snapshot = cairo_image_surface_create (format,
-
 
1372
					   image->width,
-
 
1373
					   image->height);
-
 
1374
    if (cairo_surface_status (snapshot)) {
-
 
1375
	_cairo_surface_release_source_image (surface, image, image_extra);
-
 
1376
	return snapshot;
-
 
1377
    }
-
 
1378
 
-
 
1379
    _cairo_pattern_init_for_surface (&pattern, &image->base);
-
 
1380
    status = _cairo_surface_paint (snapshot,
-
 
1381
				   CAIRO_OPERATOR_SOURCE,
-
 
1382
				   &pattern.base,
-
 
1383
				   NULL);
-
 
1384
    _cairo_pattern_fini (&pattern.base);
-
 
1385
    _cairo_surface_release_source_image (surface, image, image_extra);
-
 
1386
    if (unlikely (status)) {
-
 
1387
	cairo_surface_destroy (snapshot);
-
 
1388
	return _cairo_surface_create_in_error (status);
-
 
1389
    }
-
 
1390
 
-
 
1391
    return snapshot;
-
 
1392
}
-
 
1393
 
-
 
1394
cairo_status_t
-
 
1395
_cairo_surface_fallback_composite (cairo_operator_t		 op,
-
 
1396
				   const cairo_pattern_t	*src,
-
 
1397
				   const cairo_pattern_t	*mask,
-
 
1398
				   cairo_surface_t		*dst,
-
 
1399
				   int				 src_x,
-
 
1400
				   int				 src_y,
-
 
1401
				   int				 mask_x,
-
 
1402
				   int				 mask_y,
-
 
1403
				   int				 dst_x,
-
 
1404
				   int				 dst_y,
-
 
1405
				   unsigned int			 width,
-
 
1406
				   unsigned int			 height,
-
 
1407
				   cairo_region_t		*clip_region)
-
 
1408
{
-
 
1409
    fallback_state_t state;
-
 
1410
    cairo_region_t *fallback_region = NULL;
-
 
1411
    cairo_status_t status;
-
 
1412
 
-
 
1413
    status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
-
 
1414
    if (unlikely (status))
-
 
1415
	return status;
-
 
1416
 
-
 
1417
    /* We know this will never fail with the image backend; but
-
 
1418
     * instead of calling into it directly, we call
-
 
1419
     * _cairo_surface_composite so that we get the correct device
-
 
1420
     * offset handling.
-
 
1421
     */
-
 
1422
 
-
 
1423
    if (clip_region != NULL && (state.image_rect.x || state.image_rect.y)) {
-
 
1424
	fallback_region = cairo_region_copy (clip_region);
-
 
1425
	status = fallback_region->status;
-
 
1426
	if (unlikely (status))
-
 
1427
	    goto FAIL;
-
 
1428
 
-
 
1429
	cairo_region_translate (fallback_region,
-
 
1430
				-state.image_rect.x,
-
 
1431
				-state.image_rect.y);
-
 
1432
	clip_region = fallback_region;
-
 
1433
    }
-
 
1434
 
-
 
1435
    status = _cairo_surface_composite (op, src, mask,
-
 
1436
				       &state.image->base,
-
 
1437
				       src_x, src_y, mask_x, mask_y,
-
 
1438
				       dst_x - state.image_rect.x,
-
 
1439
				       dst_y - state.image_rect.y,
-
 
1440
				       width, height,
-
 
1441
				       clip_region);
-
 
1442
  FAIL:
-
 
1443
    if (fallback_region != NULL)
-
 
1444
	cairo_region_destroy (fallback_region);
-
 
1445
    _fallback_fini (&state);
-
 
1446
 
-
 
1447
    return status;
-
 
1448
}
-
 
1449
 
103
_cairo_surface_fallback_glyphs (void			*surface,
1450
cairo_status_t
-
 
1451
_cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
-
 
1452
					 cairo_operator_t	  op,
-
 
1453
					 const cairo_color_t	 *color,
-
 
1454
					 cairo_rectangle_int_t   *rects,
-
 
1455
					 int			  num_rects)
-
 
1456
{
-
 
1457
    fallback_state_t state;
-
 
1458
    cairo_rectangle_int_t *offset_rects = NULL;
-
 
1459
    cairo_status_t status;
-
 
1460
    int x1, y1, x2, y2;
-
 
1461
    int i;
-
 
1462
 
-
 
1463
    assert (surface->snapshot_of == NULL);
-
 
1464
 
-
 
1465
    if (num_rects <= 0)
-
 
1466
	return CAIRO_STATUS_SUCCESS;
-
 
1467
 
-
 
1468
    /* Compute the bounds of the rectangles, so that we know what area of the
-
 
1469
     * destination surface to fetch
-
 
1470
     */
-
 
1471
    x1 = rects[0].x;
-
 
1472
    y1 = rects[0].y;
-
 
1473
    x2 = rects[0].x + rects[0].width;
-
 
1474
    y2 = rects[0].y + rects[0].height;
-
 
1475
 
-
 
1476
    for (i = 1; i < num_rects; i++) {
-
 
1477
	if (rects[i].x < x1)
-
 
1478
	    x1 = rects[i].x;
-
 
1479
	if (rects[i].y < y1)
-
 
1480
	    y1 = rects[i].y;
-
 
1481
 
-
 
1482
	if ((int) (rects[i].x + rects[i].width) > x2)
-
 
1483
	    x2 = rects[i].x + rects[i].width;
-
 
1484
	if ((int) (rects[i].y + rects[i].height) > y2)
-
 
1485
	    y2 = rects[i].y + rects[i].height;
-
 
1486
    }
-
 
1487
 
-
 
1488
    status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
-
 
1489
    if (unlikely (status))
-
 
1490
	return status;
-
 
1491
 
-
 
1492
    /* If the fetched image isn't at 0,0, we need to offset the rectangles */
-
 
1493
 
-
 
1494
    if (state.image_rect.x != 0 || state.image_rect.y != 0) {
-
 
1495
	offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t));
-
 
1496
	if (unlikely (offset_rects == NULL)) {
-
 
1497
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1498
	    goto DONE;
-
 
1499
	}
-
 
1500
 
-
 
1501
	for (i = 0; i < num_rects; i++) {
-
 
1502
	    offset_rects[i].x = rects[i].x - state.image_rect.x;
-
 
1503
	    offset_rects[i].y = rects[i].y - state.image_rect.y;
-
 
1504
	    offset_rects[i].width = rects[i].width;
-
 
1505
	    offset_rects[i].height = rects[i].height;
-
 
1506
	}
-
 
1507
 
-
 
1508
	rects = offset_rects;
-
 
1509
    }
-
 
1510
 
-
 
1511
    status = _cairo_surface_fill_rectangles (&state.image->base,
-
 
1512
					     op, color,
-
 
1513
					     rects, num_rects);
-
 
1514
 
-
 
1515
    free (offset_rects);
-
 
1516
 
-
 
1517
 DONE:
-
 
1518
    _fallback_fini (&state);
-
 
1519
 
-
 
1520
    return status;
-
 
1521
}
-
 
1522
 
-
 
1523
cairo_status_t
-
 
1524
_cairo_surface_fallback_composite_trapezoids (cairo_operator_t		op,
-
 
1525
					      const cairo_pattern_t    *pattern,
-
 
1526
					      cairo_surface_t	       *dst,
-
 
1527
					      cairo_antialias_t		antialias,
-
 
1528
					      int			src_x,
-
 
1529
					      int			src_y,
-
 
1530
					      int			dst_x,
-
 
1531
					      int			dst_y,
-
 
1532
					      unsigned int		width,
-
 
1533
					      unsigned int		height,
-
 
1534
					      cairo_trapezoid_t	       *traps,
-
 
1535
					      int			num_traps,
-
 
1536
					      cairo_region_t		*clip_region)
-
 
1537
{
-
 
1538
    fallback_state_t state;
-
 
1539
    cairo_region_t *fallback_region = NULL;
-
 
1540
    cairo_trapezoid_t *offset_traps = NULL;
-
 
1541
    cairo_status_t status;
-
 
1542
 
-
 
1543
    status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
-
 
1544
    if (unlikely (status))
-
 
1545
	return status;
-
 
1546
 
-
 
1547
    /* If the destination image isn't at 0,0, we need to offset the trapezoids */
-
 
1548
 
-
 
1549
    if (state.image_rect.x != 0 || state.image_rect.y != 0) {
-
 
1550
	offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t));
-
 
1551
	if (offset_traps == NULL) {
-
 
1552
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1553
	    goto FAIL;
-
 
1554
	}
-
 
1555
 
-
 
1556
	_cairo_trapezoid_array_translate_and_scale (offset_traps, traps, num_traps,
-
 
1557
                                                    - state.image_rect.x, - state.image_rect.y,
-
 
1558
                                                    1.0, 1.0);
-
 
1559
	traps = offset_traps;
-
 
1560
 
-
 
1561
	/* similarly we need to adjust the region */
104
				cairo_operator_t	 op,
1562
	if (clip_region != NULL) {
-
 
1563
	    fallback_region = cairo_region_copy (clip_region);
-
 
1564
	    status = fallback_region->status;
-
 
1565
	    if (unlikely (status))
-
 
1566
		goto FAIL;
-
 
1567
 
-
 
1568
	    cairo_region_translate (fallback_region,
-
 
1569
				    -state.image_rect.x,
-
 
1570
				    -state.image_rect.y);
-
 
1571
	    clip_region = fallback_region;
-
 
1572
	}
-
 
1573
    }
-
 
1574
 
-
 
1575
    status = _cairo_surface_composite_trapezoids (op, pattern,
-
 
1576
					          &state.image->base,
-
 
1577
						  antialias,
-
 
1578
						  src_x, src_y,
-
 
1579
						  dst_x - state.image_rect.x,
-
 
1580
						  dst_y - state.image_rect.y,
-
 
1581
						  width, height,
-
 
1582
						  traps, num_traps,
-
 
1583
						  clip_region);
-
 
1584
 FAIL:
-
 
1585
    if (offset_traps != NULL)
-
 
1586
	free (offset_traps);
-
 
1587
 
-
 
1588
    if (fallback_region != NULL)
-
 
1589
	cairo_region_destroy (fallback_region);
-
 
1590
 
-
 
1591
    _fallback_fini (&state);
105
				const cairo_pattern_t	*source,
1592
 
-
 
1593
    return status;
-
 
1594
}
-
 
1595
 
-
 
1596
cairo_status_t
-
 
1597
_cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
-
 
1598
				       cairo_surface_t	*src,
106
				cairo_glyph_t		*glyphs,
1599
				       int		 src_x,
-
 
1600
				       int		 src_y,
-
 
1601
				       int		 width,
-
 
1602
				       int		 height,
-
 
1603
				       int		*clone_offset_x,
-
 
1604
				       int		*clone_offset_y,
-
 
1605
				       cairo_surface_t **clone_out)
-
 
1606
{
-
 
1607
    cairo_surface_t *new_surface;
-
 
1608
    cairo_surface_pattern_t pattern;
-
 
1609
    cairo_status_t status;
-
 
1610
 
-
 
1611
    new_surface = _cairo_surface_create_similar_scratch (surface,
-
 
1612
							 src->content,
-
 
1613
							 width, height);
-
 
1614
    if (new_surface == NULL)
-
 
1615
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
1616
    if (unlikely (new_surface->status))
-
 
1617
	return new_surface->status;
-
 
1618
 
-
 
1619
    /* We have to copy these here, so that the coordinate spaces are correct */
-
 
1620
    new_surface->device_transform = src->device_transform;
-
 
1621
    new_surface->device_transform_inverse = src->device_transform_inverse;
-
 
1622
 
-
 
1623
    _cairo_pattern_init_for_surface (&pattern, src);
107
				int			 num_glyphs,
1624
    cairo_matrix_init_translate (&pattern.base.matrix, src_x, src_y);
-
 
1625
    pattern.base.filter = CAIRO_FILTER_NEAREST;
-
 
1626
 
-
 
1627
    status = _cairo_surface_paint (new_surface,
-
 
1628
				   CAIRO_OPERATOR_SOURCE,
-
 
1629
				   &pattern.base,
-
 
1630
				   NULL);
-
 
1631
    _cairo_pattern_fini (&pattern.base);
-
 
1632
 
-
 
1633
    if (unlikely (status)) {
-
 
1634
	cairo_surface_destroy (new_surface);
-
 
1635
	return status;
108
				cairo_scaled_font_t	*scaled_font,