w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cairo-recording-surface.c
Go to the documentation of this file.
1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2005 Red Hat, Inc
5  * Copyright © 2007 Adrian Johnson
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is Red Hat, Inc.
33  *
34  * Contributor(s):
35  * Kristian Høgsberg <krh@redhat.com>
36  * Carl Worth <cworth@cworth.org>
37  * Adrian Johnson <ajohnson@redneon.com>
38  */
39 
40 /**
41  * SECTION:cairo-recording
42  * @Title: Recording Surfaces
43  * @Short_Description: Records all drawing operations
44  * @See_Also: #cairo_surface_t
45  *
46  * A recording surface is a surface that records all drawing operations at
47  * the highest level of the surface backend interface, (that is, the
48  * level of paint, mask, stroke, fill, and show_text_glyphs). The recording
49  * surface can then be "replayed" against any target surface by using it
50  * as a source surface.
51  *
52  * If you want to replay a surface so that the results in target will be
53  * identical to the results that would have been obtained if the original
54  * operations applied to the recording surface had instead been applied to the
55  * target surface, you can use code like this:
56  * <informalexample><programlisting>
57  * cairo_t *cr;
58  *
59  * cr = cairo_create (target);
60  * cairo_set_source_surface (cr, recording_surface, 0.0, 0.0);
61  * cairo_paint (cr);
62  * cairo_destroy (cr);
63  * </programlisting></informalexample>
64  *
65  * A recording surface is logically unbounded, i.e. it has no implicit constraint
66  * on the size of the drawing surface. However, in practice this is rarely
67  * useful as you wish to replay against a particular target surface with
68  * known bounds. For this case, it is more efficient to specify the target
69  * extents to the recording surface upon creation.
70  *
71  * The recording phase of the recording surface is careful to snapshot all
72  * necessary objects (paths, patterns, etc.), in order to achieve
73  * accurate replay. The efficiency of the recording surface could be
74  * improved by improving the implementation of snapshot for the
75  * various objects. For example, it would be nice to have a
76  * copy-on-write implementation for _cairo_surface_snapshot.
77  **/
78 
79 #include "cairoint.h"
80 
81 #include "cairo-array-private.h"
83 #include "cairo-clip-private.h"
84 #include "cairo-combsort-inline.h"
87 #include "cairo-error-private.h"
92 #include "cairo-traps-private.h"
93 
94 typedef enum {
98 
100 
101 /**
102  * CAIRO_HAS_RECORDING_SURFACE:
103  *
104  * Defined if the recording surface backend is available.
105  * The recording surface backend is always built in.
106  * This macro was added for completeness in cairo 1.10.
107  *
108  * Since: 1.10
109  **/
110 
111 /* Currently all recording surfaces do have a size which should be passed
112  * in as the maximum size of any target surface against which the
113  * recording-surface will ever be replayed.
114  *
115  * XXX: The naming of "pixels" in the size here is a misnomer. It's
116  * actually a size in whatever device-space units are desired (again,
117  * according to the intended replay target).
118  */
119 
120 static int bbtree_left_or_right (struct bbtree *bbt,
121  const cairo_box_t *box)
122 {
123  int left, right;
124 
125  if (bbt->left) {
126  cairo_box_t *e = &bbt->left->extents;
127  cairo_box_t b;
128 
129  b.p1.x = MIN (e->p1.x, box->p1.x);
130  b.p1.y = MIN (e->p1.y, box->p1.y);
131  b.p2.x = MAX (e->p2.x, box->p2.x);
132  b.p2.y = MAX (e->p2.y, box->p2.y);
133 
134  left = _cairo_fixed_integer_part (b.p2.x - b.p1.x) * _cairo_fixed_integer_part (b.p2.y - b.p1.y);
135  left -= _cairo_fixed_integer_part (e->p2.x - e->p1.x) * _cairo_fixed_integer_part (e->p2.y - e->p1.y);
136  } else
137  left = 0;
138 
139  if (bbt->right) {
140  cairo_box_t *e = &bbt->right->extents;
141  cairo_box_t b;
142 
143  b.p1.x = MIN (e->p1.x, box->p1.x);
144  b.p1.y = MIN (e->p1.y, box->p1.y);
145  b.p2.x = MAX (e->p2.x, box->p2.x);
146  b.p2.y = MAX (e->p2.y, box->p2.y);
147 
148  right = _cairo_fixed_integer_part (b.p2.x - b.p1.x) * _cairo_fixed_integer_part (b.p2.y - b.p1.y);
149  right -= _cairo_fixed_integer_part (e->p2.x - e->p1.x) * _cairo_fixed_integer_part (e->p2.y - e->p1.y);
150  } else
151  right = 0;
152 
153  return left <= right;
154 }
155 
156 #define INVALID_CHAIN ((cairo_command_header_t *)-1)
157 
158 static struct bbtree *
160 {
161  struct bbtree *bbt = _cairo_malloc (sizeof (*bbt));
162  if (bbt == NULL)
163  return NULL;
164  bbt->extents = *box;
165  bbt->left = bbt->right = NULL;
166  bbt->chain = chain;
167  return bbt;
168 }
169 
170 static void
172 {
173  _cairo_box_from_rectangle (&bbt->extents, &header->extents);
174  bbt->chain = header;
175 }
176 
177 static cairo_status_t
178 bbtree_add (struct bbtree *bbt,
180  const cairo_box_t *box)
181 {
182  if (box->p1.x < bbt->extents.p1.x || box->p1.y < bbt->extents.p1.y ||
183  box->p2.x > bbt->extents.p2.x || box->p2.y > bbt->extents.p2.y)
184  {
185  if (bbt->chain) {
186  if (bbtree_left_or_right (bbt, &bbt->extents)) {
187  if (bbt->left == NULL) {
188  bbt->left = bbtree_new (&bbt->extents, bbt->chain);
189  if (unlikely (bbt->left == NULL))
191  } else
192  bbtree_add (bbt->left, bbt->chain, &bbt->extents);
193  } else {
194  if (bbt->right == NULL) {
195  bbt->right = bbtree_new (&bbt->extents, bbt->chain);
196  if (unlikely (bbt->right == NULL))
198  } else
199  bbtree_add (bbt->right, bbt->chain, &bbt->extents);
200  }
201 
202  bbt->chain = NULL;
203  }
204 
205  bbt->extents.p1.x = MIN (bbt->extents.p1.x, box->p1.x);
206  bbt->extents.p1.y = MIN (bbt->extents.p1.y, box->p1.y);
207  bbt->extents.p2.x = MAX (bbt->extents.p2.x, box->p2.x);
208  bbt->extents.p2.y = MAX (bbt->extents.p2.y, box->p2.y);
209  }
210 
211  if (box->p1.x == bbt->extents.p1.x && box->p1.y == bbt->extents.p1.y &&
212  box->p2.x == bbt->extents.p2.x && box->p2.y == bbt->extents.p2.y)
213  {
215  while (last->chain) /* expected to be infrequent */
216  last = last->chain;
217  last->chain = bbt->chain;
218  bbt->chain = header;
219  return CAIRO_STATUS_SUCCESS;
220  }
221 
222  if (bbtree_left_or_right (bbt, box)) {
223  if (bbt->left == NULL) {
224  bbt->left = bbtree_new (box, header);
225  if (unlikely (bbt->left == NULL))
227  } else
228  return bbtree_add (bbt->left, header, box);
229  } else {
230  if (bbt->right == NULL) {
231  bbt->right = bbtree_new (box, header);
232  if (unlikely (bbt->right == NULL))
234  } else
235  return bbtree_add (bbt->right, header, box);
236  }
237 
238  return CAIRO_STATUS_SUCCESS;
239 }
240 
241 static void bbtree_del (struct bbtree *bbt)
242 {
243  if (bbt->left)
244  bbtree_del (bbt->left);
245  if (bbt->right)
246  bbtree_del (bbt->right);
247 
248  free (bbt);
249 }
250 
252 {
253  return
254  a->p1.x >= b->p2.x || a->p1.y >= b->p2.y ||
255  a->p2.x <= b->p1.x || a->p2.y <= b->p1.y;
256 }
257 
258 static void
259 bbtree_foreach_mark_visible (struct bbtree *bbt,
260  const cairo_box_t *box,
261  unsigned int **indices)
262 {
264 
265  for (chain = bbt->chain; chain; chain = chain->chain)
266  *(*indices)++ = chain->index;
267 
268  if (bbt->left && ! box_outside (box, &bbt->left->extents))
269  bbtree_foreach_mark_visible (bbt->left, box, indices);
270  if (bbt->right && ! box_outside (box, &bbt->right->extents))
271  bbtree_foreach_mark_visible (bbt->right, box, indices);
272 }
273 
274 static inline int intcmp (const unsigned int a, const unsigned int b)
275 {
276  return a - b;
277 }
279 
280 static inline int sizecmp (unsigned int a, unsigned int b, cairo_command_header_t **elements)
281 {
282  const cairo_rectangle_int_t *r;
283 
284  r = &elements[a]->extents;
285  a = r->width * r->height;
286 
287  r = &elements[b]->extents;
288  b = r->width * r->height;
289 
290  return b - a;
291 }
293 
294 static void
296 {
298  int i, num_elements;
299 
300  if (surface->bbtree.chain == INVALID_CHAIN)
301  return;
302 
303  if (surface->bbtree.left) {
304  bbtree_del (surface->bbtree.left);
305  surface->bbtree.left = NULL;
306  }
307  if (surface->bbtree.right) {
308  bbtree_del (surface->bbtree.right);
309  surface->bbtree.right = NULL;
310  }
311 
312  elements = _cairo_array_index (&surface->commands, 0);
313  num_elements = surface->commands.num_elements;
314  for (i = 0; i < num_elements; i++)
315  elements[i]->header.chain = NULL;
316 
317  surface->bbtree.chain = INVALID_CHAIN;
318 }
319 
320 static cairo_status_t
322 {
324  unsigned int *indices;
326  unsigned int i, count;
327 
328  count = surface->commands.num_elements;
329  if (count > surface->num_indices) {
330  free (surface->indices);
331  surface->indices = _cairo_malloc_ab (count, sizeof (int));
332  if (unlikely (surface->indices == NULL))
334 
335  surface->num_indices = count;
336  }
337 
338  indices = surface->indices;
339  for (i = 0; i < count; i++)
340  indices[i] = i;
341 
342  sort_commands (indices, count, elements);
343 
344  bbtree_init (&surface->bbtree, &elements[indices[0]]->header);
345  for (i = 1; i < count; i++) {
346  cairo_command_header_t *header = &elements[indices[i]]->header;
348 
349  _cairo_box_from_rectangle (&box, &header->extents);
350  status = bbtree_add (&surface->bbtree, header, &box);
351  if (unlikely (status))
352  goto cleanup;
353  }
354 
355  return CAIRO_STATUS_SUCCESS;
356 
357 cleanup:
358  bbtree_del (&surface->bbtree);
359  return status;
360 }
361 
362 /**
363  * cairo_recording_surface_create:
364  * @content: the content of the recording surface
365  * @extents: the extents to record in pixels, can be %NULL to record
366  * unbounded operations.
367  *
368  * Creates a recording-surface which can be used to record all drawing operations
369  * at the highest level (that is, the level of paint, mask, stroke, fill
370  * and show_text_glyphs). The recording surface can then be "replayed" against
371  * any target surface by using it as a source to drawing operations.
372  *
373  * The recording phase of the recording surface is careful to snapshot all
374  * necessary objects (paths, patterns, etc.), in order to achieve
375  * accurate replay.
376  *
377  * Return value: a pointer to the newly created surface. The caller
378  * owns the surface and should call cairo_surface_destroy() when done
379  * with it.
380  *
381  * Since: 1.10
382  **/
385  const cairo_rectangle_t *extents)
386 {
388 
390  if (unlikely (surface == NULL))
392 
395  NULL, /* device */
396  content,
397  TRUE); /* is_vector */
398 
399 
400  surface->unbounded = TRUE;
401 
402  /* unbounded -> 'infinite' extents */
403  if (extents != NULL) {
404  surface->extents_pixels = *extents;
405 
406  /* XXX check for overflow */
407  surface->extents.x = floor (extents->x);
408  surface->extents.y = floor (extents->y);
409  surface->extents.width = ceil (extents->x + extents->width) - surface->extents.x;
410  surface->extents.height = ceil (extents->y + extents->height) - surface->extents.y;
411 
412  surface->unbounded = FALSE;
413  }
414 
416 
417  surface->base.is_clear = TRUE;
418 
419  surface->bbtree.left = surface->bbtree.right = NULL;
420  surface->bbtree.chain = INVALID_CHAIN;
421 
422  surface->indices = NULL;
423  surface->num_indices = 0;
424  surface->optimize_clears = TRUE;
425  surface->has_bilevel_alpha = FALSE;
426  surface->has_only_op_over = FALSE;
427 
428  return &surface->base;
429 }
431 
432 static cairo_surface_t *
435  int width,
436  int height)
437 {
439  extents.x = extents.y = 0;
440  extents.width = width;
441  extents.height = height;
443 }
444 
445 static cairo_status_t
446 _cairo_recording_surface_finish (void *abstract_surface)
447 {
448  cairo_recording_surface_t *surface = abstract_surface;
450  int i, num_elements;
451 
452  num_elements = surface->commands.num_elements;
453  elements = _cairo_array_index (&surface->commands, 0);
454  for (i = 0; i < num_elements; i++) {
456 
457  switch (command->header.type) {
458  case CAIRO_COMMAND_PAINT:
459  _cairo_pattern_fini (&command->paint.source.base);
460  break;
461 
462  case CAIRO_COMMAND_MASK:
463  _cairo_pattern_fini (&command->mask.source.base);
464  _cairo_pattern_fini (&command->mask.mask.base);
465  break;
466 
468  _cairo_pattern_fini (&command->stroke.source.base);
469  _cairo_path_fixed_fini (&command->stroke.path);
470  _cairo_stroke_style_fini (&command->stroke.style);
471  break;
472 
473  case CAIRO_COMMAND_FILL:
474  _cairo_pattern_fini (&command->fill.source.base);
475  _cairo_path_fixed_fini (&command->fill.path);
476  break;
477 
479  _cairo_pattern_fini (&command->show_text_glyphs.source.base);
480  free (command->show_text_glyphs.utf8);
481  free (command->show_text_glyphs.glyphs);
482  free (command->show_text_glyphs.clusters);
483  cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font);
484  break;
485 
486  case CAIRO_COMMAND_TAG:
487  free (command->tag.tag_name);
488  if (command->tag.begin) {
489  free (command->tag.attributes);
490  _cairo_pattern_fini (&command->tag.source.base);
491  _cairo_stroke_style_fini (&command->tag.style);
492  }
493  break;
494 
495  default:
497  }
498 
499  _cairo_clip_destroy (command->header.clip);
500  free (command);
501  }
502 
503  _cairo_array_fini (&surface->commands);
504 
505  if (surface->bbtree.left)
506  bbtree_del (surface->bbtree.left);
507  if (surface->bbtree.right)
508  bbtree_del (surface->bbtree.right);
509 
510  free (surface->indices);
511 
512  return CAIRO_STATUS_SUCCESS;
513 }
514 
515 struct proxy {
518 };
519 
520 static cairo_status_t
521 proxy_acquire_source_image (void *abstract_surface,
522  cairo_image_surface_t **image_out,
523  void **image_extra)
524 {
525  struct proxy *proxy = abstract_surface;
526  return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
527 }
528 
529 static void
530 proxy_release_source_image (void *abstract_surface,
532  void *image_extra)
533 {
534  struct proxy *proxy = abstract_surface;
536 }
537 
538 static cairo_status_t
539 proxy_finish (void *abstract_surface)
540 {
541  return CAIRO_STATUS_SUCCESS;
542 }
543 
546  proxy_finish,
547  NULL,
548 
549  NULL, /* create similar */
550  NULL, /* create similar image */
551  NULL, /* map to image */
552  NULL, /* unmap image */
553 
557 };
558 
559 static cairo_surface_t *
562 {
563  struct proxy *proxy;
564 
565  proxy = _cairo_malloc (sizeof (*proxy));
566  if (unlikely (proxy == NULL))
568 
570 
571  proxy->image = image;
573 
574  return &proxy->base;
575 }
576 
577 static void
580 {
583 }
584 
585 static cairo_surface_t *
587 {
588  return ((struct proxy *)proxy)->image;
589 }
590 
591 static cairo_status_t
593  cairo_image_surface_t **image_out,
594  void **image_extra)
595 {
596  cairo_recording_surface_t *surface = abstract_surface;
599 
600  proxy = _cairo_surface_has_snapshot (abstract_surface, &proxy_backend);
601  if (proxy != NULL) {
602  *image_out = (cairo_image_surface_t *)
604  *image_extra = NULL;
605  return CAIRO_STATUS_SUCCESS;
606  }
607 
608  assert (! surface->unbounded);
610  surface->extents.width,
611  surface->extents.height);
612  if (unlikely (image->status))
613  return image->status;
614 
615  /* Handle recursion by returning future reads from the current image */
616  proxy = attach_proxy (abstract_surface, image);
618  detach_proxy (abstract_surface, proxy);
619 
620  if (unlikely (status)) {
622  return status;
623  }
624 
625  *image_out = (cairo_image_surface_t *) image;
626  *image_extra = NULL;
627  return CAIRO_STATUS_SUCCESS;
628 }
629 
630 static void
633  void *image_extra)
634 {
635  cairo_surface_destroy (&image->base);
636 }
637 
638 static cairo_status_t
644 {
646 
647  command->type = type;
648  command->op = op;
650 
651  command->extents = composite->unbounded;
652  command->chain = NULL;
653  command->index = surface->commands.num_elements;
654 
655  /* steal the clip */
656  command->clip = NULL;
658  composite->clip))
659  {
660  command->clip = composite->clip;
661  composite->clip = NULL;
662  }
663 
664  return status;
665 }
666 
667 static void
669 {
670  cairo_surface_flush (&surface->base);
671 }
672 
673 static cairo_status_t
676 {
678  return _cairo_array_append (&surface->commands, &command);
679 }
680 
681 static void
683 {
684  /* Reset the commands and temporaries */
686 
687  surface->bbtree.left = surface->bbtree.right = NULL;
688  surface->bbtree.chain = INVALID_CHAIN;
689 
690  surface->indices = NULL;
691  surface->num_indices = 0;
692 
694 }
695 
696 static cairo_int_status_t
697 _cairo_recording_surface_paint (void *abstract_surface,
699  const cairo_pattern_t *source,
700  const cairo_clip_t *clip)
701 {
703  cairo_recording_surface_t *surface = abstract_surface;
706 
707  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
708 
709  if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
710  if (surface->optimize_clears) {
712  return CAIRO_STATUS_SUCCESS;
713  }
714  }
715 
716  if (clip == NULL && surface->optimize_clears &&
718  (op == CAIRO_OPERATOR_OVER &&
720  {
722  }
723 
725  &surface->base,
726  op, source,
727  clip);
728  if (unlikely (status))
729  return status;
730 
732  if (unlikely (command == NULL)) {
734  goto CLEANUP_COMPOSITE;
735  }
736 
738  &command->header, CAIRO_COMMAND_PAINT, op,
739  &composite);
740  if (unlikely (status))
741  goto CLEANUP_COMMAND;
742 
744  if (unlikely (status))
745  goto CLEANUP_COMMAND;
746 
748  if (unlikely (status))
749  goto CLEANUP_SOURCE;
750 
752 
754  return CAIRO_STATUS_SUCCESS;
755 
756  CLEANUP_SOURCE:
757  _cairo_pattern_fini (&command->source.base);
758  CLEANUP_COMMAND:
759  _cairo_clip_destroy (command->header.clip);
760  free (command);
761 CLEANUP_COMPOSITE:
763  return status;
764 }
765 
766 static cairo_int_status_t
767 _cairo_recording_surface_mask (void *abstract_surface,
769  const cairo_pattern_t *source,
770  const cairo_pattern_t *mask,
771  const cairo_clip_t *clip)
772 {
774  cairo_recording_surface_t *surface = abstract_surface;
777 
778  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
779 
781  &surface->base,
782  op, source, mask,
783  clip);
784  if (unlikely (status))
785  return status;
786 
788  if (unlikely (command == NULL)) {
790  goto CLEANUP_COMPOSITE;
791  }
792 
794  &command->header, CAIRO_COMMAND_MASK, op,
795  &composite);
796  if (unlikely (status))
797  goto CLEANUP_COMMAND;
798 
800  if (unlikely (status))
801  goto CLEANUP_COMMAND;
802 
804  if (unlikely (status))
805  goto CLEANUP_SOURCE;
806 
808  if (unlikely (status))
809  goto CLEANUP_MASK;
810 
812 
814  return CAIRO_STATUS_SUCCESS;
815 
816  CLEANUP_MASK:
817  _cairo_pattern_fini (&command->mask.base);
818  CLEANUP_SOURCE:
819  _cairo_pattern_fini (&command->source.base);
820  CLEANUP_COMMAND:
821  _cairo_clip_destroy (command->header.clip);
822  free (command);
823 CLEANUP_COMPOSITE:
825  return status;
826 }
827 
828 static cairo_int_status_t
829 _cairo_recording_surface_stroke (void *abstract_surface,
831  const cairo_pattern_t *source,
832  const cairo_path_fixed_t *path,
834  const cairo_matrix_t *ctm,
835  const cairo_matrix_t *ctm_inverse,
836  double tolerance,
838  const cairo_clip_t *clip)
839 {
841  cairo_recording_surface_t *surface = abstract_surface;
844 
845  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
846 
848  &surface->base,
849  op, source,
850  path, style, ctm,
851  clip);
852  if (unlikely (status))
853  return status;
854 
856  if (unlikely (command == NULL)) {
858  goto CLEANUP_COMPOSITE;
859  }
860 
862  &command->header, CAIRO_COMMAND_STROKE, op,
863  &composite);
864  if (unlikely (status))
865  goto CLEANUP_COMMAND;
866 
868  if (unlikely (status))
869  goto CLEANUP_COMMAND;
870 
872  if (unlikely (status))
873  goto CLEANUP_SOURCE;
874 
876  if (unlikely (status))
877  goto CLEANUP_PATH;
878 
879  command->ctm = *ctm;
880  command->ctm_inverse = *ctm_inverse;
881  command->tolerance = tolerance;
882  command->antialias = antialias;
883 
885  if (unlikely (status))
886  goto CLEANUP_STYLE;
887 
889 
891  return CAIRO_STATUS_SUCCESS;
892 
893  CLEANUP_STYLE:
895  CLEANUP_PATH:
897  CLEANUP_SOURCE:
898  _cairo_pattern_fini (&command->source.base);
899  CLEANUP_COMMAND:
900  _cairo_clip_destroy (command->header.clip);
901  free (command);
902 CLEANUP_COMPOSITE:
904  return status;
905 }
906 
907 static cairo_int_status_t
908 _cairo_recording_surface_fill (void *abstract_surface,
910  const cairo_pattern_t *source,
911  const cairo_path_fixed_t *path,
912  cairo_fill_rule_t fill_rule,
913  double tolerance,
915  const cairo_clip_t *clip)
916 {
918  cairo_recording_surface_t *surface = abstract_surface;
921 
922  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
923 
925  &surface->base,
926  op, source, path,
927  clip);
928  if (unlikely (status))
929  return status;
930 
932  if (unlikely (command == NULL)) {
934  goto CLEANUP_COMPOSITE;
935  }
936 
938  &command->header, CAIRO_COMMAND_FILL, op,
939  &composite);
940  if (unlikely (status))
941  goto CLEANUP_COMMAND;
942 
944  if (unlikely (status))
945  goto CLEANUP_COMMAND;
946 
948  if (unlikely (status))
949  goto CLEANUP_SOURCE;
950 
951  command->fill_rule = fill_rule;
952  command->tolerance = tolerance;
953  command->antialias = antialias;
954 
956  if (unlikely (status))
957  goto CLEANUP_PATH;
958 
960 
962  return CAIRO_STATUS_SUCCESS;
963 
964  CLEANUP_PATH:
966  CLEANUP_SOURCE:
967  _cairo_pattern_fini (&command->source.base);
968  CLEANUP_COMMAND:
969  _cairo_clip_destroy (command->header.clip);
970  free (command);
971 CLEANUP_COMPOSITE:
973  return status;
974 }
975 
976 static cairo_bool_t
978 {
979  return TRUE;
980 }
981 
982 static cairo_int_status_t
985  const cairo_pattern_t *source,
986  const char *utf8,
987  int utf8_len,
989  int num_glyphs,
990  const cairo_text_cluster_t *clusters,
991  int num_clusters,
992  cairo_text_cluster_flags_t cluster_flags,
993  cairo_scaled_font_t *scaled_font,
994  const cairo_clip_t *clip)
995 {
997  cairo_recording_surface_t *surface = abstract_surface;
1000 
1001  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
1002 
1004  &surface->base,
1005  op, source,
1006  scaled_font,
1007  glyphs, num_glyphs,
1008  clip,
1009  NULL);
1010  if (unlikely (status))
1011  return status;
1012 
1014  if (unlikely (command == NULL)) {
1016  goto CLEANUP_COMPOSITE;
1017  }
1018 
1021  op, &composite);
1022  if (unlikely (status))
1023  goto CLEANUP_COMMAND;
1024 
1026  if (unlikely (status))
1027  goto CLEANUP_COMMAND;
1028 
1029  command->utf8 = NULL;
1030  command->utf8_len = utf8_len;
1031  command->glyphs = NULL;
1032  command->num_glyphs = num_glyphs;
1033  command->clusters = NULL;
1034  command->num_clusters = num_clusters;
1035 
1036  if (utf8_len) {
1037  command->utf8 = _cairo_malloc (utf8_len);
1038  if (unlikely (command->utf8 == NULL)) {
1040  goto CLEANUP_ARRAYS;
1041  }
1042  memcpy (command->utf8, utf8, utf8_len);
1043  }
1044  if (num_glyphs) {
1045  command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (glyphs[0]));
1046  if (unlikely (command->glyphs == NULL)) {
1048  goto CLEANUP_ARRAYS;
1049  }
1050  memcpy (command->glyphs, glyphs, sizeof (glyphs[0]) * num_glyphs);
1051  }
1052  if (num_clusters) {
1053  command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0]));
1054  if (unlikely (command->clusters == NULL)) {
1056  goto CLEANUP_ARRAYS;
1057  }
1058  memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
1059  }
1060 
1061  command->cluster_flags = cluster_flags;
1062 
1063  command->scaled_font = cairo_scaled_font_reference (scaled_font);
1064 
1066  if (unlikely (status))
1067  goto CLEANUP_SCALED_FONT;
1068 
1070  return CAIRO_STATUS_SUCCESS;
1071 
1072  CLEANUP_SCALED_FONT:
1073  cairo_scaled_font_destroy (command->scaled_font);
1074  CLEANUP_ARRAYS:
1075  free (command->utf8);
1076  free (command->glyphs);
1077  free (command->clusters);
1078 
1079  _cairo_pattern_fini (&command->source.base);
1080  CLEANUP_COMMAND:
1081  _cairo_clip_destroy (command->header.clip);
1082  free (command);
1083 CLEANUP_COMPOSITE:
1085  return status;
1086 }
1087 
1088 static cairo_int_status_t
1089 _cairo_recording_surface_tag (void *abstract_surface,
1091  const char *tag_name,
1092  const char *attributes,
1093  const cairo_pattern_t *source,
1094  const cairo_stroke_style_t *style,
1095  const cairo_matrix_t *ctm,
1096  const cairo_matrix_t *ctm_inverse,
1097  const cairo_clip_t *clip)
1098 {
1100  cairo_recording_surface_t *surface = abstract_surface;
1103 
1104  TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id));
1105 
1107  &surface->base,
1110  clip);
1111  if (unlikely (status))
1112  return status;
1113 
1114  command = calloc (1, sizeof (cairo_command_tag_t));
1115  if (unlikely (command == NULL)) {
1117  goto CLEANUP_COMPOSITE;
1118  }
1119 
1122  &composite);
1123  if (unlikely (status))
1124  goto CLEANUP_COMMAND;
1125 
1126  command->begin = begin;
1127  command->tag_name = strdup (tag_name);
1128  if (begin) {
1129  if (attributes)
1130  command->attributes = strdup (attributes);
1131 
1133  if (unlikely (status))
1134  goto CLEANUP_STRINGS;
1135 
1137  if (unlikely (status))
1138  goto CLEANUP_SOURCE;
1139 
1140  command->ctm = *ctm;
1141  command->ctm_inverse = *ctm_inverse;
1142  }
1143 
1145  if (unlikely (status)) {
1146  if (begin)
1147  goto CLEANUP_STRINGS;
1148  else
1149  goto CLEANUP_STYLE;
1150  }
1151 
1153 
1155  return CAIRO_STATUS_SUCCESS;
1156 
1157  CLEANUP_STYLE:
1159  CLEANUP_SOURCE:
1160  _cairo_pattern_fini (&command->source.base);
1161  CLEANUP_STRINGS:
1162  free (command->tag_name);
1163  free (command->attributes);
1164  CLEANUP_COMMAND:
1165  _cairo_clip_destroy (command->header.clip);
1166  free (command);
1167  CLEANUP_COMPOSITE:
1169  return status;
1170 }
1171 
1172 static void
1175  const cairo_command_header_t *src)
1176 {
1177  dst->type = src->type;
1178  dst->op = src->op;
1179  dst->region = CAIRO_RECORDING_REGION_ALL;
1180 
1181  dst->extents = src->extents;
1182  dst->chain = NULL;
1183  dst->index = surface->commands.num_elements;
1184 
1185  dst->clip = _cairo_clip_copy (src->clip);
1186 }
1187 
1188 static cairo_status_t
1190  const cairo_command_t *src)
1191 {
1194 
1195  command = _cairo_malloc (sizeof (*command));
1196  if (unlikely (command == NULL)) {
1198  goto err;
1199  }
1200 
1201  _command_init_copy (surface, &command->header, &src->header);
1202 
1203  status = _cairo_pattern_init_copy (&command->source.base,
1204  &src->paint.source.base);
1205  if (unlikely (status))
1206  goto err_command;
1207 
1209  if (unlikely (status))
1210  goto err_source;
1211 
1212  return CAIRO_STATUS_SUCCESS;
1213 
1214 err_source:
1215  _cairo_pattern_fini (&command->source.base);
1216 err_command:
1217  free(command);
1218 err:
1219  return status;
1220 }
1221 
1222 static cairo_status_t
1224  const cairo_command_t *src)
1225 {
1228 
1229  command = _cairo_malloc (sizeof (*command));
1230  if (unlikely (command == NULL)) {
1232  goto err;
1233  }
1234 
1235  _command_init_copy (surface, &command->header, &src->header);
1236 
1237  status = _cairo_pattern_init_copy (&command->source.base,
1238  &src->mask.source.base);
1239  if (unlikely (status))
1240  goto err_command;
1241 
1242  status = _cairo_pattern_init_copy (&command->mask.base,
1243  &src->mask.mask.base);
1244  if (unlikely (status))
1245  goto err_source;
1246 
1248  if (unlikely (status))
1249  goto err_mask;
1250 
1251  return CAIRO_STATUS_SUCCESS;
1252 
1253 err_mask:
1254  _cairo_pattern_fini (&command->mask.base);
1255 err_source:
1256  _cairo_pattern_fini (&command->source.base);
1257 err_command:
1258  free(command);
1259 err:
1260  return status;
1261 }
1262 
1263 static cairo_status_t
1265  const cairo_command_t *src)
1266 {
1269 
1270  command = _cairo_malloc (sizeof (*command));
1271  if (unlikely (command == NULL)) {
1273  goto err;
1274  }
1275 
1276  _command_init_copy (surface, &command->header, &src->header);
1277 
1278  status = _cairo_pattern_init_copy (&command->source.base,
1279  &src->stroke.source.base);
1280  if (unlikely (status))
1281  goto err_command;
1282 
1283  status = _cairo_path_fixed_init_copy (&command->path, &src->stroke.path);
1284  if (unlikely (status))
1285  goto err_source;
1286 
1288  &src->stroke.style);
1289  if (unlikely (status))
1290  goto err_path;
1291 
1292  command->ctm = src->stroke.ctm;
1293  command->ctm_inverse = src->stroke.ctm_inverse;
1294  command->tolerance = src->stroke.tolerance;
1295  command->antialias = src->stroke.antialias;
1296 
1298  if (unlikely (status))
1299  goto err_style;
1300 
1301  return CAIRO_STATUS_SUCCESS;
1302 
1303 err_style:
1305 err_path:
1307 err_source:
1308  _cairo_pattern_fini (&command->source.base);
1309 err_command:
1310  free(command);
1311 err:
1312  return status;
1313 }
1314 
1315 static cairo_status_t
1317  const cairo_command_t *src)
1318 {
1321 
1322  command = _cairo_malloc (sizeof (*command));
1323  if (unlikely (command == NULL)) {
1325  goto err;
1326  }
1327 
1328  _command_init_copy (surface, &command->header, &src->header);
1329 
1330  status = _cairo_pattern_init_copy (&command->source.base,
1331  &src->fill.source.base);
1332  if (unlikely (status))
1333  goto err_command;
1334 
1335  status = _cairo_path_fixed_init_copy (&command->path, &src->fill.path);
1336  if (unlikely (status))
1337  goto err_source;
1338 
1339  command->fill_rule = src->fill.fill_rule;
1340  command->tolerance = src->fill.tolerance;
1341  command->antialias = src->fill.antialias;
1342 
1344  if (unlikely (status))
1345  goto err_path;
1346 
1347  return CAIRO_STATUS_SUCCESS;
1348 
1349 err_path:
1351 err_source:
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
1361  const cairo_command_t *src)
1362 {
1365 
1366  command = _cairo_malloc (sizeof (*command));
1367  if (unlikely (command == NULL)) {
1369  goto err;
1370  }
1371 
1372  _command_init_copy (surface, &command->header, &src->header);
1373 
1374  status = _cairo_pattern_init_copy (&command->source.base,
1375  &src->show_text_glyphs.source.base);
1376  if (unlikely (status))
1377  goto err_command;
1378 
1379  command->utf8 = NULL;
1380  command->utf8_len = src->show_text_glyphs.utf8_len;
1381  command->glyphs = NULL;
1382  command->num_glyphs = src->show_text_glyphs.num_glyphs;
1383  command->clusters = NULL;
1384  command->num_clusters = src->show_text_glyphs.num_clusters;
1385 
1386  if (command->utf8_len) {
1387  command->utf8 = _cairo_malloc (command->utf8_len);
1388  if (unlikely (command->utf8 == NULL)) {
1390  goto err_arrays;
1391  }
1392  memcpy (command->utf8, src->show_text_glyphs.utf8, command->utf8_len);
1393  }
1394  if (command->num_glyphs) {
1395  command->glyphs = _cairo_malloc_ab (command->num_glyphs,
1396  sizeof (command->glyphs[0]));
1397  if (unlikely (command->glyphs == NULL)) {
1399  goto err_arrays;
1400  }
1401  memcpy (command->glyphs, src->show_text_glyphs.glyphs,
1402  sizeof (command->glyphs[0]) * command->num_glyphs);
1403  }
1404  if (command->num_clusters) {
1405  command->clusters = _cairo_malloc_ab (command->num_clusters,
1406  sizeof (command->clusters[0]));
1407  if (unlikely (command->clusters == NULL)) {
1409  goto err_arrays;
1410  }
1411  memcpy (command->clusters, src->show_text_glyphs.clusters,
1412  sizeof (command->clusters[0]) * command->num_clusters);
1413  }
1414 
1415  command->cluster_flags = src->show_text_glyphs.cluster_flags;
1416 
1417  command->scaled_font =
1418  cairo_scaled_font_reference (src->show_text_glyphs.scaled_font);
1419 
1421  if (unlikely (status))
1422  goto err_arrays;
1423 
1424  return CAIRO_STATUS_SUCCESS;
1425 
1426 err_arrays:
1427  free (command->utf8);
1428  free (command->glyphs);
1429  free (command->clusters);
1430  _cairo_pattern_fini (&command->source.base);
1431 err_command:
1432  free(command);
1433 err:
1434  return status;
1435 }
1436 
1437 static cairo_status_t
1439  const cairo_command_t *src)
1440 {
1443 
1444  command = calloc (1, sizeof (*command));
1445  if (unlikely (command == NULL)) {
1447  goto err;
1448  }
1449 
1450  _command_init_copy (surface, &command->header, &src->header);
1451 
1452  command->begin = src->tag.begin;
1453  command->tag_name = strdup (src->tag.tag_name);
1454  if (src->tag.begin) {
1455  if (src->tag.attributes)
1456  command->attributes = strdup (src->tag.attributes);
1457 
1458  status = _cairo_pattern_init_copy (&command->source.base,
1459  &src->stroke.source.base);
1460  if (unlikely (status))
1461  goto err_command;
1462 
1464  &src->stroke.style);
1465  if (unlikely (status))
1466  goto err_source;
1467 
1468  command->ctm = src->stroke.ctm;
1469  command->ctm_inverse = src->stroke.ctm_inverse;
1470  }
1471 
1473  if (unlikely (status)) {
1474  if (src->tag.begin)
1475  goto err_command;
1476  else
1477  goto err_style;
1478  }
1479 
1480  return CAIRO_STATUS_SUCCESS;
1481 
1482 err_style:
1484 err_source:
1485  _cairo_pattern_fini (&command->source.base);
1486 err_command:
1487  free(command->tag_name);
1488  free(command->attributes);
1489  free(command);
1490 err:
1491  return status;
1492 }
1493 
1494 static cairo_status_t
1497 {
1499  int i, num_elements;
1501 
1502  elements = _cairo_array_index (&src->commands, 0);
1503  num_elements = src->commands.num_elements;
1504  for (i = 0; i < num_elements; i++) {
1505  const cairo_command_t *command = elements[i];
1506 
1507  switch (command->header.type) {
1508  case CAIRO_COMMAND_PAINT:
1510  break;
1511 
1512  case CAIRO_COMMAND_MASK:
1514  break;
1515 
1516  case CAIRO_COMMAND_STROKE:
1518  break;
1519 
1520  case CAIRO_COMMAND_FILL:
1522  break;
1523 
1526  break;
1527 
1528  case CAIRO_COMMAND_TAG:
1530  break;
1531 
1532  default:
1534  }
1535 
1536  if (unlikely (status))
1537  return status;
1538  }
1539 
1540  return CAIRO_STATUS_SUCCESS;
1541 }
1542 
1543 /**
1544  * _cairo_recording_surface_snapshot:
1545  * @surface: a #cairo_surface_t which must be a recording surface
1546  *
1547  * Make an immutable copy of @surface. It is an error to call a
1548  * surface-modifying function on the result of this function.
1549  *
1550  * The caller owns the return value and should call
1551  * cairo_surface_destroy() when finished with it. This function will not
1552  * return %NULL, but will return a nil surface instead.
1553  *
1554  * Return value: The snapshot surface.
1555  **/
1556 static cairo_surface_t *
1558 {
1559  cairo_recording_surface_t *other = abstract_other;
1562 
1564  if (unlikely (surface == NULL))
1566 
1567  _cairo_surface_init (&surface->base,
1569  NULL, /* device */
1570  other->base.content,
1571  other->base.is_vector);
1572 
1573  surface->extents_pixels = other->extents_pixels;
1574  surface->extents = other->extents;
1575  surface->unbounded = other->unbounded;
1576 
1577  surface->base.is_clear = other->base.is_clear;
1578 
1579  surface->bbtree.left = surface->bbtree.right = NULL;
1580  surface->bbtree.chain = INVALID_CHAIN;
1581 
1582  surface->indices = NULL;
1583  surface->num_indices = 0;
1584  surface->optimize_clears = TRUE;
1585 
1586  _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
1588  if (unlikely (status)) {
1589  cairo_surface_destroy (&surface->base);
1591  }
1592 
1593  return &surface->base;
1594 }
1595 
1596 static cairo_bool_t
1598  cairo_rectangle_int_t *rectangle)
1599 {
1600  cairo_recording_surface_t *surface = abstract_surface;
1601 
1602  if (surface->unbounded)
1603  return FALSE;
1604 
1605  *rectangle = surface->extents;
1606  return TRUE;
1607 }
1608 
1612 
1614 
1616  NULL, /* create similar image */
1617  NULL, /* map to image */
1618  NULL, /* unmap image */
1619 
1624 
1625  NULL, /* copy_page */
1626  NULL, /* show_page */
1627 
1629  NULL, /* get_font_options */
1630 
1631  NULL, /* flush */
1632  NULL, /* mark_dirty_rectangle */
1633 
1634  /* Here are the 5 basic drawing operations, (which are in some
1635  * sense the only things that cairo_recording_surface should need to
1636  * implement). However, we implement the more generic show_text_glyphs
1637  * instead of show_glyphs. One or the other is eough. */
1638 
1643  NULL, /* fill-stroke */
1644  NULL,
1647  NULL, /* get_supported_mime_types */
1649 };
1650 
1654 {
1657  int i, num_elements;
1659 
1660  if (unlikely (abstract_surface->status))
1661  return abstract_surface->status;
1662 
1663  surface = (cairo_recording_surface_t *) abstract_surface;
1665 
1666  num_elements = surface->commands.num_elements;
1667  elements = _cairo_array_index (&surface->commands, 0);
1668  for (i = 0; i < num_elements; i++) {
1670 
1671  switch (command->header.type) {
1672  case CAIRO_COMMAND_PAINT:
1673  case CAIRO_COMMAND_MASK:
1675  break;
1676 
1677  case CAIRO_COMMAND_STROKE:
1678  {
1679  cairo_traps_t traps;
1680 
1681  _cairo_traps_init (&traps);
1682 
1683  /* XXX call cairo_stroke_to_path() when that is implemented */
1685  &command->stroke.style,
1686  &command->stroke.ctm,
1687  &command->stroke.ctm_inverse,
1688  command->stroke.tolerance,
1689  &traps);
1690 
1692  status = _cairo_traps_path (&traps, path);
1693 
1694  _cairo_traps_fini (&traps);
1695  break;
1696  }
1697  case CAIRO_COMMAND_FILL:
1698  {
1700  &command->fill.path,
1701  0, 0);
1702  break;
1703  }
1705  {
1706  status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
1707  command->show_text_glyphs.glyphs,
1708  command->show_text_glyphs.num_glyphs,
1709  path);
1710  break;
1711  }
1712 
1713  case CAIRO_COMMAND_TAG:
1714  break;
1715 
1716  default:
1718  }
1719 
1720  if (unlikely (status))
1721  break;
1722  }
1723 
1724  return status;
1725 }
1726 
1727 static int
1730 {
1731  unsigned int num_visible, *indices;
1732  cairo_box_t box;
1733 
1734  if (surface->commands.num_elements == 0)
1735  return 0;
1736 
1738 
1739  if (surface->bbtree.chain == INVALID_CHAIN)
1741 
1742  indices = surface->indices;
1743  bbtree_foreach_mark_visible (&surface->bbtree, &box, &indices);
1744  num_visible = indices - surface->indices;
1745  if (num_visible > 1)
1746  sort_indices (surface->indices, num_visible);
1747 
1748  return num_visible;
1749 }
1750 
1751 static void
1754  const cairo_pattern_t *source)
1755 {
1756  if (op != CAIRO_OPERATOR_OVER)
1757  surface->has_only_op_over = FALSE;
1758 
1761  cairo_surface_t *surf = surf_pat->surface;
1762  cairo_surface_t *free_me = NULL;
1763 
1764  if (_cairo_surface_is_snapshot (surf))
1765  free_me = surf = _cairo_surface_snapshot_get_target (surf);
1766 
1767  if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) {
1769 
1771  surface->has_bilevel_alpha = FALSE;
1772 
1774  surface->has_only_op_over = FALSE;
1775 
1776  } else if (surf->type == CAIRO_SURFACE_TYPE_IMAGE) {
1777  cairo_image_surface_t *img_surf = (cairo_image_surface_t *) surf;
1778 
1780  surface->has_bilevel_alpha = FALSE;
1781 
1782  } else {
1784  surface->has_bilevel_alpha = FALSE;
1785  }
1786 
1787  cairo_surface_destroy (free_me);
1788  return;
1789 
1790  } else if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1793 
1797  if (raster) {
1798  if (raster->type == CAIRO_SURFACE_TYPE_IMAGE) {
1800  surface->has_bilevel_alpha = FALSE;
1801  }
1802 
1804  if (raster->type == CAIRO_SURFACE_TYPE_IMAGE)
1805  return;
1806  }
1807  }
1808 
1810  surface->has_bilevel_alpha = FALSE;
1811 }
1812 
1813 static cairo_status_t
1815  const cairo_rectangle_int_t *surface_extents,
1816  const cairo_matrix_t *surface_transform,
1818  const cairo_clip_t *target_clip,
1819  cairo_bool_t surface_is_unbounded,
1822 {
1823  cairo_surface_wrapper_t wrapper;
1825  cairo_bool_t replay_all =
1829  cairo_bool_t use_indices = FALSE;
1830  const cairo_rectangle_int_t *r;
1831  unsigned int i, num_elements;
1832 
1833  if (unlikely (surface->base.status))
1834  return surface->base.status;
1835 
1836  if (unlikely (target->status))
1837  return target->status;
1838 
1839  if (unlikely (surface->base.finished))
1841 
1842  if (surface->base.is_clear)
1843  return CAIRO_STATUS_SUCCESS;
1844 
1846 
1847  _cairo_surface_wrapper_init (&wrapper, target);
1848  if (surface_extents)
1849  _cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents);
1851  if (! surface->unbounded && !surface_is_unbounded) {
1852  _cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents);
1853  r = &surface->extents;
1854  }
1855  _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform);
1856  _cairo_surface_wrapper_set_clip (&wrapper, target_clip);
1857 
1858  /* Compute the extents of the target clip in recorded device space */
1859  if (! _cairo_surface_wrapper_get_target_extents (&wrapper, surface_is_unbounded, &extents))
1860  goto done;
1861 
1862  surface->has_bilevel_alpha = TRUE;
1863  surface->has_only_op_over = TRUE;
1864 
1865  num_elements = surface->commands.num_elements;
1866  elements = _cairo_array_index (&surface->commands, 0);
1867  if (extents.width < r->width || extents.height < r->height) {
1868  num_elements =
1870  use_indices = num_elements != surface->commands.num_elements;
1871  }
1872 
1873  for (i = 0; i < num_elements; i++) {
1874  cairo_command_t *command = elements[use_indices ? surface->indices[i] : i];
1875 
1876  if (! replay_all && command->header.region != region)
1877  continue;
1878 
1879  if (! _cairo_rectangle_intersects (&extents, &command->header.extents))
1880  continue;
1881 
1882  switch (command->header.type) {
1883  case CAIRO_COMMAND_PAINT:
1885  command->header.op,
1886  &command->paint.source.base,
1887  command->header.clip);
1890  command->header.op,
1891  &command->paint.source.base);
1892  }
1893  break;
1894 
1895  case CAIRO_COMMAND_MASK:
1896  status = _cairo_surface_wrapper_mask (&wrapper,
1897  command->header.op,
1898  &command->mask.source.base,
1899  &command->mask.mask.base,
1900  command->header.clip);
1903  command->header.op,
1904  &command->mask.source.base);
1906  command->header.op,
1907  &command->mask.mask.base);
1908  }
1909  break;
1910 
1911  case CAIRO_COMMAND_STROKE:
1913  command->header.op,
1914  &command->stroke.source.base,
1915  &command->stroke.path,
1916  &command->stroke.style,
1917  &command->stroke.ctm,
1918  &command->stroke.ctm_inverse,
1919  command->stroke.tolerance,
1920  command->stroke.antialias,
1921  command->header.clip);
1924  command->header.op,
1925  &command->stroke.source.base);
1926  }
1927  break;
1928 
1929  case CAIRO_COMMAND_FILL:
1931  if (_cairo_surface_wrapper_has_fill_stroke (&wrapper)) {
1932  cairo_command_t *stroke_command;
1933 
1934  stroke_command = NULL;
1935  if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1)
1936  stroke_command = elements[i + 1];
1937 
1938  if (stroke_command != NULL &&
1941  {
1942  if (stroke_command->header.region != region)
1943  stroke_command = NULL;
1944  }
1945 
1946  if (stroke_command != NULL &&
1947  stroke_command->header.type == CAIRO_COMMAND_STROKE &&
1948  _cairo_path_fixed_equal (&command->fill.path,
1949  &stroke_command->stroke.path) &&
1950  _cairo_clip_equal (command->header.clip,
1951  stroke_command->header.clip))
1952  {
1954  command->header.op,
1955  &command->fill.source.base,
1956  command->fill.fill_rule,
1957  command->fill.tolerance,
1958  command->fill.antialias,
1959  &command->fill.path,
1960  stroke_command->header.op,
1961  &stroke_command->stroke.source.base,
1962  &stroke_command->stroke.style,
1963  &stroke_command->stroke.ctm,
1964  &stroke_command->stroke.ctm_inverse,
1965  stroke_command->stroke.tolerance,
1966  stroke_command->stroke.antialias,
1967  command->header.clip);
1970  command->header.op,
1971  &command->fill.source.base);
1973  command->header.op,
1974  &command->stroke.source.base);
1975  }
1976  i++;
1977  }
1978  }
1980  status = _cairo_surface_wrapper_fill (&wrapper,
1981  command->header.op,
1982  &command->fill.source.base,
1983  &command->fill.path,
1984  command->fill.fill_rule,
1985  command->fill.tolerance,
1986  command->fill.antialias,
1987  command->header.clip);
1990  command->header.op,
1991  &command->fill.source.base);
1992  }
1993  }
1994  break;
1995 
1998  command->header.op,
1999  &command->show_text_glyphs.source.base,
2000  command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
2001  command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs,
2002  command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
2003  command->show_text_glyphs.cluster_flags,
2004  command->show_text_glyphs.scaled_font,
2005  command->header.clip);
2008  command->header.op,
2009  &command->show_text_glyphs.source.base);
2010  }
2011  break;
2012 
2013  case CAIRO_COMMAND_TAG:
2014  status = _cairo_surface_wrapper_tag (&wrapper,
2015  command->tag.begin,
2016  command->tag.tag_name,
2017  command->tag.attributes,
2018  &command->tag.source.base,
2019  &command->tag.style,
2020  &command->tag.ctm,
2021  &command->tag.ctm_inverse,
2022  command->header.clip);
2023  break;
2024 
2025  default:
2027  }
2028 
2031  command->header.region = CAIRO_RECORDING_REGION_NATIVE;
2032  } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
2035  } else {
2037  }
2038  }
2039 
2040  if (unlikely (status))
2041  break;
2042  }
2043 
2044 done:
2045  _cairo_surface_wrapper_fini (&wrapper);
2046  return _cairo_surface_set_error (&surface->base, status);
2047 }
2048 
2051  long unsigned index,
2053 {
2054  cairo_surface_wrapper_t wrapper;
2057 
2058  if (unlikely (surface->base.status))
2059  return surface->base.status;
2060 
2061  if (unlikely (target->status))
2062  return target->status;
2063 
2064  if (unlikely (surface->base.finished))
2066 
2068 
2069  /* XXX
2070  * Use a surface wrapper because we may want to do transformed
2071  * replay in the future.
2072  */
2073  _cairo_surface_wrapper_init (&wrapper, target);
2074 
2075  if (index > surface->commands.num_elements)
2077 
2078  elements = _cairo_array_index (&surface->commands, 0);
2079  command = elements[index];
2080  switch (command->header.type) {
2081  case CAIRO_COMMAND_PAINT:
2083  command->header.op,
2084  &command->paint.source.base,
2085  command->header.clip);
2086  break;
2087 
2088  case CAIRO_COMMAND_MASK:
2089  status = _cairo_surface_wrapper_mask (&wrapper,
2090  command->header.op,
2091  &command->mask.source.base,
2092  &command->mask.mask.base,
2093  command->header.clip);
2094  break;
2095 
2096  case CAIRO_COMMAND_STROKE:
2098  command->header.op,
2099  &command->stroke.source.base,
2100  &command->stroke.path,
2101  &command->stroke.style,
2102  &command->stroke.ctm,
2103  &command->stroke.ctm_inverse,
2104  command->stroke.tolerance,
2105  command->stroke.antialias,
2106  command->header.clip);
2107  break;
2108 
2109  case CAIRO_COMMAND_FILL:
2110  status = _cairo_surface_wrapper_fill (&wrapper,
2111  command->header.op,
2112  &command->fill.source.base,
2113  &command->fill.path,
2114  command->fill.fill_rule,
2115  command->fill.tolerance,
2116  command->fill.antialias,
2117  command->header.clip);
2118  break;
2119 
2122  command->header.op,
2123  &command->show_text_glyphs.source.base,
2124  command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
2125  command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs,
2126  command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
2127  command->show_text_glyphs.cluster_flags,
2128  command->show_text_glyphs.scaled_font,
2129  command->header.clip);
2130  break;
2131 
2132  case CAIRO_COMMAND_TAG:
2133  status = _cairo_surface_wrapper_tag (&wrapper,
2134  command->tag.begin,
2135  command->tag.tag_name,
2136  command->tag.attributes,
2137  &command->tag.source.base,
2138  &command->tag.style,
2139  &command->tag.ctm,
2140  &command->tag.ctm_inverse,
2141  command->header.clip);
2142  break;
2143 
2144  default:
2146  }
2147 
2148  _cairo_surface_wrapper_fini (&wrapper);
2149  return _cairo_surface_set_error (&surface->base, status);
2150 }
2151 /**
2152  * _cairo_recording_surface_replay:
2153  * @surface: the #cairo_recording_surface_t
2154  * @target: a target #cairo_surface_t onto which to replay the operations
2155  * @width_pixels: width of the surface, in pixels
2156  * @height_pixels: height of the surface, in pixels
2157  *
2158  * A recording surface can be "replayed" against any target surface,
2159  * after which the results in target will be identical to the results
2160  * that would have been obtained if the original operations applied to
2161  * the recording surface had instead been applied to the target surface.
2162  **/
2166 {
2168  target, NULL, FALSE,
2171 }
2172 
2175  const cairo_matrix_t *surface_transform,
2177  const cairo_clip_t *target_clip)
2178 {
2180  target, target_clip, FALSE,
2183 }
2184 
2185 /* Replay recording to surface. When the return status of each operation is
2186  * one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
2187  * %CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
2188  * will be stored in the recording surface. Any other status will abort the
2189  * replay and return the status.
2190  */
2193  const cairo_matrix_t *surface_transform,
2195  cairo_bool_t surface_is_unbounded)
2196 {
2198  target, NULL,
2199  surface_is_unbounded,
2202 }
2203 
2206  const cairo_rectangle_int_t *surface_extents,
2209 {
2211  surface_extents, NULL,
2212  target, NULL, FALSE,
2214  region);
2215 }
2216 
2217 static cairo_status_t
2219  cairo_box_t *bbox,
2220  const cairo_matrix_t *transform)
2221 {
2222  cairo_surface_t *null_surface;
2223  cairo_surface_t *analysis_surface;
2225 
2226  null_surface = _cairo_null_surface_create (surface->base.content);
2227  analysis_surface = _cairo_analysis_surface_create (null_surface);
2228  cairo_surface_destroy (null_surface);
2229 
2230  status = analysis_surface->status;
2231  if (unlikely (status))
2232  return status;
2233 
2234  if (transform != NULL)
2235  _cairo_analysis_surface_set_ctm (analysis_surface, transform);
2236 
2237  status = _cairo_recording_surface_replay (&surface->base, analysis_surface);
2238  _cairo_analysis_surface_get_bounding_box (analysis_surface, bbox);
2239  cairo_surface_destroy (analysis_surface);
2240 
2241  return status;
2242 }
2243 
2244 /**
2245  * cairo_recording_surface_ink_extents:
2246  * @surface: a #cairo_recording_surface_t
2247  * @x0: the x-coordinate of the top-left of the ink bounding box
2248  * @y0: the y-coordinate of the top-left of the ink bounding box
2249  * @width: the width of the ink bounding box
2250  * @height: the height of the ink bounding box
2251  *
2252  * Measures the extents of the operations stored within the recording-surface.
2253  * This is useful to compute the required size of an image surface (or
2254  * equivalent) into which to replay the full sequence of drawing operations.
2255  *
2256  * Since: 1.10
2257  **/
2258 void
2260  double *x0,
2261  double *y0,
2262  double *width,
2263  double *height)
2264 {
2266  cairo_box_t bbox;
2267 
2268  memset (&bbox, 0, sizeof (bbox));
2269 
2272  goto DONE;
2273  }
2274 
2276  &bbox,
2277  NULL);
2278  if (unlikely (status))
2280 
2281 DONE:
2282  if (x0)
2283  *x0 = _cairo_fixed_to_double (bbox.p1.x);
2284  if (y0)
2285  *y0 = _cairo_fixed_to_double (bbox.p1.y);
2286  if (width)
2287  *width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
2288  if (height)
2289  *height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
2290 }
2291 
2294  cairo_box_t *bbox,
2295  const cairo_matrix_t *transform)
2296 {
2297  if (! surface->unbounded) {
2298  _cairo_box_from_rectangle (bbox, &surface->extents);
2299  if (transform != NULL)
2301 
2302  return CAIRO_STATUS_SUCCESS;
2303  }
2304 
2306 }
2307 
2310  cairo_box_t *bbox,
2311  const cairo_matrix_t *transform)
2312 {
2314 }
2315 
2316 /**
2317  * cairo_recording_surface_get_extents:
2318  * @surface: a #cairo_recording_surface_t
2319  * @extents: the #cairo_rectangle_t to be assigned the extents
2320  *
2321  * Get the extents of the recording-surface.
2322  *
2323  * Return value: %TRUE if the surface is bounded, of recording type, and
2324  * not in an error state, otherwise %FALSE
2325  *
2326  * Since: 1.12
2327  **/
2331 {
2332  cairo_recording_surface_t *record;
2333 
2336  return FALSE;
2337  }
2338 
2339  record = (cairo_recording_surface_t *)surface;
2340  if (record->unbounded)
2341  return FALSE;
2342 
2343  *extents = record->extents_pixels;
2344  return TRUE;
2345 }
2346 
2349 {
2350  return surface->has_bilevel_alpha;
2351 }
2352 
2355 {
2356  return surface->has_only_op_over;
2357 }
#define strdup
Definition: Utility.h:167
#define y0
#define width(a)
Definition: aptex-macros.h:198
#define tolerance
Definition: aptex-macros.h:786
#define type(a)
Definition: aptex-macros.h:171
#define count(a)
Definition: aptex-macros.h:781
#define box(a)
Definition: aptex-macros.h:675
#define x0
#define height(a)
Definition: aptex-macros.h:200
static boolean chain
Definition: aptex.h:592
void _cairo_analysis_surface_set_ctm(cairo_surface_t *surface, const cairo_matrix_t *ctm)
cairo_surface_t * _cairo_analysis_surface_create(cairo_surface_t *target)
void _cairo_analysis_surface_get_bounding_box(cairo_surface_t *surface, cairo_box_t *bbox)
cairo_surface_t * _cairo_null_surface_create(cairo_content_t content)
void _cairo_array_fini(cairo_array_t *array)
Definition: cairo-array.c:75
void * _cairo_array_index(cairo_array_t *array, unsigned int index)
Definition: cairo-array.c:166
void _cairo_array_init(cairo_array_t *array, unsigned int element_size)
Definition: cairo-array.c:58
cairo_status_t _cairo_array_append(cairo_array_t *array, const void *element)
Definition: cairo-array.c:262
#define CAIRO_INT_STATUS_SUCCESS
void _cairo_clip_destroy(cairo_clip_t *clip)
Definition: cairo-clip.c:128
cairo_clip_t * _cairo_clip_copy(const cairo_clip_t *clip)
Definition: cairo-clip.c:144
cairo_bool_t _cairo_clip_equal(const cairo_clip_t *clip_a, const cairo_clip_t *clip_b)
Definition: cairo-clip.c:352
#define CAIRO_COMBSORT_DECLARE(NAME, TYPE, CMP)
#define CAIRO_COMBSORT_DECLARE_WITH_DATA(NAME, TYPE, CMP)
#define slim_hidden_def(name)
cairo_int_status_t _cairo_composite_rectangles_init_for_fill(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_clip_t *clip)
void _cairo_composite_rectangles_fini(cairo_composite_rectangles_t *extents)
cairo_int_status_t _cairo_composite_rectangles_init_for_mask(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip)
cairo_int_status_t _cairo_composite_rectangles_init_for_glyphs(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, const cairo_clip_t *clip, cairo_bool_t *overlap)
cairo_bool_t _cairo_composite_rectangles_can_reduce_clip(cairo_composite_rectangles_t *composite, cairo_clip_t *clip)
cairo_int_status_t _cairo_composite_rectangles_init_for_stroke(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_clip_t *clip)
cairo_int_status_t _cairo_composite_rectangles_init_for_paint(cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip)
cairo_t * _cairo_default_context_create(void *target)
cairo_status_t _cairo_error(cairo_status_t status)
Definition: cairo-error.c:65
enum _cairo_int_status cairo_int_status_t
#define _cairo_error_throw(status)
#define _cairo_int_status_is_error(status)
@ CAIRO_INT_STATUS_UNSUPPORTED
@ CAIRO_INT_STATUS_IMAGE_FALLBACK
static int _cairo_fixed_integer_part(cairo_fixed_t f)
static double _cairo_fixed_to_double(cairo_fixed_t f)
cairo_image_transparency_t _cairo_image_analyze_transparency(cairo_image_surface_t *image)
cairo_surface_t * _cairo_image_surface_create_with_content(cairo_content_t content, int width, int height)
cairo_surface_t * cairo_image_surface_create(cairo_format_t format, int width, int height)
#define _cairo_malloc_ab(a, size)
#define _cairo_malloc(size)
void _cairo_matrix_transform_bounding_box_fixed(const cairo_matrix_t *matrix, cairo_box_t *bbox, cairo_bool_t *is_tight)
Definition: cairo-matrix.c:525
cairo_bool_t _cairo_path_fixed_equal(const cairo_path_fixed_t *a, const cairo_path_fixed_t *b)
cairo_status_t _cairo_path_fixed_append(cairo_path_fixed_t *path, const cairo_path_fixed_t *other, cairo_fixed_t tx, cairo_fixed_t ty)
void _cairo_path_fixed_fini(cairo_path_fixed_t *path)
cairo_status_t _cairo_path_fixed_init_copy(cairo_path_fixed_t *path, const cairo_path_fixed_t *other)
cairo_int_status_t _cairo_path_fixed_stroke_polygon_to_traps(const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_traps_t *traps)
cairo_bool_t _cairo_pattern_is_opaque_solid(const cairo_pattern_t *pattern)
cairo_surface_t * _cairo_raster_source_pattern_acquire(const cairo_pattern_t *abstract_pattern, cairo_surface_t *target, const cairo_rectangle_int_t *extents)
void _cairo_pattern_fini(cairo_pattern_t *pattern)
void _cairo_raster_source_pattern_release(const cairo_pattern_t *abstract_pattern, cairo_surface_t *surface)
cairo_status_t _cairo_pattern_init_copy(cairo_pattern_t *pattern, const cairo_pattern_t *other)
cairo_bool_t _cairo_pattern_is_opaque(const cairo_pattern_t *pattern, const cairo_rectangle_int_t *extents)
cairo_bool_t _cairo_pattern_is_clear(const cairo_pattern_t *pattern)
cairo_status_t _cairo_pattern_init_snapshot(cairo_pattern_t *pattern, const cairo_pattern_t *other)
const cairo_solid_pattern_t _cairo_pattern_black
static cairo_bool_t _cairo_surface_is_recording(const cairo_surface_t *surface)
@ CAIRO_RECORDING_REGION_IMAGE_FALLBACK
@ CAIRO_COMMAND_SHOW_TEXT_GLYPHS
cairo_recording_replay_type_t
@ CAIRO_RECORDING_CREATE_REGIONS
@ CAIRO_RECORDING_REPLAY
cairo_status_t _cairo_recording_surface_replay_region(cairo_surface_t *surface, const cairo_rectangle_int_t *surface_extents, cairo_surface_t *target, cairo_recording_region_type_t region)
cairo_bool_t _cairo_recording_surface_has_only_bilevel_alpha(cairo_recording_surface_t *surface)
cairo_bool_t cairo_recording_surface_get_extents(cairo_surface_t *surface, cairo_rectangle_t *extents)
cairo_status_t _cairo_recording_surface_get_bbox(cairo_recording_surface_t *surface, cairo_box_t *bbox, const cairo_matrix_t *transform)
cairo_int_status_t _cairo_recording_surface_get_path(cairo_surface_t *abstract_surface, cairo_path_fixed_t *path)
void cairo_recording_surface_ink_extents(cairo_surface_t *surface, double *x0, double *y0, double *width, double *height)
cairo_status_t _cairo_recording_surface_replay_one(cairo_recording_surface_t *surface, long unsigned index, cairo_surface_t *target)
cairo_bool_t _cairo_recording_surface_has_only_op_over(cairo_recording_surface_t *surface)
cairo_status_t _cairo_recording_surface_replay(cairo_surface_t *surface, cairo_surface_t *target)
cairo_status_t _cairo_recording_surface_replay_and_create_regions(cairo_surface_t *surface, const cairo_matrix_t *surface_transform, cairo_surface_t *target, cairo_bool_t surface_is_unbounded)
cairo_status_t _cairo_recording_surface_replay_with_clip(cairo_surface_t *surface, const cairo_matrix_t *surface_transform, cairo_surface_t *target, const cairo_clip_t *target_clip)
cairo_surface_t * cairo_recording_surface_create(cairo_content_t content, const cairo_rectangle_t *extents)
cairo_status_t _cairo_recording_surface_get_ink_bbox(cairo_recording_surface_t *surface, cairo_box_t *bbox, const cairo_matrix_t *transform)
const cairo_rectangle_int_t _cairo_unbounded_rectangle
void _cairo_box_from_rectangle(cairo_box_t *box, const cairo_rectangle_int_t *rect)
cairo_status_t _cairo_scaled_font_glyph_path(cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, cairo_path_fixed_t *path)
cairo_scaled_font_t * cairo_scaled_font_reference(cairo_scaled_font_t *scaled_font)
void cairo_scaled_font_destroy(cairo_scaled_font_t *scaled_font)
#define static
cairo_status_t _cairo_stroke_style_init_copy(cairo_stroke_style_t *style, const cairo_stroke_style_t *other)
void _cairo_stroke_style_fini(cairo_stroke_style_t *style)
cairo_surface_t * _cairo_surface_default_source(void *surface, cairo_rectangle_int_t *extents)
cairo_surface_t * _cairo_surface_create_in_error(cairo_status_t status)
static cairo_surface_t * _cairo_surface_snapshot_get_target(cairo_surface_t *surface)
static cairo_bool_t _cairo_surface_is_snapshot(cairo_surface_t *surface)
void _cairo_surface_wrapper_set_clip(cairo_surface_wrapper_t *wrapper, const cairo_clip_t *clip)
cairo_status_t _cairo_surface_wrapper_paint(cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip)
cairo_status_t _cairo_surface_wrapper_show_text_glyphs(cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, const char *utf8, int utf8_len, const cairo_glyph_t *glyphs, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip)
cairo_status_t _cairo_surface_wrapper_fill_stroke(cairo_surface_wrapper_t *wrapper, cairo_operator_t fill_op, const cairo_pattern_t *fill_source, cairo_fill_rule_t fill_rule, double fill_tolerance, cairo_antialias_t fill_antialias, const cairo_path_fixed_t *path, cairo_operator_t stroke_op, const cairo_pattern_t *stroke_source, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *stroke_ctm, const cairo_matrix_t *stroke_ctm_inverse, double stroke_tolerance, cairo_antialias_t stroke_antialias, const cairo_clip_t *clip)
cairo_status_t _cairo_surface_wrapper_fill(cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
static cairo_bool_t _cairo_surface_wrapper_has_fill_stroke(cairo_surface_wrapper_t *wrapper)
cairo_status_t _cairo_surface_wrapper_stroke(cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
void _cairo_surface_wrapper_fini(cairo_surface_wrapper_t *wrapper)
cairo_bool_t _cairo_surface_wrapper_get_target_extents(cairo_surface_wrapper_t *wrapper, cairo_bool_t surface_is_unbounded, cairo_rectangle_int_t *extents)
cairo_status_t _cairo_surface_wrapper_tag(cairo_surface_wrapper_t *wrapper, cairo_bool_t begin, const char *tag_name, const char *attributes, const cairo_pattern_t *source, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, const cairo_clip_t *clip)
void _cairo_surface_wrapper_intersect_extents(cairo_surface_wrapper_t *wrapper, const cairo_rectangle_int_t *extents)
void _cairo_surface_wrapper_set_inverse_transform(cairo_surface_wrapper_t *wrapper, const cairo_matrix_t *transform)
void _cairo_surface_wrapper_init(cairo_surface_wrapper_t *wrapper, cairo_surface_t *target)
cairo_status_t _cairo_surface_wrapper_mask(cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip)
cairo_surface_t * cairo_surface_reference(cairo_surface_t *surface)
void _cairo_surface_release_source_image(cairo_surface_t *surface, cairo_image_surface_t *image, void *image_extra)
void _cairo_surface_init(cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, cairo_content_t content, cairo_bool_t is_vector)
void cairo_surface_destroy(cairo_surface_t *surface)
cairo_int_status_t _cairo_surface_set_error(cairo_surface_t *surface, cairo_int_status_t status)
void cairo_surface_finish(cairo_surface_t *surface)
cairo_surface_t * _cairo_surface_has_snapshot(cairo_surface_t *surface, const cairo_surface_backend_t *backend)
cairo_status_t _cairo_surface_acquire_source_image(cairo_surface_t *surface, cairo_image_surface_t **image_out, void **image_extra)
void cairo_surface_flush(cairo_surface_t *surface)
void _cairo_surface_attach_snapshot(cairo_surface_t *surface, cairo_surface_t *snapshot, cairo_surface_func_t detach_func)
void _cairo_traps_init(cairo_traps_t *traps)
Definition: cairo-traps.c:54
void _cairo_traps_fini(cairo_traps_t *traps)
Definition: cairo-traps.c:111
cairo_status_t _cairo_traps_path(const cairo_traps_t *traps, cairo_path_fixed_t *path)
Definition: cairo-traps.c:1000
@ CAIRO_IMAGE_HAS_ALPHA
@ CAIRO_INTERNAL_SURFACE_TYPE_NULL
enum _cairo_operator cairo_operator_t
@ CAIRO_SURFACE_TYPE_IMAGE
Definition: cairo.h:2398
@ CAIRO_SURFACE_TYPE_RECORDING
Definition: cairo.h:2414
enum _cairo_fill_rule cairo_fill_rule_t
enum _cairo_antialias cairo_antialias_t
int cairo_bool_t
Definition: cairo.h:107
@ CAIRO_STATUS_SUCCESS
Definition: cairo.h:315
@ CAIRO_STATUS_SURFACE_TYPE_MISMATCH
Definition: cairo.h:329
@ CAIRO_STATUS_SURFACE_FINISHED
Definition: cairo.h:328
@ CAIRO_STATUS_NO_MEMORY
Definition: cairo.h:317
@ CAIRO_STATUS_READ_ERROR
Definition: cairo.h:326
enum _cairo_content cairo_content_t
@ CAIRO_OPERATOR_CLEAR
Definition: cairo.h:614
@ CAIRO_OPERATOR_SOURCE
Definition: cairo.h:616
@ CAIRO_OPERATOR_OVER
Definition: cairo.h:617
enum _cairo_status cairo_status_t
@ CAIRO_FORMAT_ARGB32
Definition: cairo.h:418
enum _cairo_text_cluster_flags cairo_text_cluster_flags_t
@ CAIRO_PATTERN_TYPE_SURFACE
Definition: cairo.h:2826
@ CAIRO_PATTERN_TYPE_RASTER_SOURCE
Definition: cairo.h:2830
static cairo_bool_t _cairo_rectangle_intersects(const cairo_rectangle_int_t *dst, const cairo_rectangle_int_t *src)
Definition: cairoint.h:347
#define TRACE(x)
Definition: cairoint.h:2145
#define ASSERT_NOT_REACHED
Definition: cairoint.h:155
static cairo_status_t _cairo_recording_surface_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra)
static cairo_int_status_t _cairo_recording_surface_fill(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
static cairo_bool_t _cairo_recording_surface_get_extents(void *abstract_surface, cairo_rectangle_int_t *rectangle)
static cairo_int_status_t _cairo_recording_surface_mask(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip)
static cairo_status_t _cairo_recording_surface_copy__paint(cairo_recording_surface_t *surface, const cairo_command_t *src)
static cairo_status_t _cairo_recording_surface_commit(cairo_recording_surface_t *surface, cairo_command_header_t *command)
static void bbtree_foreach_mark_visible(struct bbtree *bbt, const cairo_box_t *box, unsigned int **indices)
static cairo_surface_t * _cairo_recording_surface_snapshot(void *abstract_other)
static cairo_status_t _recording_surface_get_ink_bbox(cairo_recording_surface_t *surface, cairo_box_t *bbox, const cairo_matrix_t *transform)
static const cairo_surface_backend_t cairo_recording_surface_backend
static int sizecmp(unsigned int a, unsigned int b, cairo_command_header_t **elements)
#define INVALID_CHAIN
static void bbtree_init(struct bbtree *bbt, cairo_command_header_t *header)
static cairo_status_t _cairo_recording_surface_create_bbtree(cairo_recording_surface_t *surface)
static void sort_indices(unsigned int *base, unsigned int nmemb)
static cairo_surface_t * _cairo_recording_surface_create_similar(void *abstract_surface, cairo_content_t content, int width, int height)
static void _cairo_recording_surface_merge_source_attributes(cairo_recording_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source)
static void bbtree_del(struct bbtree *bbt)
static cairo_status_t _cairo_recording_surface_copy__mask(cairo_recording_surface_t *surface, const cairo_command_t *src)
static cairo_status_t proxy_finish(void *abstract_surface)
static cairo_status_t _command_init(cairo_recording_surface_t *surface, cairo_command_header_t *command, cairo_command_type_t type, cairo_operator_t op, cairo_composite_rectangles_t *composite)
static cairo_bool_t box_outside(const cairo_box_t *a, const cairo_box_t *b)
static cairo_int_status_t _cairo_recording_surface_show_text_glyphs(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip)
static cairo_status_t _cairo_recording_surface_copy__stroke(cairo_recording_surface_t *surface, const cairo_command_t *src)
static cairo_surface_t * attach_proxy(cairo_surface_t *source, cairo_surface_t *image)
static cairo_int_status_t _cairo_recording_surface_paint(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip)
static cairo_status_t _cairo_recording_surface_copy__fill(cairo_recording_surface_t *surface, const cairo_command_t *src)
static struct bbtree * bbtree_new(const cairo_box_t *box, cairo_command_header_t *chain)
static cairo_status_t _cairo_recording_surface_finish(void *abstract_surface)
static int _cairo_recording_surface_get_visible_commands(cairo_recording_surface_t *surface, const cairo_rectangle_int_t *extents)
static void proxy_release_source_image(void *abstract_surface, cairo_image_surface_t *image, void *image_extra)
static cairo_status_t _cairo_recording_surface_copy__glyphs(cairo_recording_surface_t *surface, const cairo_command_t *src)
static void sort_commands(unsigned int *base, unsigned int nmemb, void *data)
static cairo_bool_t _cairo_recording_surface_has_show_text_glyphs(void *abstract_surface)
static void _cairo_recording_surface_release_source_image(void *abstract_surface, cairo_image_surface_t *image, void *image_extra)
static cairo_status_t proxy_acquire_source_image(void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra)
static void _cairo_recording_surface_reset(cairo_recording_surface_t *surface)
static void _command_init_copy(cairo_recording_surface_t *surface, cairo_command_header_t *dst, const cairo_command_header_t *src)
static cairo_status_t _cairo_recording_surface_replay_internal(cairo_recording_surface_t *surface, const cairo_rectangle_int_t *surface_extents, const cairo_matrix_t *surface_transform, cairo_surface_t *target, const cairo_clip_t *target_clip, cairo_bool_t surface_is_unbounded, cairo_recording_replay_type_t type, cairo_recording_region_type_t region)
static const cairo_surface_backend_t proxy_backend
static int intcmp(const unsigned int a, const unsigned int b)
static cairo_int_status_t _cairo_recording_surface_stroke(void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip)
static int bbtree_left_or_right(struct bbtree *bbt, const cairo_box_t *box)
static cairo_int_status_t _cairo_recording_surface_tag(void *abstract_surface, cairo_bool_t begin, const char *tag_name, const char *attributes, const cairo_pattern_t *source, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, const cairo_clip_t *clip)
static cairo_status_t _cairo_recording_surface_copy(cairo_recording_surface_t *dst, cairo_recording_surface_t *src)
static void detach_proxy(cairo_surface_t *source, cairo_surface_t *proxy)
static void _cairo_recording_surface_break_self_copy_loop(cairo_recording_surface_t *surface)
static cairo_status_t _cairo_recording_surface_copy__tag(cairo_recording_surface_t *surface, const cairo_command_t *src)
static cairo_surface_t * get_proxy(cairo_surface_t *proxy)
static void _cairo_recording_surface_destroy_bbtree(cairo_recording_surface_t *surface)
static cairo_status_t bbtree_add(struct bbtree *bbt, cairo_command_header_t *header, const cairo_box_t *box)
#define b
Definition: jpegint.h:372
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define free(a)
Definition: decNumber.cpp:310
void glyphs(int opcode)
Definition: disdvi.c:775
int command
Definition: t4ht.c:934
quarterword * raster
Definition: dvips.c:153
static gregorio_element ** elements
static FIELD_PTR begin
Definition: genind.c:37
__gmp_expr< mpf_t, __gmp_unary_expr< __gmp_expr< mpf_t, U >, __gmp_ceil_function > > ceil(const __gmp_expr< mpf_t, U > &expr)
Definition: gmpxx.h:3340
#define a(n)
Definition: gpos-common.c:148
#define memcpy(d, s, n)
Definition: gsftopk.c:64
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
unsigned char * image
Definition: in_pcx.cpp:323
#define unlikely(x)
Definition: jbig2arith.cc:116
#define MIN(a, b)
Definition: jpegint.h:269
#define MAX(a, b)
Definition: jpegint.h:267
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
sizeof(AF_ModuleRec)
Arabic default style
Definition: afstyles.h:94
FT_BBox bbox
Definition: ftbbox.c:467
#define DONE
Definition: inflate.c:9
@ right
Definition: annotate.c:15
voidp calloc()
#define inline
Definition: config.h:132
#define floor(x)
Definition: cpascal.h:52
union hdr header
Definition: pbmtomacp.c:291
#define target(code, i)
Definition: lpeg.c:1165
@ other
Definition: mtxline.h:22
@ err
Definition: mtxline.h:24
utf< uint8 > utf8
Definition: UtfCodec.h:249
static cairo_surface_t * surface
Definition: pdftocairo.cc:234
static GooString antialias
Definition: pdftocairo.cc:119
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld cleanup[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
#define index(s, c)
Definition: plain2.h:351
void composite()
static int32_t last
Definition: ppagelist.c:29
int r
Definition: ppmqvga.c:68
bstring c int memset(void *s, int c, int length)
#define status
#define mask(n)
Definition: lbitlib.c:93
lft_cell * left
Definition: routines.h:73
ShellFileEnvironment e
Definition: sh6.c:388
cairo_recording_region_type_t region
cairo_status_t status
cairo_content_t content
unsigned int unique_id
cairo_surface_type_t type
Definition: nsfix.c:44
Definition: jquant2.c:258
Definition: sd.h:76
Definition: mendex.h:20
Definition: sh.h:1226
Definition: tpic.c:45
cairo_surface_t base
cairo_surface_t * image
Definition: regions.h:31
Definition: sh.h:1345
int type
Definition: sh.h:1347
op
Definition: tex4ht.c:3129
cairo_command_stroke_t stroke
cairo_command_header_t header