1 /* cairo-trace - a utility to record and replay calls to the Cairo library.
3 * Copyright © 2008 Chris Wilson
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 /* The autoconf on OpenBSD 4.5 produces the malformed constant name
26 * SIZEOF_VOID__ rather than SIZEOF_VOID_P. Work around that here. */
27 #if !defined(SIZEOF_VOID_P) && defined(SIZEOF_VOID__)
28 # define SIZEOF_VOID_P SIZEOF_VOID__
36 #include <sys/types.h>
42 #include <locale.h> /* for locale independent %f printing */
51 # include <cairo-ft.h>
59 #ifndef CAIRO_TRACE_OUTDIR
60 #define CAIRO_TRACE_OUTDIR "."
64 # include <byteswap.h>
67 # define bswap_16(p) \
68 (((((uint16_t)(p)) & 0x00ff) << 8) | \
69 (((uint16_t)(p)) >> 8))
72 # define bswap_32(p) \
73 (((((uint32_t)(p)) & 0x000000ff) << 24) | \
74 ((((uint32_t)(p)) & 0x0000ff00) << 8) | \
75 ((((uint32_t)(p)) & 0x00ff0000) >> 8) | \
76 ((((uint32_t)(p))) >> 24))
80 #define le16(x) bswap_16 (x)
81 #define le32(x) bswap_32 (x)
88 #define be16(x) bswap_16 (x)
89 #define be32(x) bswap_32 (x)
90 #define to_be32(x) bswap_32 (x)
93 #if CAIRO_HAS_SYMBOL_LOOKUP
94 #include "lookup-symbol.h"
97 /* Reverse the bits in a byte with 7 operations (no 64-bit):
98 * Devised by Sean Anderson, July 13, 2001.
99 * Source: http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
101 #define CAIRO_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16)
103 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
104 #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \
105 __attribute__((__format__(__printf__, fmt_index, va_index)))
107 #define CAIRO_PRINTF_FORMAT(fmt_index, va_index)
110 /* XXX implement manual vprintf so that the user can control precision of
114 static void *_dlhandle = RTLD_NEXT;
115 #define DLCALL(name, args...) ({ \
116 static typeof (&name) name##_real; \
117 if (name##_real == NULL) { \
118 name##_real = (typeof (&name))(dlsym (_dlhandle, #name)); \
119 if (name##_real == NULL && _dlhandle == RTLD_NEXT) { \
120 _dlhandle = dlopen ("libcairo." SHARED_LIB_EXT, RTLD_LAZY); \
121 name##_real = (typeof (&name))(dlsym (_dlhandle, #name)); \
122 assert (name##_real != NULL); \
125 (*name##_real) (args); \
128 #define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0]))
129 #define ARRAY_LENGTH(a) ((int) ARRAY_SIZE(a))
131 #if SIZEOF_VOID_P == 4
133 #elif SIZEOF_VOID_P == 8
136 #error Unexpected pointer size
138 #define BUCKET(b, ptr) (((unsigned long) (ptr) >> PTR_SHIFT) % ARRAY_LENGTH (b))
140 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
141 #define _BOOLEAN_EXPR(expr) \
150 #define LIKELY(expr) (__builtin_expect (_BOOLEAN_EXPR(expr), 1))
151 #define UNLIKELY(expr) (__builtin_expect (_BOOLEAN_EXPR(expr), 0))
153 #define LIKELY(expr) (expr)
154 #define UNLIKELY(expr) (expr)
157 typedef struct _object Object;
158 typedef struct _type Type;
163 unsigned long int token;
165 cairo_bool_t foreign;
166 cairo_bool_t defined;
167 cairo_bool_t unknown;
170 void (*destroy)(void *);
188 pthread_mutex_t mutex;
190 unsigned long int min;
191 unsigned long int count;
192 unsigned int map[64];
193 struct _bitmap *next;
195 Object *objects[607];
199 static struct _type_table {
200 pthread_mutex_t mutex;
201 Type *op_types[_N_OP_TYPES];
204 static FILE *logfile;
205 static cairo_bool_t _flush;
206 static cairo_bool_t _error;
207 static cairo_bool_t _line_info;
208 static cairo_bool_t _mark_dirty;
209 static const cairo_user_data_key_t destroy_key;
210 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
211 static pthread_key_t counter_key;
213 static void _init_trace (void);
215 #define INIT_TRACE_ONCE() pthread_once (&once_control, _init_trace)
217 #if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
218 # define _enter_trace() INIT_TRACE_ONCE ()
219 # define _exit_trace() do { } while (0)
220 # define _should_trace() 1
221 # define USE_ENTER_EXIT 0
223 static void _enter_trace (void);
224 static void _exit_trace (void);
225 static cairo_bool_t _should_trace (void);
226 # define USE_ENTER_EXIT 1
229 #if HAVE_BUILTIN_RETURN_ADDRESS && CAIRO_HAS_SYMBOL_LOOKUP
230 #define _emit_line_info() do { \
231 if (_line_info && _write_lock ()) { \
232 void *addr = __builtin_return_address(0); \
234 _trace_printf ("%% %s() called by %s\n", __FUNCTION__, \
235 lookup_symbol (caller, sizeof (caller), addr)); \
240 #define _emit_line_info()
244 _type_release_token (Type *t, unsigned long int token)
246 struct _bitmap *b, **prev = NULL;
250 if (token < b->min + sizeof (b->map) * CHAR_BIT) {
251 unsigned int bit, elem;
254 elem = token / (sizeof (b->map[0]) * CHAR_BIT);
255 bit = token % (sizeof (b->map[0]) * CHAR_BIT);
256 b->map[elem] &= ~(1 << bit);
257 if (! --b->count && prev) {
268 static unsigned long int
269 _type_next_token (Type *t)
271 struct _bitmap *b, *bb, **prev = NULL;
272 unsigned long int min = 0;
279 if (b->count < sizeof (b->map) * CHAR_BIT) {
280 unsigned int n, m, bit;
281 for (n = 0; n < ARRAY_SIZE (b->map); n++) {
282 if (b->map[n] == (unsigned int) -1)
285 for (m=0, bit=1; m<sizeof (b->map[0])*CHAR_BIT; m++, bit<<=1) {
286 if ((b->map[n] & bit) == 0) {
289 return n * sizeof (b->map[0])*CHAR_BIT + m + b->min;
294 min += sizeof (b->map) * CHAR_BIT;
300 bb = malloc (sizeof (struct _bitmap));
306 memset (bb->map + 1, 0, sizeof (bb->map) - sizeof (bb->map[0]));
312 _object_destroy (Object *obj)
316 pthread_mutex_lock (&obj->type->mutex);
317 bucket = BUCKET (obj->type->objects, obj->addr);
318 _type_release_token (obj->type, obj->token);
320 if (obj->prev != NULL)
321 obj->prev->next = obj->next;
323 obj->type->objects[bucket] = obj->next;
325 if (obj->next != NULL)
326 obj->next->prev = obj->prev;
327 pthread_mutex_unlock (&obj->type->mutex);
329 if (obj->data != NULL && obj->destroy != NULL)
330 obj->destroy (obj->data);
336 _type_create (const char *typename,
337 enum operand_type op_type,
342 pthread_mutex_lock (&Types.mutex);
344 t = malloc (sizeof (Type));
346 t->op_type = op_type;
347 t->op_code = op_code;
349 pthread_mutex_init (&t->mutex, NULL);
353 memset (t->map.map, 0, sizeof (t->map.map));
356 memset (t->objects, 0, sizeof (t->objects));
360 Types.op_types[op_type] = t;
361 pthread_mutex_unlock (&Types.mutex);
365 _get_type (enum operand_type type)
367 return Types.op_types[type];
371 _type_destroy (Type *t)
376 for (n = 0; n < ARRAY_LENGTH (t->objects); n++) {
377 Object *obj = t->objects[n];
378 while (obj != NULL) {
379 Object *next = obj->next;
380 _object_destroy (obj);
387 struct _bitmap *next = b->next;
392 pthread_mutex_destroy (&t->mutex);
397 _type_get_object (Type *type, const void *ptr)
400 int bucket = BUCKET (type->objects, ptr);
402 for (obj = type->objects[bucket]; obj != NULL; obj = obj->next) {
403 if (obj->addr == ptr) {
404 if (obj->prev != NULL) { /* mru */
405 obj->prev->next = obj->next;
406 if (obj->next != NULL)
407 obj->next->prev = obj->prev;
409 type->objects[bucket]->prev = obj;
410 obj->next = type->objects[bucket];
411 type->objects[bucket] = obj;
421 _object_create (Type *type, const void *ptr)
424 int bucket = BUCKET (type->objects, ptr);
426 obj = malloc (sizeof (Object));
427 obj->defined = FALSE;
428 obj->foreign = FALSE;
432 obj->token = _type_next_token (type);
436 obj->next = type->objects[bucket];
437 if (type->objects[bucket] != NULL)
438 type->objects[bucket]->prev = obj;
439 type->objects[bucket] = obj;
448 int *counter = pthread_getspecific (counter_key);
449 if (counter == NULL) {
450 counter = calloc(1, sizeof(int));
451 pthread_setspecific (counter_key, counter);
460 _get_counter ()[0]++;
466 _get_counter ()[0]--;
472 return _get_counter ()[0] <= 1;
474 #endif /* USE_ENTER_EXIT */
479 pthread_mutex_init (&Types.mutex, NULL);
480 pthread_key_create (&counter_key, free);
482 _type_create ("unclassed", NONE, "");
483 _type_create ("cairo_t", CONTEXT, "c");
484 _type_create ("cairo_font_face_t", FONT_FACE, "f");
485 _type_create ("cairo_pattern_t", PATTERN, "p");
486 _type_create ("cairo_scaled_font_t", SCALED_FONT, "sf");
487 _type_create ("cairo_surface_t", SURFACE, "s");
493 if (logfile != NULL) {
499 static void __attribute__ ((destructor))
506 for (n = 0; n < ARRAY_LENGTH (Types.op_types); n++) {
507 if (Types.op_types[n]) {
508 _type_destroy (Types.op_types[n]);
509 Types.op_types[n] = NULL;
513 pthread_mutex_destroy (&Types.mutex);
516 /* Format a double in a locale independent way and trim trailing
517 * zeros. Based on code from Alex Larson <alexl@redhat.com>.
518 * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
520 * The code in the patch is copyright Red Hat, Inc under the LGPL.
522 #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
524 _trace_dtostr (char *buffer, size_t size, double d)
526 struct lconv *locale_data;
527 const char *decimal_point;
528 int decimal_point_len;
531 int num_zeros, decimal_digits;
533 /* Omit the minus sign from negative zero. */
537 locale_data = localeconv ();
538 decimal_point = locale_data->decimal_point;
539 decimal_point_len = strlen (decimal_point);
541 /* Using "%f" to print numbers less than 0.1 will result in
542 * reduced precision due to the default 6 digits after the
545 * For numbers is < 0.1, we print with maximum precision and count
546 * the number of zeros between the decimal point and the first
547 * significant digit. We then print the number again with the
548 * number of decimal places that gives us the required number of
549 * significant digits. This ensures the number is correctly
552 if (fabs (d) >= 0.1) {
553 snprintf (buffer, size, "%f", d);
555 snprintf (buffer, size, "%.18f", d);
558 if (*p == '+' || *p == '-')
564 if (strncmp (p, decimal_point, decimal_point_len) == 0)
565 p += decimal_point_len;
571 decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
573 if (decimal_digits < 18)
574 snprintf (buffer, size, "%.*f", decimal_digits, d);
578 if (*p == '+' || *p == '-')
584 if (strncmp (p, decimal_point, decimal_point_len) == 0) {
586 decimal_len = strlen (p + decimal_point_len);
587 memmove (p + 1, p + decimal_point_len, decimal_len);
588 p[1 + decimal_len] = 0;
590 /* Remove trailing zeros and decimal point if possible. */
591 for (p = p + decimal_len; *p == '0'; p--)
602 LENGTH_MODIFIER_LONG = 0x100
605 /* Here's a limited reimplementation of printf. The reason for doing
606 * this is primarily to special case handling of doubles. We want
607 * locale independent formatting of doubles and we want to trim
608 * trailing zeros. This is handled by dtostr() above, and the code
609 * below handles everything else by calling snprintf() to do the
610 * formatting. This functionality is only for internal use and we
611 * only implement the formats we actually use.
613 static void CAIRO_PRINTF_FORMAT(1, 0)
614 _trace_vprintf (const char *fmt, va_list ap)
616 #define SINGLE_FMT_BUFFER_SIZE 32
617 char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE];
618 int single_fmt_length;
620 const char *f, *start;
621 int length_modifier, width;
622 cairo_bool_t var_width;
625 assert (_should_trace ());
652 length_modifier = LENGTH_MODIFIER_LONG;
656 /* The only format strings exist in the cairo implementation
657 * itself. So there's an internal consistency problem if any
658 * of them is larger than our format buffer size. */
659 single_fmt_length = f - start + 1;
661 /* Reuse the format string for this conversion. */
662 memcpy (single_fmt, start, single_fmt_length);
663 single_fmt[single_fmt_length] = '\0';
665 /* Flush contents of buffer before snprintf()'ing into it. */
666 ret_ignored = fwrite (buffer, 1, p-buffer, logfile);
668 /* We group signed and unsigned together in this switch, the
669 * only thing that matters here is the size of the arguments,
670 * since we're just passing the data through to sprintf(). */
671 switch (*f | length_modifier) {
682 width = va_arg (ap, int);
683 snprintf (buffer, sizeof buffer,
684 single_fmt, width, va_arg (ap, int));
686 snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
689 case 'd' | LENGTH_MODIFIER_LONG:
690 case 'u' | LENGTH_MODIFIER_LONG:
691 case 'o' | LENGTH_MODIFIER_LONG:
692 case 'x' | LENGTH_MODIFIER_LONG:
693 case 'X' | LENGTH_MODIFIER_LONG:
695 width = va_arg (ap, int);
696 snprintf (buffer, sizeof buffer,
697 single_fmt, width, va_arg (ap, long int));
699 snprintf (buffer, sizeof buffer,
700 single_fmt, va_arg (ap, long int));
704 snprintf (buffer, sizeof buffer,
705 single_fmt, va_arg (ap, const char *));
709 _trace_dtostr (buffer, sizeof buffer, va_arg (ap, double));
712 buffer[0] = va_arg (ap, int);
718 p = buffer + strlen (buffer);
722 ret_ignored = fwrite (buffer, 1, p-buffer, logfile);
726 static void CAIRO_PRINTF_FORMAT(1, 2)
727 _trace_printf (const char *fmt, ...)
732 _trace_vprintf (fmt, ap);
737 get_prog_name (char *buf, int length)
742 memset (buf, 0, length);
746 file = fopen ("/proc/self/cmdline", "rb");
748 slash = fgets (buf, length, file);
754 char const *name = getenv ("CAIRO_TRACE_PROG_NAME");
756 strncpy (buf, name, length-1);
760 slash = strrchr (buf, '/');
762 size_t len = strlen (slash+1);
763 memmove (buf, slash+1, len+1);
770 char name[4096] = "";
772 get_prog_name (name, sizeof (name));
774 _trace_printf ("%%!CairoScript - %s\n", name);
780 static cairo_bool_t initialized;
782 const char *filename;
786 return logfile != NULL;
790 env = getenv ("CAIRO_TRACE_FLUSH");
795 env = getenv ("CAIRO_TRACE_LINE_INFO");
797 _line_info = atoi (env);
800 env = getenv ("CAIRO_TRACE_MARK_DIRTY");
802 _mark_dirty = atoi (env);
804 filename = getenv ("CAIRO_TRACE_FD");
805 if (filename != NULL) {
806 int fd = atoi (filename);
810 logfile = fdopen (fd, "w");
811 if (logfile == NULL) {
812 fprintf (stderr, "Failed to open trace file descriptor '%s': %s\n",
813 filename, strerror (errno));
817 setenv ("CAIRO_TRACE_FD", "-1", 1);
821 filename = getenv ("CAIRO_TRACE_OUTFILE_EXACT");
822 if (filename == NULL) {
823 char name[4096] = "";
825 filename = getenv ("CAIRO_TRACE_OUTDIR");
826 if (filename == NULL)
827 filename = CAIRO_TRACE_OUTDIR;
829 get_prog_name (name, sizeof (name));
831 strcpy (name, "cairo-trace.dat");
833 snprintf (buf, sizeof (buf), "%s/%s.%d.trace",
834 filename, name, getpid());
838 setenv ("CAIRO_TRACE_FD", "-1", 1);
841 logfile = fopen (filename, "wb");
842 if (logfile == NULL) {
843 fprintf (stderr, "Failed to open trace file '%s': %s\n",
844 filename, strerror (errno));
848 fprintf (stderr, "cairo-trace: Recording cairo trace data to %s\n",
852 atexit (_close_trace);
863 if (! _should_trace ())
866 if (! _init_logfile ())
869 #if HAVE_FLOCKFILE && HAVE_FUNLOCKFILE
881 #if HAVE_FLOCKFILE && HAVE_FUNLOCKFILE
882 funlockfile (logfile);
891 _type_object_create (enum operand_type op_type, const void *ptr)
896 type = _get_type (op_type);
898 pthread_mutex_lock (&type->mutex);
899 obj = _object_create (type, ptr);
900 pthread_mutex_unlock (&type->mutex);
906 _get_object (enum operand_type op_type, const void *ptr)
911 type = _get_type (op_type);
912 pthread_mutex_lock (&type->mutex);
913 obj = _type_get_object (type, ptr);
914 pthread_mutex_unlock (&type->mutex);
919 static Object *current_object[2048]; /* XXX limit operand stack */
920 static int current_stack_depth;
923 ensure_operands (int num_operands)
925 if (current_stack_depth < num_operands)
929 fprintf (stderr, "Operand stack underflow!\n");
930 for (n = 0; n < current_stack_depth; n++) {
931 Object *obj = current_object[n];
933 fprintf (stderr, " [%3d] = %s%ld\n",
934 n, obj->type->op_code, obj->token);
942 _consume_operand (bool discard)
947 obj = current_object[--current_stack_depth];
948 if (!discard && ! obj->defined) {
949 _trace_printf ("dup /%s%ld exch def\n",
958 _exch_operands (void)
963 tmp = current_object[current_stack_depth-1];
965 current_object[current_stack_depth-1] = current_object[current_stack_depth-2];
966 current_object[current_stack_depth-2] = tmp;
967 tmp = current_object[current_stack_depth-1];
972 _pop_operands_to_depth (int depth)
974 while (current_stack_depth > depth) {
978 c_obj = current_object[--current_stack_depth];
980 if (! c_obj->defined) {
984 _trace_printf ("/%s%ld exch def\n",
985 c_obj->type->op_code,
987 c_obj->defined = TRUE;
989 _trace_printf ("pop %% %s%ld\n",
990 c_obj->type->op_code, c_obj->token);
998 _pop_operands_to_object (Object *obj)
1000 if (obj->operand == -1)
1003 if (obj->operand == current_stack_depth - 1)
1006 if (! _pop_operands_to_depth (obj->operand + 2))
1010 _trace_printf ("exch ");
1015 _pop_operands_to (enum operand_type t, const void *ptr)
1017 return _pop_operands_to_object (_get_object (t, ptr));
1021 _is_current_object (Object *obj, int depth)
1023 if (current_stack_depth <= depth)
1025 return current_object[current_stack_depth-depth-1] == obj;
1029 _is_current (enum operand_type type, const void *ptr, int depth)
1031 return _is_current_object (_get_object (type, ptr), depth);
1035 _push_object(Object *obj)
1038 if (current_stack_depth == ARRAY_LENGTH (current_object))
1042 fprintf (stderr, "Operand stack overflow!\n");
1043 for (n = 0; n < current_stack_depth; n++) {
1044 obj = current_object[n];
1046 fprintf (stderr, " [%3d] = %s%ld\n",
1047 n, obj->type->op_code, obj->token);
1053 obj->operand = current_stack_depth;
1054 current_object[current_stack_depth++] = obj;
1058 _push_operand (enum operand_type t, const void *ptr)
1060 _push_object(_get_object(t, ptr));
1064 _object_remove (Object *obj)
1066 if (obj->operand != -1) {
1067 ensure_operands (1);
1068 if (obj->operand == current_stack_depth - 1) {
1069 _trace_printf ("pop %% %s%ld destroyed\n",
1070 obj->type->op_code, obj->token);
1071 } else if (obj->operand == current_stack_depth - 2) {
1073 _trace_printf ("exch pop %% %s%ld destroyed\n",
1074 obj->type->op_code, obj->token);
1078 _trace_printf ("%d -1 roll pop %% %s%ld destroyed\n",
1079 current_stack_depth - obj->operand,
1080 obj->type->op_code, obj->token);
1082 for (n = obj->operand; n < current_stack_depth - 1; n++) {
1083 current_object[n] = current_object[n+1];
1084 current_object[n]->operand = n;
1087 current_stack_depth--;
1092 _object_undef (void *ptr)
1096 if (_write_lock ()) {
1097 _object_remove (obj);
1100 _trace_printf ("/%s%ld undef\n",
1101 obj->type->op_code, obj->token);
1107 _object_destroy (obj);
1111 _create_context_id (cairo_t *cr)
1115 obj = _get_object (CONTEXT, cr);
1117 obj = _type_object_create (CONTEXT, cr);
1118 DLCALL (cairo_set_user_data,
1119 cr, &destroy_key, obj, _object_undef);
1126 _get_id (enum operand_type op_type, const void *ptr)
1130 obj = _get_object (op_type, ptr);
1132 if (logfile != NULL) {
1133 _trace_printf ("%% Unknown object of type %s, trace is incomplete.",
1134 _get_type (op_type)->name);
1144 _has_id (enum operand_type op_type, const void *ptr)
1146 return _get_object (op_type, ptr) != NULL;
1150 _get_context_id (cairo_t *cr)
1152 return _get_id (CONTEXT, cr);
1156 _create_font_face_id (cairo_font_face_t *font_face)
1160 obj = _get_object (FONT_FACE, font_face);
1162 obj = _type_object_create (FONT_FACE, font_face);
1163 DLCALL (cairo_font_face_set_user_data,
1164 font_face, &destroy_key, obj, _object_undef);
1171 _get_font_face_id (cairo_font_face_t *font_face)
1173 return _get_id (FONT_FACE, font_face);
1177 _emit_font_face_id (cairo_font_face_t *font_face)
1179 Object *obj = _get_object (FONT_FACE, font_face);
1181 _trace_printf ("null ");
1184 _trace_printf ("f%ld ", obj->token);
1186 _trace_printf ("%d index ", current_stack_depth - obj->operand - 1);
1192 _has_pattern_id (cairo_pattern_t *pattern)
1194 return _has_id (PATTERN, pattern);
1198 _create_pattern_id (cairo_pattern_t *pattern)
1202 obj = _get_object (PATTERN, pattern);
1204 obj = _type_object_create (PATTERN, pattern);
1205 DLCALL (cairo_pattern_set_user_data,
1206 pattern, &destroy_key, obj, _object_undef);
1213 _emit_pattern_id (cairo_pattern_t *pattern)
1215 Object *obj = _get_object (PATTERN, pattern);
1217 _trace_printf ("null ");
1220 _trace_printf ("p%ld ", obj->token);
1222 _trace_printf ("%d index ",
1223 current_stack_depth - obj->operand - 1);
1229 _create_scaled_font_id (cairo_scaled_font_t *font)
1233 obj = _get_object (SCALED_FONT, font);
1235 obj = _type_object_create (SCALED_FONT, font);
1236 DLCALL (cairo_scaled_font_set_user_data,
1237 font, &destroy_key, obj, _object_undef);
1244 _get_scaled_font_id (const cairo_scaled_font_t *font)
1246 return _get_id (SCALED_FONT, font);
1250 _has_scaled_font_id (const cairo_scaled_font_t *font)
1252 return _has_id (SCALED_FONT, font);
1256 _create_surface (cairo_surface_t *surface)
1260 obj = _get_object (SURFACE, surface);
1262 obj = _type_object_create (SURFACE, surface);
1263 DLCALL (cairo_surface_set_user_data,
1264 surface, &destroy_key, obj, _object_undef);
1271 _get_surface_id (cairo_surface_t *surface)
1273 return _get_id (SURFACE, surface);
1277 _matrix_is_identity (const cairo_matrix_t *m)
1279 return m->xx == 1. && m->yx == 0. &&
1280 m->xy == 0. && m->yy == 1. &&
1281 m->x0 == 0. && m->y0 == 0.;
1284 #define BUFFER_SIZE 16384
1285 struct _data_stream {
1286 z_stream zlib_stream;
1287 unsigned char zin_buf[BUFFER_SIZE];
1288 unsigned char zout_buf[BUFFER_SIZE];
1289 unsigned char four_tuple[4];
1294 _write_zlib_data_start (struct _data_stream *stream)
1296 stream->zlib_stream.zalloc = Z_NULL;
1297 stream->zlib_stream.zfree = Z_NULL;
1298 stream->zlib_stream.opaque = Z_NULL;
1300 deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION);
1302 stream->zlib_stream.next_in = stream->zin_buf;
1303 stream->zlib_stream.avail_in = 0;
1304 stream->zlib_stream.next_out = stream->zout_buf;
1305 stream->zlib_stream.avail_out = BUFFER_SIZE;
1309 _write_base85_data_start (struct _data_stream *stream)
1311 stream->base85_pending = 0;
1315 _expand_four_tuple_to_five (unsigned char four_tuple[4],
1316 unsigned char five_tuple[5])
1320 cairo_bool_t all_zero = TRUE;
1322 value = four_tuple[0] << 24 |
1323 four_tuple[1] << 16 |
1324 four_tuple[2] << 8 |
1326 for (i = 0; i < 5; i++) {
1328 if (digit != 0 && all_zero)
1330 five_tuple[4-i] = digit + 33;
1338 _write_base85_data (struct _data_stream *stream,
1339 const unsigned char *data,
1340 unsigned long length)
1342 unsigned char five_tuple[5];
1345 assert (_should_trace ());
1348 stream->four_tuple[stream->base85_pending++] = *data++;
1349 if (stream->base85_pending == 4) {
1350 if (_expand_four_tuple_to_five (stream->four_tuple, five_tuple))
1351 ret = fwrite ("z", 1, 1, logfile);
1353 ret = fwrite (five_tuple, 5, 1, logfile);
1355 stream->base85_pending = 0;
1361 _write_zlib_data (struct _data_stream *stream, cairo_bool_t flush)
1363 cairo_bool_t finished;
1366 int ret = deflate (&stream->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH);
1367 if (flush || stream->zlib_stream.avail_out == 0) {
1368 _write_base85_data (stream,
1370 BUFFER_SIZE - stream->zlib_stream.avail_out);
1371 stream->zlib_stream.next_out = stream->zout_buf;
1372 stream->zlib_stream.avail_out = BUFFER_SIZE;
1376 if (stream->zlib_stream.avail_in != 0)
1378 if (flush && ret != Z_STREAM_END)
1380 } while (! finished);
1382 stream->zlib_stream.next_in = stream->zin_buf;
1386 _write_data_start (struct _data_stream *stream, uint32_t len)
1388 _write_zlib_data_start (stream);
1389 _write_base85_data_start (stream);
1391 _trace_printf ("<|");
1392 len = to_be32 (len);
1393 _write_base85_data (stream, (unsigned char *) &len, sizeof (len));
1397 _write_data (struct _data_stream *stream,
1399 unsigned int length)
1402 const unsigned char *p = data;
1406 if (count > BUFFER_SIZE - stream->zlib_stream.avail_in)
1407 count = BUFFER_SIZE - stream->zlib_stream.avail_in;
1408 memcpy (stream->zin_buf + stream->zlib_stream.avail_in, p, count);
1410 stream->zlib_stream.avail_in += count;
1413 if (stream->zlib_stream.avail_in == BUFFER_SIZE)
1414 _write_zlib_data (stream, FALSE);
1419 _write_zlib_data_end (struct _data_stream *stream)
1421 _write_zlib_data (stream, TRUE);
1422 deflateEnd (&stream->zlib_stream);
1427 _write_base85_data_end (struct _data_stream *stream)
1429 unsigned char five_tuple[5];
1432 assert (_should_trace ());
1434 if (stream->base85_pending) {
1435 memset (stream->four_tuple + stream->base85_pending,
1436 0, 4 - stream->base85_pending);
1437 _expand_four_tuple_to_five (stream->four_tuple, five_tuple);
1438 ret = fwrite (five_tuple, stream->base85_pending+1, 1, logfile);
1444 _write_data_end (struct _data_stream *stream)
1446 _write_zlib_data_end (stream);
1447 _write_base85_data_end (stream);
1449 _trace_printf ("~>");
1453 _emit_data (const void *data, unsigned int length)
1455 struct _data_stream stream;
1457 _write_data_start (&stream, length);
1458 _write_data (&stream, data, length);
1459 _write_data_end (&stream);
1463 _format_to_string (cairo_format_t format)
1465 #define f(name) case CAIRO_FORMAT_ ## name: return #name
1476 return "UNKNOWN_FORMAT";
1480 _format_to_content_string (cairo_format_t format)
1483 case CAIRO_FORMAT_INVALID:
1485 case CAIRO_FORMAT_ARGB32:
1486 return "COLOR_ALPHA";
1487 case CAIRO_FORMAT_RGB30:
1488 case CAIRO_FORMAT_RGB24:
1489 case CAIRO_FORMAT_RGB16_565:
1491 case CAIRO_FORMAT_A8:
1492 case CAIRO_FORMAT_A1:
1499 _status_to_string (cairo_status_t status)
1501 #define f(name) case CAIRO_STATUS_ ## name: return "STATUS_" #name
1506 f(INVALID_POP_GROUP);
1507 f(NO_CURRENT_POINT);
1512 f(INVALID_PATH_DATA);
1515 f(SURFACE_FINISHED);
1516 f(SURFACE_TYPE_MISMATCH);
1517 f(PATTERN_TYPE_MISMATCH);
1523 f(INVALID_DSC_COMMENT);
1525 f(CLIP_NOT_REPRESENTABLE);
1528 f(FONT_TYPE_MISMATCH);
1529 f(USER_FONT_IMMUTABLE);
1532 f(INVALID_CLUSTERS);
1536 f(USER_FONT_NOT_IMPLEMENTED);
1537 f(DEVICE_TYPE_MISMATCH);
1539 f(INVALID_MESH_CONSTRUCTION);
1541 case CAIRO_STATUS_LAST_STATUS:
1544 return "UNKNOWN_STATUS";
1548 static void CAIRO_PRINTF_FORMAT(2, 3)
1549 _emit_image (cairo_surface_t *image,
1553 int stride, row, width, height;
1555 cairo_format_t format;
1556 uint8_t row_stack[BUFFER_SIZE];
1559 struct _data_stream stream;
1560 cairo_status_t status;
1562 status = DLCALL (cairo_surface_status, image);
1564 _trace_printf ("<< /status //%s >> image",
1565 _status_to_string (status));
1569 width = DLCALL (cairo_image_surface_get_width, image);
1570 height = DLCALL (cairo_image_surface_get_height, image);
1571 stride = DLCALL (cairo_image_surface_get_stride, image);
1572 format = DLCALL (cairo_image_surface_get_format, image);
1573 data = DLCALL (cairo_image_surface_get_data, image);
1575 _trace_printf ("dict\n"
1578 " /format //%s set\n",
1580 _format_to_string (format));
1584 va_start (ap, info);
1585 _trace_vprintf (info, ap);
1589 if (DLCALL (cairo_version) >= CAIRO_VERSION_ENCODE (1, 9, 0)) {
1590 const char *mime_types[] = {
1591 CAIRO_MIME_TYPE_JPEG,
1592 CAIRO_MIME_TYPE_JP2,
1593 CAIRO_MIME_TYPE_PNG,
1597 for (mime_type = mime_types; *mime_type; mime_type++) {
1598 const unsigned char *mime_data;
1599 unsigned long mime_length;
1601 DLCALL (cairo_surface_get_mime_data,
1602 image, *mime_type, &mime_data, &mime_length);
1603 if (mime_data != NULL) {
1604 _trace_printf (" /mime-type (%s) set\n"
1607 _write_base85_data_start (&stream);
1608 _write_base85_data (&stream, mime_data, mime_length);
1609 _write_base85_data_end (&stream);
1610 _trace_printf ("~> set\n"
1618 case CAIRO_FORMAT_A1: len = (width + 7)/8; break;
1619 case CAIRO_FORMAT_A8: len = width; break;
1620 case CAIRO_FORMAT_RGB16_565: len = 2*width; break;
1621 case CAIRO_FORMAT_RGB24: len = 3*width; break;
1623 case CAIRO_FORMAT_RGB30:
1624 case CAIRO_FORMAT_INVALID:
1625 case CAIRO_FORMAT_ARGB32: len = 4*width; break;
1628 _trace_printf (" /source ");
1629 _write_data_start (&stream, len * height);
1631 #ifdef WORDS_BIGENDIAN
1633 case CAIRO_FORMAT_A1:
1634 for (row = height; row--; ) {
1635 _write_data (&stream, data, (width+7)/8);
1639 case CAIRO_FORMAT_A8:
1640 for (row = height; row--; ) {
1641 _write_data (&stream, data, width);
1645 case CAIRO_FORMAT_RGB16_565:
1646 for (row = height; row--; ) {
1647 _write_data (&stream, data, 2*width);
1651 case CAIRO_FORMAT_RGB24:
1652 for (row = height; row--; ) {
1655 for (col = width; col--; ) {
1656 _write_data (&stream, rowdata, 3);
1662 case CAIRO_FORMAT_RGB30:
1663 case CAIRO_FORMAT_ARGB32:
1664 for (row = height; row--; ) {
1665 _write_data (&stream, data, 4*width);
1669 case CAIRO_FORMAT_INVALID:
1674 if (stride > ARRAY_LENGTH (row_stack)) {
1675 rowdata = malloc (stride);
1676 if (rowdata == NULL)
1679 rowdata = row_stack;
1682 case CAIRO_FORMAT_A1:
1683 for (row = height; row--; ) {
1685 for (col = 0; col < (width + 7)/8; col++)
1686 rowdata[col] = CAIRO_BITSWAP8 (data[col]);
1687 _write_data (&stream, rowdata, (width+7)/8);
1691 case CAIRO_FORMAT_A8:
1692 for (row = height; row--; ) {
1693 _write_data (&stream, rowdata, width);
1697 case CAIRO_FORMAT_RGB16_565: /* XXX endianness */
1698 for (row = height; row--; ) {
1699 uint16_t *src = (uint16_t *) data;
1700 uint16_t *dst = (uint16_t *)rowdata;
1702 for (col = 0; col < width; col++)
1703 dst[col] = bswap_16 (src[col]);
1704 _write_data (&stream, rowdata, 2*width);
1708 case CAIRO_FORMAT_RGB24:
1709 for (row = height; row--; ) {
1710 uint8_t *src = data;
1712 for (col = 0; col < width; col++) {
1713 rowdata[3*col+2] = *src++;
1714 rowdata[3*col+1] = *src++;
1715 rowdata[3*col+0] = *src++;
1718 _write_data (&stream, rowdata, 3*width);
1722 case CAIRO_FORMAT_RGB30:
1723 case CAIRO_FORMAT_ARGB32:
1724 for (row = height; row--; ) {
1725 uint32_t *src = (uint32_t *) data;
1726 uint32_t *dst = (uint32_t *) rowdata;
1728 for (col = 0; col < width; col++)
1729 dst[col] = bswap_32 (src[col]);
1730 _write_data (&stream, rowdata, 4*width);
1734 case CAIRO_FORMAT_INVALID:
1738 if (rowdata != row_stack)
1742 _write_data_end (&stream);
1744 _trace_printf (" set\n image");
1748 _encode_string_literal (char *out, int max,
1749 const char *utf8, int len)
1761 len = strlen (utf8);
1764 while (utf8 < end) {
1768 switch ((c = *utf8++)) {
1801 if (isprint (c) || isspace (c)) {
1810 octal = snprintf (out, max, "\\%03d", octal);
1823 to_octal (int value, char *buf, size_t size)
1826 buf[--size] = '0' + (value & 7);
1832 _emit_string_literal (const char *utf8, int len)
1838 _trace_printf ("()");
1843 len = strlen (utf8);
1846 _trace_printf ("(");
1847 while (utf8 < end) {
1848 switch ((c = *utf8++)) {
1868 _trace_printf ("\\%c", c);
1871 if (isprint (c) || isspace (c)) {
1872 _trace_printf ("%c", c);
1874 char buf[4] = { '\\' };
1877 to_octal (c, buf+1, 3);
1878 ret_ignored = fwrite (buf, 4, 1, logfile);
1884 _trace_printf (")");
1888 _emit_current (Object *obj)
1890 if (obj != NULL && ! _pop_operands_to_object (obj)) {
1891 _trace_printf ("%s%ld\n", obj->type->op_code, obj->token);
1897 _emit_context (cairo_t *cr)
1899 _emit_current (_get_object (CONTEXT, cr));
1903 _emit_pattern (cairo_pattern_t *pattern)
1905 _emit_current (_get_object (PATTERN, pattern));
1909 _emit_surface (cairo_surface_t *surface)
1911 _emit_current (_get_object (SURFACE, surface));
1914 static void CAIRO_PRINTF_FORMAT(2, 3)
1915 _emit_cairo_op (cairo_t *cr, const char *fmt, ...)
1919 if (cr == NULL || ! _write_lock ())
1925 _trace_vprintf ( fmt, ap);
1932 cairo_create (cairo_surface_t *target)
1940 ret = DLCALL (cairo_create, target);
1941 context_id = _create_context_id (ret);
1944 if (target != NULL && _write_lock ()) {
1945 surface_id = _get_surface_id (target);
1946 if (surface_id != -1) {
1947 _get_object (SURFACE, target)->foreign = FALSE;
1949 /* we presume that we will continue to use the context */
1950 if (_pop_operands_to (SURFACE, target)){
1951 _consume_operand (false);
1953 _trace_printf ("s%ld ", surface_id);
1955 _trace_printf ("context %% c%ld\n", context_id);
1956 _push_operand (CONTEXT, ret);
1966 cairo_save (cairo_t *cr)
1970 _emit_cairo_op (cr, "save\n");
1971 DLCALL (cairo_save, cr);
1976 cairo_restore (cairo_t *cr)
1980 _emit_cairo_op (cr, "restore\n");
1981 DLCALL (cairo_restore, cr);
1986 cairo_push_group (cairo_t *cr)
1990 _emit_cairo_op (cr, "//COLOR_ALPHA push-group\n");
1991 DLCALL (cairo_push_group, cr);
1996 _content_to_string (cairo_content_t content)
1999 case CAIRO_CONTENT_ALPHA: return "ALPHA";
2000 case CAIRO_CONTENT_COLOR: return "COLOR";
2002 case CAIRO_CONTENT_COLOR_ALPHA: return "COLOR_ALPHA";
2007 cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
2011 _emit_cairo_op (cr, "//%s push-group\n", _content_to_string (content));
2012 DLCALL (cairo_push_group_with_content, cr, content);
2017 cairo_pop_group (cairo_t *cr)
2019 cairo_pattern_t *ret;
2023 ret = DLCALL (cairo_pop_group, cr);
2026 _emit_cairo_op (cr, "pop-group %% p%ld\n", _create_pattern_id (ret));
2027 _push_operand (PATTERN, ret);
2034 cairo_pop_group_to_source (cairo_t *cr)
2038 _emit_cairo_op (cr, "pop-group set-source\n");
2039 DLCALL (cairo_pop_group_to_source, cr);
2044 _operator_to_string (cairo_operator_t op)
2046 #define f(name) case CAIRO_OPERATOR_ ## name: return #name
2067 case CAIRO_OPERATOR_COLOR_DODGE: return "DODGE";
2068 case CAIRO_OPERATOR_COLOR_BURN: return "BURN";
2079 return "UNKNOWN_OPERATOR";
2083 cairo_set_operator (cairo_t *cr, cairo_operator_t op)
2087 _emit_cairo_op (cr, "//%s set-operator\n", _operator_to_string (op));
2088 DLCALL (cairo_set_operator, cr, op);
2093 cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
2097 _emit_cairo_op (cr, "%g %g %g set-source-rgb\n", red, green, blue);
2098 DLCALL (cairo_set_source_rgb, cr, red, green, blue);
2103 cairo_set_source_rgba (cairo_t *cr, double red, double green, double blue, double alpha)
2107 _emit_cairo_op (cr, "%g %g %g %g set-source-rgba\n",
2108 red, green, blue, alpha);
2109 DLCALL (cairo_set_source_rgba, cr, red, green, blue, alpha);
2114 _emit_source_image (cairo_surface_t *surface)
2117 cairo_surface_t *image;
2120 obj = _get_object (SURFACE, surface);
2124 image = DLCALL (cairo_image_surface_create,
2125 CAIRO_FORMAT_ARGB32,
2128 cr = DLCALL (cairo_create, image);
2129 DLCALL (cairo_set_source_surface, cr, surface, 0, 0);
2130 DLCALL (cairo_paint, cr);
2131 DLCALL (cairo_destroy, cr);
2133 _emit_image (image, NULL);
2134 _trace_printf (" set-source-image ");
2135 DLCALL (cairo_surface_destroy, image);
2137 obj->foreign = FALSE;
2141 _emit_source_image_rectangle (cairo_surface_t *surface,
2143 int width, int height)
2146 cairo_surface_t *image;
2149 obj = _get_object (SURFACE, surface);
2154 _emit_source_image (surface);
2158 image = DLCALL (cairo_image_surface_create,
2159 CAIRO_FORMAT_ARGB32,
2162 cr = DLCALL (cairo_create, image);
2163 DLCALL (cairo_set_source_surface, cr, surface, x, y);
2164 DLCALL (cairo_paint, cr);
2165 DLCALL (cairo_destroy, cr);
2167 _emit_image (image, NULL);
2168 _trace_printf (" %d %d set-device-offset set-source-image ",
2170 DLCALL (cairo_surface_destroy, image);
2174 cairo_set_source_surface (cairo_t *cr, cairo_surface_t *surface, double x, double y)
2178 if (cr != NULL && surface != NULL && _write_lock ()) {
2179 Object *obj = _get_object (SURFACE, surface);
2181 if (_is_current (SURFACE, surface, 0) &&
2182 _is_current (CONTEXT, cr, 1))
2184 _consume_operand (false);
2186 else if (_is_current (SURFACE, surface, 1) &&
2187 _is_current (CONTEXT, cr, 0))
2189 _trace_printf ("exch ");
2191 _consume_operand (false);
2192 } else if (obj->defined) {
2194 _trace_printf ("s%ld ", obj->token);
2197 _trace_printf ("%d index ",
2198 current_stack_depth - obj->operand - 1);
2202 _emit_source_image (surface);
2204 _trace_printf ("pattern");
2205 if (x != 0. || y != 0.)
2206 _trace_printf (" %g %g translate", -x, -y);
2208 _trace_printf (" set-source\n");
2212 DLCALL (cairo_set_source_surface, cr, surface, x, y);
2217 cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
2221 if (cr != NULL && source != NULL && _write_lock ()) {
2222 Object *obj = _get_object (PATTERN, source);
2223 cairo_bool_t need_context_and_pattern = TRUE;
2225 if (_is_current (PATTERN, source, 0) &&
2226 _is_current (CONTEXT, cr, 1))
2229 _consume_operand (false);
2230 need_context_and_pattern = FALSE;
2233 else if (_is_current (PATTERN, source, 1) &&
2234 _is_current (CONTEXT, cr, 0))
2237 _trace_printf ("exch ");
2239 _consume_operand (false);
2240 need_context_and_pattern = FALSE;
2244 if (need_context_and_pattern) {
2246 _emit_pattern_id (source);
2249 _trace_printf ("set-source\n");
2253 DLCALL (cairo_set_source, cr, source);
2258 cairo_get_source (cairo_t *cr)
2260 cairo_pattern_t *ret;
2264 ret = DLCALL (cairo_get_source, cr);
2266 if (! _has_pattern_id (ret)) {
2267 _emit_cairo_op (cr, "/source get /p%ld exch def\n",
2268 _create_pattern_id (ret));
2269 _get_object (PATTERN, ret)->defined = TRUE;
2277 cairo_set_tolerance (cairo_t *cr, double tolerance)
2281 _emit_cairo_op (cr, "%g set-tolerance\n", tolerance);
2282 DLCALL (cairo_set_tolerance, cr, tolerance);
2287 _antialias_to_string (cairo_antialias_t antialias)
2289 #define f(name) case CAIRO_ANTIALIAS_ ## name: return "ANTIALIAS_" #name
2290 switch (antialias) {
2302 return "UNKNOWN_ANTIALIAS";
2306 cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
2311 "//%s set-antialias\n", _antialias_to_string (antialias));
2312 DLCALL (cairo_set_antialias, cr, antialias);
2317 _fill_rule_to_string (cairo_fill_rule_t rule)
2319 #define f(name) case CAIRO_FILL_RULE_ ## name: return #name
2325 return "UNKNOWN_FILL_RULE";
2329 cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
2334 "//%s set-fill-rule\n", _fill_rule_to_string (fill_rule));
2335 DLCALL (cairo_set_fill_rule, cr, fill_rule);
2340 cairo_set_line_width (cairo_t *cr, double width)
2344 _emit_cairo_op (cr, "%g set-line-width\n", width);
2345 DLCALL (cairo_set_line_width, cr, width);
2350 _line_cap_to_string (cairo_line_cap_t line_cap)
2352 #define f(name) case CAIRO_LINE_CAP_ ## name: return "LINE_CAP_" #name
2359 return "UNKNOWN_LINE_CAP";
2363 cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
2367 _emit_cairo_op (cr, "//%s set-line-cap\n", _line_cap_to_string (line_cap));
2368 DLCALL (cairo_set_line_cap, cr, line_cap);
2373 _line_join_to_string (cairo_line_join_t line_join)
2375 #define f(name) case CAIRO_LINE_JOIN_ ## name: return "LINE_JOIN_" #name
2376 switch (line_join) {
2382 return "UNKNOWN_LINE_JOIN";
2386 cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
2391 "//%s set-line-join\n", _line_join_to_string (line_join));
2392 DLCALL (cairo_set_line_join, cr, line_join);
2397 cairo_set_dash (cairo_t *cr, const double *dashes, int num_dashes, double offset)
2401 if (cr != NULL && _write_lock ()) {
2406 _trace_printf ("[");
2407 for (n = 0; n < num_dashes; n++) {
2409 _trace_printf (" ");
2410 _trace_printf ("%g", dashes[n]);
2412 _trace_printf ("] %g set-dash\n", offset);
2417 DLCALL (cairo_set_dash, cr, dashes, num_dashes, offset);
2422 cairo_set_miter_limit (cairo_t *cr, double limit)
2426 _emit_cairo_op (cr, "%g set-miter-limit\n", limit);
2427 DLCALL (cairo_set_miter_limit, cr, limit);
2432 cairo_translate (cairo_t *cr, double tx, double ty)
2436 _emit_cairo_op (cr, "%g %g translate\n", tx, ty);
2437 DLCALL (cairo_translate, cr, tx, ty);
2442 cairo_scale (cairo_t *cr, double sx, double sy)
2446 _emit_cairo_op (cr, "%g %g scale\n", sx, sy);
2447 DLCALL (cairo_scale, cr, sx, sy);
2452 cairo_rotate (cairo_t *cr, double angle)
2456 _emit_cairo_op (cr, "%g rotate\n", angle);
2457 DLCALL (cairo_rotate, cr, angle);
2462 cairo_transform (cairo_t *cr, const cairo_matrix_t *matrix)
2466 _emit_cairo_op (cr, "%g %g %g %g %g %g matrix transform\n",
2467 matrix->xx, matrix->yx,
2468 matrix->xy, matrix->yy,
2469 matrix->x0, matrix->y0);
2470 DLCALL (cairo_transform, cr, matrix);
2475 cairo_set_matrix (cairo_t *cr, const cairo_matrix_t *matrix)
2479 if (_matrix_is_identity (matrix)) {
2480 _emit_cairo_op (cr, "identity set-matrix\n");
2482 _emit_cairo_op (cr, "%g %g %g %g %g %g matrix set-matrix\n",
2483 matrix->xx, matrix->yx,
2484 matrix->xy, matrix->yy,
2485 matrix->x0, matrix->y0);
2487 DLCALL (cairo_set_matrix, cr, matrix);
2492 cairo_get_target (cairo_t *cr)
2494 cairo_surface_t *ret;
2498 ret = DLCALL (cairo_get_target, cr);
2500 Object *obj = _create_surface (ret);
2502 if (! obj->defined) {
2504 "/target get /s%ld exch def\n",
2506 obj->defined = TRUE;
2515 cairo_get_group_target (cairo_t *cr)
2517 cairo_surface_t *ret;
2521 ret = DLCALL (cairo_get_group_target, cr);
2523 Object *obj = _create_surface (ret);
2525 if (! obj->defined) {
2527 "/group-target get /s%ld exch def\n",
2529 obj->defined = TRUE;
2538 cairo_identity_matrix (cairo_t *cr)
2542 _emit_cairo_op (cr, "identity set-matrix\n");
2543 DLCALL (cairo_identity_matrix, cr);
2548 cairo_new_path (cairo_t *cr)
2552 _emit_cairo_op (cr, "n ");
2553 DLCALL (cairo_new_path, cr);
2558 cairo_move_to (cairo_t *cr, double x, double y)
2561 _emit_cairo_op (cr, "%g %g m ", x, y);
2562 DLCALL (cairo_move_to, cr, x, y);
2567 cairo_new_sub_path (cairo_t *cr)
2570 _emit_cairo_op (cr, "N ");
2571 DLCALL (cairo_new_sub_path, cr);
2576 cairo_line_to (cairo_t *cr, double x, double y)
2579 _emit_cairo_op (cr, "%g %g l ", x, y);
2580 DLCALL (cairo_line_to, cr, x, y);
2585 cairo_curve_to (cairo_t *cr, double x1, double y1, double x2, double y2, double x3, double y3)
2588 _emit_cairo_op (cr, "%g %g %g %g %g %g c ", x1, y1, x2, y2, x3, y3);
2589 DLCALL (cairo_curve_to, cr, x1, y1, x2, y2, x3, y3);
2594 cairo_arc (cairo_t *cr, double xc, double yc, double radius, double angle1, double angle2)
2597 _emit_cairo_op (cr, "%g %g %g %g %g arc\n", xc, yc, radius, angle1, angle2);
2598 DLCALL (cairo_arc, cr, xc, yc, radius, angle1, angle2);
2603 cairo_arc_negative (cairo_t *cr, double xc, double yc, double radius, double angle1, double angle2)
2606 _emit_cairo_op (cr, "%g %g %g %g %g arc-\n",
2607 xc, yc, radius, angle1, angle2);
2608 DLCALL (cairo_arc_negative, cr, xc, yc, radius, angle1, angle2);
2613 cairo_rel_move_to (cairo_t *cr, double dx, double dy)
2616 _emit_cairo_op (cr, "%g %g M ", dx, dy);
2617 DLCALL (cairo_rel_move_to, cr, dx, dy);
2622 cairo_rel_line_to (cairo_t *cr, double dx, double dy)
2625 _emit_cairo_op (cr, "%g %g L ", dx, dy);
2626 DLCALL (cairo_rel_line_to, cr, dx, dy);
2631 cairo_rel_curve_to (cairo_t *cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
2634 _emit_cairo_op (cr, "%g %g %g %g %g %g C ",
2635 dx1, dy1, dx2, dy2, dx3, dy3);
2636 DLCALL (cairo_rel_curve_to, cr, dx1, dy1, dx2, dy2, dx3, dy3);
2641 cairo_rectangle (cairo_t *cr, double x, double y, double width, double height)
2644 _emit_cairo_op (cr, "%g %g %g %g rectangle\n", x, y, width, height);
2645 DLCALL (cairo_rectangle, cr, x, y, width, height);
2650 cairo_close_path (cairo_t *cr)
2653 _emit_cairo_op (cr, "h\n");
2654 DLCALL (cairo_close_path, cr);
2659 cairo_paint (cairo_t *cr)
2663 _emit_cairo_op (cr, "paint\n");
2664 DLCALL (cairo_paint, cr);
2669 cairo_paint_with_alpha (cairo_t *cr, double alpha)
2673 _emit_cairo_op (cr, "%g paint-with-alpha\n", alpha);
2674 DLCALL (cairo_paint_with_alpha, cr, alpha);
2679 cairo_mask (cairo_t *cr, cairo_pattern_t *pattern)
2683 if (cr != NULL && pattern != NULL && _write_lock ()) {
2684 Object *obj = _get_object (PATTERN, pattern);
2685 cairo_bool_t need_context_and_pattern = TRUE;
2687 if (_is_current (PATTERN, pattern, 0) &&
2688 _is_current (CONTEXT, cr, 1))
2691 _consume_operand (false);
2692 need_context_and_pattern = FALSE;
2695 else if (_is_current (PATTERN, pattern, 1) &&
2696 _is_current (CONTEXT, cr, 0))
2699 _trace_printf ("exch ");
2701 _consume_operand (false);
2702 need_context_and_pattern = FALSE;
2706 if (need_context_and_pattern) {
2708 _emit_pattern_id (pattern);
2711 _trace_printf (" mask\n");
2714 DLCALL (cairo_mask, cr, pattern);
2719 cairo_mask_surface (cairo_t *cr, cairo_surface_t *surface, double x, double y)
2723 if (cr != NULL && surface != NULL && _write_lock ()) {
2724 Object *obj = _get_object (SURFACE, surface);
2725 if (_is_current (SURFACE, surface, 0) &&
2726 _is_current (CONTEXT, cr, 1))
2728 _consume_operand (false);
2730 else if (_is_current (SURFACE, surface, 1) &&
2731 _is_current (CONTEXT, cr, 0))
2733 _trace_printf ("exch ");
2735 _consume_operand (false);
2736 } else if (obj->defined){
2738 _trace_printf ("s%ld ", obj->token);
2741 _trace_printf ("%d index ",
2742 current_stack_depth - obj->operand - 1);
2744 _trace_printf ("pattern");
2746 if (x != 0. || y != 0.)
2747 _trace_printf (" %g %g translate", -x, -y);
2749 _trace_printf (" mask\n");
2753 DLCALL (cairo_mask_surface, cr, surface, x, y);
2758 cairo_stroke (cairo_t *cr)
2762 _emit_cairo_op (cr, "stroke\n");
2763 DLCALL (cairo_stroke, cr);
2768 cairo_stroke_preserve (cairo_t *cr)
2772 _emit_cairo_op (cr, "stroke+\n");
2773 DLCALL (cairo_stroke_preserve, cr);
2778 cairo_fill (cairo_t *cr)
2782 _emit_cairo_op (cr, "fill\n");
2783 DLCALL (cairo_fill, cr);
2788 cairo_fill_preserve (cairo_t *cr)
2792 _emit_cairo_op (cr, "fill+\n");
2793 DLCALL (cairo_fill_preserve, cr);
2798 cairo_copy_page (cairo_t *cr)
2802 _emit_cairo_op (cr, "copy-page\n");
2803 DLCALL (cairo_copy_page, cr);
2808 cairo_show_page (cairo_t *cr)
2812 _emit_cairo_op (cr, "show-page\n");
2813 DLCALL (cairo_show_page, cr);
2818 cairo_clip (cairo_t *cr)
2822 _emit_cairo_op (cr, "clip\n");
2823 DLCALL (cairo_clip, cr);
2828 cairo_clip_preserve (cairo_t *cr)
2832 _emit_cairo_op (cr, "clip+\n");
2833 DLCALL (cairo_clip_preserve, cr);
2838 cairo_reset_clip (cairo_t *cr)
2842 _emit_cairo_op (cr, "reset-clip\n");
2843 DLCALL (cairo_reset_clip, cr);
2849 _slant_to_string (cairo_font_slant_t font_slant)
2851 #define f(name) case CAIRO_FONT_SLANT_ ## name: return "SLANT_" #name
2852 switch (font_slant) {
2858 return "UNKNOWN_SLANT";
2862 _weight_to_string (cairo_font_weight_t font_weight)
2864 #define f(name) case CAIRO_FONT_WEIGHT_ ## name: return "WEIGHT_" #name
2865 switch (font_weight) {
2870 return "UNKNOWN_WEIGHT";
2874 cairo_select_font_face (cairo_t *cr, const char *family, cairo_font_slant_t slant, cairo_font_weight_t weight)
2878 if (cr != NULL && _write_lock ()) {
2880 _emit_string_literal (family, -1);
2881 _trace_printf (" //%s //%s select-font-face\n",
2882 _slant_to_string (slant),
2883 _weight_to_string (weight));
2886 DLCALL (cairo_select_font_face, cr, family, slant, weight);
2891 cairo_get_font_face (cairo_t *cr)
2893 cairo_font_face_t *ret;
2898 ret = DLCALL (cairo_get_font_face, cr);
2899 font_face_id = _create_font_face_id (ret);
2901 _emit_cairo_op (cr, "/font-face get %% f%ld\n", font_face_id);
2902 _push_operand (FONT_FACE, ret);
2909 cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face)
2913 if (cr != NULL && font_face != NULL && _write_lock ()) {
2914 if (_is_current (FONT_FACE, font_face, 0) &&
2915 _is_current (CONTEXT, cr, 1))
2917 _consume_operand (false);
2919 else if (_is_current (FONT_FACE, font_face, 1) &&
2920 _is_current (CONTEXT, cr, 0))
2922 _trace_printf ("exch ");
2924 _consume_operand (false);
2929 _emit_font_face_id (font_face);
2932 _trace_printf ("set-font-face\n");
2936 DLCALL (cairo_set_font_face, cr, font_face);
2941 cairo_set_font_size (cairo_t *cr, double size)
2945 _emit_cairo_op (cr, "%g set-font-size\n", size);
2946 DLCALL (cairo_set_font_size, cr, size);
2951 cairo_set_font_matrix (cairo_t *cr, const cairo_matrix_t *matrix)
2955 _emit_cairo_op (cr, "%g %g %g %g %g %g matrix set-font-matrix\n",
2956 matrix->xx, matrix->yx,
2957 matrix->xy, matrix->yy,
2958 matrix->x0, matrix->y0);
2959 DLCALL (cairo_set_font_matrix, cr, matrix);
2964 _subpixel_order_to_string (cairo_subpixel_order_t subpixel_order)
2966 #define f(name) case CAIRO_SUBPIXEL_ORDER_ ## name: return "SUBPIXEL_ORDER_" #name
2967 switch (subpixel_order) {
2975 return "UNKNOWN_SUBPIXEL_ORDER";
2979 _hint_style_to_string (cairo_hint_style_t hint_style)
2981 #define f(name) case CAIRO_HINT_STYLE_ ## name: return "HINT_STYLE_" #name
2982 switch (hint_style) {
2990 return "UNKNOWN_HINT_STYLE";
2994 _hint_metrics_to_string (cairo_hint_metrics_t hint_metrics)
2996 #define f(name) case CAIRO_HINT_METRICS_ ## name: return "HINT_METRICS_" #name
2997 switch (hint_metrics) {
3003 return "UNKNOWN_HINT_METRICS";
3007 _emit_font_options (const cairo_font_options_t *options)
3009 cairo_antialias_t antialias;
3010 cairo_subpixel_order_t subpixel_order;
3011 cairo_hint_style_t hint_style;
3012 cairo_hint_metrics_t hint_metrics;
3014 _trace_printf ("<<");
3016 antialias = DLCALL (cairo_font_options_get_antialias, options);
3017 if (antialias != CAIRO_ANTIALIAS_DEFAULT) {
3018 _trace_printf (" /antialias //%s",
3019 _antialias_to_string (antialias));
3022 subpixel_order = DLCALL (cairo_font_options_get_subpixel_order, options);
3023 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
3024 _trace_printf (" /subpixel-order //%s",
3025 _subpixel_order_to_string (subpixel_order));
3028 hint_style = DLCALL (cairo_font_options_get_hint_style, options);
3029 if (hint_style != CAIRO_HINT_STYLE_DEFAULT) {
3030 _trace_printf (" /hint-style //%s",
3031 _hint_style_to_string (hint_style));
3034 hint_metrics = DLCALL (cairo_font_options_get_hint_metrics, options);
3035 if (hint_metrics != CAIRO_HINT_METRICS_DEFAULT) {
3036 _trace_printf (" /hint-metrics //%s",
3037 _hint_metrics_to_string (hint_metrics));
3040 _trace_printf (" >>");
3044 cairo_set_font_options (cairo_t *cr, const cairo_font_options_t *options)
3048 if (cr != NULL && options != NULL && _write_lock ()) {
3050 _emit_font_options (options);
3051 _trace_printf (" set-font-options\n");
3055 DLCALL (cairo_set_font_options, cr, options);
3059 cairo_scaled_font_t *
3060 cairo_get_scaled_font (cairo_t *cr)
3062 cairo_scaled_font_t *ret;
3066 ret = DLCALL (cairo_get_scaled_font, cr);
3068 if (cr != NULL && ! _has_scaled_font_id (ret)) {
3069 _emit_cairo_op (cr, "/scaled-font get /sf%ld exch def\n",
3070 _create_scaled_font_id (ret));
3071 _get_object (SCALED_FONT, ret)->defined = TRUE;
3079 cairo_set_scaled_font (cairo_t *cr, const cairo_scaled_font_t *scaled_font)
3083 if (cr != NULL && scaled_font != NULL) {
3084 if (_pop_operands_to (SCALED_FONT, scaled_font)) {
3085 if (_is_current (CONTEXT, cr, 1)) {
3086 if (_write_lock ()) {
3087 _consume_operand (false);
3088 _trace_printf ("set-scaled-font\n");
3092 if (_get_object (CONTEXT, cr)->defined) {
3093 if (_write_lock ()) {
3094 _consume_operand (false);
3095 _trace_printf ("c%ld exch set-scaled-font pop\n",
3096 _get_context_id (cr));
3100 _emit_cairo_op (cr, "sf%ld set-scaled-font\n",
3101 _get_scaled_font_id (scaled_font));
3105 _emit_cairo_op (cr, "sf%ld set-scaled-font\n",
3106 _get_scaled_font_id (scaled_font));
3109 DLCALL (cairo_set_scaled_font, cr, scaled_font);
3114 _emit_matrix (const cairo_matrix_t *m)
3116 if (_matrix_is_identity(m))
3118 _trace_printf ("identity");
3122 _trace_printf ("%g %g %g %g %g %g matrix",
3129 cairo_scaled_font_t *
3130 cairo_scaled_font_create (cairo_font_face_t *font_face,
3131 const cairo_matrix_t *font_matrix,
3132 const cairo_matrix_t *ctm,
3133 const cairo_font_options_t *options)
3135 cairo_scaled_font_t *ret;
3136 long scaled_font_id;
3140 ret = DLCALL (cairo_scaled_font_create, font_face, font_matrix, ctm, options);
3141 scaled_font_id = _create_scaled_font_id (ret);
3144 if (font_face != NULL &&
3145 font_matrix != NULL &&
3150 if (_pop_operands_to (FONT_FACE, font_face))
3151 _consume_operand (false);
3153 _trace_printf ("f%ld ", _get_font_face_id (font_face));
3155 _emit_matrix (font_matrix);
3156 _trace_printf (" ");
3159 _trace_printf (" ");
3161 _emit_font_options (options);
3163 if (_get_object (SCALED_FONT, ret)->defined) {
3164 _trace_printf (" scaled-font pop %% sf%ld\n",
3167 _trace_printf (" scaled-font dup /sf%ld exch def\n",
3169 _push_operand (SCALED_FONT, ret);
3171 _get_object (SCALED_FONT, ret)->defined = TRUE;
3182 cairo_show_text (cairo_t *cr, const char *utf8)
3186 if (cr != NULL && _write_lock ()) {
3188 _emit_string_literal (utf8, -1);
3189 _trace_printf (" show-text\n");
3192 DLCALL (cairo_show_text, cr, utf8);
3197 _glyph_advance (cairo_scaled_font_t *font,
3198 const cairo_glyph_t *glyph,
3199 double *x, double *y)
3201 cairo_text_extents_t extents;
3203 DLCALL (cairo_scaled_font_glyph_extents, font, glyph, 1, &extents);
3204 *x += extents.x_advance;
3205 *y += extents.y_advance;
3208 #define TOLERANCE 1e-5
3210 _emit_glyphs (cairo_scaled_font_t *font,
3211 const cairo_glyph_t *glyphs,
3217 if (num_glyphs == 0) {
3218 _trace_printf ("[]");
3222 for (n = 0; n < num_glyphs; n++) {
3223 if (glyphs[n].index > 255)
3229 if (n < num_glyphs) { /* need full glyph range */
3232 _trace_printf ("[%g %g [", x, y);
3234 while (num_glyphs--) {
3235 if (fabs (glyphs->x - x) > TOLERANCE ||
3236 fabs (glyphs->y - y) > TOLERANCE)
3240 _trace_printf ("] %g %g [", x, y);
3245 _trace_printf (" ");
3246 _trace_printf ("%lu", glyphs->index);
3249 _glyph_advance (font, glyphs, &x, &y);
3252 _trace_printf ("]]");
3254 struct _data_stream stream;
3256 if (num_glyphs == 1) {
3257 _trace_printf ("[%g %g <%02lx>]", x, y, glyphs->index);
3259 _trace_printf ("[%g %g <~", x, y);
3260 _write_base85_data_start (&stream);
3261 while (num_glyphs--) {
3264 if (fabs (glyphs->x - x) > TOLERANCE ||
3265 fabs (glyphs->y - y) > TOLERANCE)
3269 _write_base85_data_end (&stream);
3270 _trace_printf ("~> %g %g <~", x, y);
3271 _write_base85_data_start (&stream);
3275 _write_base85_data (&stream, &c, 1);
3277 _glyph_advance (font, glyphs, &x, &y);
3280 _write_base85_data_end (&stream);
3281 _trace_printf ("~>]");
3287 cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
3291 if (cr != NULL && glyphs != NULL && _write_lock ()) {
3292 cairo_scaled_font_t *font;
3295 font = DLCALL (cairo_get_scaled_font, cr);
3297 _emit_glyphs (font, glyphs, num_glyphs);
3298 _trace_printf (" show-glyphs\n");
3302 DLCALL (cairo_show_glyphs, cr, glyphs, num_glyphs);
3307 _direction_to_string (cairo_bool_t backward)
3309 const char *names[] = {
3313 return names[!!backward];
3317 cairo_show_text_glyphs (cairo_t *cr,
3320 const cairo_glyph_t *glyphs,
3322 const cairo_text_cluster_t *clusters,
3324 cairo_text_cluster_flags_t backward)
3326 cairo_scaled_font_t *font;
3330 font = DLCALL (cairo_get_scaled_font, cr);
3333 if (cr != NULL && glyphs != NULL && clusters != NULL && _write_lock ()) {
3338 _emit_string_literal (utf8, utf8_len);
3340 _emit_glyphs (font, glyphs, num_glyphs);
3341 _trace_printf (" [");
3342 for (n = 0; n < num_clusters; n++) {
3343 _trace_printf (" %d %d",
3344 clusters[n].num_bytes,
3345 clusters[n].num_glyphs);
3347 _trace_printf (" ] //%s show-text-glyphs\n",
3348 _direction_to_string (backward));
3353 DLCALL (cairo_show_text_glyphs, cr,
3356 clusters, num_clusters,
3362 cairo_text_path (cairo_t *cr, const char *utf8)
3366 if (cr != NULL && _write_lock ()) {
3368 _emit_string_literal (utf8, -1);
3369 _trace_printf (" text-path\n");
3372 DLCALL (cairo_text_path, cr, utf8);
3377 cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
3379 cairo_scaled_font_t *font;
3383 font = DLCALL (cairo_get_scaled_font, cr);
3386 if (cr != NULL && glyphs != NULL && _write_lock ()) {
3388 _emit_glyphs (font, glyphs, num_glyphs);
3389 _trace_printf (" glyph-path\n");
3394 DLCALL (cairo_glyph_path, cr, glyphs, num_glyphs);
3399 cairo_append_path (cairo_t *cr, const cairo_path_t *path)
3401 /* XXX no support for named paths, so manually reconstruct */
3403 cairo_path_data_t *p;
3408 if (cr == NULL || path == NULL) {
3409 DLCALL (cairo_append_path, cr, path);
3414 for (i=0; i < path->num_data; i += path->data[i].header.length) {
3416 switch (p->header.type) {
3417 case CAIRO_PATH_MOVE_TO:
3418 if (p->header.length >= 2)
3419 cairo_move_to (cr, p[1].point.x, p[1].point.y);
3421 case CAIRO_PATH_LINE_TO:
3422 if (p->header.length >= 2)
3423 cairo_line_to (cr, p[1].point.x, p[1].point.y);
3425 case CAIRO_PATH_CURVE_TO:
3426 if (p->header.length >= 4)
3428 p[1].point.x, p[1].point.y,
3429 p[2].point.x, p[2].point.y,
3430 p[3].point.x, p[3].point.y);
3432 case CAIRO_PATH_CLOSE_PATH:
3433 if (p->header.length >= 1)
3434 cairo_close_path (cr);
3444 cairo_image_surface_create (cairo_format_t format, int width, int height)
3446 cairo_surface_t *ret;
3450 ret = DLCALL (cairo_image_surface_create, format, width, height);
3453 if (_write_lock ()) {
3454 Object *obj = _create_surface (ret);
3455 const char *format_str = _format_to_string (format);
3456 const char *content_str = _format_to_content_string (format);
3458 _trace_printf ("dict\n"
3461 " /format //%s set\n"
3462 " /content //%s set\n"
3463 " image dup /s%ld exch def\n",
3464 width, height, format_str, content_str, obj->token);
3466 obj->height = height;
3467 obj->defined = TRUE;
3477 cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, int width, int height, int stride)
3479 cairo_surface_t *ret;
3483 ret = DLCALL (cairo_image_surface_create_for_data, data, format, width, height, stride);
3486 if (_write_lock ()) {
3487 Object *obj = _create_surface (ret);
3489 /* cairo_image_surface_create_for_data() is both used to supply
3490 * foreign pixel data to cairo and in order to read pixels back.
3491 * Defer grabbing the pixel contents until we have to, but only for
3492 * "large" images, for small images the overhead of embedding pixels
3495 * Choose 32x32 as that captures most icons which thanks to GdkPixbuf
3496 * are frequently reloaded.
3498 if (width * height < 32*32) {
3499 _emit_image (ret, NULL);
3500 _trace_printf (" dup /s%ld exch def\n",
3503 _trace_printf ("dict\n"
3506 " /format //%s set\n"
3507 " image dup /s%ld exch def\n",
3509 _format_to_string (format),
3512 obj->foreign = TRUE;
3516 obj->height = height;
3517 obj->defined = TRUE;
3527 cairo_image_surface_get_data (cairo_surface_t *surface)
3531 /* Just leave some breadcrumbs */
3534 if (surface != NULL && _write_lock ()) {
3535 _trace_printf ("%% s%ld get-data\n", _get_surface_id (surface));
3538 ptr = DLCALL (cairo_image_surface_get_data, surface);
3545 cairo_pattern_create_raster_source (void *data, cairo_content_t content, int width, int height)
3547 cairo_pattern_t *ret;
3551 ret = DLCALL (cairo_pattern_create_raster_source, data, content, width, height);
3554 if (_write_lock ()) {
3555 long pattern_id = _create_pattern_id (ret);
3556 cairo_format_t format;
3557 cairo_surface_t *image;
3560 /* Impossible to accurately record the interaction with this custom
3561 * pattern so just suck all the data into an image upfront */
3563 case CAIRO_CONTENT_ALPHA: format = CAIRO_FORMAT_A8; break;
3564 case CAIRO_CONTENT_COLOR: format = CAIRO_FORMAT_RGB24; break;
3566 case CAIRO_CONTENT_COLOR_ALPHA: format = CAIRO_FORMAT_ARGB32; break;
3569 _trace_printf ("%% raster-source\n");
3571 image = DLCALL (cairo_image_surface_create, format, width, height);
3572 cr = DLCALL (cairo_create, image);
3573 DLCALL (cairo_set_source, cr, ret);
3574 DLCALL (cairo_paint, cr);
3575 DLCALL (cairo_destroy, cr);
3577 _emit_image (image, NULL);
3578 DLCALL (cairo_surface_destroy, image);
3579 _trace_printf (" pattern dup /s%ld exch def\n",
3582 _push_operand (PATTERN, ret);
3591 cairo_surface_create_similar (cairo_surface_t *other,
3592 cairo_content_t content,
3593 int width, int height)
3595 cairo_surface_t *ret;
3599 ret = DLCALL (cairo_surface_create_similar, other, content, width, height);
3602 if (other != NULL && _write_lock ()) {
3603 Object *other_obj = _get_object(SURFACE, other);
3604 Object *new_obj = _create_surface (ret);
3606 if (other_obj->defined)
3607 _trace_printf ("s%ld ", other_obj->token);
3608 else if (current_stack_depth == other_obj->operand + 1)
3609 _trace_printf ("dup ");
3611 _trace_printf ("%d index ",
3612 current_stack_depth - other_obj->operand - 1);
3613 _trace_printf ("%d %d //%s similar %% s%ld\n",
3615 _content_to_string (content),
3618 _push_object (new_obj);
3627 cairo_surface_create_similar_image (cairo_surface_t *other,
3628 cairo_format_t format,
3629 int width, int height)
3631 cairo_surface_t *ret;
3635 ret = DLCALL (cairo_surface_create_similar_image,
3636 other, format, width, height);
3639 if (other != NULL && _write_lock ()) {
3640 Object *other_obj = _get_object(SURFACE, other);
3641 Object *new_obj = _create_surface (ret);
3643 if (other_obj->defined)
3644 _trace_printf ("s%ld ", other_obj->token);
3645 else if (current_stack_depth == other_obj->operand + 1)
3646 _trace_printf ("dup ");
3648 _trace_printf ("%d index ",
3649 current_stack_depth - other_obj->operand - 1);
3650 _trace_printf ("s%ld //%s %d %d similar-image %% s%ld\n",
3651 _get_surface_id (other),
3652 _format_to_string (format),
3656 _push_object (new_obj);
3665 cairo_surface_map_to_image (cairo_surface_t *surface,
3666 const cairo_rectangle_int_t *extents)
3668 cairo_surface_t *ret;
3672 ret = DLCALL (cairo_surface_map_to_image, surface, extents);
3675 if (_write_lock ()) {
3676 Object *obj = _create_surface (ret);
3678 _emit_surface (surface);
3680 _trace_printf ("[%d %d %d %d] map-to-image %% s%ld\n",
3681 extents->x, extents->y,
3682 extents->width, extents->height,
3684 obj->width = extents->width;
3685 obj->height = extents->height;
3687 _trace_printf ("[ ] map-to-image %% s%ld\n", obj->token);
3690 obj->unknown = TRUE;
3700 cairo_surface_unmap_image (cairo_surface_t *surface,
3701 cairo_surface_t *image)
3706 if (_write_lock ()) {
3707 Object *s = _get_object (SURFACE, surface);
3708 Object *i = _get_object (SURFACE, image);
3709 if (!(s->operand == current_stack_depth - 2 &&
3710 i->operand == current_stack_depth - 1)) {
3711 if (i->operand != s->operand + 1 || ! _pop_operands_to_depth (i->operand + 1)) {
3712 _emit_surface (surface);
3713 _emit_surface (image);
3716 _trace_printf ("unmap-image\n");
3717 _consume_operand (true);
3721 DLCALL (cairo_surface_unmap_image, surface, image);
3727 cairo_surface_create_for_rectangle (cairo_surface_t *target,
3729 double width, double height)
3731 cairo_surface_t *ret;
3735 ret = DLCALL (cairo_surface_create_for_rectangle, target, x, y, width, height);
3738 if (target != NULL && _write_lock ()) {
3739 Object *target_obj = _get_object (SURFACE, target);
3740 Object *child_obj = _create_surface (ret);
3742 if (target_obj->defined)
3743 _trace_printf ("s%ld ", target_obj->token);
3744 else if (current_stack_depth == target_obj->operand + 1)
3745 _trace_printf ("dup ");
3747 _trace_printf ("%d index ", current_stack_depth - target_obj->operand - 1);
3748 _trace_printf ("%f %f %f %f subsurface %% s%ld\n",
3749 x, y, width, height,
3752 _push_object (child_obj);
3760 static void CAIRO_PRINTF_FORMAT(2, 3)
3761 _emit_surface_op (cairo_surface_t *surface, const char *fmt, ...)
3765 if (surface == NULL || ! _write_lock ())
3768 _emit_surface (surface);
3771 _trace_vprintf ( fmt, ap);
3778 cairo_surface_finish (cairo_surface_t *surface)
3782 DLCALL (cairo_surface_finish, surface);
3787 cairo_surface_flush (cairo_surface_t *surface)
3791 if (surface != NULL && _write_lock ()) {
3792 _trace_printf ("%% s%ld flush\n", _get_surface_id (surface));
3795 DLCALL (cairo_surface_flush, surface);
3800 cairo_surface_mark_dirty (cairo_surface_t *surface)
3805 /* Call cairo before emitting the trace since _emit_surface() might cause
3806 * snapshots to be creates while mark_dirty assert()s that there are none.
3808 DLCALL (cairo_surface_mark_dirty, surface);
3810 if (surface != NULL && _write_lock ()) {
3812 _emit_surface (surface);
3813 _trace_printf ("%% mark-dirty\n");
3814 _emit_source_image (surface);
3816 _trace_printf ("%% s%ld mark-dirty\n", _get_surface_id (surface));
3823 cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
3824 int x, int y, int width, int height)
3828 /* Call cairo before emitting the trace since _emit_surface() might cause
3829 * snapshots to be creates while mark_dirty assert()s that there are none.
3831 DLCALL (cairo_surface_mark_dirty_rectangle, surface, x, y, width, height);
3834 if (surface != NULL && _write_lock ()) {
3836 _emit_surface (surface);
3837 _trace_printf ("%% %d %d %d %d mark-dirty-rectangle\n",
3838 x, y, width, height);
3839 _emit_source_image_rectangle (surface, x,y, width, height);
3841 _trace_printf ("%% s%ld %d %d %d %d mark-dirty-rectangle\n",
3842 _get_surface_id (surface), x, y, width, height);
3849 cairo_surface_set_device_offset (cairo_surface_t *surface, double x_offset, double y_offset)
3853 _emit_surface_op (surface, "%g %g set-device-offset\n",
3854 x_offset, y_offset);
3855 DLCALL (cairo_surface_set_device_offset, surface, x_offset, y_offset);
3860 cairo_surface_set_fallback_resolution (cairo_surface_t *surface, double x_pixels_per_inch, double y_pixels_per_inch)
3864 _emit_surface_op (surface, "%g %g set-fallback-resolution\n",
3865 x_pixels_per_inch, y_pixels_per_inch);
3866 DLCALL (cairo_surface_set_fallback_resolution, surface, x_pixels_per_inch, y_pixels_per_inch);
3871 cairo_surface_copy_page (cairo_surface_t *surface)
3875 _emit_surface_op (surface, "copy-page\n");
3876 DLCALL (cairo_surface_copy_page, surface);
3881 cairo_surface_show_page (cairo_surface_t *surface)
3885 _emit_surface_op (surface, "show-page\n");
3886 DLCALL (cairo_surface_show_page, surface);
3891 cairo_surface_set_mime_data (cairo_surface_t *surface,
3892 const char *mime_type,
3893 const unsigned char *data,
3894 unsigned long length,
3895 cairo_destroy_func_t destroy,
3901 if (surface != NULL && _write_lock ()) {
3902 _emit_surface (surface);
3903 _emit_string_literal (mime_type, -1);
3904 _trace_printf (" ");
3905 _emit_data (data, length);
3906 _trace_printf (" /deflate filter set-mime-data\n");
3911 ret = DLCALL (cairo_surface_set_mime_data,
3921 #if CAIRO_HAS_PNG_FUNCTIONS
3923 cairo_surface_write_to_png (cairo_surface_t *surface, const char *filename)
3928 if (surface != NULL && _write_lock ()) {
3929 _trace_printf ("%% s%ld ", _get_surface_id (surface));
3930 _emit_string_literal (filename, -1);
3931 _trace_printf (" write-to-png pop\n");
3934 ret = DLCALL (cairo_surface_write_to_png, surface, filename);
3940 cairo_surface_write_to_png_stream (cairo_surface_t *surface,
3941 cairo_write_func_t write_func,
3947 if (surface != NULL && _write_lock ()) {
3950 _trace_printf ("%% s%ld ", _get_surface_id (surface));
3951 #if CAIRO_HAS_SYMBOL_LOOKUP
3952 lookup_symbol (symbol, sizeof (symbol), write_func);
3956 _emit_string_literal (symbol, -1);
3957 _trace_printf (" write-to-png-stream pop\n");
3960 ret = DLCALL (cairo_surface_write_to_png_stream,
3961 surface, write_func, data);
3967 static void CAIRO_PRINTF_FORMAT(2, 3)
3968 _emit_pattern_op (cairo_pattern_t *pattern, const char *fmt, ...)
3972 if (pattern == NULL || ! _write_lock ())
3975 _emit_pattern (pattern);
3978 _trace_vprintf (fmt, ap);
3985 cairo_pattern_create_rgb (double red, double green, double blue)
3987 cairo_pattern_t *ret;
3992 ret = DLCALL (cairo_pattern_create_rgb, red, green, blue);
3993 pattern_id = _create_pattern_id (ret);
3996 if (_write_lock ()) {
3997 _trace_printf ("/p%ld %g %g %g rgb def\n",
3998 pattern_id, red, green, blue);
3999 _get_object (PATTERN, ret)->defined = TRUE;
4008 cairo_pattern_create_rgba (double red, double green, double blue, double alpha)
4010 cairo_pattern_t *ret;
4015 ret = DLCALL (cairo_pattern_create_rgba, red, green, blue, alpha);
4016 pattern_id = _create_pattern_id (ret);
4019 if (_write_lock ()) {
4020 _trace_printf ("/p%ld %g %g %g %g rgba def\n",
4021 pattern_id, red, green, blue, alpha);
4022 _get_object (PATTERN, ret)->defined = TRUE;
4031 cairo_pattern_create_for_surface (cairo_surface_t *surface)
4033 cairo_pattern_t *ret;
4039 ret = DLCALL (cairo_pattern_create_for_surface, surface);
4040 pattern_id = _create_pattern_id (ret);
4043 if (surface != NULL && _write_lock ()) {
4044 surface_id = _get_surface_id (surface);
4046 if (_pop_operands_to (SURFACE, surface)) {
4047 _consume_operand (false);
4049 _trace_printf ("s%ld ", surface_id);
4052 if (_get_object (SURFACE, surface)->foreign)
4053 _emit_source_image (surface);
4055 _trace_printf ("pattern %% p%ld\n", pattern_id);
4056 _push_operand (PATTERN, ret);
4065 cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
4067 cairo_pattern_t *ret;
4072 ret = DLCALL (cairo_pattern_create_linear, x0, y0, x1, y1);
4073 pattern_id = _create_pattern_id (ret);
4076 if (_write_lock ()) {
4077 _trace_printf ("%g %g %g %g linear %% p%ld\n",
4078 x0, y0, x1, y1, pattern_id);
4079 _push_operand (PATTERN, ret);
4088 cairo_pattern_create_radial (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1)
4090 cairo_pattern_t *ret;
4095 ret = DLCALL (cairo_pattern_create_radial,
4098 pattern_id = _create_pattern_id (ret);
4101 if (_write_lock ()) {
4102 _trace_printf ("%g %g %g %g %g %g radial %% p%ld\n",
4103 cx0, cy0, radius0, cx1, cy1, radius1,
4105 _push_operand (PATTERN, ret);
4114 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, double offset, double red, double green, double blue)
4118 _emit_pattern_op (pattern,
4119 "%g %g %g %g 1 add-color-stop\n",
4120 offset, red, green, blue);
4121 DLCALL (cairo_pattern_add_color_stop_rgb, pattern, offset, red, green, blue);
4126 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, double offset, double red, double green, double blue, double alpha)
4130 _emit_pattern_op (pattern,
4131 "%g %g %g %g %g add-color-stop\n",
4132 offset, red, green, blue, alpha);
4133 DLCALL (cairo_pattern_add_color_stop_rgba, pattern, offset, red, green, blue, alpha);
4138 cairo_pattern_set_matrix (cairo_pattern_t *pattern, const cairo_matrix_t *matrix)
4142 if (_matrix_is_identity (matrix)) {
4143 _emit_pattern_op (pattern, "identity set-matrix\n");
4145 _emit_pattern_op (pattern,
4146 "%g %g %g %g %g %g matrix set-matrix\n",
4147 matrix->xx, matrix->yx,
4148 matrix->xy, matrix->yy,
4149 matrix->x0, matrix->y0);
4151 DLCALL (cairo_pattern_set_matrix, pattern, matrix);
4156 _filter_to_string (cairo_filter_t filter)
4158 #define f(name) case CAIRO_FILTER_ ## name: return "FILTER_" #name
4168 return "UNKNOWN_FILTER";
4172 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
4176 _emit_pattern_op (pattern, "//%s set-filter\n", _filter_to_string (filter));
4177 DLCALL (cairo_pattern_set_filter, pattern, filter);
4182 _extend_to_string (cairo_extend_t extend)
4184 #define f(name) case CAIRO_EXTEND_ ## name: return "EXTEND_" #name
4192 return "UNKNOWN_EXTEND";
4196 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
4200 _emit_pattern_op (pattern, "//%s set-extend\n", _extend_to_string (extend));
4201 DLCALL (cairo_pattern_set_extend, pattern, extend);
4205 #if CAIRO_HAS_FT_FONT
4206 #if CAIRO_HAS_FC_FONT
4208 cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4210 cairo_font_face_t *ret;
4215 ret = DLCALL (cairo_ft_font_face_create_for_pattern, pattern);
4216 font_face_id = _create_font_face_id (ret);
4219 if (pattern != NULL && _write_lock ()) {
4223 obj = _get_object (FONT_FACE, ret);
4224 if (obj->operand != -1)
4225 _object_remove (obj);
4227 parsed = DLCALL (FcNameUnparse, pattern);
4228 _trace_printf ("dict\n"
4231 _emit_string_literal ((char *) parsed, -1);
4232 _trace_printf (" set\n"
4235 _push_operand (FONT_FACE, ret);
4244 #endif /* CAIRO_HAS_FC_FONT*/
4246 typedef struct _ft_face_data {
4247 unsigned long index;
4253 _ft_face_data_destroy (void *arg)
4255 FtFaceData *data = arg;
4261 cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags)
4263 cairo_font_face_t *ret;
4270 ret = DLCALL (cairo_ft_font_face_create_for_ft_face, face, load_flags);
4271 font_face_id = _create_font_face_id (ret);
4278 obj = _get_object (NONE, face);
4286 if (_write_lock ()) {
4287 obj = _get_object (FONT_FACE, ret);
4288 if (obj->operand != -1)
4289 _object_remove (obj);
4291 _trace_printf ("<< /type 42 /source ");
4292 _emit_data (data->data, data->size);
4293 _trace_printf (" /index %lu /flags %d >> font %% f%ld\n",
4294 data->index, load_flags, font_face_id);
4295 _push_operand (FONT_FACE, ret);
4304 _ft_read_file (FtFaceData *data, const char *path)
4309 file = fopen (path, "rb");
4312 unsigned long int allocated = sizeof (buf);
4313 data->data = malloc (allocated);
4315 ret = fread (buf, 1, sizeof (buf), file);
4318 memcpy ((char *) data->data + data->size, buf, ret);
4320 if (ret != sizeof (buf))
4323 if (data->size == allocated) {
4325 data->data = realloc (data->data, allocated);
4331 return file != NULL;
4335 FT_New_Face (FT_Library library, const char *pathname, FT_Long index, FT_Face *face)
4341 ret = DLCALL (FT_New_Face, library, pathname, index, face);
4343 Object *obj = _type_object_create (NONE, *face);
4344 FtFaceData *data = malloc (sizeof (FtFaceData));
4345 data->index = index;
4348 _ft_read_file (data, pathname);
4350 obj->destroy = _ft_face_data_destroy;
4358 FT_New_Memory_Face (FT_Library library, const FT_Byte *mem, FT_Long size, FT_Long index, FT_Face *face)
4364 ret = DLCALL (FT_New_Memory_Face, library, mem, size, index, face);
4366 Object *obj = _type_object_create (NONE, *face);
4367 FtFaceData *data = malloc (sizeof (FtFaceData));
4368 data->index = index;
4370 data->data = malloc (size);
4371 memcpy (data->data, mem, size);
4373 obj->destroy = _ft_face_data_destroy;
4381 * FT_New_Memory_Face() and FT_New_Face() appear to wrap FT_Open_Face() so we
4382 * get a redundant call to FT_Open_Face() from those paths (no PLT hiding
4383 * within FT, naughty library!) but we do not intercept a direct call to
4384 * FT_Open_Face(). So far this has not caused any issues, but it will one
4388 FT_Open_Face (FT_Library library, const FT_Open_Args *args, FT_Long index, FT_Face *face)
4394 ret = DLCALL (FT_Open_Face, library, args, index, face);
4396 Object *obj = _get_object (NONE, *face);
4400 data = malloc (sizeof (FtFaceData));
4401 data->index = index;
4402 if (args->flags & FT_OPEN_MEMORY) {
4403 data->size = args->memory_size;
4404 data->data = malloc (args->memory_size);
4405 memcpy (data->data, args->memory_base, args->memory_size);
4406 } else if (args->flags & FT_OPEN_STREAM) {
4407 fprintf (stderr, "FT_Open_Face (stream, %ld) = %p\n",
4410 } else if (args->flags & FT_OPEN_PATHNAME) {
4413 _ft_read_file (data, args->pathname);
4416 obj = _type_object_create (NONE, *face);
4418 obj->destroy = _ft_face_data_destroy;
4427 FT_Done_Face (FT_Face face)
4432 _object_destroy (_get_object (NONE, face));
4434 ret = DLCALL (FT_Done_Face, face);
4441 _surface_object_set_size (cairo_surface_t *surface, int width, int height)
4445 obj = _get_object (SURFACE, surface);
4447 obj->height = height;
4451 _surface_object_set_size_from_surface (cairo_surface_t *surface)
4453 _surface_object_set_size (surface,
4454 DLCALL (cairo_image_surface_get_width, surface),
4455 DLCALL (cairo_image_surface_get_height, surface));
4458 #if CAIRO_HAS_PS_SURFACE
4459 #include<cairo-ps.h>
4462 cairo_ps_surface_create (const char *filename, double width_in_points, double height_in_points)
4464 cairo_surface_t *ret;
4468 ret = DLCALL (cairo_ps_surface_create, filename, width_in_points, height_in_points);
4471 if (_write_lock ()) {
4472 Object *obj = _create_surface (ret);
4474 _trace_printf ("dict\n"
4477 _emit_string_literal (filename, -1);
4478 _trace_printf (" set\n"
4481 " surface %% s%ld\n",
4485 obj->width = width_in_points;
4486 obj->height = height_in_points;
4496 cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points)
4498 cairo_surface_t *ret;
4502 ret = DLCALL (cairo_ps_surface_create_for_stream, write_func, closure, width_in_points, height_in_points);
4505 if (_write_lock ()) {
4506 Object *obj = _create_surface (ret);
4508 _trace_printf ("dict\n"
4512 " surface %% s%ld\n",
4516 obj->width = width_in_points;
4517 obj->height = height_in_points;
4527 cairo_ps_surface_set_size (cairo_surface_t *surface, double width_in_points, double height_in_points)
4531 DLCALL (cairo_ps_surface_set_size, surface, width_in_points, height_in_points);
4537 #if CAIRO_HAS_PDF_SURFACE
4538 #include <cairo-pdf.h>
4541 cairo_pdf_surface_create (const char *filename, double width_in_points, double height_in_points)
4543 cairo_surface_t *ret;
4547 ret = DLCALL (cairo_pdf_surface_create, filename, width_in_points, height_in_points);
4550 if (_write_lock ()) {
4551 Object *obj = _create_surface (ret);
4553 _trace_printf ("dict\n"
4556 _emit_string_literal (filename, -1);
4557 _trace_printf (" set\n"
4560 " surface %% s%ld\n",
4564 obj->width = width_in_points;
4565 obj->height = height_in_points;
4575 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points)
4577 cairo_surface_t *ret;
4581 ret = DLCALL (cairo_pdf_surface_create_for_stream, write_func, closure, width_in_points, height_in_points);
4584 if (_write_lock ()) {
4585 Object *obj = _create_surface (ret);
4587 _trace_printf ("dict\n"
4591 " surface %% s%ld\n",
4595 obj->width = width_in_points;
4596 obj->height = height_in_points;
4605 cairo_pdf_surface_set_size (cairo_surface_t *surface, double width_in_points, double height_in_points)
4609 DLCALL (cairo_pdf_surface_set_size, surface, width_in_points, height_in_points);
4614 #if CAIRO_HAS_SVG_SURFACE
4615 #include <cairo-svg.h>
4618 cairo_svg_surface_create (const char *filename, double width, double height)
4620 cairo_surface_t *ret;
4624 ret = DLCALL (cairo_svg_surface_create, filename, width, height);
4627 if (_write_lock ()) {
4628 Object *obj = _create_surface (ret);
4630 _trace_printf ("dict\n"
4633 _emit_string_literal (filename, -1);
4634 _trace_printf (" set\n"
4637 " surface %% s%ld\n",
4642 obj->height = height;
4652 cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width, double height)
4654 cairo_surface_t *ret;
4658 ret = DLCALL (cairo_svg_surface_create_for_stream, write_func, closure, width, height);
4661 if (_write_lock ()) {
4662 Object *obj = _create_surface (ret);
4664 _trace_printf ("dict\n"
4668 " surface %% s%ld\n",
4673 obj->height = height;
4684 #if CAIRO_HAS_PNG_FUNCTIONS
4686 cairo_image_surface_create_from_png (const char *filename)
4688 cairo_surface_t *ret;
4692 ret = DLCALL (cairo_image_surface_create_from_png, filename);
4695 if (_write_lock ()) {
4696 Object *obj = _create_surface (ret);
4697 char filename_string[4096];
4699 _encode_string_literal (filename_string, sizeof (filename_string),
4701 _emit_image (ret, " /filename %s set\n", filename_string);
4702 _trace_printf (" dup /s%ld exch def\n", obj->token);
4703 _surface_object_set_size_from_surface (ret);
4704 obj->defined = TRUE;
4714 cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, void *closure)
4716 cairo_surface_t *ret;
4720 ret = DLCALL (cairo_image_surface_create_from_png_stream, read_func, closure);
4723 if (_write_lock ()) {
4724 Object *obj = _create_surface (ret);
4726 _emit_image (ret, NULL);
4727 _trace_printf (" dup /s%ld exch def\n",
4730 _surface_object_set_size_from_surface (ret);
4731 obj->defined = TRUE;
4742 _content_from_surface (cairo_surface_t *surface)
4744 return _content_to_string (DLCALL (cairo_surface_get_content, surface));
4747 #if CAIRO_HAS_XLIB_SURFACE
4748 #include <cairo-xlib.h>
4751 cairo_xlib_surface_create (Display *dpy,
4754 int width, int height)
4756 cairo_surface_t *ret;
4760 ret = DLCALL (cairo_xlib_surface_create,
4761 dpy, drawable, visual, width, height);
4764 if (_write_lock ()) {
4765 Object *obj = _create_surface (ret);
4767 _trace_printf ("dict\n"
4768 " /type /xlib set\n"
4769 " /drawable 16!%lx set\n"
4770 " /content //%s set\n"
4773 " surface dup /s%ld exch def\n",
4775 _content_from_surface (ret),
4778 obj->defined = TRUE;
4780 obj->height = height;
4781 obj->foreign = TRUE;
4791 cairo_xlib_surface_create_for_bitmap (Display *dpy,
4794 int width, int height)
4796 cairo_surface_t *ret;
4800 ret = DLCALL (cairo_xlib_surface_create_for_bitmap,
4801 dpy, bitmap, screen, width, height);
4804 if (_write_lock ()) {
4805 Object *obj = _create_surface (ret);
4807 _trace_printf ("dict\n"
4808 " /type /xlib set\n"
4809 " /drawable 16!%lx set\n"
4810 " /content //%s set\n"
4814 " surface dup /s%ld exch def\n",
4816 _content_from_surface (ret),
4819 obj->defined = TRUE;
4821 obj->height = height;
4822 obj->foreign = TRUE;
4831 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
4832 #include <cairo-xlib-xrender.h>
4834 cairo_xlib_surface_create_with_xrender_format (Display *dpy,
4837 XRenderPictFormat *format,
4838 int width, int height)
4840 cairo_surface_t *ret;
4844 ret = DLCALL (cairo_xlib_surface_create_with_xrender_format,
4845 dpy, drawable, screen, format, width, height);
4848 if (_write_lock ()) {
4849 Object *obj = _create_surface (ret);
4851 _trace_printf ("dict\n"
4852 " /type /xrender set\n"
4853 " /drawable 16!%lx set\n"
4854 " /content //%s set\n"
4858 " surface dup /s%ld exch def\n",
4860 _content_from_surface (ret),
4864 obj->defined = TRUE;
4866 obj->height = height;
4867 obj->foreign = TRUE;
4878 #if CAIRO_HAS_SCRIPT_SURFACE
4879 #include <cairo-script.h>
4881 cairo_script_surface_create (cairo_device_t *device,
4882 cairo_content_t content,
4886 cairo_surface_t *ret;
4890 ret = DLCALL (cairo_script_surface_create, device, content, width, height);
4893 if (_write_lock ()) {
4894 Object *obj = _create_surface (ret);
4896 _trace_printf ("dict\n"
4897 " /type /script set\n"
4898 " /content %s set\n"
4901 " surface dup /s%ld exch def\n",
4902 _content_to_string (content),
4906 obj->height = height;
4907 obj->defined = TRUE;
4917 cairo_script_surface_create_for_target (cairo_device_t *device,
4918 cairo_surface_t *target)
4920 cairo_surface_t *ret;
4924 ret = DLCALL (cairo_script_surface_create_for_target, device, target);
4927 if (_write_lock ()) {
4928 Object *obj = _create_surface (ret);
4930 _trace_printf ("dict\n"
4931 " /type /script set\n"
4932 " surface dup /s%ld exch def\n",
4934 obj->defined = TRUE;
4944 #if CAIRO_HAS_TEST_SURFACES
4945 #include <test-paginated-surface.h>
4947 _cairo_test_paginated_surface_create (cairo_surface_t *surface)
4949 cairo_surface_t *ret;
4953 ret = DLCALL (_cairo_test_paginated_surface_create, surface);
4956 if (_write_lock ()) {
4957 Object *obj = _create_surface (ret);
4959 /* XXX store initial data? */
4960 _trace_printf ("dict\n"
4961 " /type /test-paginated set\n"
4962 " /target s%ld set\n"
4963 " surface dup /s%ld exch def\n",
4964 _get_surface_id (surface),
4974 #include <test-compositor-surface.h>
4977 _cairo_test_fallback_compositor_surface_create (cairo_content_t content, int width, int height)
4979 cairo_surface_t *ret;
4983 ret = DLCALL (_cairo_test_fallback_compositor_surface_create, content, width, height);
4986 if (_write_lock ()) {
4987 Object *obj = _create_surface (ret);
4989 _trace_printf ("dict\n"
4990 " /type /test-fallback-compositor set\n"
4991 " /content //%s set\n"
4994 " surface dup /s%ld exch def\n",
4995 _content_to_string (content),
4998 obj->defined = TRUE;
5008 _cairo_test_mask_compositor_surface_create (cairo_content_t content, int width, int height)
5010 cairo_surface_t *ret;
5014 ret = DLCALL (_cairo_test_mask_compositor_surface_create, content, width, height);
5017 if (_write_lock ()) {
5018 Object *obj = _create_surface (ret);
5020 _trace_printf ("dict\n"
5021 " /type /test-mask-compositor set\n"
5022 " /content //%s set\n"
5025 " surface dup /s%ld exch def\n",
5026 _content_to_string (content),
5029 obj->defined = TRUE;
5039 _cairo_test_spans_compositor_surface_create (cairo_content_t content, int width, int height)
5041 cairo_surface_t *ret;
5045 ret = DLCALL (_cairo_test_spans_compositor_surface_create, content, width, height);
5048 if (_write_lock ()) {
5049 Object *obj = _create_surface (ret);
5051 _trace_printf ("dict\n"
5052 " /type /test-spans-compositor set\n"
5053 " /content //%s set\n"
5056 " surface dup /s%ld exch def\n",
5057 _content_to_string (content),
5060 obj->defined = TRUE;
5070 _cairo_test_traps_compositor_surface_create (cairo_content_t content, int width, int height)
5072 cairo_surface_t *ret;
5076 ret = DLCALL (_cairo_test_traps_compositor_surface_create, content, width, height);
5079 if (_write_lock ()) {
5080 Object *obj = _create_surface (ret);
5082 _trace_printf ("dict\n"
5083 " /type /test-traps-compositor set\n"
5084 " /content //%s set\n"
5087 " surface dup /s%ld exch def\n",
5088 _content_to_string (content),
5091 obj->defined = TRUE;
5103 cairo_recording_surface_create (cairo_content_t content,
5104 const cairo_rectangle_t *extents)
5106 cairo_surface_t *ret;
5110 ret = DLCALL (cairo_recording_surface_create, content, extents);
5113 if (_write_lock ()) {
5114 Object *obj = _create_surface (ret);
5117 _trace_printf ("//%s [ %f %f %f %f ] record dup /s%ld exch def\n",
5118 _content_to_string (content),
5119 extents->x, extents->y,
5120 extents->width, extents->height,
5122 obj->width = extents->width;
5123 obj->height = extents->height;
5125 _trace_printf ("//%s [ ] record dup /s%ld exch def\n",
5126 _content_to_string (content),
5129 obj->defined = TRUE;
5138 #if CAIRO_HAS_VG_SURFACE
5139 #include <cairo-vg.h>
5141 cairo_vg_surface_create (cairo_vg_context_t *context,
5142 cairo_content_t content,
5143 int width, int height)
5145 cairo_surface_t *ret;
5149 ret = DLCALL (cairo_vg_surface_create, context, content, width, height);
5152 if (_write_lock ()) {
5153 Object *obj = _create_surface (ret);
5155 _trace_printf ("dict\n"
5157 " /content //%s set\n"
5160 " surface dup /s%ld exch def\n",
5161 _content_to_string (content),
5165 obj->height = height;
5166 obj->defined = TRUE;
5176 cairo_vg_surface_create_for_image (cairo_vg_context_t *context,
5178 VGImageFormat format,
5179 int width, int height)
5181 cairo_surface_t *ret;
5185 ret = DLCALL (cairo_vg_surface_create_for_image,
5186 context, image, format, width, height);
5189 if (_write_lock ()) {
5190 Object *obj = _create_surface (ret);
5191 cairo_content_t content;
5193 content = DLCALL (cairo_surface_get_content, ret);
5194 _trace_printf ("dict\n"
5196 " /content //%s set\n"
5199 " surface dup /s%ld exch def\n",
5200 _content_to_string (content),
5204 obj->height = height;
5205 obj->defined = TRUE;
5215 #if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE
5216 #include <cairo-gl.h>
5218 cairo_gl_surface_create (cairo_device_t *abstract_device,
5219 cairo_content_t content,
5223 cairo_surface_t *ret;
5227 ret = DLCALL (cairo_gl_surface_create, abstract_device, content, width, height);
5230 if (_write_lock ()) {
5231 Object *obj = _create_surface (ret);
5233 _trace_printf ("dict\n"
5235 " /content //%s set\n"
5238 " surface dup /s%ld exch def\n",
5239 _content_to_string (content),
5243 obj->height = height;
5244 obj->defined = TRUE;
5254 cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device,
5255 cairo_content_t content,
5260 cairo_surface_t *ret;
5264 ret = DLCALL (cairo_gl_surface_create_for_texture, abstract_device, content, tex, width, height);
5267 if (_write_lock ()) {
5268 Object *obj = _create_surface (ret);
5270 _trace_printf ("dict\n"
5272 " /content //%s set\n"
5275 " surface dup /s%ld exch def\n",
5276 _content_to_string (content),
5280 obj->height = height;
5281 obj->defined = TRUE;
5290 #if CAIRO_HAS_GLX_FUNCTIONS
5292 cairo_gl_surface_create_for_window (cairo_device_t *device,
5294 int width, int height)
5296 cairo_surface_t *ret;
5300 ret = DLCALL (cairo_gl_surface_create_for_window, device, win, width, height);
5303 if (_write_lock ()) {
5304 Object *obj = _create_surface (ret);
5306 _trace_printf ("dict\n"
5310 " surface dup /s%ld exch def\n",
5314 obj->height = height;
5315 obj->defined = TRUE;
5325 #if CAIRO_HAS_WGL_FUNCTIONS
5327 cairo_gl_surface_create_for_dc (cairo_device_t *device,
5332 cairo_surface_t *ret;
5336 ret = DLCALL (cairo_gl_surface_create_for_dc, device, dc, width, height);
5339 if (_write_lock ()) {
5340 Object *obj = _create_surface (ret);
5342 _trace_printf ("dict\n"
5346 " surface dup /s%ld exch def\n",
5350 obj->height = height;
5351 obj->defined = TRUE;
5361 #if CAIRO_HAS_EGL_FUNCTIONS
5363 cairo_gl_surface_create_for_egl (cairo_device_t *device,
5368 cairo_surface_t *ret;
5372 ret = DLCALL (cairo_gl_surface_create_for_egl, device, egl, width, height);
5375 if (_write_lock ()) {
5376 Object *obj = _create_surface (ret);
5378 _trace_printf ("dict\n"
5382 " surface dup /s%ld exch def\n",
5386 obj->height = height;
5387 obj->defined = TRUE;