[cairo-commit] 21 commits - perf/cairo-perf-graph-files.c perf/cairo-perf-report.c perf/twin.c src/cairo.c src/cairo-cff-subset.c src/cairo-ft-font.c src/cairo-os2-surface.c src/cairo-private.h src/cairo-quartz-font.c src/cairo-scaled-font.c test/pdf2png.c util/cairo-script util/cairo-trace
Chris Wilson
ickle at kemper.freedesktop.org
Fri Jan 2 01:53:59 PST 2009
perf/cairo-perf-graph-files.c | 2
perf/cairo-perf-report.c | 7 -
perf/twin.c | 2
src/cairo-cff-subset.c | 21 +--
src/cairo-ft-font.c | 47 +++----
src/cairo-os2-surface.c | 1
src/cairo-private.h | 2
src/cairo-quartz-font.c | 6
src/cairo-scaled-font.c | 33 +++--
src/cairo.c | 45 ++++++
test/pdf2png.c | 4
util/cairo-script/cairo-script-interpreter.h | 1
util/cairo-script/cairo-script-objects.c | 27 +++-
util/cairo-script/cairo-script-operators.c | 60 ++++-----
util/cairo-script/cairo-script-private.h | 1
util/cairo-script/cairo-script-scanner.c | 2
util/cairo-script/cairo-script-stack.c | 2
util/cairo-script/csi-exec.c | 1
util/cairo-script/csi-replay.c | 175 ++++++++++++++++++++++-----
util/cairo-trace/cairo-trace.in | 29 ----
util/cairo-trace/trace.c | 35 ++++-
21 files changed, 340 insertions(+), 163 deletions(-)
New commits:
commit c601f308430f4d33929109fb9170b9322edca3c6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Jan 1 16:55:08 2009 +0000
[cairo] Early return if we attempt to set the same colour.
Profiling a silly video renderer that called set-source; rectangle; fill;
for each pixel, we can shave 5% off the cairo overhead by introducing an
early return if we attempt to reset the current colour.
diff --git a/src/cairo.c b/src/cairo.c
index 1566864..d16adc1 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -633,6 +633,30 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op)
}
slim_hidden_def (cairo_set_operator);
+
+static cairo_bool_t
+_current_source_matches_solid (cairo_t *cr,
+ double red,
+ double green,
+ double blue,
+ double alpha)
+{
+ const cairo_pattern_t *current;
+ cairo_color_t color;
+
+ current = cr->gstate->source;
+ if (current->type != CAIRO_PATTERN_TYPE_SOLID)
+ return FALSE;
+
+ _cairo_restrict_value (&red, 0.0, 1.0);
+ _cairo_restrict_value (&green, 0.0, 1.0);
+ _cairo_restrict_value (&blue, 0.0, 1.0);
+ _cairo_restrict_value (&alpha, 0.0, 1.0);
+
+ _cairo_color_init_rgba (&color, red, green, blue, alpha);
+ return _cairo_color_equal (&color,
+ &((cairo_solid_pattern_t *) current)->color);
+}
/**
* cairo_set_source_rgb
* @cr: a cairo context
@@ -659,6 +683,9 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
if (cr->status)
return;
+ if (_current_source_matches_solid (cr, red, green, blue, 1.))
+ return;
+
/* push the current pattern to the freed lists */
cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
@@ -696,6 +723,9 @@ cairo_set_source_rgba (cairo_t *cr,
if (cr->status)
return;
+ if (_current_source_matches_solid (cr, red, green, blue, alpha))
+ return;
+
/* push the current pattern to the freed lists */
cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
commit fb3522f33a565576002595bf03e07f6c8b16a471
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 19:19:54 2008 +0000
[os2] Fix memory leak of surface on error path
Of we fail to create the mutex, free the surface before returning the
failure.
Reported: http://bugs.freedesktop.org/show_bug.cgi?id=19208.
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 1f7b35e..62b4ccd 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -788,6 +788,7 @@ cairo_os2_surface_create (HPS hps_client_window,
FALSE);
if (rc != NO_ERROR) {
/* Could not create mutex semaphore! */
+ free (local_os2_surface);
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
commit 8d23c3a6c2ab0ae168afb695e2b8c5f121ed2be3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 19:17:28 2008 +0000
[quartz] Delay allocation of string until after guard.
Fixes a memory leak should we bail due to the version of Quartz being
insufficient.
Reported: http://bugs.freedesktop.org/show_bug.cgi?id=19209.
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 63f050c..a800cb4 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -135,8 +135,8 @@ static cairo_status_t
_cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face)
{
- const char *family = toy_face->family;
- char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
+ const char *family;
+ char *full_name;
CFStringRef cgFontName = NULL;
CGFontRef cgFont = NULL;
int loop;
@@ -145,6 +145,8 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
if (! _cairo_quartz_font_symbols_present)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ family = toy_face->family;
+ full_name = malloc (strlen (family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
/* handle CSS-ish faces */
if (!strcmp(family, "serif") || !strcmp(family, "Times Roman"))
family = "Times";
commit 9c9ed8f0b5ce8bc3036dcb0bf841ffaa24797cfa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 13:04:31 2008 +0000
[scaled-font] Post-process hash value.
Mix the bits within the hash value to reduce clustering.
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 0c519ed..013d680 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -530,6 +530,17 @@ _hash_matrix_fnv (const cairo_matrix_t *matrix,
return hval;
}
+static uint32_t
+_hash_mix_bits (uint32_t hash)
+{
+ hash += hash << 12;
+ hash ^= hash >> 7;
+ hash += hash << 3;
+ hash ^= hash >> 17;
+ hash += hash << 5;
+ return hash;
+}
+
static void
_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
cairo_font_face_t *font_face,
@@ -552,10 +563,14 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
/* We do a bytewise hash on the font matrices */
hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash);
hash = _hash_matrix_fnv (&scaled_font->ctm, hash);
+ hash = _hash_mix_bits (hash);
hash ^= (unsigned long) scaled_font->font_face;
hash ^= cairo_font_options_hash (&scaled_font->options);
+ /* final mixing of bits */
+ hash = _hash_mix_bits (hash);
+
assert (hash != ZOMBIE);
scaled_font->hash_entry.hash = hash;
}
commit 555dd6b97ec432787d83242727164d25b459cf54
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 13:02:00 2008 +0000
[scaled-font] Switch to a constant loop for hashing.
As we only use the FNV hash for hashing matrices, expose the constant size
to the compiler so that it can perform its magic.
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 5ef484b..0c519ed 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -517,14 +517,15 @@ _cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t
#define FNV1_32_INIT ((uint32_t)0x811c9dc5)
static uint32_t
-_hash_bytes_fnv (unsigned char *buffer,
- int len,
- uint32_t hval)
+_hash_matrix_fnv (const cairo_matrix_t *matrix,
+ uint32_t hval)
{
- while (len--) {
+ const uint8_t *buffer = (const uint8_t *) matrix;
+ int len = sizeof (cairo_matrix_t);
+ do {
hval *= FNV_32_PRIME;
hval ^= *buffer++;
- }
+ } while (--len);
return hval;
}
@@ -549,13 +550,10 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
_cairo_font_options_init_copy (&scaled_font->options, options);
/* We do a bytewise hash on the font matrices */
- hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx),
- sizeof(cairo_matrix_t), hash);
- hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx),
- sizeof(cairo_matrix_t), hash);
+ hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash);
+ hash = _hash_matrix_fnv (&scaled_font->ctm, hash);
hash ^= (unsigned long) scaled_font->font_face;
-
hash ^= cairo_font_options_hash (&scaled_font->options);
assert (hash != ZOMBIE);
commit f5274f5847519208865159fa9bb254d76ba8ddac
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 16:31:28 2008 +0000
Iterate over hash table using foreach() in destructors.
Don't use the remarkably inefficient _cairo_hash_table_random_entry() to
remove all entries from the hash table!
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 75e1ab5..2baf414 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -666,18 +666,19 @@ cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
}
static void
-cff_dict_fini (cairo_hash_table_t *dict)
+_cff_dict_entry_pluck (void *_entry, void *dict)
{
- cff_dict_operator_t *entry;
+ cff_dict_operator_t *entry = _entry;
- while (1) {
- entry = _cairo_hash_table_random_entry (dict, NULL);
- if (entry == NULL)
- break;
- free (entry->operand);
- _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) entry);
- free (entry);
- }
+ _cairo_hash_table_remove (dict, &entry->base);
+ free (entry->operand);
+ free (entry);
+}
+
+static void
+cff_dict_fini (cairo_hash_table_t *dict)
+{
+ _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
_cairo_hash_table_destroy (dict);
}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 6b8e57a..17699de 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -222,34 +222,35 @@ FAIL:
cairo_ft_unscaled_font_map = NULL;
}
+
+static void
+_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
+{
+ cairo_ft_unscaled_font_t *unscaled = entry;
+ cairo_ft_unscaled_font_map_t *font_map = closure;
+
+ _cairo_hash_table_remove (font_map->hash_table,
+ &unscaled->base.hash_entry);
+
+ _font_map_release_face_lock_held (font_map, unscaled);
+ _cairo_ft_unscaled_font_fini (unscaled);
+ free (unscaled);
+}
+
static void
_cairo_ft_unscaled_font_map_destroy (void)
{
- cairo_ft_unscaled_font_t *unscaled;
cairo_ft_unscaled_font_map_t *font_map;
CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
+ font_map = cairo_ft_unscaled_font_map;
+ cairo_ft_unscaled_font_map = NULL;
+ CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
- if (cairo_ft_unscaled_font_map) {
- font_map = cairo_ft_unscaled_font_map;
-
- /* This is rather inefficient, but destroying the hash table
- * is something we only do during debugging, (during
- * cairo_debug_reset_static_data), when efficiency is not
- * relevant. */
- while (1) {
- unscaled = _cairo_hash_table_random_entry (font_map->hash_table,
- NULL);
- if (unscaled == NULL)
- break;
- _cairo_hash_table_remove (font_map->hash_table,
- &unscaled->base.hash_entry);
-
- _font_map_release_face_lock_held (font_map, unscaled);
- _cairo_ft_unscaled_font_fini (unscaled);
- free (unscaled);
- }
-
+ if (font_map != NULL) {
+ _cairo_hash_table_foreach (font_map->hash_table,
+ _cairo_ft_unscaled_font_map_pluck_entry,
+ font_map);
assert (font_map->num_open_faces == 0);
FT_Done_FreeType (font_map->ft_library);
@@ -257,11 +258,7 @@ _cairo_ft_unscaled_font_map_destroy (void)
_cairo_hash_table_destroy (font_map->hash_table);
free (font_map);
-
- cairo_ft_unscaled_font_map = NULL;
}
-
- CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
}
static cairo_ft_unscaled_font_map_t *
commit 1c4ea84b24f3f7e480f9c50b5bd77ac703c36ef0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 20:32:44 2008 +0000
[cairo] Early return if we attempt to set the same scaled_font
If the application calls cairo_set_scaled_font() with the current
scaled font, we can return early as it is a no-op.
diff --git a/src/cairo.c b/src/cairo.c
index b6d0373..1566864 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2880,6 +2880,9 @@ cairo_set_scaled_font (cairo_t *cr,
if (unlikely (status))
goto BAIL;
+ if (scaled_font == cr->gstate->scaled_font)
+ return;
+
status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
if (unlikely (status))
goto BAIL;
commit b661f3d27ba77cdf470a86f6320b1bb31d92a9f0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 18:34:16 2008 +0000
[cairo] Embed a second gstate.
Experiment with embedding a second gstate into the initial context to
reduce allocations.
diff --git a/src/cairo-private.h b/src/cairo-private.h
index 43bd223..a60a6aa 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -48,7 +48,7 @@ struct _cairo {
cairo_user_data_array_t user_data;
cairo_gstate_t *gstate;
- cairo_gstate_t gstate_tail[1];
+ cairo_gstate_t gstate_tail[2];
cairo_gstate_t *gstate_freelist;
cairo_path_fixed_t path[1];
diff --git a/src/cairo.c b/src/cairo.c
index a9a5082..b6d0373 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,9 +49,7 @@ static const cairo_t _cairo_nil = {
CAIRO_STATUS_NO_MEMORY, /* status */
{ 0, 0, 0, NULL }, /* user_data */
NULL, /* gstate */
- {{ /* gstate_tail */
- 0
- }},
+ {{ 0 }, { 0 }}, /* gstate_tail */
NULL, /* gstate_freelist */
{{ /* path */
{ 0, 0 }, /* last_move_point */
@@ -164,8 +162,9 @@ cairo_create (cairo_surface_t *target)
_cairo_user_data_array_init (&cr->user_data);
_cairo_path_fixed_init (cr->path);
- cr->gstate = cr->gstate_tail;
- cr->gstate_freelist = NULL;
+ cr->gstate = &cr->gstate_tail[0];
+ cr->gstate_freelist = &cr->gstate_tail[1];
+ cr->gstate_tail[1].next = NULL;
status = _cairo_gstate_init (cr->gstate, target);
if (unlikely (status))
@@ -222,7 +221,7 @@ cairo_destroy (cairo_t *cr)
if (! _cairo_reference_count_dec_and_test (&cr->ref_count))
return;
- while (cr->gstate != cr->gstate_tail) {
+ while (cr->gstate != &cr->gstate_tail[0]) {
if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
break;
}
@@ -237,6 +236,7 @@ cairo_destroy (cairo_t *cr)
cairo_surface_flush (surface);
_cairo_gstate_fini (cr->gstate);
+ cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
while (cr->gstate_freelist != NULL) {
cairo_gstate_t *gstate = cr->gstate_freelist;
cr->gstate_freelist = gstate->next;
commit 8abd21bd3afc143501f66fdcdc0c6c4139df490b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Dec 23 15:09:15 2008 +0000
[script] Call the context creation hook
Hook in the creation hook so applications can record or even modify the
contexts used in replay.
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 6b328a9..d2bdb4c 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -956,6 +956,7 @@ _context (csi_t *ctx)
csi_status_t status;
cairo_surface_t *surface;
cairo_t *cr;
+ csi_context_create_func_t hook;
csi_proxy_t *proxy;
check (1);
@@ -964,7 +965,11 @@ _context (csi_t *ctx)
if (_csi_unlikely (status))
return status;
- cr = cairo_create (surface);
+ hook = ctx->hooks.context_create;
+ if (hook != NULL)
+ cr = hook (ctx->hooks.closure, surface);
+ else
+ cr = cairo_create (surface);
proxy = _csi_proxy_create (ctx, cr, NULL,
ctx->hooks.context_destroy,
commit 2c9323d3942cbf93b100f711000f48a3eb869271
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 14:11:37 2008 +0000
[script] more targets
diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index 0a71606..cfae74c 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -41,9 +41,9 @@ _destroy_window (void *closure)
}
static cairo_surface_t *
-_surface_create (void *closure,
- cairo_content_t content,
- double width, double height)
+_xrender_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
{
Display *dpy;
XRenderPictFormat *xrender_format;
@@ -105,29 +105,104 @@ _surface_create (void *closure,
return surface;
}
-#else
-/* fallback: just use an image surface */
+#endif
+
+#if CAIRO_HAS_PDF_SURFACE
+#include <cairo-pdf.h>
static cairo_surface_t *
-_surface_create (void *closure,
- cairo_content_t content,
- double width, double height)
+_pdf_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
{
- return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ return cairo_pdf_surface_create_for_stream (NULL, NULL, width, height);
+}
+#endif
+
+#if CAIRO_HAS_PS_SURFACE
+#include <cairo-ps.h>
+static cairo_surface_t *
+_ps_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
+{
+ return cairo_ps_surface_create_for_stream (NULL, NULL, width, height);
}
#endif
+#if CAIRO_HAS_SVG_SURFACE
+#include <cairo-svg.h>
+static cairo_surface_t *
+_svg_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
+{
+ return cairo_svg_surface_create_for_stream (NULL, NULL, width, height);
+}
+#endif
+
+static cairo_surface_t *
+_image_surface_create (void *closure,
+ cairo_content_t content,
+ double width, double height)
+{
+ return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+}
+
int
main (int argc, char **argv)
{
cairo_script_interpreter_t *csi;
- const cairo_script_interpreter_hooks_t hooks = {
- .surface_create = _surface_create
+ cairo_script_interpreter_hooks_t hooks = {
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+ .surface_create = _xrender_surface_create
+#elif CAIRO_PDF_SURFACE
+ .surface_create = _pdf_surface_create
+#elif CAIRO_PS_SURFACE
+ .surface_create = _ps_surface_create
+#elif CAIRO_SVG_SURFACE
+ .surface_create = _svg_surface_create
+#else
+ .surface_create = _image_surface_create
+#endif
};
int i;
+ const struct backends {
+ const char *name;
+ csi_surface_create_func_t create;
+ } backends[] = {
+ { "--image", _image_surface_create },
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+ { "--xrender", _xrender_surface_create },
+#endif
+#if CAIRO_HAS_PDF_SURFACE
+ { "--pdf", _pdf_surface_create },
+#endif
+#if CAIRO_HAS_PS_SURFACE
+ { "--ps", _ps_surface_create },
+#endif
+#if CAIRO_HAS_SVG_SURFACE
+ { "--svg", _svg_surface_create },
+#endif
+ { NULL, NULL }
+ };
csi = cairo_script_interpreter_create ();
cairo_script_interpreter_install_hooks (csi, &hooks);
- for (i = 1; i < argc; i++)
- cairo_script_interpreter_run (csi, argv[i]);
+
+ for (i = 1; i < argc; i++) {
+ const struct backends *b;
+
+ for (b = backends; b->name != NULL; b++) {
+ if (strcmp (b->name, argv[i]) == 0) {
+ hooks.surface_create = b->create;
+ cairo_script_interpreter_install_hooks (csi, &hooks);
+ break;
+ }
+ }
+
+ if (b->name == NULL)
+ cairo_script_interpreter_run (csi, argv[i]);
+ }
+
return cairo_script_interpreter_destroy (csi);
}
commit fd96cea4fefeeee8bcccde663faa559151e2606e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 12:54:53 2008 +0000
[script] Improve array construction.
Limit the memory allocation to the initial array size and perform a direct
copy from the operand stack to the array.
diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c
index df4fe8d..552241f 100644
--- a/util/cairo-script/cairo-script-objects.c
+++ b/util/cairo-script/cairo-script-objects.c
@@ -38,26 +38,30 @@
csi_status_t
csi_array_new (csi_t *ctx,
+ csi_integer_t initial_size,
csi_object_t *obj)
{
csi_array_t *array;
- if (ctx->free_array != NULL) {
- array = ctx->free_array;
- ctx->free_array = NULL;
- } else {
+ if (ctx->free_array == NULL ||
+ ctx->free_array->stack.size <= initial_size)
+ {
csi_status_t status;
array = _csi_slab_alloc (ctx, sizeof (csi_array_t));
if (_csi_unlikely (array == NULL))
return _csi_error (CSI_STATUS_NO_MEMORY);
- status = _csi_stack_init (ctx, &array->stack, 32);
+ status = _csi_stack_init (ctx, &array->stack,
+ initial_size ? initial_size : 32);
if (_csi_unlikely (status)) {
_csi_slab_free (ctx, array, sizeof (csi_array_t));
return status;
}
+ } else {
+ array = ctx->free_array;
+ ctx->free_array = NULL;
}
array->base.type = CSI_OBJECT_TYPE_ARRAY;
@@ -153,16 +157,25 @@ void
csi_array_free (csi_t *ctx, csi_array_t *array)
{
if (ctx->free_array != NULL) {
+ if (array->stack.size > ctx->free_array->stack.size) {
+ csi_array_t *tmp = ctx->free_array;
+ ctx->free_array = array;
+ array = tmp;
+ }
+
_csi_stack_fini (ctx, &array->stack);
_csi_slab_free (ctx, array, sizeof (csi_array_t));
} else {
csi_integer_t n;
- ctx->free_array = array;
-
for (n = 0; n < array->stack.len; n++)
csi_object_free (ctx, &array->stack.objects[n]);
array->stack.len = 0;
+
+ if (ctx->free_array == NULL)
+ ctx->free_array = array;
+ else
+ csi_array_free (ctx, array);
}
}
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 41c58d6..6b328a9 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -567,44 +567,35 @@ static csi_status_t
end_array_construction (csi_t *ctx)
{
csi_object_t obj;
- csi_array_t *array;
csi_status_t status;
+ int len = 0;
- status = csi_array_new (ctx, &obj);
- if (_csi_unlikely (status))
- return status;
-
- array = obj.datum.array;
do {
- csi_object_t *value;
+ check (len + 1);
- check (1);
-
- value = _csi_peek_ostack (ctx, 0);
- if (csi_object_get_type (value) == CSI_OBJECT_TYPE_MARK) {
- pop (1);
+ if (csi_object_get_type (_csi_peek_ostack (ctx, len)) ==
+ CSI_OBJECT_TYPE_MARK)
+ {
break;
}
- status = csi_array_append (ctx, array, value);
- if (_csi_unlikely (status))
- return status;
-
- pop (1);
+ len++;
} while (TRUE);
- /* and reverse */
- if (array->stack.len) {
- unsigned int i, j;
+ status = csi_array_new (ctx, len, &obj);
+ if (_csi_unlikely (status))
+ return status;
- for (i = 0, j = array->stack.len; i < --j; i++) {
- csi_object_t tmp;
+ if (len != 0) {
+ csi_array_t *array;
- tmp = array->stack.objects[i];
- array->stack.objects[i] = array->stack.objects[j];
- array->stack.objects[j] = tmp;
- }
+ array = obj.datum.array;
+ memcpy (array->stack.objects,
+ _csi_peek_ostack (ctx, len - 1),
+ sizeof (csi_object_t) * len);
+ array->stack.len = len;
}
+ ctx->ostack.len -= len + 1;
return push (&obj);
}
@@ -824,7 +815,7 @@ _array (csi_t *ctx)
csi_object_t obj;
csi_status_t status;
- status = csi_array_new (ctx, &obj);
+ status = csi_array_new (ctx, 0, &obj);
if (_csi_unlikely (status))
return status;
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index d21be15..f74cb49 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -618,6 +618,7 @@ _csi_error (csi_status_t status);
csi_private csi_status_t
csi_array_new (csi_t *ctx,
+ csi_integer_t initial_size,
csi_object_t *obj);
csi_private csi_status_t
diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c
index 3f8a271..c08e447 100644
--- a/util/cairo-script/cairo-script-scanner.c
+++ b/util/cairo-script/cairo-script-scanner.c
@@ -350,7 +350,7 @@ token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
&scan->procedure_stack,
&scan->build_procedure);
- scan->status = csi_array_new (ctx, &scan->build_procedure);
+ scan->status = csi_array_new (ctx, 0, &scan->build_procedure);
scan->build_procedure.type |= CSI_OBJECT_ATTR_EXECUTABLE;
reset (scan);
return;
diff --git a/util/cairo-script/cairo-script-stack.c b/util/cairo-script/cairo-script-stack.c
index 4f5df46..d6c123b 100644
--- a/util/cairo-script/cairo-script-stack.c
+++ b/util/cairo-script/cairo-script-stack.c
@@ -44,7 +44,7 @@ _csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size)
stack->len = 0;
stack->size = size;
/* assert ((unsigned) size < INT32_MAX / sizeof (csi_object_t)); */
- stack->objects = _csi_alloc (ctx, stack->size * sizeof (csi_object_t));
+ stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t));
if (_csi_unlikely (stack->objects == NULL))
status = _csi_error (CSI_STATUS_NO_MEMORY);
commit ecb8dce27c769158fe4a92432a90b24a96f8afa9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 18:32:44 2008 +0000
[script] Recreate surface content.
Use the content recorded in the trace, defaulting to COLOR_ALPHA, to
determine the replayed surface type.
diff --git a/util/cairo-script/cairo-script-interpreter.h b/util/cairo-script/cairo-script-interpreter.h
index d619388..e6d5730 100644
--- a/util/cairo-script/cairo-script-interpreter.h
+++ b/util/cairo-script/cairo-script-interpreter.h
@@ -48,6 +48,7 @@ typedef void
void *ptr);
typedef cairo_surface_t *
(*csi_surface_create_func_t) (void *closure,
+ cairo_content_t content,
double width,
double height);
typedef cairo_t *
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 935ca7f..41c58d6 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -5149,6 +5149,7 @@ _surface (csi_t *ctx)
csi_object_t key;
double width, height;
csi_surface_create_func_t hook;
+ long content;
cairo_surface_t *surface;
csi_status_t status;
@@ -5165,10 +5166,15 @@ _surface (csi_t *ctx)
if (_csi_unlikely (status))
return status;
+ content = CAIRO_CONTENT_COLOR_ALPHA;
+ status = _csi_dictionary_get_integer (ctx, dict, "content", TRUE, &content);
+ if (_csi_unlikely (status))
+ return status;
+
hook = ctx->hooks.surface_create;
assert (hook != NULL);
- surface = hook (ctx->hooks.closure, width, height);
+ surface = hook (ctx->hooks.closure, content, width, height);
if (_csi_unlikely (surface == NULL)) {
return _csi_error (CSI_STATUS_NULL_POINTER);
}
diff --git a/util/cairo-script/csi-exec.c b/util/cairo-script/csi-exec.c
index 0b64ea4..d8589e6 100644
--- a/util/cairo-script/csi-exec.c
+++ b/util/cairo-script/csi-exec.c
@@ -6,6 +6,7 @@
static cairo_surface_t *
_surface_create (void *closure,
+ cairo_content_t content,
double width, double height)
{
return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index ea2b0d4..0a71606 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -28,6 +28,12 @@ _get_display (void)
}
static void
+_destroy_pixmap (void *closure)
+{
+ XFreePixmap (_get_display(), (Pixmap) closure);
+}
+
+static void
_destroy_window (void *closure)
{
XFlush (_get_display ());
@@ -36,44 +42,74 @@ _destroy_window (void *closure)
static cairo_surface_t *
_surface_create (void *closure,
+ cairo_content_t content,
double width, double height)
{
Display *dpy;
- Visual *visual;
XRenderPictFormat *xrender_format;
- XSetWindowAttributes attr;
- Window w;
cairo_surface_t *surface;
dpy = _get_display ();
- visual = DefaultVisual (dpy, DefaultScreen (dpy));
- xrender_format = XRenderFindVisualFormat (dpy, visual);
- if (xrender_format == NULL) {
- fprintf (stderr, "X server does not have the Render extension.\n");
- exit (1);
+ content = CAIRO_CONTENT_COLOR_ALPHA;
+ if (1) {
+ Pixmap pixmap;
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+ break;
+ case CAIRO_CONTENT_COLOR:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
+ break;
+ case CAIRO_CONTENT_ALPHA:
+ default:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardA8);
+ }
+
+ pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+ width, height, xrender_format->depth);
+
+ surface = cairo_xlib_surface_create_with_xrender_format (dpy, pixmap,
+ DefaultScreenOfDisplay (dpy),
+ xrender_format,
+ width, height);
+ cairo_surface_set_user_data (surface, &_key,
+ (void *) pixmap, _destroy_pixmap);
+ } else {
+ XSetWindowAttributes attr;
+ Visual *visual;
+ Window w;
+
+ visual = DefaultVisual (dpy, DefaultScreen (dpy));
+ xrender_format = XRenderFindVisualFormat (dpy, visual);
+ if (xrender_format == NULL) {
+ fprintf (stderr, "X server does not have the Render extension.\n");
+ exit (1);
+ }
+
+ attr.override_redirect = True;
+ w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
+ width <= 0 ? 1 : width,
+ height <= 0 ? 1 : height,
+ 0, xrender_format->depth,
+ InputOutput, visual, CWOverrideRedirect, &attr);
+ XMapWindow (dpy, w);
+
+ surface = cairo_xlib_surface_create_with_xrender_format (dpy, w,
+ DefaultScreenOfDisplay (dpy),
+ xrender_format,
+ width, height);
+ cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window);
}
- attr.override_redirect = True;
- w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
- width <= 0 ? 1 : width,
- height <= 0 ? 1 : height,
- 0, xrender_format->depth,
- InputOutput, visual, CWOverrideRedirect, &attr);
- XMapWindow (dpy, w);
-
- surface = cairo_xlib_surface_create_with_xrender_format (dpy, w,
- DefaultScreenOfDisplay (dpy),
- xrender_format,
- width, height);
- cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window);
-
return surface;
}
#else
/* fallback: just use an image surface */
static cairo_surface_t *
_surface_create (void *closure,
+ cairo_content_t content,
double width, double height)
{
return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 87797fa..5bf91f0 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -2589,7 +2589,7 @@ _emit_glyphs (cairo_scaled_font_t *font,
struct _data_stream stream;
if (num_glyphs == 1) {
- fprintf (logfile, "[%g %g <%lx>]", x, y, glyphs->index);
+ fprintf (logfile, "[%g %g <%02lx>]", x, y, glyphs->index);
} else {
fprintf (logfile, "[%g %g <~", x, y);
_write_base85_data_start (&stream);
@@ -3724,10 +3724,12 @@ cairo_xlib_surface_create (Display *dpy,
"dict\n"
" /type /xlib set\n"
" /drawable 16!%lx set\n"
+ " /content //%s set\n"
" /width %d set\n"
" /height %d set\n"
" surface dup /s%ld exch def\n",
drawable,
+ _content_to_string (cairo_surface_get_content (ret)),
width,
height,
surface_id);
@@ -3761,11 +3763,13 @@ cairo_xlib_surface_create_for_bitmap (Display *dpy,
"dict\n"
" /type /xlib set\n"
" /drawable 16!%lx set\n"
+ " /content //%s set\n"
" /width %d set\n"
" /height %d set\n"
" /depth 1 set\n"
" surface dup /s%ld exch def\n",
bitmap,
+ _content_to_string (cairo_surface_get_content (ret)),
width,
height,
surface_id);
@@ -3802,11 +3806,13 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
"dict\n"
" /type /xrender set\n"
" /drawable 16!%lx set\n"
+ " /content //%s set\n"
" /width %d set\n"
" /height %d set\n"
" /depth %d set\n"
" surface dup /s%ld exch def\n",
drawable,
+ _content_to_string (cairo_surface_get_content (ret)),
width,
height,
format->depth,
commit d21529b9ef31228182d2f61bb4f7beb6319b10c4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 15:38:13 2008 +0000
[trace] Correct escaped characters in string literal.
Laziness caused the control character to be used instead of its
replacement in the escaped string!
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index b9d1a77..87797fa 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -1391,13 +1391,24 @@ _emit_string_literal (const char *utf8, int len)
while (utf8 < end) {
switch ((c = *utf8++)) {
case '\n':
+ c = 'n';
+ goto ESCAPED_CHAR;
case '\r':
- case '\\':
+ c = 'r';
+ goto ESCAPED_CHAR;
case '\t':
+ c = 't';
+ goto ESCAPED_CHAR;
case '\b':
+ c = 'b';
+ goto ESCAPED_CHAR;
case '\f':
+ c = 'f';
+ goto ESCAPED_CHAR;
+ case '\\':
case '(':
case ')':
+ESCAPED_CHAR:
fprintf (logfile, "\\%c", c);
break;
default:
commit ca39c4bf7f90646b70b2bbe9e7318fcfae99e35e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 15:35:40 2008 +0000
[trace] Correct a couple of typos.
A couple of minor typos in the escaped characters strings.
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 9613045..b9d1a77 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -1326,7 +1326,7 @@ _encode_string_literal (char *out, int max,
break;
case '\r':
*out++ = '\\';
- *out++ = 'n';
+ *out++ = 'r';
max -= 2;
case '\t':
*out++ = '\\';
@@ -1340,7 +1340,7 @@ _encode_string_literal (char *out, int max,
break;
case '\f':
*out++ = '\\';
- *out++ = 'r';
+ *out++ = 'f';
max -= 2;
break;
case '\\':
commit 1f2fec7388092c8fea87651f9094ca2e0be2104b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Dec 19 18:04:03 2008 +0000
[trace] Fix OBO in emit_glyphs()
The largest index that will fit within 8 bits is 255 not 256!
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 6df507a..9613045 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -2539,7 +2539,7 @@ _emit_glyphs (cairo_scaled_font_t *font,
}
for (n = 0; n < num_glyphs; n++) {
- if (glyphs[n].index > 256)
+ if (glyphs[n].index > 255)
break;
}
commit 7ebe9e68371e4e77139d9abeb7feb390203b1c8e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 21:59:16 2008 +0000
[trace] Minor tidy.
Improve scoping of variables.
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 30656a1..6df507a 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -2614,13 +2614,13 @@ _emit_glyphs (cairo_scaled_font_t *font,
void
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
{
- cairo_scaled_font_t *font;
-
- font = DLCALL (cairo_get_scaled_font, cr);
-
_emit_line_info ();
if (cr != NULL && glyphs != NULL && _write_lock ()) {
+ cairo_scaled_font_t *font;
+
_emit_context (cr);
+ font = DLCALL (cairo_get_scaled_font, cr);
+
_emit_glyphs (font, glyphs, num_glyphs);
fprintf (logfile, " show-glyphs\n");
_write_unlock ();
commit 931556005a1946c5e730afc7977551a2bc5be42c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 21:57:19 2008 +0000
[trace] Remove the forced switching to C locale
This interferes with the application being traced. It is not clear from
printf(3) whether "%.f" is locale dependent or not - but until we have a
failure do not break applications unnecessarily!
diff --git a/util/cairo-trace/cairo-trace.in b/util/cairo-trace/cairo-trace.in
index b265b43..40c9d19 100644
--- a/util/cairo-trace/cairo-trace.in
+++ b/util/cairo-trace/cairo-trace.in
@@ -64,10 +64,6 @@ fi
LD_PRELOAD=@libdir@/cairo/cairo-trace.so
export LD_PRELOAD
-# Force the decimal output to the 'C' locale
-LC_ALL=C
-export LC_ALL
-
if test -n "$nocallers"; then
CAIRO_TRACE_LINE_INFO=0
export CAIRO_TRACE_LINE_INFO
commit d0f41b92bf9a9ee313dde6f451b26fffb65a0906
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 17:26:43 2008 +0000
[trace] Do not force the output filename.
Handle the case of tracing an application that spawns it own graphical
children but using the autonaming facility within cairo-trace. Currently
the traced process tree would all attempt to write to the same file,
creating a broken trace. This means sacrificing the display of the output
name, but allows use for a wider range of applications.
diff --git a/util/cairo-trace/cairo-trace.in b/util/cairo-trace/cairo-trace.in
index a9ff14e..b265b43 100644
--- a/util/cairo-trace/cairo-trace.in
+++ b/util/cairo-trace/cairo-trace.in
@@ -4,20 +4,19 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
nofile=
-verbose=
flush=
nocallers=
usage() {
cat << EOF
-usage: cairo-trace [--no-file|--verbose] command
+usage: cairo-trace [--no-file] command
cairo-trace will generate a log of all calls made by command to
cairo. This log will be stored in a file in the local directory
called command.pid.trace.
Whatever else happens is driven by its argument:
--flush - Flush the output trace after every call.
- --verbose - Show the trace on stdout.
- --no-file - Disable the creation of an output file.
+ --no-file - Disable the creation of an output file. Outputs to the
+ terminal instead.
--no-callers - Do not lookup the caller address/symbol/line whilst tracing.
Enviroment variables understood by cairo-trace:
@@ -31,10 +30,6 @@ skip=1
while test $skip -eq 1; do
skip=0
case $1 in
- --verbose)
- skip=1
- verbose=1
- ;;
--flush)
skip=1
flush=1
@@ -66,11 +61,6 @@ fi
#echo $*
-filename=""
-if test -z "$nofile"; then
- filename=`basename -- $1`.$$.trace
-fi
-
LD_PRELOAD=@libdir@/cairo/cairo-trace.so
export LD_PRELOAD
@@ -88,11 +78,8 @@ if test -n "$flush"; then
export CAIRO_TRACE_FLUSH
fi
-if test -z "$filename"; then
- CAIRO_TRACE_FD=3 "$@" 3>&1 >/dev/null
-elif test -z "$verbose"; then
- echo "Recording trace in $filename."
- CAIRO_TRACE_OUTFILE_EXACT=$filename "$@"
+if test -z "$nofile"; then
+ CAIRO_TRACE_OUTDIR=. "$@"
else
- CAIRO_TRACE_FD=3 "$@" 3>&1 >/dev/null | tee $filename
+ CAIRO_TRACE_FD=3 "$@" 3>&1 >/dev/null
fi
commit 19e8c5c7f4a561f2454380c8f4098a832d716d28
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 19:27:33 2008 +0000
[test] Fix mismatched free.
A couple of strings allocated using glib functions but freed with system
malloc.
Reported: http://bugs.freedesktop.org/show_bug.cgi?id=19210.
diff --git a/test/pdf2png.c b/test/pdf2png.c
index 8471a18..fc4390b 100644
--- a/test/pdf2png.c
+++ b/test/pdf2png.c
@@ -56,11 +56,11 @@ int main (int argc, char *argv[])
} else {
gchar *dir = g_get_current_dir ();
absolute = g_build_filename (dir, filename, (gchar *) 0);
- free (dir);
+ g_free (dir);
}
uri = g_filename_to_uri (absolute, NULL, &error);
- free (absolute);
+ g_free (absolute);
if (uri == NULL)
FAIL (error->message);
commit 6662eede2af2da50bff1902e694204c69e84f036
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 19:14:23 2008 +0000
[perf] Fix errors reported by cppcheck
Trivial mistakes, identified in bugs
http://bugs.freedesktop.org/show_bug.cgi?id=19206 and
http://bugs.freedesktop.org/show_bug.cgi?id=19207.
diff --git a/perf/cairo-perf-graph-files.c b/perf/cairo-perf-graph-files.c
index 5122b9f..04235d6 100644
--- a/perf/cairo-perf-graph-files.c
+++ b/perf/cairo-perf-graph-files.c
@@ -319,7 +319,7 @@ gv_report_selected (GraphView *gv, int i, struct _app_data *app)
argv[4] = NULL;
do_git (app, argv);
- free (id);
+ g_free (id);
}
}
diff --git a/perf/cairo-perf-report.c b/perf/cairo-perf-report.c
index 79e2f92..2f748f4 100644
--- a/perf/cairo-perf-report.c
+++ b/perf/cairo-perf-report.c
@@ -397,10 +397,11 @@ cairo_perf_report_load (cairo_perf_report_t *report,
configuration = xmalloc (strlen (filename) * sizeof (char) + 1);
strcpy (configuration, filename);
- baseName = strdup (basename (configuration));
- report->configuration = xmalloc (strlen (filename) * sizeof (char) + 1);
- strcpy(report->configuration, baseName);
+ baseName = basename (configuration);
+ report->configuration = xmalloc (strlen (baseName) * sizeof (char) + 1);
+ strcpy (report->configuration, baseName);
free (configuration);
+
dot = strrchr (report->configuration, '.');
if (dot)
*dot = '\0';
commit 8419c4f124c6ffa75b44901dccab33df8bb6287a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Dec 20 15:34:41 2008 +0000
[perf] Correct another reference to '<cairo>'
I think that's the last use of the old internal name for twin!
diff --git a/perf/twin.c b/perf/twin.c
index adedb25..84ac759 100644
--- a/perf/twin.c
+++ b/perf/twin.c
@@ -18,7 +18,7 @@ do_twin (cairo_t *cr,
cairo_perf_timer_start ();
cairo_select_font_face (cr,
- "<cairo>",
+ "@cairo:",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
More information about the cairo-commit
mailing list