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 72... Line 72...
72
 * necessary objects (paths, patterns, etc.), in order to achieve
72
 * necessary objects (paths, patterns, etc.), in order to achieve
73
 * accurate replay. The efficiency of the recording surface could be
73
 * accurate replay. The efficiency of the recording surface could be
74
 * improved by improving the implementation of snapshot for the
74
 * improved by improving the implementation of snapshot for the
75
 * various objects. For example, it would be nice to have a
75
 * various objects. For example, it would be nice to have a
76
 * copy-on-write implementation for _cairo_surface_snapshot.
76
 * copy-on-write implementation for _cairo_surface_snapshot.
77
 */
77
 **/
Line 78... Line 78...
78
 
78
 
-
 
79
#include "cairoint.h"
-
 
80
 
79
#include "cairoint.h"
81
#include "cairo-array-private.h"
80
#include "cairo-analysis-surface-private.h"
82
#include "cairo-analysis-surface-private.h"
-
 
83
#include "cairo-clip-private.h"
-
 
84
#include "cairo-combsort-inline.h"
-
 
85
#include "cairo-composite-rectangles-private.h"
81
#include "cairo-clip-private.h"
86
#include "cairo-default-context-private.h"
-
 
87
#include "cairo-error-private.h"
82
#include "cairo-error-private.h"
88
#include "cairo-image-surface-private.h"
83
#include "cairo-recording-surface-private.h"
89
#include "cairo-recording-surface-inline.h"
-
 
90
#include "cairo-surface-wrapper-private.h"
Line 84... Line 91...
84
#include "cairo-surface-wrapper-private.h"
91
#include "cairo-traps-private.h"
85
 
92
 
86
typedef enum {
93
typedef enum {
87
    CAIRO_RECORDING_REPLAY,
94
    CAIRO_RECORDING_REPLAY,
Line 96... Line 103...
96
 * Defined if the recording surface backend is available.
103
 * Defined if the recording surface backend is available.
97
 * The recording surface backend is always built in.
104
 * The recording surface backend is always built in.
98
 * This macro was added for completeness in cairo 1.10.
105
 * This macro was added for completeness in cairo 1.10.
99
 *
106
 *
100
 * Since: 1.10
107
 * Since: 1.10
101
 */
108
 **/
Line 102... Line 109...
102
 
109
 
103
/* Currently all recording surfaces do have a size which should be passed
110
/* Currently all recording surfaces do have a size which should be passed
104
 * in as the maximum size of any target surface against which the
111
 * in as the maximum size of any target surface against which the
105
 * recording-surface will ever be replayed.
112
 * recording-surface will ever be replayed.
106
 *
113
 *
107
 * XXX: The naming of "pixels" in the size here is a misnomer. It's
114
 * XXX: The naming of "pixels" in the size here is a misnomer. It's
108
 * actually a size in whatever device-space units are desired (again,
115
 * actually a size in whatever device-space units are desired (again,
109
 * according to the intended replay target).
116
 * according to the intended replay target).
Line -... Line 117...
-
 
117
 */
-
 
118
 
-
 
119
static int bbtree_left_or_right (struct bbtree *bbt,
-
 
120
				 const cairo_box_t *box)
-
 
121
{
-
 
122
    int left, right;
-
 
123
 
-
 
124
    if (bbt->left) {
-
 
125
	cairo_box_t *e = &bbt->left->extents;
-
 
126
	cairo_box_t b;
-
 
127
 
-
 
128
	b.p1.x = MIN (e->p1.x, box->p1.x);
-
 
129
	b.p1.y = MIN (e->p1.y, box->p1.y);
-
 
130
	b.p2.x = MAX (e->p2.x, box->p2.x);
-
 
131
	b.p2.y = MAX (e->p2.y, box->p2.y);
-
 
132
 
-
 
133
	left = _cairo_fixed_integer_part (b.p2.x - b.p1.x) * _cairo_fixed_integer_part (b.p2.y - b.p1.y);
-
 
134
	left -= _cairo_fixed_integer_part (e->p2.x - e->p1.x) * _cairo_fixed_integer_part (e->p2.y - e->p1.y);
-
 
135
    } else
-
 
136
	left = 0;
-
 
137
 
-
 
138
    if (bbt->right) {
-
 
139
	cairo_box_t *e = &bbt->right->extents;
-
 
140
	cairo_box_t b;
-
 
141
 
-
 
142
	b.p1.x = MIN (e->p1.x, box->p1.x);
-
 
143
	b.p1.y = MIN (e->p1.y, box->p1.y);
-
 
144
	b.p2.x = MAX (e->p2.x, box->p2.x);
-
 
145
	b.p2.y = MAX (e->p2.y, box->p2.y);
-
 
146
 
-
 
147
	right = _cairo_fixed_integer_part (b.p2.x - b.p1.x) * _cairo_fixed_integer_part (b.p2.y - b.p1.y);
-
 
148
	right -= _cairo_fixed_integer_part (e->p2.x - e->p1.x) * _cairo_fixed_integer_part (e->p2.y - e->p1.y);
-
 
149
    } else
-
 
150
	right = 0;
-
 
151
 
-
 
152
    return left <= right;
-
 
153
}
-
 
154
 
-
 
155
#define INVALID_CHAIN ((cairo_command_header_t *)-1)
-
 
156
 
-
 
157
static struct bbtree *
-
 
158
bbtree_new (const cairo_box_t *box, cairo_command_header_t *chain)
-
 
159
{
-
 
160
    struct bbtree *bbt = malloc (sizeof (*bbt));
-
 
161
    if (bbt == NULL)
-
 
162
	return NULL;
-
 
163
    bbt->extents = *box;
-
 
164
    bbt->left = bbt->right = NULL;
-
 
165
    bbt->chain = chain;
-
 
166
    return bbt;
-
 
167
}
-
 
168
 
-
 
169
static void
-
 
170
bbtree_init (struct bbtree *bbt, cairo_command_header_t *header)
-
 
171
{
-
 
172
    _cairo_box_from_rectangle (&bbt->extents, &header->extents);
-
 
173
    bbt->chain = header;
-
 
174
}
-
 
175
 
-
 
176
static cairo_status_t
-
 
177
bbtree_add (struct bbtree *bbt,
-
 
178
	    cairo_command_header_t *header,
-
 
179
	    const cairo_box_t *box)
-
 
180
{
-
 
181
    if (box->p1.x < bbt->extents.p1.x || box->p1.y < bbt->extents.p1.y ||
-
 
182
	box->p2.x > bbt->extents.p2.x || box->p2.y > bbt->extents.p2.y)
-
 
183
    {
-
 
184
	if (bbt->chain) {
-
 
185
	    if (bbtree_left_or_right (bbt, &bbt->extents)) {
-
 
186
		if (bbt->left == NULL) {
-
 
187
		    bbt->left = bbtree_new (&bbt->extents, bbt->chain);
-
 
188
		    if (unlikely (bbt->left == NULL))
-
 
189
			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
190
		} else
-
 
191
		    bbtree_add (bbt->left, bbt->chain, &bbt->extents);
-
 
192
	    } else {
-
 
193
		if (bbt->right == NULL) {
-
 
194
		    bbt->right = bbtree_new (&bbt->extents, bbt->chain);
-
 
195
		    if (unlikely (bbt->right == NULL))
-
 
196
			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
197
		} else
-
 
198
		    bbtree_add (bbt->right, bbt->chain, &bbt->extents);
-
 
199
	    }
-
 
200
 
-
 
201
	    bbt->chain = NULL;
-
 
202
	}
-
 
203
 
-
 
204
	bbt->extents.p1.x = MIN (bbt->extents.p1.x, box->p1.x);
-
 
205
	bbt->extents.p1.y = MIN (bbt->extents.p1.y, box->p1.y);
-
 
206
	bbt->extents.p2.x = MAX (bbt->extents.p2.x, box->p2.x);
-
 
207
	bbt->extents.p2.y = MAX (bbt->extents.p2.y, box->p2.y);
-
 
208
    }
-
 
209
 
-
 
210
    if (box->p1.x == bbt->extents.p1.x && box->p1.y == bbt->extents.p1.y &&
-
 
211
	box->p2.x == bbt->extents.p2.x && box->p2.y == bbt->extents.p2.y)
-
 
212
    {
-
 
213
	cairo_command_header_t *last = header;
-
 
214
	while (last->chain) /* expected to be infrequent */
-
 
215
	    last = last->chain;
-
 
216
	last->chain = bbt->chain;
-
 
217
	bbt->chain = header;
-
 
218
	return CAIRO_STATUS_SUCCESS;
-
 
219
    }
-
 
220
 
-
 
221
    if (bbtree_left_or_right (bbt, box)) {
-
 
222
	if (bbt->left == NULL) {
-
 
223
	    bbt->left = bbtree_new (box, header);
-
 
224
	    if (unlikely (bbt->left == NULL))
-
 
225
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
226
	} else
-
 
227
	    return bbtree_add (bbt->left, header, box);
-
 
228
    } else {
-
 
229
	if (bbt->right == NULL) {
-
 
230
	    bbt->right = bbtree_new (box, header);
-
 
231
	    if (unlikely (bbt->right == NULL))
-
 
232
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
233
	} else
-
 
234
	    return bbtree_add (bbt->right, header, box);
-
 
235
    }
-
 
236
 
-
 
237
    return CAIRO_STATUS_SUCCESS;
-
 
238
}
-
 
239
 
-
 
240
static void bbtree_del (struct bbtree *bbt)
-
 
241
{
-
 
242
    if (bbt->left)
-
 
243
	bbtree_del (bbt->left);
-
 
244
    if (bbt->right)
-
 
245
	bbtree_del (bbt->right);
-
 
246
 
-
 
247
    free (bbt);
-
 
248
}
-
 
249
 
-
 
250
static cairo_bool_t box_outside (const cairo_box_t *a, const cairo_box_t *b)
-
 
251
{
-
 
252
    return
-
 
253
	a->p1.x >= b->p2.x || a->p1.y >= b->p2.y ||
-
 
254
	a->p2.x <= b->p1.x || a->p2.y <= b->p1.y;
-
 
255
}
-
 
256
 
-
 
257
static void
-
 
258
bbtree_foreach_mark_visible (struct bbtree *bbt,
-
 
259
			     const cairo_box_t *box,
-
 
260
			     unsigned int **indices)
-
 
261
{
-
 
262
    cairo_command_header_t *chain;
-
 
263
 
-
 
264
    for (chain = bbt->chain; chain; chain = chain->chain)
-
 
265
	*(*indices)++ = chain->index;
-
 
266
 
-
 
267
    if (bbt->left && ! box_outside (box, &bbt->left->extents))
-
 
268
	bbtree_foreach_mark_visible (bbt->left, box, indices);
-
 
269
    if (bbt->right && ! box_outside (box, &bbt->right->extents))
-
 
270
	bbtree_foreach_mark_visible (bbt->right, box, indices);
-
 
271
}
-
 
272
 
-
 
273
static inline int intcmp (const unsigned int a, const unsigned int b)
-
 
274
{
-
 
275
    return a - b;
-
 
276
}
-
 
277
CAIRO_COMBSORT_DECLARE (sort_indices, unsigned int, intcmp)
-
 
278
 
-
 
279
static inline int sizecmp (unsigned int a, unsigned int b, cairo_command_header_t **elements)
-
 
280
{
-
 
281
    const cairo_rectangle_int_t *r;
-
 
282
 
-
 
283
    r = &elements[a]->extents;
-
 
284
    a = r->width * r->height;
-
 
285
 
-
 
286
    r = &elements[b]->extents;
-
 
287
    b = r->width * r->height;
-
 
288
 
-
 
289
    return b - a;
-
 
290
}
-
 
291
CAIRO_COMBSORT_DECLARE_WITH_DATA (sort_commands, unsigned int, sizecmp)
-
 
292
 
-
 
293
static void
-
 
294
_cairo_recording_surface_destroy_bbtree (cairo_recording_surface_t *surface)
-
 
295
{
-
 
296
    cairo_command_t **elements;
-
 
297
    int i, num_elements;
-
 
298
 
-
 
299
    if (surface->bbtree.chain == INVALID_CHAIN)
-
 
300
	return;
-
 
301
 
-
 
302
    if (surface->bbtree.left) {
-
 
303
	bbtree_del (surface->bbtree.left);
-
 
304
	surface->bbtree.left = NULL;
-
 
305
    }
-
 
306
    if (surface->bbtree.right) {
-
 
307
	bbtree_del (surface->bbtree.right);
-
 
308
	surface->bbtree.right = NULL;
-
 
309
    }
-
 
310
 
-
 
311
    elements = _cairo_array_index (&surface->commands, 0);
-
 
312
    num_elements = surface->commands.num_elements;
-
 
313
    for (i = 0; i < num_elements; i++)
-
 
314
	elements[i]->header.chain = NULL;
-
 
315
 
-
 
316
    surface->bbtree.chain = INVALID_CHAIN;
-
 
317
}
-
 
318
 
-
 
319
static cairo_status_t
-
 
320
_cairo_recording_surface_create_bbtree (cairo_recording_surface_t *surface)
-
 
321
{
-
 
322
    cairo_command_t **elements = _cairo_array_index (&surface->commands, 0);
-
 
323
    unsigned int *indices;
-
 
324
    cairo_status_t status;
-
 
325
    unsigned int i, count;
-
 
326
 
-
 
327
    count = surface->commands.num_elements;
-
 
328
    if (count > surface->num_indices) {
-
 
329
	free (surface->indices);
-
 
330
	surface->indices = _cairo_malloc_ab (count, sizeof (int));
-
 
331
	if (unlikely (surface->indices == NULL))
-
 
332
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
333
 
-
 
334
	surface->num_indices = count;
-
 
335
    }
-
 
336
 
-
 
337
    indices = surface->indices;
-
 
338
    for (i = 0; i < count; i++)
-
 
339
	indices[i] = i;
-
 
340
 
-
 
341
    sort_commands (indices, count, elements);
-
 
342
 
-
 
343
    bbtree_init (&surface->bbtree, &elements[indices[0]]->header);
-
 
344
    for (i = 1; i < count; i++) {
-
 
345
	cairo_command_header_t *header = &elements[indices[i]]->header;
-
 
346
	cairo_box_t box;
-
 
347
 
-
 
348
	_cairo_box_from_rectangle (&box, &header->extents);
-
 
349
	status = bbtree_add (&surface->bbtree, header, &box);
-
 
350
	if (unlikely (status))
-
 
351
	    goto cleanup;
-
 
352
    }
-
 
353
 
-
 
354
    return CAIRO_STATUS_SUCCESS;
-
 
355
 
-
 
356
cleanup:
-
 
357
    bbtree_del (&surface->bbtree);
-
 
358
    return status;
110
 */
359
}
111
 
360
 
112
/**
361
/**
113
 * cairo_recording_surface_create:
362
 * cairo_recording_surface_create:
114
 * @content: the content of the recording surface
363
 * @content: the content of the recording surface
Line 132... Line 381...
132
 **/
381
 **/
133
cairo_surface_t *
382
cairo_surface_t *
134
cairo_recording_surface_create (cairo_content_t		 content,
383
cairo_recording_surface_create (cairo_content_t		 content,
135
				const cairo_rectangle_t	*extents)
384
				const cairo_rectangle_t	*extents)
136
{
385
{
137
    cairo_recording_surface_t *recording_surface;
386
    cairo_recording_surface_t *surface;
138
    cairo_status_t status;
-
 
Line 139... Line 387...
139
 
387
 
140
    recording_surface = malloc (sizeof (cairo_recording_surface_t));
388
    surface = malloc (sizeof (cairo_recording_surface_t));
141
    if (unlikely (recording_surface == NULL))
389
    if (unlikely (surface == NULL))
Line 142... Line 390...
142
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
390
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
143
 
391
 
144
    _cairo_surface_init (&recording_surface->base,
392
    _cairo_surface_init (&surface->base,
145
			 &cairo_recording_surface_backend,
393
			 &cairo_recording_surface_backend,
Line 146... Line -...
146
			 NULL, /* device */
-
 
Line 147... Line 394...
147
			 content);
394
			 NULL, /* device */
148
 
-
 
Line 149... Line 395...
149
    recording_surface->content = content;
395
			 content);
150
 
396
 
151
    recording_surface->unbounded = TRUE;
397
 
Line 152... Line 398...
152
    _cairo_clip_init (&recording_surface->clip);
398
    surface->unbounded = TRUE;
153
 
399
 
154
    /* unbounded -> 'infinite' extents */
400
    /* unbounded -> 'infinite' extents */
155
    if (extents != NULL) {
401
    if (extents != NULL) {
156
	recording_surface->extents_pixels = *extents;
402
	surface->extents_pixels = *extents;
Line 157... Line -...
157
 
-
 
158
	/* XXX check for overflow */
-
 
159
	recording_surface->extents.x = floor (extents->x);
-
 
160
	recording_surface->extents.y = floor (extents->y);
403
 
161
	recording_surface->extents.width = ceil (extents->x + extents->width) - recording_surface->extents.x;
-
 
162
	recording_surface->extents.height = ceil (extents->y + extents->height) - recording_surface->extents.y;
404
	/* XXX check for overflow */
Line 163... Line 405...
163
 
405
	surface->extents.x = floor (extents->x);
164
	status = _cairo_clip_rectangle (&recording_surface->clip,
-
 
Line 165... Line 406...
165
					&recording_surface->extents);
406
	surface->extents.y = floor (extents->y);
Line 166... Line 407...
166
	if (unlikely (status)) {
407
	surface->extents.width = ceil (extents->x + extents->width) - surface->extents.x;
167
	    free (recording_surface);
408
	surface->extents.height = ceil (extents->y + extents->height) - surface->extents.y;
Line -... Line 409...
-
 
409
 
-
 
410
	surface->unbounded = FALSE;
-
 
411
    }
-
 
412
 
168
	    return _cairo_surface_create_in_error (status);
413
    _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
169
	}
414
 
170
 
415
    surface->base.is_clear = TRUE;
Line 171... Line 416...
171
	recording_surface->unbounded = FALSE;
416
 
172
    }
417
    surface->bbtree.left = surface->bbtree.right = NULL;
Line 194... Line 439...
194
}
439
}
Line 195... Line 440...
195
 
440
 
196
static cairo_status_t
441
static cairo_status_t
197
_cairo_recording_surface_finish (void *abstract_surface)
442
_cairo_recording_surface_finish (void *abstract_surface)
198
{
443
{
199
    cairo_recording_surface_t *recording_surface = abstract_surface;
444
    cairo_recording_surface_t *surface = abstract_surface;
200
    cairo_command_t **elements;
445
    cairo_command_t **elements;
Line 201... Line 446...
201
    int i, num_elements;
446
    int i, num_elements;
202
 
447
 
203
    num_elements = recording_surface->commands.num_elements;
448
    num_elements = surface->commands.num_elements;
204
    elements = _cairo_array_index (&recording_surface->commands, 0);
449
    elements = _cairo_array_index (&surface->commands, 0);
Line 205... Line 450...
205
    for (i = 0; i < num_elements; i++) {
450
    for (i = 0; i < num_elements; i++) {
206
	cairo_command_t *command = elements[i];
451
	cairo_command_t *command = elements[i];
Line 236... Line 481...
236
 
481
 
237
	default:
482
	default:
238
	    ASSERT_NOT_REACHED;
483
	    ASSERT_NOT_REACHED;
Line 239... Line 484...
239
	}
484
	}
240
 
485
 
241
	_cairo_clip_fini (&command->header.clip);
486
	_cairo_clip_destroy (command->header.clip);
Line 242... Line 487...
242
	free (command);
487
	free (command);
-
 
488
    }
-
 
489
 
-
 
490
    _cairo_array_fini (&surface->commands);
-
 
491
 
-
 
492
    if (surface->bbtree.left)
-
 
493
	bbtree_del (surface->bbtree.left);
-
 
494
    if (surface->bbtree.right)
-
 
495
	bbtree_del (surface->bbtree.right);
-
 
496
 
-
 
497
    free (surface->indices);
-
 
498
 
-
 
499
    return CAIRO_STATUS_SUCCESS;
-
 
500
}
-
 
501
 
-
 
502
struct proxy {
-
 
503
    cairo_surface_t base;
-
 
504
    cairo_surface_t *image;
-
 
505
};
-
 
506
 
-
 
507
static cairo_status_t
-
 
508
proxy_acquire_source_image (void			 *abstract_surface,
-
 
509
			    cairo_image_surface_t	**image_out,
-
 
510
			    void			**image_extra)
-
 
511
{
-
 
512
    struct proxy *proxy = abstract_surface;
-
 
513
    return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
-
 
514
}
-
 
515
 
-
 
516
static void
-
 
517
proxy_release_source_image (void			*abstract_surface,
243
    }
518
			    cairo_image_surface_t	*image,
-
 
519
			    void			*image_extra)
-
 
520
{
Line -... Line 521...
-
 
521
    struct proxy *proxy = abstract_surface;
-
 
522
    _cairo_surface_release_source_image (proxy->image, image, image_extra);
-
 
523
}
244
 
524
 
245
    _cairo_array_fini (&recording_surface->commands);
525
static cairo_status_t
Line -... Line 526...
-
 
526
proxy_finish (void *abstract_surface)
-
 
527
{
-
 
528
    return CAIRO_STATUS_SUCCESS;
-
 
529
}
-
 
530
 
-
 
531
static const cairo_surface_backend_t proxy_backend  = {
-
 
532
    CAIRO_INTERNAL_SURFACE_TYPE_NULL,
-
 
533
    proxy_finish,
-
 
534
    NULL,
-
 
535
 
-
 
536
    NULL, /* create similar */
-
 
537
    NULL, /* create similar image */
-
 
538
    NULL, /* map to image */
-
 
539
    NULL, /* unmap image */
-
 
540
 
-
 
541
    _cairo_surface_default_source,
-
 
542
    proxy_acquire_source_image,
-
 
543
    proxy_release_source_image,
-
 
544
};
-
 
545
 
-
 
546
static cairo_surface_t *
-
 
547
attach_proxy (cairo_surface_t *source,
-
 
548
	      cairo_surface_t *image)
-
 
549
{
-
 
550
    struct proxy *proxy;
-
 
551
 
-
 
552
    proxy = malloc (sizeof (*proxy));
-
 
553
    if (unlikely (proxy == NULL))
-
 
554
	return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
-
 
555
 
-
 
556
    _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content);
-
 
557
 
-
 
558
    proxy->image = image;
-
 
559
    _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
-
 
560
 
-
 
561
    return &proxy->base;
-
 
562
}
-
 
