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; |