563
 
-
 
564
static void
-
 
565
detach_proxy (cairo_surface_t *source,
-
 
566
	      cairo_surface_t *proxy)
-
 
567
{
-
 
568
    cairo_surface_finish (proxy);
-
 
569
    cairo_surface_destroy (proxy);
-
 
570
}
-
 
571
 
-
 
572
static cairo_surface_t *
246
    _cairo_clip_fini (&recording_surface->clip);
573
get_proxy (cairo_surface_t *proxy)
247
 
574
{
248
    return CAIRO_STATUS_SUCCESS;
575
    return ((struct proxy *)proxy)->image;
249
}
576
}
250
 
577
 
251
static cairo_status_t
-
 
252
_cairo_recording_surface_acquire_source_image (void			 *abstract_surface,
578
static cairo_status_t
253
					       cairo_image_surface_t	**image_out,
579
_cairo_recording_surface_acquire_source_image (void			 *abstract_surface,
-
 
580
					       cairo_image_surface_t	**image_out,
Line 254... Line 581...
254
					       void			**image_extra)
581
					       void			**image_extra)
255
{
-
 
256
    cairo_status_t status;
582
{
257
    cairo_recording_surface_t *surface = abstract_surface;
583
    cairo_recording_surface_t *surface = abstract_surface;
-
 
584
    cairo_surface_t *image, *proxy;
258
    cairo_surface_t *image;
585
    cairo_status_t status;
259
 
586
 
260
    image = _cairo_surface_has_snapshot (&surface->base,
587
    proxy = _cairo_surface_has_snapshot (abstract_surface, &proxy_backend);
Line -... Line 588...
-
 
588
    if (proxy != NULL) {
261
					 &_cairo_image_surface_backend);
589
	*image_out = (cairo_image_surface_t *)
262
    if (image != NULL) {
590
	    cairo_surface_reference (get_proxy (proxy));
263
	*image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
591
	*image_extra = NULL;
264
	*image_extra = NULL;
592
	return CAIRO_STATUS_SUCCESS;
265
	return CAIRO_STATUS_SUCCESS;
593
    }
Line 266... Line 594...
266
    }
594
 
267
 
-
 
268
    image = _cairo_image_surface_create_with_content (surface->content,
595
    assert (! surface->unbounded);
269
						      surface->extents.width,
-
 
270
						      surface->extents.height);
596
    image = _cairo_image_surface_create_with_content (surface->base.content,
-
 
597
						      surface->extents.width,
-
 
598
						      surface->extents.height);
271
    if (unlikely (image->status))
599
    if (unlikely (image->status))
272
	return image->status;
600
	return image->status;
273
 
601
 
274
    cairo_surface_set_device_offset (image,
602
    /* Handle recursion by returning future reads from the current image */
Line 275... Line -...
275
				     -surface->extents.x,
-
 
276
				     -surface->extents.y);
-
 
277
 
603
    proxy = attach_proxy (abstract_surface, image);
278
    status = _cairo_recording_surface_replay (&surface->base, image);
604
    status = _cairo_recording_surface_replay (&surface->base, image);
279
    if (unlikely (status)) {
605
    detach_proxy (abstract_surface, proxy);
280
	cairo_surface_destroy (image);
606
 
Line 295... Line 621...
295
{
621
{
296
    cairo_surface_destroy (&image->base);
622
    cairo_surface_destroy (&image->base);
297
}
623
}
Line 298... Line 624...
298
 
624
 
299
static cairo_status_t
625
static cairo_status_t
300
_command_init (cairo_recording_surface_t *recording_surface,
626
_command_init (cairo_recording_surface_t *surface,
301
	       cairo_command_header_t *command,
627
	       cairo_command_header_t *command,
302
	       cairo_command_type_t type,
628
	       cairo_command_type_t type,
303
	       cairo_operator_t op,
629
	       cairo_operator_t op,
304
	       cairo_clip_t *clip)
630
	       cairo_composite_rectangles_t *composite)
305
{
631
{
Line 306... Line 632...
306
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
632
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
307
 
633
 
308
    command->type = type;
634
    command->type = type;
-
 
635
    command->op = op;
-
 
636
    command->region = CAIRO_RECORDING_REGION_ALL;
-
 
637
 
309
    command->op = op;
638
    command->extents = composite->unbounded;
-
 
639
    command->chain = NULL;
-
 
640
    command->index = surface->commands.num_elements;
310
    command->region = CAIRO_RECORDING_REGION_ALL;
641
 
311
    _cairo_clip_init_copy (&command->clip, clip);
642
    /* steal the clip */
-
 
643
    command->clip = NULL;
-
 
644
    if (! _cairo_composite_rectangles_can_reduce_clip (composite,
-
 
645
						       composite->clip))
-
 
646
    {
-
 
647
	command->clip = composite->clip;
Line 312... Line 648...
312
    if (recording_surface->clip.path != NULL)
648
	composite->clip = NULL;
313
	status = _cairo_clip_apply_clip (&command->clip, &recording_surface->clip);
649
    }
Line -... Line 650...
-
 
650
 
-
 
651
    return status;
-
 
652
}
-
 
653
 
-
 
654
static void
-
 
655
_cairo_recording_surface_break_self_copy_loop (cairo_recording_surface_t *surface)
-
 
656
{
-
 
657
    cairo_surface_flush (&surface->base);
-
 
658
}
-
 
659
 
-
 
660
static cairo_status_t
-
 
661
_cairo_recording_surface_commit (cairo_recording_surface_t *surface,
-
 
662
				 cairo_command_header_t *command)
-
 
663
{
-
 
664
    _cairo_recording_surface_break_self_copy_loop (surface);
-
 
665
    return _cairo_array_append (&surface->commands, &command);
-
 
666
}
-
 
667
 
-
 
668
static void
-
 
669
_cairo_recording_surface_reset (cairo_recording_surface_t *surface)
-
 
670
{
-
 
671
    /* Reset the commands and temporaries */
-
 
672
    _cairo_recording_surface_finish (surface);
-
 
673
 
-
 
674
    surface->bbtree.left = surface->bbtree.right = NULL;
-
 
675
    surface->bbtree.chain = INVALID_CHAIN;
-
 
676
 
-
 
677
    surface->indices = NULL;
-
 
678
    surface->num_indices = 0;
-
 
679
 
-
 
680
    _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
-
 
681
}
-
 
682
 
-
 
683
static cairo_bool_t
-
 
684
is_identity_recording_pattern (const cairo_pattern_t *pattern)
-
 
685
{
-
 
686
    cairo_surface_t *surface;
-
 
687
 
-
 
688
    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
-
 
689
	return FALSE;
-
 
690
 
-
 
691
    if (!_cairo_matrix_is_identity(&pattern->matrix))
-
 
692
	return FALSE;
-
 
693
 
314
 
694
    surface = ((cairo_surface_pattern_t *)pattern)->surface;
315
    return status;
695
    return surface->backend->type == CAIRO_SURFACE_TYPE_RECORDING;
316
}
696
}
317
 
697
 
318
static cairo_int_status_t
698
static cairo_int_status_t
319
_cairo_recording_surface_paint (void			  *abstract_surface,
699
_cairo_recording_surface_paint (void			  *abstract_surface,
320
				cairo_operator_t	   op,
700
				cairo_operator_t	   op,
321
				const cairo_pattern_t	  *source,
701
				const cairo_pattern_t	  *source,
322
				cairo_clip_t		  *clip)
702
				const cairo_clip_t	  *clip)
-
 
703
{
-
 
704
    cairo_status_t status;
-
 
705
    cairo_recording_surface_t *surface = abstract_surface;
-
 
706
    cairo_command_paint_t *command;
-
 
707
    cairo_composite_rectangles_t composite;
-
 
708
 
-
 
709
    TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
-
 
710
 
-
 
711
    if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
-
 
712
	if (surface->optimize_clears) {
-
 
713
	    _cairo_recording_surface_reset (surface);
-
 
714
	    return CAIRO_STATUS_SUCCESS;
-
 
715
	}
-
 
716
    }
-
 
717
 
-
 
718
    if (clip == NULL && surface->optimize_clears &&
-
 
719
	(op == CAIRO_OPERATOR_SOURCE ||
-
 
720
	 (op == CAIRO_OPERATOR_OVER &&
-
 
721
	  (surface->base.is_clear || _cairo_pattern_is_opaque_solid (source)))))
-
 
722
    {
-
 
723
	_cairo_recording_surface_reset (surface);
-
 
724
	if (is_identity_recording_pattern (source)) {
-
 
725
	    cairo_surface_t *src = ((cairo_surface_pattern_t *)source)->surface;
-
 
726
	    return _cairo_recording_surface_replay (src, &surface->base);
-
 
727
	}
-
 
728
    }
-
 
729
 
-
 
730
    status = _cairo_composite_rectangles_init_for_paint (&composite,
-
 
731
							 &surface->base,
Line 323... Line 732...
323
{
732
							 op, source,
324
    cairo_status_t status;
733
							 clip);
325
    cairo_recording_surface_t *recording_surface = abstract_surface;
734
    if (unlikely (status))
-
 
735
	return status;
-
 
736
 
Line 326... Line 737...
326
    cairo_command_paint_t *command;
737
    command = malloc (sizeof (cairo_command_paint_t));
327
 
738
    if (unlikely (command == NULL)) {
-
 
739
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
328
    command = malloc (sizeof (cairo_command_paint_t));
740
	goto CLEANUP_COMPOSITE;
329
    if (unlikely (command == NULL))
741
    }
Line 330... Line 742...
330
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
742
 
331
 
743
    status = _command_init (surface,
332
    status = _command_init (recording_surface,
744
			    &command->header, CAIRO_COMMAND_PAINT, op,
Line 333... Line 745...
333
			    &command->header, CAIRO_COMMAND_PAINT, op, clip);
745
			    &composite);
334
    if (unlikely (status))
746
    if (unlikely (status))
335
	goto CLEANUP_COMMAND;
747
	goto CLEANUP_COMMAND;
Line 336... Line -...
336
 
-
 
337
    status = _cairo_pattern_init_snapshot (&command->source.base, source);
-
 
338
    if (unlikely (status))
748
 
339
	goto CLEANUP_COMMAND;
-
 
340
 
-
 
Line -... Line 749...
-
 
749
    status = _cairo_pattern_init_snapshot (&command->source.base, source);
341
    status = _cairo_array_append (&recording_surface->commands, &command);
750
    if (unlikely (status))
Line 342... Line 751...
342
    if (unlikely (status))
751
	goto CLEANUP_COMMAND;
343
	goto CLEANUP_SOURCE;
752
 
344
 
753
    status = _cairo_recording_surface_commit (surface, &command->header);
345
    /* An optimisation that takes care to not replay what was done
754
    if (unlikely (status))
346
     * before surface is cleared. We don't erase recorded commands
755
	goto CLEANUP_SOURCE;
-
 
756
 
-
 
757
    _cairo_recording_surface_destroy_bbtree (surface);
347
     * since we may have earlier snapshots of this surface. */
758
 
348
    if (op == CAIRO_OPERATOR_CLEAR && clip == NULL)
759
    _cairo_composite_rectangles_fini (&composite);
Line 349... Line 760...
349
	recording_surface->replay_start_idx = recording_surface->commands.num_elements;
760
    return CAIRO_STATUS_SUCCESS;
350
 
761
 
351
    return CAIRO_STATUS_SUCCESS;
762
  CLEANUP_SOURCE:
352
 
763
    _cairo_pattern_fini (&command->source.base);
353
  CLEANUP_SOURCE:
764
  CLEANUP_COMMAND:
354
    _cairo_pattern_fini (&command->source.base);
765
    _cairo_clip_destroy (command->header.clip);
355
  CLEANUP_COMMAND:
766
    free (command);
356
    _cairo_clip_fini (&command->header.clip);
767
CLEANUP_COMPOSITE:
357
    free (command);
768
    _cairo_composite_rectangles_fini (&composite);
358
    return status;
769
    return status;
-
 
770
}
-
 
771
 
-
 
772
static cairo_int_status_t
-
 
773
_cairo_recording_surface_mask (void			*abstract_surface,
-
 
774
			       cairo_operator_t		 op,
-
 
775
			       const cairo_pattern_t	*source,
-
 
776
			       const cairo_pattern_t	*mask,
-
 
777
			       const cairo_clip_t	*clip)
-
 
778
{
-
 
779
    cairo_status_t status;
Line 359... Line 780...
359
}
780
    cairo_recording_surface_t *surface = abstract_surface;
360
 
781
    cairo_command_mask_t *command;
361
static cairo_int_status_t
782
    cairo_composite_rectangles_t composite;
-
 
783
 
-
 
784
    TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
Line 362... Line 785...
362
_cairo_recording_surface_mask (void			*abstract_surface,
785
 
363
			       cairo_operator_t		 op,
786
    status = _cairo_composite_rectangles_init_for_mask (&composite,
-
 
787
							&surface->base,
364
			       const cairo_pattern_t	*source,
788
							op, source, mask,
365
			       const cairo_pattern_t	*mask,
789
							clip);
Line 366... Line 790...
366
			       cairo_clip_t		*clip)
790
    if (unlikely (status))
367
{
791
	return status;
Line 384... Line 808...
384
 
808
 
385
    status = _cairo_pattern_init_snapshot (&command->mask.base, mask);
809
    status = _cairo_pattern_init_snapshot (&command->mask.base, mask);
386
    if (unlikely (status))
810
    if (unlikely (status))
Line 387... Line 811...
387
	goto CLEANUP_SOURCE;
811
	goto CLEANUP_SOURCE;
388
 
812
 
389
    status = _cairo_array_append (&recording_surface->commands, &command);
813
    status = _cairo_recording_surface_commit (surface, &command->header);
Line -... Line 814...
-
 
814
    if (unlikely (status))
-
 
815
	goto CLEANUP_MASK;
-
 
816
 
390
    if (unlikely (status))
817
    _cairo_recording_surface_destroy_bbtree (surface);
Line 391... Line 818...
391
	goto CLEANUP_MASK;
818
 
392
 
819
    _cairo_composite_rectangles_fini (&composite);
393
    return CAIRO_STATUS_SUCCESS;
820
    return CAIRO_STATUS_SUCCESS;
394
 
821
 
395
  CLEANUP_MASK:
822
  CLEANUP_MASK:
396
    _cairo_pattern_fini (&command->mask.base);
823
    _cairo_pattern_fini (&command->mask.base);
397
  CLEANUP_SOURCE:
824
  CLEANUP_SOURCE:
-
 
825
    _cairo_pattern_fini (&command->source.base);
-
 
826
  CLEANUP_COMMAND:
398
    _cairo_pattern_fini (&command->source.base);
827
    _cairo_clip_destroy (command->header.clip);
399
  CLEANUP_COMMAND:
828
    free (command);
Line 400... Line 829...
400
    _cairo_clip_fini (&command->header.clip);
829
CLEANUP_COMPOSITE:
401
    free (command);
830
    _cairo_composite_rectangles_fini (&composite);
402
    return status;
831
    return status;
403
}
832
}
404
 
833
 
405
static cairo_int_status_t
834
static cairo_int_status_t
406
_cairo_recording_surface_stroke (void			*abstract_surface,
835
_cairo_recording_surface_stroke (void			*abstract_surface,
407
				 cairo_operator_t	 op,
836
				 cairo_operator_t	 op,
408
				 const cairo_pattern_t	*source,
837
				 const cairo_pattern_t	*source,
409
				 cairo_path_fixed_t	*path,
838
				 const cairo_path_fixed_t	*path,
410
				 const cairo_stroke_style_t	*style,
839
				 const cairo_stroke_style_t	*style,
411
				 const cairo_matrix_t		*ctm,
840
				 const cairo_matrix_t		*ctm,
412
				 const cairo_matrix_t		*ctm_inverse,
841
				 const cairo_matrix_t		*ctm_inverse,
413
				 double			 tolerance,
842
				 double			 tolerance,
414
				 cairo_antialias_t	 antialias,
843
				 cairo_antialias_t	 antialias,
-
 
844
				 const cairo_clip_t	*clip)
-
 
845
{
-
 
846
    cairo_status_t status;
-
 
847
    cairo_recording_surface_t *surface = abstract_surface;
-
 
848
    cairo_command_stroke_t *command;
-
 
849
    cairo_composite_rectangles_t composite;
-
 
850
 
-
 
851
    TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
-
 
852
 
-
 
853
    status = _cairo_composite_rectangles_init_for_stroke (&composite,
-
 
854
							  &surface->base,
Line 415... Line 855...
415
				 cairo_clip_t		*clip)
855
							  op, source,
416
{
856
							  path, style, ctm,
417
    cairo_status_t status;
857
							  clip);
-
 
858
    if (unlikely (status))
-
 
859
	return status;
Line 418... Line 860...
418
    cairo_recording_surface_t *recording_surface = abstract_surface;
860
 
419
    cairo_command_stroke_t *command;
861
    command = malloc (sizeof (cairo_command_stroke_t));
-
 
862
    if (unlikely (command == NULL)) {
420
 
863
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
421
    command = malloc (sizeof (cairo_command_stroke_t));
864
	goto CLEANUP_COMPOSITE;
Line 422... Line 865...
422
    if (unlikely (command == NULL))
865
    }
423
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
866
 
Line 442... Line 885...
442
    command->ctm = *ctm;
885
    command->ctm = *ctm;
443
    command->ctm_inverse = *ctm_inverse;
886
    command->ctm_inverse = *ctm_inverse;
444
    command->tolerance = tolerance;
887
    command->tolerance = tolerance;
445
    command->antialias = antialias;
888
    command->antialias = antialias;
Line 446... Line 889...
446
 
889
 
447
    status = _cairo_array_append (&recording_surface->commands, &command);
890
    status = _cairo_recording_surface_commit (surface, &command->header);
448
    if (unlikely (status))
891
    if (unlikely (status))
Line -... Line 892...
-
 
892
	goto CLEANUP_STYLE;
-
 
893
 
-
 
894
    _cairo_recording_surface_destroy_bbtree (surface);
449
	goto CLEANUP_STYLE;
895
 
Line 450... Line 896...
450
 
896
    _cairo_composite_rectangles_fini (&composite);
451
    return CAIRO_STATUS_SUCCESS;
897
    return CAIRO_STATUS_SUCCESS;
452
 
898
 
453
  CLEANUP_STYLE:
899
  CLEANUP_STYLE:
454
    _cairo_stroke_style_fini (&command->style);
900
    _cairo_stroke_style_fini (&command->style);
455
  CLEANUP_PATH:
901
  CLEANUP_PATH:
456
    _cairo_path_fixed_fini (&command->path);
902
    _cairo_path_fixed_fini (&command->path);
457
  CLEANUP_SOURCE:
903
  CLEANUP_SOURCE:
458
    _cairo_pattern_fini (&command->source.base);
904
    _cairo_pattern_fini (&command->source.base);
-
 
905
  CLEANUP_COMMAND:
-
 
906
    _cairo_clip_destroy (command->header.clip);
459
  CLEANUP_COMMAND:
907
    free (command);
460
    _cairo_clip_fini (&command->header.clip);
908
CLEANUP_COMPOSITE:
Line 461... Line 909...
461
    free (command);
909
    _cairo_composite_rectangles_fini (&composite);
462
    return status;
910
    return status;
463
}
911
}
464
 
912
 
465
static cairo_int_status_t
913
static cairo_int_status_t
466
_cairo_recording_surface_fill (void			*abstract_surface,
914
_cairo_recording_surface_fill (void			*abstract_surface,
467
			       cairo_operator_t		 op,
915
			       cairo_operator_t		 op,
468
			       const cairo_pattern_t	*source,
916
			       const cairo_pattern_t	*source,
469
			       cairo_path_fixed_t	*path,
917
			       const cairo_path_fixed_t	*path,
470
			       cairo_fill_rule_t	 fill_rule,
918
			       cairo_fill_rule_t	 fill_rule,
471
			       double			 tolerance,
919
			       double			 tolerance,
472
			       cairo_antialias_t	 antialias,
920
			       cairo_antialias_t	 antialias,
473
			       cairo_clip_t		*clip)
921
			       const cairo_clip_t	*clip)
-
 
922
{
-
 
923
    cairo_status_t status;
-
 
924
    cairo_recording_surface_t *surface = abstract_surface;
-
 
925
    cairo_command_fill_t *command;
-
 
926
    cairo_composite_rectangles_t composite;
-
 
927
 
-
 
928
    TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
-
 
929
 
-
 
930
    status = _cairo_composite_rectangles_init_for_fill (&composite,
-
 
931
							&surface->base,
Line 474... Line 932...
474
{
932
							op, source, path,
475
    cairo_status_t status;
933
							clip);
476
    cairo_recording_surface_t *recording_surface = abstract_surface;
934
    if (unlikely (status))
-
 
935
	return status;
-
 
936
 
Line 477... Line 937...
477
    cairo_command_fill_t *command;
937
    command = malloc (sizeof (cairo_command_fill_t));
478
 
938
    if (unlikely (command == NULL)) {
-
 
939
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
479
    command = malloc (sizeof (cairo_command_fill_t));
940
	goto CLEANUP_COMPOSITE;
480
    if (unlikely (command == NULL))
941
    }
Line 481... Line 942...
481
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
942
 
482
 
943
    status =_command_init (surface,
Line 495... Line 956...
495
 
956
 
496
    command->fill_rule = fill_rule;
957
    command->fill_rule = fill_rule;
497
    command->tolerance = tolerance;
958
    command->tolerance = tolerance;
Line 498... Line 959...
498
    command->antialias = antialias;
959
    command->antialias = antialias;
499
 
960
 
500
    status = _cairo_array_append (&recording_surface->commands, &command);
961
    status = _cairo_recording_surface_commit (surface, &command->header);
Line -... Line 962...
-
 
962
    if (unlikely (status))
-
 
963
	goto CLEANUP_PATH;
-
 
964
 
501
    if (unlikely (status))
965
    _cairo_recording_surface_destroy_bbtree (surface);
Line 502... Line 966...
502
	goto CLEANUP_PATH;
966
 
503
 
967
    _cairo_composite_rectangles_fini (&composite);
504
    return CAIRO_STATUS_SUCCESS;
968
    return CAIRO_STATUS_SUCCESS;
505
 
969
 
506
  CLEANUP_PATH:
970
  CLEANUP_PATH:
507
    _cairo_path_fixed_fini (&command->path);
971
    _cairo_path_fixed_fini (&command->path);
508
  CLEANUP_SOURCE:
972
  CLEANUP_SOURCE:
-
 
973
    _cairo_pattern_fini (&command->source.base);
-
 
974
  CLEANUP_COMMAND:
509
    _cairo_pattern_fini (&command->source.base);
975
    _cairo_clip_destroy (command->header.clip);
510
  CLEANUP_COMMAND:
976
    free (command);
Line 511... Line 977...
511
    _cairo_clip_fini (&command->header.clip);
977
CLEANUP_COMPOSITE:
512
    free (command);
978
    _cairo_composite_rectangles_fini (&composite);
Line 529... Line 995...
529
					   int				 num_glyphs,
995
					   int				 num_glyphs,
530
					   const cairo_text_cluster_t	*clusters,
996
					   const cairo_text_cluster_t	*clusters,
531
					   int				 num_clusters,
997
					   int				 num_clusters,
532
					   cairo_text_cluster_flags_t	 cluster_flags,
998
					   cairo_text_cluster_flags_t	 cluster_flags,
533
					   cairo_scaled_font_t		*scaled_font,
999
					   cairo_scaled_font_t		*scaled_font,
534
					   cairo_clip_t			*clip)
1000
					   const cairo_clip_t		*clip)
535
{
1001
{
536
    cairo_status_t status;
1002
    cairo_status_t status;
537
    cairo_recording_surface_t *recording_surface = abstract_surface;
1003
    cairo_recording_surface_t *surface = abstract_surface;
538
    cairo_command_show_text_glyphs_t *command;
1004
    cairo_command_show_text_glyphs_t *command;
-
 
1005
    cairo_composite_rectangles_t composite;
-
 
1006
 
-
 
1007
    TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
-
 
1008
 
-
 
1009
    status = _cairo_composite_rectangles_init_for_glyphs (&composite,
-
 
1010
							  &surface->base,
-
 
1011
							  op, source,
-
 
1012
							  scaled_font,
-
 
1013
							  glyphs, num_glyphs,
-
 
1014
							  clip,
-
 
1015
							  NULL);
-
 
1016
    if (unlikely (status))
-
 
1017
	return status;
Line 539... Line 1018...
539
 
1018
 
540
    command = malloc (sizeof (cairo_command_show_text_glyphs_t));
1019
    command = malloc (sizeof (cairo_command_show_text_glyphs_t));
541
    if (unlikely (command == NULL))
1020
    if (unlikely (command == NULL)) {
-
 
1021
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1022
	goto CLEANUP_COMPOSITE;
Line 542... Line 1023...
542
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1023
    }
543
 
1024
 
544
    status = _command_init (recording_surface,
1025
    status = _command_init (surface,
545
			    &command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
1026
			    &command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
546
			    op, clip);
1027
			    op, &composite);
Line 547... Line 1028...
547
    if (unlikely (status))
1028
    if (unlikely (status))
548
	goto CLEANUP_COMMAND;
1029
	goto CLEANUP_COMMAND;
Line 585... Line 1066...
585
 
1066
 
Line 586... Line 1067...
586
    command->cluster_flags = cluster_flags;
1067
    command->cluster_flags = cluster_flags;
Line 587... Line 1068...
587
 
1068
 
588
    command->scaled_font = cairo_scaled_font_reference (scaled_font);
1069
    command->scaled_font = cairo_scaled_font_reference (scaled_font);
589
 
1070
 
Line -... Line 1071...
-
 
1071
    status = _cairo_recording_surface_commit (surface, &command->header);
590
    status = _cairo_array_append (&recording_surface->commands, &command);
1072
    if (unlikely (status))
Line 591... Line 1073...
591
    if (unlikely (status))
1073
	goto CLEANUP_SCALED_FONT;
592
	goto CLEANUP_SCALED_FONT;
1074
 
593
 
1075
    _cairo_composite_rectangles_fini (&composite);
Line 600... Line 1082...
600
    free (command->glyphs);
1082
    free (command->glyphs);
601
    free (command->clusters);
1083
    free (command->clusters);
Line 602... Line 1084...
602
 
1084
 
603
    _cairo_pattern_fini (&command->source.base);
1085
    _cairo_pattern_fini (&command->source.base);
604
  CLEANUP_COMMAND:
1086
  CLEANUP_COMMAND:
-
 
1087
    _cairo_clip_destroy (command->header.clip);
-
 
1088
    free (command);
-
 
1089
CLEANUP_COMPOSITE:
-
 
1090
    _cairo_composite_rectangles_fini (&composite);
-
 
1091
    return status;
-
 
1092
}
-
 
1093
 
-
 
1094
static void
-
 
1095
_command_init_copy (cairo_recording_surface_t *surface,
-
 
1096
		    cairo_command_header_t *dst,
-
 
1097
		    const cairo_command_header_t *src)
-
 
1098
{
-
 
1099
    dst->type = src->type;
-
 
1100
    dst->op = src->op;
-
 
1101
    dst->region = CAIRO_RECORDING_REGION_ALL;
-
 
1102
 
-
 
1103
    dst->extents = src->extents;
-
 
1104
    dst->chain = NULL;
-
 
1105
    dst->index = surface->commands.num_elements;
-
 
1106
 
-
 
1107
    dst->clip = _cairo_clip_copy (src->clip);
-
 
1108
}
-
 
1109
 
-
 
1110
static cairo_status_t
-
 
1111
_cairo_recording_surface_copy__paint (cairo_recording_surface_t *surface,
-
 
1112
				      const cairo_command_t *src)
-
 
1113
{
-
 
1114
    cairo_command_paint_t *command;
-
 
1115
    cairo_status_t status;
-
 
1116
 
-
 
1117
    command = malloc (sizeof (*command));
-
 
1118
    if (unlikely (command == NULL)) {
-
 
1119
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1120
	goto err;
-
 
1121
    }
-
 
1122
 
-
 
1123
    _command_init_copy (surface, &command->header, &src->header);
-
 
1124
 
-
 
1125
    status = _cairo_pattern_init_copy (&command->source.base,
-
 
1126
				       &src->paint.source.base);
-
 
1127
    if (unlikely (status))
-
 
1128
	goto err_command;
-
 
1129
 
-
 
1130
    status = _cairo_recording_surface_commit (surface, &command->header);
-
 
1131
    if (unlikely (status))
-
 
1132
	goto err_source;
-
 
1133
 
-
 
1134
    return CAIRO_STATUS_SUCCESS;
-
 
1135
 
-
 
1136
err_source:
-
 
1137
    _cairo_pattern_fini (&command->source.base);
-
 
1138
err_command:
-
 
1139
    free(command);
-
 
1140
err:
-
 
1141
    return status;
-
 
1142
}
-
 
1143
 
-
 
1144
static cairo_status_t
-
 
1145
_cairo_recording_surface_copy__mask (cairo_recording_surface_t *surface,
-
 
1146
				     const cairo_command_t *src)
-
 
1147
{
-
 
1148
    cairo_command_mask_t *command;
-
 
1149
    cairo_status_t status;
-
 
1150
 
-
 
1151
    command = malloc (sizeof (*command));
-
 
1152
    if (unlikely (command == NULL)) {
-
 
1153
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1154
	goto err;
-
 
1155
    }
-
 
1156
 
-
 
1157
    _command_init_copy (surface, &command->header, &src->header);
-
 
1158
 
-
 
1159
    status = _cairo_pattern_init_copy (&command->source.base,
-
 
1160
				       &src->mask.source.base);
-
 
1161
    if (unlikely (status))
-
 
1162
	goto err_command;
-
 
1163
 
-
 
1164
    status = _cairo_pattern_init_copy (&command->mask.base,
-
 
1165
				       &src->mask.source.base);
-
 
1166
    if (unlikely (status))
-
 
1167
	goto err_source;
-
 
1168
 
-
 
1169
    status = _cairo_recording_surface_commit (surface, &command->header);
-
 
1170
    if (unlikely (status))
-
 
1171
	goto err_mask;
-
 
1172
 
-
 
1173
    return CAIRO_STATUS_SUCCESS;
-
 
1174
 
-
 
1175
err_mask:
-
 
1176
    _cairo_pattern_fini (&command->mask.base);
-
 
1177
err_source:
-
 
1178
    _cairo_pattern_fini (&command->source.base);
605
    _cairo_clip_fini (&command->header.clip);
1179
err_command:
-
 
1180
    free(command);
606
    free (command);
1181
err:
607
    return status;
1182
    return status;
Line -... Line 1183...
-
 
1183
}
-
 
1184
 
-
 
1185
static cairo_status_t
-
 
1186
_cairo_recording_surface_copy__stroke (cairo_recording_surface_t *surface,
-
 
1187
				     const cairo_command_t *src)
-
 
1188
{
-
 
1189
    cairo_command_stroke_t *command;
-
 
1190
    cairo_status_t status;
-
 
1191
 
-
 
1192
    command = malloc (sizeof (*command));
-
 
1193
    if (unlikely (command == NULL)) {
-
 
1194
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1195
	goto err;
-
 
1196
    }
-
 
1197
 
-
 
1198
    _command_init_copy (surface, &command->header, &src->header);
-
 
1199
 
-
 
1200
    status = _cairo_pattern_init_copy (&command->source.base,
-
 
1201
				       &src->stroke.source.base);
-
 
1202
    if (unlikely (status))
-
 
1203
	goto err_command;
-
 
1204
 
-
 
1205
    status = _cairo_path_fixed_init_copy (&command->path, &src->stroke.path);
-
 
1206
    if (unlikely (status))
-
 
1207
	goto err_source;
-
 
1208
 
-
 
1209
    status = _cairo_stroke_style_init_copy (&command->style,
-
 
1210
					    &src->stroke.style);
-
 
1211
    if (unlikely (status))
-
 
1212
	goto err_path;
-
 
1213
 
-
 
1214
    command->ctm = src->stroke.ctm;
-
 
1215
    command->ctm_inverse = src->stroke.ctm_inverse;
-
 
1216
    command->tolerance = src->stroke.tolerance;
-
 
1217
    command->antialias = src->stroke.antialias;
-
 
1218
 
-
 
1219
    status = _cairo_recording_surface_commit (surface, &command->header);
-
 
1220
    if (unlikely (status))
-
 
1221
	goto err_style;
-
 
1222
 
-
 
1223
    return CAIRO_STATUS_SUCCESS;
-
 
1224
 
-
 
1225
err_style:
-
 
1226
    _cairo_stroke_style_fini (&command->style);
-
 
1227
err_path:
-
 
1228
    _cairo_path_fixed_fini (&command->path);
-
 
1229
err_source:
-
 
1230
    _cairo_pattern_fini (&command->source.base);
-
 
1231
err_command:
-
 
1232
    free(command);
-
 
1233
err:
-
 
1234
    return status;
-
 
1235
}
-
 
1236
 
-
 
1237
static cairo_status_t
-
 
1238
_cairo_recording_surface_copy__fill (cairo_recording_surface_t *surface,
-
 
1239
				     const cairo_command_t *src)
-
 
1240
{
-
 
1241
    cairo_command_fill_t *command;
-
 
1242
    cairo_status_t status;
-
 
1243
 
-
 
1244
    command = malloc (sizeof (*command));
-
 
1245
    if (unlikely (command == NULL)) {
-
 
1246
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1247
	goto err;
-
 
1248
    }
-
 
1249
 
-
 
1250
    _command_init_copy (surface, &command->header, &src->header);
-
 
1251
 
-
 
1252
    status = _cairo_pattern_init_copy (&command->source.base,
-
 
1253
				       &src->fill.source.base);
-
 
1254
    if (unlikely (status))
-
 
1255
	goto err_command;
-
 
1256
 
-
 
1257
    status = _cairo_path_fixed_init_copy (&command->path, &src->fill.path);
-
 
1258
    if (unlikely (status))
-
 
1259
	goto err_source;
-
 
1260
 
-
 
1261
    command->fill_rule = src->fill.fill_rule;
-
 
1262
    command->tolerance = src->fill.tolerance;
-
 
1263
    command->antialias = src->fill.antialias;
-
 
1264
 
-
 
1265
    status = _cairo_recording_surface_commit (surface, &command->header);
-
 
1266
    if (unlikely (status))
-
 
1267
	goto err_path;
-
 
1268
 
-
 
1269
    return CAIRO_STATUS_SUCCESS;
-
 
1270
 
-
 
1271
err_path:
-
 
1272
    _cairo_path_fixed_fini (&command->path);
-
 
1273
err_source:
-
 
1274
    _cairo_pattern_fini (&command->source.base);
-
 
1275
err_command:
-
 
1276
    free(command);
-
 
1277
err:
-
 
1278
    return status;
-
 
1279
}
-
 
1280
 
-
 
1281
static cairo_status_t
-
 
1282
_cairo_recording_surface_copy__glyphs (cairo_recording_surface_t *surface,
-
 
1283
				       const cairo_command_t *src)
-
 
1284
{
-
 
1285
    cairo_command_show_text_glyphs_t *command;
-
 
1286
    cairo_status_t status;
-
 
1287
 
-
 
1288
    command = malloc (sizeof (*command));
-
 
1289
    if (unlikely (command == NULL)) {
-
 
1290
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1291
	goto err;
-
 
1292
    }
-
 
1293
 
-
 
1294
    _command_init_copy (surface, &command->header, &src->header);
-
 
1295
 
-
 
1296
    status = _cairo_pattern_init_copy (&command->source.base,
-
 
1297
				       &src->show_text_glyphs.source.base);
-
 
1298
    if (unlikely (status))
-
 
1299
	goto err_command;
-
 
1300
 
-
 
1301
    command->utf8 = NULL;
-
 
1302
    command->utf8_len = src->show_text_glyphs.utf8_len;
-
 
1303
    command->glyphs = NULL;
-
 
1304
    command->num_glyphs = src->show_text_glyphs.num_glyphs;
-
 
1305
    command->clusters = NULL;
-
 
1306
    command->num_clusters = src->show_text_glyphs.num_clusters;
-
 
1307
 
-
 
1308
    if (command->utf8_len) {
-
 
1309
	command->utf8 = malloc (command->utf8_len);
-
 
1310
	if (unlikely (command->utf8 == NULL)) {
-
 
1311
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1312
	    goto err_arrays;
-
 
1313
	}
-
 
1314
	memcpy (command->utf8, src->show_text_glyphs.utf8, command->utf8_len);
-
 
1315
    }
-
 
1316
    if (command->num_glyphs) {
-
 
1317
	command->glyphs = _cairo_malloc_ab (command->num_glyphs,
-
 
1318
					    sizeof (command->glyphs[0]));
-
 
1319
	if (unlikely (command->glyphs == NULL)) {
-
 
1320
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1321
	    goto err_arrays;
-
 
1322
	}
-
 
1323
	memcpy (command->glyphs, src->show_text_glyphs.glyphs,
-
 
1324
		sizeof (command->glyphs[0]) * command->num_glyphs);
-
 
1325
    }
-
 
1326
    if (command->num_clusters) {
-
 
1327
	command->clusters = _cairo_malloc_ab (command->num_clusters,
-
 
1328
					      sizeof (command->clusters[0]));
-
 
1329
	if (unlikely (command->clusters == NULL)) {
-
 
1330
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1331
	    goto err_arrays;
-
 
1332
	}
-
 
1333
	memcpy (command->clusters, src->show_text_glyphs.clusters,
-
 
1334
		sizeof (command->clusters[0]) * command->num_clusters);
-
 
1335
    }
-
 
1336
 
-
 
1337
    command->cluster_flags = src->show_text_glyphs.cluster_flags;
-
 
1338
 
-
 
1339
    command->scaled_font =
-
 
1340
	cairo_scaled_font_reference (src->show_text_glyphs.scaled_font);
-
 
1341
 
-
 
1342
    status = _cairo_recording_surface_commit (surface, &command->header);
-
 
1343
    if (unlikely (status))
-
 
1344
	goto err_arrays;
-
 
1345
 
-
 
1346
    return CAIRO_STATUS_SUCCESS;
-
 
1347
 
-
 
1348
err_arrays:
-
 
1349
    free (command->utf8);
-
 
1350
    free (command->glyphs);
-
 
1351
    free (command->clusters);
-
 
1352
    _cairo_pattern_fini (&command->source.base);
-
 
1353
err_command:
-
 
1354
    free(command);
-
 
1355
err:
-
 
1356
    return status;
-
 
1357
}
-
 
1358
 
-
 
1359
static cairo_status_t
-
 
1360
_cairo_recording_surface_copy (cairo_recording_surface_t *dst,
-
 
1361
			       cairo_recording_surface_t *src)
-
 
1362
{
-
 
1363
    cairo_command_t **elements;
-
 
1364
    int i, num_elements;
-
 
1365
    cairo_status_t status;
-
 
1366
 
-
 
1367
    elements = _cairo_array_index (&src->commands, 0);
-
 
1368
    num_elements = src->commands.num_elements;
-
 
1369
    for (i = 0; i < num_elements; i++) {
-
 
1370
	const cairo_command_t *command = elements[i];
-
 
1371
 
-
 
1372
	switch (command->header.type) {
-
 
1373
	case CAIRO_COMMAND_PAINT:
-
 
1374
	    status = _cairo_recording_surface_copy__paint (dst, command);
-
 
1375
	    break;
-
 
1376
 
-
 
1377
	case CAIRO_COMMAND_MASK:
-
 
1378
	    status = _cairo_recording_surface_copy__mask (dst, command);
-
 
1379
	    break;
-
 
1380
 
-
 
1381
	case CAIRO_COMMAND_STROKE:
-
 
1382
	    status = _cairo_recording_surface_copy__stroke (dst, command);
-
 
1383
	    break;
-
 
1384
 
-
 
1385
	case CAIRO_COMMAND_FILL:
-
 
1386
	    status = _cairo_recording_surface_copy__fill (dst, command);
-
 
1387
	    break;
-
 
1388
 
-
 
1389
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
-
 
1390
	    status = _cairo_recording_surface_copy__glyphs (dst, command);
-
 
1391
	    break;
-
 
1392
 
-
 
1393
	default:
-
 
1394
	    ASSERT_NOT_REACHED;
-
 
1395
	}
-
 
1396
 
-
 
1397
	if (unlikely (status))
-
 
1398
	    return status;
-
 
1399
    }
-
 
1400
 
-
 
1401
    return CAIRO_STATUS_SUCCESS;
608
}
1402
}
609
 
1403
 
610
/**
1404
/**
611
 * _cairo_recording_surface_snapshot
1405
 * _cairo_recording_surface_snapshot:
612
 * @surface: a #cairo_surface_t which must be a recording surface
1406
 * @surface: a #cairo_surface_t which must be a recording surface
613
 *
1407
 *
614
 * Make an immutable copy of @surface. It is an error to call a
1408
 * Make an immutable copy of @surface. It is an error to call a
Line 622... Line 1416...
622
 **/
1416
 **/
623
static cairo_surface_t *
1417
static cairo_surface_t *
624
_cairo_recording_surface_snapshot (void *abstract_other)
1418
_cairo_recording_surface_snapshot (void *abstract_other)
625
{
1419
{
626
    cairo_recording_surface_t *other = abstract_other;
1420
    cairo_recording_surface_t *other = abstract_other;
627
    cairo_recording_surface_t *recording_surface;
1421
    cairo_recording_surface_t *surface;
628
    cairo_status_t status;
1422
    cairo_status_t status;
Line 629... Line 1423...
629
 
1423
 
630
    recording_surface = malloc (sizeof (cairo_recording_surface_t));
1424
    surface = malloc (sizeof (cairo_recording_surface_t));
631
    if (unlikely (recording_surface == NULL))
1425
    if (unlikely (surface == NULL))
Line 632... Line 1426...
632
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1426
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
633
 
1427
 
634
    _cairo_surface_init (&recording_surface->base,
1428
    _cairo_surface_init (&surface->base,
635
			 &cairo_recording_surface_backend,
1429
			 &cairo_recording_surface_backend,
Line 636... Line 1430...
636
			 NULL, /* device */
1430
			 NULL, /* device */
637
			 other->base.content);
1431
			 other->base.content);
638
 
1432
 
639
    recording_surface->extents_pixels = other->extents_pixels;
-
 
Line 640... Line 1433...
640
    recording_surface->extents = other->extents;
1433
    surface->extents_pixels = other->extents_pixels;
Line 641... Line 1434...
641
    recording_surface->unbounded = other->unbounded;
1434
    surface->extents = other->extents;
642
    recording_surface->content = other->content;
1435
    surface->unbounded = other->unbounded;
-
 
1436
 
643
 
1437
    surface->base.is_clear = other->base.is_clear;
644
    _cairo_clip_init_copy (&recording_surface->clip, &other->clip);
1438
 
645
 
1439
    surface->bbtree.left = surface->bbtree.right = NULL;
Line 646... Line 1440...
646
    /* XXX We should in theory be able to reuse the original array, but we
1440
    surface->bbtree.chain = INVALID_CHAIN;
647
     * need to handle reference cycles during subsurface and self-copy.
1441
 
648
     */
1442
    surface->indices = NULL;
649
    recording_surface->replay_start_idx = 0;
1443
    surface->num_indices = 0;
650
    recording_surface->base.is_clear = TRUE;
1444
    surface->optimize_clears = TRUE;
651
 
1445
 
Line 652... Line 1446...
652
    _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *));
1446
    _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
653
    status = _cairo_recording_surface_replay (&other->base, &recording_surface->base);
1447
    status = _cairo_recording_surface_copy (surface, other);
Line 654... Line 1448...
654
    if (unlikely (status)) {
1448
    if (unlikely (status)) {
655
	cairo_surface_destroy (&recording_surface->base);
1449
	cairo_surface_destroy (&surface->base);
656
	return _cairo_surface_create_in_error (status);
1450
	return _cairo_surface_create_in_error (status);
Line 670... Line 1464...
670
 
1464
 
671
    *rectangle = surface->extents;
1465
    *rectangle = surface->extents;
672
    return TRUE;
1466
    return TRUE;
Line 673... Line -...
673
}
-
 
674
 
-
 
675
/**
-
 
676
 * _cairo_surface_is_recording:
-
 
677
 * @surface: a #cairo_surface_t
-
 
678
 *
-
 
679
 * Checks if a surface is a #cairo_recording_surface_t
-
 
680
 *
-
 
681
 * Return value: %TRUE if the surface is a recording surface
-
 
682
 **/
-
 
683
cairo_bool_t
-
 
684
_cairo_surface_is_recording (const cairo_surface_t *surface)
-
 
685
{
-
 
686
    return surface->backend == &cairo_recording_surface_backend;
-
 
687
}
1467
}
688
 
1468
 
689
static const cairo_surface_backend_t cairo_recording_surface_backend = {
-
 
690
    CAIRO_SURFACE_TYPE_RECORDING,
1469
static const cairo_surface_backend_t cairo_recording_surface_backend = {
-
 
1470
    CAIRO_SURFACE_TYPE_RECORDING,
-
 
1471
    _cairo_recording_surface_finish,
-
 
1472
 
-
 
1473
    _cairo_default_context_create,
-
 
1474
 
-
 
1475
    _cairo_recording_surface_create_similar,
-
 
1476
    NULL, /* create similar image */
-
 
1477
    NULL, /* map to image */
-
 
1478
    NULL, /* unmap image */
691
    _cairo_recording_surface_create_similar,
1479
 
692
    _cairo_recording_surface_finish,
1480
    _cairo_surface_default_source,
693
    _cairo_recording_surface_acquire_source_image,
-
 
694
    _cairo_recording_surface_release_source_image,
-
 
695
    NULL, /* acquire_dest_image */
-
 
696
    NULL, /* release_dest_image */
-
 
697
    NULL, /* clone_similar */
-
 
698
    NULL, /* composite */
1481
    _cairo_recording_surface_acquire_source_image,
699
    NULL, /* fill_rectangles */
-
 
700
    NULL, /* composite_trapezoids */
-
 
-
 
1482
    _cairo_recording_surface_release_source_image,
701
    NULL, /* create_span_renderer */
1483
    _cairo_recording_surface_snapshot,
702
    NULL, /* check_span_renderer */
1484
 
-
 
1485
    NULL, /* copy_page */
703
    NULL, /* copy_page */
1486
    NULL, /* show_page */
704
    NULL, /* show_page */
-
 
705
    _cairo_recording_surface_get_extents,
1487
 
-
 
1488
    _cairo_recording_surface_get_extents,
706
    NULL, /* old_show_glyphs */
1489
    NULL, /* get_font_options */
707
    NULL, /* get_font_options */
1490
 
708
    NULL, /* flush */
-
 
709
    NULL, /* mark_dirty_rectangle */
-
 
Line 710... Line 1491...
710
    NULL, /* scaled_font_fini */
1491
    NULL, /* flush */
711
    NULL, /* scaled_glyph_fini */
1492
    NULL, /* mark_dirty_rectangle */
712
 
1493
 
713
    /* Here are the 5 basic drawing operations, (which are in some
1494
    /* Here are the 5 basic drawing operations, (which are in some
Line 714... Line 1495...
714
     * sense the only things that cairo_recording_surface should need to
1495
     * sense the only things that cairo_recording_surface should need to
715
     * implement).  However, we implement the more generic show_text_glyphs
1496
     * implement).  However, we implement the more generic show_text_glyphs
716
     * instead of show_glyphs.  One or the other is eough. */
1497
     * instead of show_glyphs.  One or the other is eough. */
717
 
1498
 
-
 
1499
    _cairo_recording_surface_paint,
718
    _cairo_recording_surface_paint,
1500
    _cairo_recording_surface_mask,
719
    _cairo_recording_surface_mask,
-
 
720
    _cairo_recording_surface_stroke,
-
 
721
    _cairo_recording_surface_fill,
-
 
722
    NULL,
-
 
723
 
-
 
724
    _cairo_recording_surface_snapshot,
-
 
725
 
-
 
726
    NULL, /* is_similar */
-
 
727
    NULL, /* fill_stroke */
1501
    _cairo_recording_surface_stroke,
728
    NULL, /* create_solid_pattern_surface */
1502
    _cairo_recording_surface_fill,
729
    NULL, /* can_repaint_solid_pattern_surface */
1503
    NULL, /* fill-stroke */
Line 730... Line 1504...
730
 
1504
    NULL,
731
    _cairo_recording_surface_has_show_text_glyphs,
1505
    _cairo_recording_surface_has_show_text_glyphs,
732
    _cairo_recording_surface_show_text_glyphs
1506
    _cairo_recording_surface_show_text_glyphs,
733
};
1507
};
734
 
1508
 
735
cairo_int_status_t
1509
cairo_int_status_t
736
_cairo_recording_surface_get_path (cairo_surface_t    *surface,
1510
_cairo_recording_surface_get_path (cairo_surface_t    *abstract_surface,
737
				   cairo_path_fixed_t *path)
1511
				   cairo_path_fixed_t *path)
Line 738... Line 1512...
738
{
1512
{
739
    cairo_recording_surface_t *recording_surface;
1513
    cairo_recording_surface_t *surface;
Line 740... Line 1514...
740
    cairo_command_t **elements;
1514
    cairo_command_t **elements;
741
    int i, num_elements;
1515
    int i, num_elements;
Line 742... Line 1516...
742
    cairo_int_status_t status;
1516
    cairo_int_status_t status;
743
 
1517
 
744
    if (surface->status)
1518
    if (unlikely (abstract_surface->status))
745
	return surface->status;
1519
	return abstract_surface->status;
Line 746... Line 1520...
746
 
1520
 
747
    recording_surface = (cairo_recording_surface_t *) surface;
1521
    surface = (cairo_recording_surface_t *) abstract_surface;
748
    status = CAIRO_STATUS_SUCCESS;
1522
    status = CAIRO_STATUS_SUCCESS;
Line 763... Line 1537...
763
	    cairo_traps_t traps;
1537
	    cairo_traps_t traps;
Line 764... Line 1538...
764
 
1538
 
Line 765... Line 1539...
765
	    _cairo_traps_init (&traps);
1539
	    _cairo_traps_init (&traps);
766
 
1540
 
767
	    /* XXX call cairo_stroke_to_path() when that is implemented */
1541
	    /* XXX call cairo_stroke_to_path() when that is implemented */
768
	    status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
1542
	    status = _cairo_path_fixed_stroke_polygon_to_traps (&command->stroke.path,
769
							&command->stroke.style,
1543
								&command->stroke.style,
770
							&command->stroke.ctm,
1544
								&command->stroke.ctm,
771
							&command->stroke.ctm_inverse,
1545
								&command->stroke.ctm_inverse,
Line 772... Line 1546...
772
							command->stroke.tolerance,
1546
								command->stroke.tolerance,
773
							&traps);
1547
								&traps);
Line 774... Line 1548...
774
 
1548
 
775
	    if (status == CAIRO_STATUS_SUCCESS)
1549
	    if (status == CAIRO_INT_STATUS_SUCCESS)
776
		status = _cairo_traps_path (&traps, path);
1550
		status = _cairo_traps_path (&traps, path);
777
 
1551
 
778
	    _cairo_traps_fini (&traps);
1552
	    _cairo_traps_fini (&traps);
779
	    break;
1553
	    break;
780
	}
1554
	}
781
	case CAIRO_COMMAND_FILL:
1555
	case CAIRO_COMMAND_FILL:
782
	{
1556
	{
783
	    status = _cairo_path_fixed_append (path,
1557
	    status = _cairo_path_fixed_append (path,
784
					       &command->fill.path, CAIRO_DIRECTION_FORWARD,
1558
					       &command->fill.path,
785
					       0, 0);
1559
					       0, 0);
Line 800... Line 1574...
800
 
1574
 
801
	if (unlikely (status))
1575
	if (unlikely (status))
802
	    break;
1576
	    break;
Line -... Line 1577...
-
 
1577
    }
-
 
1578
 
-
 
1579
    return status;
-
 
1580
}
-
 
1581
 
-
 
1582
static int
-
 
1583
_cairo_recording_surface_get_visible_commands (cairo_recording_surface_t *surface,
-
 
1584
					       const cairo_rectangle_int_t *extents)
-
 
1585
{
-
 
1586
    unsigned int num_visible, *indices;
-
 
1587
    cairo_box_t box;
-
 
1588
 
-
 
1589
    if (surface->commands.num_elements == 0)
-
 
1590
	    return 0;
-
 
1591
 
-
 
1592
    _cairo_box_from_rectangle (&box, extents);
803
    }
1593
 
-
 
1594
    if (surface->bbtree.chain == INVALID_CHAIN)
-
 
1595
	_cairo_recording_surface_create_bbtree (surface);
-
 
1596
 
-
 
1597
    indices = surface->indices;
-
 
1598
    bbtree_foreach_mark_visible (&surface->bbtree, &box, &indices);
-
 
1599
    num_visible = indices - surface->indices;
-
 
1600
    if (num_visible > 1)
-
 
1601
	sort_indices (surface->indices, num_visible);
804
 
1602
 
Line 805... Line -...
805
    return _cairo_surface_set_error (surface, status);
-
 
806
}
1603
    return num_visible;
807
 
1604
}
808
#define _clip(c) ((c)->header.clip.path ? &(c)->header.clip : NULL)
1605
 
-
 
1606
static cairo_status_t
809
static cairo_status_t
1607
_cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
-
 
1608
					  const cairo_rectangle_int_t *surface_extents,
810
_cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
1609
					  const cairo_matrix_t *surface_transform,
811
					  const cairo_rectangle_int_t *surface_extents,
1610
					  cairo_surface_t	     *target,
812
					  cairo_surface_t	     *target,
1611
					  const cairo_clip_t *target_clip,
813
					  cairo_recording_replay_type_t type,
-
 
814
					  cairo_recording_region_type_t region)
-
 
815
{
-
 
816
    cairo_recording_surface_t *recording_surface;
-
 
817
    cairo_command_t **elements;
1612
					  cairo_recording_replay_type_t type,
-
 
1613
					  cairo_recording_region_type_t region)
-
 
1614
{
-
 
1615
    cairo_surface_wrapper_t wrapper;
-
 
1616
    cairo_command_t **elements;
-
 
1617
    cairo_bool_t replay_all =
-
 
1618
	type == CAIRO_RECORDING_REPLAY &&
-
 
1619
	region == CAIRO_RECORDING_REGION_ALL;
-
 
1620
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
-
 
1621
    cairo_rectangle_int_t extents;
Line 818... Line 1622...
818
    int i, num_elements;
1622
    cairo_bool_t use_indices = FALSE;
819
    cairo_int_status_t status;
1623
    const cairo_rectangle_int_t *r;
Line 820... Line 1624...
820
    cairo_surface_wrapper_t wrapper;
1624
    unsigned int i, num_elements;
821
 
1625
 
Line 822... Line 1626...
822
    if (unlikely (surface->status))
1626
    if (unlikely (surface->base.status))
823
	return surface->status;
1627
	return surface->base.status;
Line 824... Line 1628...
824
 
1628
 
825
    if (unlikely (target->status))
1629
    if (unlikely (target->status))
Line 826... Line 1630...
826
	return target->status;
1630
	return target->status;
Line 827... Line 1631...
827
 
1631
 
-
 
1632
    if (unlikely (surface->base.finished))
828
    if (unlikely (surface->finished))
1633
	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
-
 
1634
 
-
 
1635
    if (surface->base.is_clear)
-
 
1636
	return CAIRO_STATUS_SUCCESS;
-
 
1637
 
-
 
1638
    assert (_cairo_surface_is_recording (&surface->base));
-
 
1639
 
-
 
1640
    _cairo_surface_wrapper_init (&wrapper, target);
Line -... Line 1641...
-
 
1641
    if (surface_extents)
-
 
1642
	_cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents);
-
 
1643
    r = &_cairo_unbounded_rectangle;
-
 
1644
    if (! surface->unbounded) {
-
 
1645
	_cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents);
-
 
1646
	r = &surface->extents;
-
 
1647
    }
-
 
1648
    _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform);
829
	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
1649
    _cairo_surface_wrapper_set_clip (&wrapper, target_clip);
830
 
1650
 
-
 
1651
    /* Compute the extents of the target clip in recorded device space */
Line 831... Line 1652...
831
    if (surface->is_clear)
1652
    if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents))
832
	return CAIRO_STATUS_SUCCESS;
1653
	goto done;
Line 833... Line 1654...
833
 
1654
 
834
    assert (_cairo_surface_is_recording (surface));
1655
    num_elements = surface->commands.num_elements;
Line 835... Line 1656...
835
 
1656
    elements = _cairo_array_index (&surface->commands, 0);
836
    _cairo_surface_wrapper_init (&wrapper, target);
-
 
837
    _cairo_surface_wrapper_set_extents (&wrapper, surface_extents);
1657
    if (extents.width < r->width || extents.height < r->height) {
838
 
-
 
Line 839... Line 1658...
839
    recording_surface = (cairo_recording_surface_t *) surface;
1658
	num_elements =
840
    status = CAIRO_STATUS_SUCCESS;
1659
	    _cairo_recording_surface_get_visible_commands (surface, &extents);
841
 
1660
	use_indices = num_elements != surface->commands.num_elements;
842
    num_elements = recording_surface->commands.num_elements;
1661
    }
843
    elements = _cairo_array_index (&recording_surface->commands, 0);
1662
 
844
 
1663
    for (i = 0; i < num_elements; i++) {
845
    for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
1664
	cairo_command_t *command = elements[use_indices ? surface->indices[i] : i];
Line 846... Line 1665...
846
	cairo_command_t *command = elements[i];
1665
 
847
 
1666
	if (! replay_all && command->header.region != region)
848
	if (type == CAIRO_RECORDING_REPLAY && region != CAIRO_RECORDING_REGION_ALL) {
1667
	    continue;
849
	    if (command->header.region != region)
1668
 
850
		continue;
1669
	if (! _cairo_rectangle_intersects (&extents, &command->header.extents))
851
        }
1670
	    continue;
852
 
1671
 
Line 853... Line 1672...
853
	switch (command->header.type) {
1672
	switch (command->header.type) {
854
	case CAIRO_COMMAND_PAINT:
-
 
855
	    status = _cairo_surface_wrapper_paint (&wrapper,
1673
	case CAIRO_COMMAND_PAINT:
856
						   command->header.op,
1674
	    status = _cairo_surface_wrapper_paint (&wrapper,
857
						   &command->paint.source.base,
1675
						   command->header.op,
858
						   _clip (command));
1676
						   &command->paint.source.base,
859
	    break;
1677
						   command->header.clip);
860
 
1678
	    break;
861
	case CAIRO_COMMAND_MASK:
1679
 
862
	    status = _cairo_surface_wrapper_mask (&wrapper,
1680
	case CAIRO_COMMAND_MASK:
863
						  command->header.op,
1681
	    status = _cairo_surface_wrapper_mask (&wrapper,
864
						  &command->mask.source.base,
1682
						  command->header.op,
865
						  &command->mask.mask.base,
1683
						  &command->mask.source.base,
866
						  _clip (command));
1684
						  &command->mask.mask.base,
867
	    break;
1685
						  command->header.clip);
868
 
-
 
-
 
1686
	    break;
-
 
1687
 
869
	case CAIRO_COMMAND_STROKE:
1688
	case CAIRO_COMMAND_STROKE:
Line 870... Line 1689...
870
	{
1689
	    status = _cairo_surface_wrapper_stroke (&wrapper,
871
	    status = _cairo_surface_wrapper_stroke (&wrapper,
1690
						    command->header.op,
872
						    command->header.op,
1691
						    &command->stroke.source.base,
Line 896... Line 1715...
896
		    stroke_command = NULL;
1715
			stroke_command = NULL;
897
	    }
1716
		}
Line 898... Line 1717...
898
 
1717
 
899
	    if (stroke_command != NULL &&
1718
		if (stroke_command != NULL &&
900
		stroke_command->header.type == CAIRO_COMMAND_STROKE &&
1719
		    stroke_command->header.type == CAIRO_COMMAND_STROKE &&
901
		_cairo_path_fixed_is_equal (&command->fill.path,
1720
		    _cairo_path_fixed_equal (&command->fill.path,
-
 
1721
					     &stroke_command->stroke.path) &&
-
 
1722
		    _cairo_clip_equal (command->header.clip,
902
					    &stroke_command->stroke.path))
1723
				       stroke_command->header.clip))
903
	    {
1724
		{
904
		status = _cairo_surface_wrapper_fill_stroke (&wrapper,
1725
		    status = _cairo_surface_wrapper_fill_stroke (&wrapper,
905
							     command->header.op,
1726
								 command->header.op,
906
							     &command->fill.source.base,
1727
								 &command->fill.source.base,
Line 913... Line 1734...
913
							     &stroke_command->stroke.style,
1734
								 &stroke_command->stroke.style,
914
							     &stroke_command->stroke.ctm,
1735
								 &stroke_command->stroke.ctm,
915
							     &stroke_command->stroke.ctm_inverse,
1736
								 &stroke_command->stroke.ctm_inverse,
916
							     stroke_command->stroke.tolerance,
1737
								 stroke_command->stroke.tolerance,
917
							     stroke_command->stroke.antialias,
1738
								 stroke_command->stroke.antialias,
918
							     _clip (command));
1739
								 command->header.clip);
919
		i++;
1740
		    i++;
920
	    }
1741
		}
921
	    else
-
 
922
	    {
1742
	    }
-
 
1743
	    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
923
		status = _cairo_surface_wrapper_fill (&wrapper,
1744
		status = _cairo_surface_wrapper_fill (&wrapper,
924
						      command->header.op,
1745
						      command->header.op,
925
						      &command->fill.source.base,
1746
						      &command->fill.source.base,
926
						      &command->fill.path,
1747
						      &command->fill.path,
927
						      command->fill.fill_rule,
1748
						      command->fill.fill_rule,
928
						      command->fill.tolerance,
1749
						      command->fill.tolerance,
929
						      command->fill.antialias,
1750
						      command->fill.antialias,
930
						      _clip (command));
1751
						      command->header.clip);
931
	    }
1752
	    }
932
	    break;
1753
	    break;
933
	}
-
 
934
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
-
 
935
	{
-
 
936
	    cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
-
 
937
	    cairo_glyph_t *glyphs_copy;
-
 
938
	    int num_glyphs = command->show_text_glyphs.num_glyphs;
-
 
939
 
-
 
940
            /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
-
 
941
	     * to modify the glyph array that's passed in.  We must always
-
 
942
	     * copy the array before handing it to the backend.
-
 
943
	     */
-
 
944
	    glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-
 
945
	    if (unlikely (glyphs_copy == NULL)) {
-
 
946
		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
947
		break;
-
 
948
	    }
-
 
949
 
-
 
950
	    memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
-
 
Line -... Line 1754...
-
 
1754
 
951
 
1755
	case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
952
	    status = _cairo_surface_wrapper_show_text_glyphs (&wrapper,
1756
	    status = _cairo_surface_wrapper_show_text_glyphs (&wrapper,
953
							      command->header.op,
1757
							      command->header.op,
954
							      &command->show_text_glyphs.source.base,
1758
							      &command->show_text_glyphs.source.base,
955
							      command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
1759
							      command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
956
							      glyphs_copy, num_glyphs,
1760
							      command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs,
957
							      command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
1761
							      command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
958
							      command->show_text_glyphs.cluster_flags,
1762
							      command->show_text_glyphs.cluster_flags,
959
							      command->show_text_glyphs.scaled_font,
1763
							      command->show_text_glyphs.scaled_font,
960
							      _clip (command));
-
 
961
	    free (glyphs_copy);
1764
							      command->header.clip);
962
	    break;
1765
	    break;
963
	}
1766
 
964
	default:
1767
	default:
965
	    ASSERT_NOT_REACHED;
1768
	    ASSERT_NOT_REACHED;
Line 966... Line 1769...
966
	}
1769
	}
967
 
1770
 
968
	if (type == CAIRO_RECORDING_CREATE_REGIONS) {
1771
	if (type == CAIRO_RECORDING_CREATE_REGIONS) {
969
	    if (status == CAIRO_STATUS_SUCCESS) {
1772
	    if (status == CAIRO_INT_STATUS_SUCCESS) {
970
		command->header.region = CAIRO_RECORDING_REGION_NATIVE;
1773
		command->header.region = CAIRO_RECORDING_REGION_NATIVE;
971
	    } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
1774
	    } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
972
		command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK;
1775
		command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK;
973
		status = CAIRO_STATUS_SUCCESS;
1776
		status = CAIRO_INT_STATUS_SUCCESS;
974
	    } else {
1777
	    } else {
975
		assert (_cairo_status_is_error (status));
1778
		assert (_cairo_int_status_is_error (status));
Line 976... Line 1779...
976
	    }
1779
	    }
977
	}
1780
	}
978
 
1781
 
Line 979... Line 1782...
979
	if (unlikely (status))
1782
	if (unlikely (status))
980
	    break;
-
 
981
    }
1783
	    break;
982
 
-
 
983
    /* free up any caches */
1784
    }
984
    for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
1785
 
Line -... Line 1786...
-
 
1786
done:
-
 
1787
    _cairo_surface_wrapper_fini (&wrapper);
-
 
1788
    return _cairo_surface_set_error (&surface->base, status);
-
 
1789
}
-
 
1790
 
985
	cairo_command_t *command = elements[i];
1791
cairo_status_t
-
 
1792
_cairo_recording_surface_replay_one (cairo_recording_surface_t	*surface,
-
 
1793
				     long unsigned index,
-
 
1794
				     cairo_surface_t	     *target)
-
 
1795
{
-
 
1796
    cairo_surface_wrapper_t wrapper;
-
 
1797
    cairo_command_t **elements, *command;
-
 
1798
    cairo_int_status_t status;
-
 
1799
 
-
 
1800
    if (unlikely (surface->base.status))
-
 
1801
	return surface->base.status;
-
 
1802
 
-
 
1803
    if (unlikely (target->status))
-
 
1804
	return target->status;
-
 
1805
 
-
 
1806
    if (unlikely (surface->base.finished))
-
 
1807
	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
-
 
1808
 
-
 
1809
    assert (_cairo_surface_is_recording (&surface->base));
-
 
1810
 
-
 
1811
    /* XXX
-
 
1812
     * Use a surface wrapper because we may want to do transformed
-
 
1813
     * replay in the future.
-
 
1814
     */
-
 
1815
    _cairo_surface_wrapper_init (&wrapper, target);
-
 
1816
 
-
 
1817
    if (index > surface->commands.num_elements)
-
 
1818
	return _cairo_error (CAIRO_STATUS_READ_ERROR);
-
 
1819
 
-
 
1820
    elements = _cairo_array_index (&surface->commands, 0);
-
 
1821
    command = elements[index];
-
 
1822
    switch (command->header.type) {
-
 
1823
    case CAIRO_COMMAND_PAINT:
-
 
1824
	status = _cairo_surface_wrapper_paint (&wrapper,
-
 
1825
					       command->header.op,
-
 
1826
					       &command->paint.source.base,
-
 
1827
					       command->header.clip);
-
 
1828
	break;
-
 
1829
 
-
 
1830
    case CAIRO_COMMAND_MASK:
-
 
1831
	status = _cairo_surface_wrapper_mask (&wrapper,
-
 
1832
					      command->header.op,
-
 
1833
					      &command->mask.source.base,
-
 
1834
					      &command->mask.mask.base,
-
 
1835
					      command->header.clip);
-
 
1836
	break;
-
 
1837
 
-
 
1838
    case CAIRO_COMMAND_STROKE:
-
 
1839
	status = _cairo_surface_wrapper_stroke (&wrapper,
-
 
1840
						command->header.op,
-
 
1841
						&command->stroke.source.base,
-
 
1842
						&command->stroke.path,
-
 
1843
						&command->stroke.style,
-
 
1844
						&command->stroke.ctm,
Line -... Line 1845...
-
 
1845
						&command->stroke.ctm_inverse,
986
 
1846
						command->stroke.tolerance,
-
 
1847
						command->stroke.antialias,
-
 
1848
						command->header.clip);
-
 
1849
	break;
-
 
1850
 
-
 
1851
    case CAIRO_COMMAND_FILL:
-
 
1852
	status = _cairo_surface_wrapper_fill (&wrapper,
-
 
1853
					      command->header.op,
-
 
1854
					      &command->fill.source.base,
-
 
1855
					      &command->fill.path,
-
 
1856
					      command->fill.fill_rule,
-
 
1857
					      command->fill.tolerance,
-
 
1858
					      command->fill.antialias,
-
 
1859
					      command->header.clip);
-
 
1860
	break;
-
 
1861
 
-
 
1862
    case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
-
 
1863
	status = _cairo_surface_wrapper_show_text_glyphs (&wrapper,
-
 
1864
							  command->header.op,
-
 
1865
							  &command->show_text_glyphs.source.base,
-
 
1866
							  command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
-
 
1867
							  command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs,
-
 
1868
							  command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
-
 
1869
							  command->show_text_glyphs.cluster_flags,
987
	_cairo_clip_drop_cache (&command->header.clip);
1870
							  command->show_text_glyphs.scaled_font,
Line -... Line 1871...
-
 
1871
							  command->header.clip);
-
 
1872
	break;
-
 
1873
 
988
    }
1874
    default:
989
 
1875
	ASSERT_NOT_REACHED;
990
    _cairo_surface_wrapper_fini (&wrapper);
1876
    }
991
 
1877
 
992
    return _cairo_surface_set_error (surface, status);
1878
    _cairo_surface_wrapper_fini (&wrapper);
Line 1006... Line 1892...
1006
 **/
1892
 **/
1007
cairo_status_t
1893
cairo_status_t
1008
_cairo_recording_surface_replay (cairo_surface_t *surface,
1894
_cairo_recording_surface_replay (cairo_surface_t *surface,
1009
				 cairo_surface_t *target)
1895
				 cairo_surface_t *target)
1010
{
1896
{
1011
    return _cairo_recording_surface_replay_internal (surface, NULL,
1897
    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL,
1012
						     target,
1898
						     target, NULL,
-
 
1899
						     CAIRO_RECORDING_REPLAY,
-
 
1900
						     CAIRO_RECORDING_REGION_ALL);
-
 
1901
}
-
 
1902
 
-
 
1903
cairo_status_t
-
 
1904
_cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
-
 
1905
					   const cairo_matrix_t *surface_transform,
-
 
1906
					   cairo_surface_t *target,
-
 
1907
					   const cairo_clip_t *target_clip)
-
 
1908
{
-
 
1909
    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform,
-
 
1910
						     target, target_clip,
1013
						     CAIRO_RECORDING_REPLAY,
1911
						     CAIRO_RECORDING_REPLAY,
1014
						     CAIRO_RECORDING_REGION_ALL);
1912
						     CAIRO_RECORDING_REGION_ALL);
1015
}
1913
}
Line 1016... Line 1914...
1016
 
1914
 
Line 1022... Line 1920...
1022
 */
1920
 */
1023
cairo_status_t
1921
cairo_status_t
1024
_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
1922
_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
1025
						    cairo_surface_t *target)
1923
						    cairo_surface_t *target)
1026
{
1924
{
1027
    return _cairo_recording_surface_replay_internal (surface, NULL,
1925
    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL,
1028
						     target,
1926
						     target, NULL,
1029
						     CAIRO_RECORDING_CREATE_REGIONS,
1927
						     CAIRO_RECORDING_CREATE_REGIONS,
1030
						     CAIRO_RECORDING_REGION_ALL);
1928
						     CAIRO_RECORDING_REGION_ALL);
1031
}
1929
}
Line 1032... Line 1930...
1032
 
1930
 
1033
cairo_status_t
1931
cairo_status_t
1034
_cairo_recording_surface_replay_region (cairo_surface_t          *surface,
1932
_cairo_recording_surface_replay_region (cairo_surface_t          *surface,
1035
					const cairo_rectangle_int_t *surface_extents,
1933
					const cairo_rectangle_int_t *surface_extents,
1036
					cairo_surface_t          *target,
1934
					cairo_surface_t          *target,
1037
					cairo_recording_region_type_t  region)
1935
					cairo_recording_region_type_t  region)
1038
{
1936
{
-
 
1937
    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface,
1039
    return _cairo_recording_surface_replay_internal (surface, surface_extents,
1938
						     surface_extents, NULL,
1040
						     target,
1939
						     target, NULL,
1041
						     CAIRO_RECORDING_REPLAY,
1940
						     CAIRO_RECORDING_REPLAY,
1042
						     region);
1941
						     region);
Line 1043... Line 1942...
1043
}
1942
}
Line 1049... Line 1948...
1049
{
1948
{
1050
    cairo_surface_t *null_surface;
1949
    cairo_surface_t *null_surface;
1051
    cairo_surface_t *analysis_surface;
1950
    cairo_surface_t *analysis_surface;
1052
    cairo_status_t status;
1951
    cairo_status_t status;
Line 1053... Line 1952...
1053
 
1952
 
1054
    null_surface = _cairo_null_surface_create (surface->content);
1953
    null_surface = _cairo_null_surface_create (surface->base.content);
1055
    analysis_surface = _cairo_analysis_surface_create (null_surface);
1954
    analysis_surface = _cairo_analysis_surface_create (null_surface);
Line 1056... Line 1955...
1056
    cairo_surface_destroy (null_surface);
1955
    cairo_surface_destroy (null_surface);
1057
 
1956
 
Line 1093... Line 1992...
1093
    cairo_status_t status;
1992
    cairo_status_t status;
1094
    cairo_box_t bbox;
1993
    cairo_box_t bbox;
Line 1095... Line 1994...
1095
 
1994
 
Line 1096... Line 1995...
1096
    memset (&bbox, 0, sizeof (bbox));
1995
    memset (&bbox, 0, sizeof (bbox));
1097
 
1996
 
1098
    if (! _cairo_surface_is_recording (surface)) {
1997
    if (surface->status || ! _cairo_surface_is_recording (surface)) {
1099
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1998
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
Line 1100... Line 1999...
1100
	goto DONE;
1999
	goto DONE;
Line 1130... Line 2029...
1130
	return CAIRO_STATUS_SUCCESS;
2029
	return CAIRO_STATUS_SUCCESS;
1131
    }
2030
    }
Line 1132... Line 2031...
1132
 
2031
 
1133
    return _recording_surface_get_ink_bbox (surface, bbox, transform);
2032
    return _recording_surface_get_ink_bbox (surface, bbox, transform);
-
 
2033
}
-
 
2034
 
-
 
2035
cairo_status_t
-
 
2036
_cairo_recording_surface_get_ink_bbox (cairo_recording_surface_t *surface,
-
 
2037
				       cairo_box_t *bbox,
-
 
2038
				       const cairo_matrix_t *transform)
-
 
2039
{
-
 
2040
    return _recording_surface_get_ink_bbox (surface, bbox, transform);
-
 
2041
}
-
 
2042
 
-
 
2043
/**
-
 
2044
 * cairo_recording_surface_get_extents:
-
 
2045
 * @surface: a #cairo_recording_surface_t
-
 
2046
 * @extents: the #cairo_rectangle_t to be assigned the extents
-
 
2047
 *
-
 
2048
 * Get the extents of the recording-surface.
-
 
2049
 *
-
 
2050
 * Return value: %TRUE if the surface is bounded, of recording type, and
-
 
2051
 * not in an error state, otherwise %FALSE
-
 
2052
 *
-
 
2053
 * Since: 1.12
-
 
2054
 **/
-
 
2055
cairo_bool_t
-
 
2056
cairo_recording_surface_get_extents (cairo_surface_t *surface,
-
 
2057
				     cairo_rectangle_t *extents)
-
 
2058
{
-
 
2059
    cairo_recording_surface_t *record;
-
 
2060
 
-
 
2061
    if (surface->status || ! _cairo_surface_is_recording (surface)) {
-
 
2062
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
-
 
2063
	return FALSE;
-
 
2064
    }
-
 
2065
 
-
 
2066
    record = (cairo_recording_surface_t *)surface;
-
 
2067
    if (record->unbounded)
-
 
2068
	return FALSE;
-
 
2069
 
-
 
2070
    *extents = record->extents_pixels;
-
 
2071
    return TRUE;