diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-13 17:21:05 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-29 08:08:36 +0100 |
commit | a9d997fecd54cea7dcd71487a24dbae14d0073a8 (patch) | |
tree | 78939c70f6411d9600630d5080871dc730e152ab | |
parent | 28887ac272c8a36a41da4d6d58044164b94da6f3 (diff) |
[script] Introduce cairo_script_context_t
cairo_script_context_t is an encapsulation object for interfacing with the
output - multiple surfaces can share the same context, meaning that they
write to the same destination file/stream.
-rw-r--r-- | boilerplate/cairo-boilerplate-script.c | 5 | ||||
-rw-r--r-- | boilerplate/cairo-boilerplate.c | 26 | ||||
-rw-r--r-- | src/cairo-script-surface.c | 225 | ||||
-rw-r--r-- | src/cairo-script.h | 47 | ||||
-rw-r--r-- | test/cairo-test-trace.c | 5 | ||||
-rw-r--r-- | util/cairo-script/csi-trace.c | 13 | ||||
-rw-r--r-- | util/cairo-trace/trace.c | 20 |
7 files changed, 145 insertions, 196 deletions
diff --git a/boilerplate/cairo-boilerplate-script.c b/boilerplate/cairo-boilerplate-script.c index 24a5843a..b944a55d 100644 --- a/boilerplate/cairo-boilerplate-script.c +++ b/boilerplate/cairo-boilerplate-script.c @@ -48,6 +48,7 @@ _cairo_boilerplate_script_create_surface (const char *name, void **closure) { script_target_closure_t *ptc; + cairo_script_context_t *ctx; cairo_surface_t *surface; cairo_status_t status; @@ -59,7 +60,9 @@ _cairo_boilerplate_script_create_surface (const char *name, xasprintf (&ptc->filename, "%s.out.cs", name); xunlink (ptc->filename); - surface = cairo_script_surface_create (ptc->filename, width, height); + ctx = cairo_script_context_create (ptc->filename); + surface = cairo_script_surface_create (ctx, width, height); + cairo_script_context_destroy (ctx); status = cairo_surface_set_user_data (surface, &script_closure_key, ptc, NULL); diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c index f15f7393..1abfe09e 100644 --- a/boilerplate/cairo-boilerplate.c +++ b/boilerplate/cairo-boilerplate.c @@ -151,17 +151,6 @@ _cairo_boilerplate_meta_create_surface (const char *name, extents.height = height; return cairo_meta_surface_create (content, &extents); } - -#if CAIRO_HAS_SCRIPT_SURFACE -static cairo_status_t -stdio_write (void *closure, const unsigned char *data, unsigned int len) -{ - if (fwrite (data, len, 1, closure) != 1) - return CAIRO_STATUS_WRITE_ERROR; - - return CAIRO_STATUS_SUCCESS; -} -#endif #endif const cairo_user_data_key_t cairo_boilerplate_output_basename_key; @@ -172,7 +161,6 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src, int width, int height) { - FILE *file = NULL; cairo_surface_t *surface, *image; cairo_t *cr; cairo_status_t status; @@ -195,17 +183,14 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src, test_name = cairo_surface_get_user_data (src, &cairo_boilerplate_output_basename_key); if (test_name != NULL) { + cairo_script_context_t *ctx; char *filename; xasprintf (&filename, "%s.out.trace", test_name); - file = fopen (filename, "w"); + ctx = cairo_script_context_create (filename); + surface = cairo_script_surface_create_for_target (ctx, image); + cairo_script_context_destroy (ctx); free (filename); - - if (file != NULL) { - surface = cairo_script_surface_create_for_target (image, - stdio_write, - file); - } } } #endif @@ -224,9 +209,6 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src, } cairo_destroy (cr); - if (file != NULL) - fclose (file); - return image; } diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c index a59f5125..a47324d4 100644 --- a/src/cairo-script-surface.c +++ b/src/cairo-script-surface.c @@ -61,7 +61,6 @@ #define static cairo_warn static -typedef struct _cairo_script_vmcontext cairo_script_vmcontext_t; typedef struct _cairo_script_surface cairo_script_surface_t; typedef struct _cairo_script_implicit_context cairo_script_implicit_context_t; typedef struct _cairo_script_surface_font_private cairo_script_surface_font_private_t; @@ -71,7 +70,9 @@ struct deferred_finish { cairo_list_t operand; }; -struct _cairo_script_vmcontext { +struct _cairo_script_context { + cairo_status_t status; + int ref; int active; @@ -93,7 +94,7 @@ struct _cairo_script_vmcontext { }; struct _cairo_script_surface_font_private { - cairo_script_vmcontext_t *ctx; + cairo_script_context_t *ctx; cairo_bool_t has_sfnt; unsigned long id; unsigned long subset_glyph_index; @@ -122,7 +123,7 @@ struct _cairo_script_surface { cairo_surface_wrapper_t wrapper; - cairo_script_vmcontext_t *ctx; + cairo_script_context_t *ctx; cairo_surface_clipper_t clipper; unsigned long id; @@ -139,13 +140,13 @@ struct _cairo_script_surface { static const cairo_surface_backend_t _cairo_script_surface_backend; static cairo_script_surface_t * -_cairo_script_surface_create_internal (cairo_script_vmcontext_t *ctx, +_cairo_script_surface_create_internal (cairo_script_context_t *ctx, double width, double height, cairo_surface_t *passthrough); static cairo_status_t -_vmcontext_destroy (cairo_script_vmcontext_t *ctx); +_context_destroy (cairo_script_context_t *ctx); static void _cairo_script_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); @@ -384,7 +385,7 @@ target_depth (cairo_script_surface_t *surface) static void _get_target (cairo_script_surface_t *surface) { - cairo_script_vmcontext_t *ctx = surface->ctx; + cairo_script_context_t *ctx = surface->ctx; if (! target_is_active (surface)) { int depth = target_depth (surface); @@ -1083,7 +1084,7 @@ _emit_png_surface (cairo_script_surface_t *surface, } struct def { - cairo_script_vmcontext_t *ctx; + cairo_script_context_t *ctx; cairo_user_data_array_t *user_data; unsigned int tag; cairo_list_t link; @@ -1600,7 +1601,7 @@ _cairo_script_surface_create_similar (void *abstract_surface, { cairo_script_surface_t *surface, *other = abstract_surface; cairo_surface_t *passthrough = NULL; - cairo_script_vmcontext_t *ctx; + cairo_script_context_t *ctx; cairo_status_t status; ctx = other->ctx; @@ -1650,10 +1651,11 @@ _cairo_script_surface_create_similar (void *abstract_surface, } static cairo_status_t -_vmcontext_destroy (cairo_script_vmcontext_t *ctx) +_context_destroy (cairo_script_context_t *ctx) { cairo_status_t status; + assert (ctx->ref > 0); if (--ctx->ref) return _cairo_output_stream_flush (ctx->stream); @@ -1771,7 +1773,7 @@ _cairo_script_surface_finish (void *abstract_surface) _bitmap_release_id (&surface->ctx->surface_id, surface->id); } - status2 = _vmcontext_destroy (surface->ctx); + status2 = _context_destroy (surface->ctx); if (status == CAIRO_STATUS_SUCCESS) status = status2; @@ -1877,13 +1879,13 @@ _cairo_script_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clip } static void -ctx_active (cairo_script_vmcontext_t *ctx) +ctx_active (cairo_script_context_t *ctx) { ctx->active++; } static void -ctx_inactive (cairo_script_vmcontext_t *ctx) +ctx_inactive (cairo_script_context_t *ctx) { if (--ctx->active > 0) return; @@ -3069,34 +3071,6 @@ _cairo_script_surface_backend = { _cairo_script_surface_show_text_glyphs }; -static cairo_bool_t -_cairo_surface_is_script (cairo_surface_t *surface) -{ - return surface->backend == &_cairo_script_surface_backend; -} - -static cairo_script_vmcontext_t * -_cairo_script_vmcontext_create (cairo_output_stream_t *stream) -{ - cairo_script_vmcontext_t *ctx; - - ctx = malloc (sizeof (cairo_script_vmcontext_t)); - if (unlikely (ctx == NULL)) - return NULL; - - memset (ctx, 0, sizeof (cairo_script_vmcontext_t)); - - cairo_list_init (&ctx->operands); - cairo_list_init (&ctx->deferred); - ctx->stream = stream; - ctx->mode = CAIRO_SCRIPT_MODE_ASCII; - - cairo_list_init (&ctx->fonts); - cairo_list_init (&ctx->defines); - - return ctx; -} - static void _cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr) { @@ -3118,7 +3092,7 @@ _cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr) } static cairo_script_surface_t * -_cairo_script_surface_create_internal (cairo_script_vmcontext_t *ctx, +_cairo_script_surface_create_internal (cairo_script_context_t *ctx, double width, double height, cairo_surface_t *passthrough) @@ -3126,7 +3100,7 @@ _cairo_script_surface_create_internal (cairo_script_vmcontext_t *ctx, cairo_script_surface_t *surface; if (unlikely (ctx == NULL)) - return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); surface = malloc (sizeof (cairo_script_surface_t)); if (unlikely (surface == NULL)) @@ -3157,132 +3131,125 @@ _cairo_script_surface_create_internal (cairo_script_vmcontext_t *ctx, return surface; } -cairo_surface_t * -cairo_script_surface_create (const char *filename, - double width, - double height) +static const cairo_script_context_t _nil_context = { + CAIRO_STATUS_NO_MEMORY, + -1 +}; + +static cairo_script_context_t * +_cairo_script_context_create_internal (cairo_output_stream_t *stream) { - cairo_output_stream_t *stream; - cairo_script_surface_t *surface; + cairo_script_context_t *ctx; - stream = _cairo_output_stream_create_for_filename (filename); - if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); + ctx = malloc (sizeof (cairo_script_context_t)); + if (unlikely (ctx == NULL)) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_script_context_t *) &_nil_context; + } + memset (ctx, 0, sizeof (cairo_script_context_t)); + ctx->status = CAIRO_STATUS_SUCCESS; + ctx->ref = 1; - surface = _cairo_script_surface_create_internal - (_cairo_script_vmcontext_create (stream), width, height, NULL); - if (surface->base.status) - return &surface->base; + cairo_list_init (&ctx->operands); + cairo_list_init (&ctx->deferred); + ctx->stream = stream; + ctx->mode = CAIRO_SCRIPT_MODE_ASCII; - _cairo_output_stream_puts (surface->ctx->stream, "%!CairoScript\n"); - return &surface->base; + cairo_list_init (&ctx->fonts); + cairo_list_init (&ctx->defines); + + _cairo_output_stream_puts (ctx->stream, "%!CairoScript\n"); + + return ctx; } -cairo_surface_t * -cairo_script_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width, - double height) +cairo_script_context_t * +cairo_script_context_create (const char *filename) { cairo_output_stream_t *stream; - stream = _cairo_output_stream_create (write_func, NULL, closure); + stream = _cairo_output_stream_create_for_filename (filename); if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); + return (cairo_script_context_t *) &_nil_context; - return &_cairo_script_surface_create_internal - (_cairo_script_vmcontext_create (stream), width, height, NULL)->base; + return _cairo_script_context_create_internal (stream); } -cairo_surface_t * -cairo_script_surface_create_for_target (cairo_surface_t *target, - cairo_write_func_t write_func, - void *closure) +cairo_script_context_t * +cairo_script_context_create_for_stream (cairo_write_func_t write_func, + void *closure) { cairo_output_stream_t *stream; - cairo_script_surface_t *surface; - cairo_rectangle_int_t extents; - - if (unlikely (target->status)) - return _cairo_surface_create_in_error (target->status); stream = _cairo_output_stream_create (write_func, NULL, closure); if (_cairo_output_stream_get_status (stream)) - return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); + return (cairo_script_context_t *) &_nil_context; - if (! _cairo_surface_get_extents (target, &extents)) - extents.width = extents.height = -1; - - surface = _cairo_script_surface_create_internal - (_cairo_script_vmcontext_create (stream), - extents.width, extents.height, - target); - if (unlikely (surface->base.status)) - return &surface->base; - - _cairo_output_stream_puts (surface->ctx->stream, "%!CairoScript\n"); - return &surface->base; + return _cairo_script_context_create_internal (stream); } void -cairo_script_surface_write_comment (cairo_surface_t *abstract_surface, +cairo_script_context_write_comment (cairo_script_context_t *context, const char *comment, int len) { - cairo_script_surface_t *surface; - cairo_status_t status_ignored; - - if (! _cairo_surface_is_script (abstract_surface)) { - status_ignored = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - if (abstract_surface->status) - return; - - surface = (cairo_script_surface_t *) abstract_surface; - if (len < 0) len = strlen (comment); - _cairo_output_stream_puts (surface->ctx->stream, "% "); - _cairo_output_stream_write (surface->ctx->stream, comment, len); - _cairo_output_stream_puts (surface->ctx->stream, "\n"); + _cairo_output_stream_puts (context->stream, "% "); + _cairo_output_stream_write (context->stream, comment, len); + _cairo_output_stream_puts (context->stream, "\n"); } void -cairo_script_surface_set_mode (cairo_surface_t *abstract_surface, +cairo_script_context_set_mode (cairo_script_context_t *context, cairo_script_mode_t mode) { - cairo_script_surface_t *surface; - cairo_status_t status_ignored; + context->mode = mode; +} - if (! _cairo_surface_is_script (abstract_surface)) { - status_ignored = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } +cairo_script_mode_t +cairo_script_context_get_mode (cairo_script_context_t *context) +{ + return context->mode; +} - if (abstract_surface->status) - return; +cairo_surface_t * +cairo_script_surface_create (cairo_script_context_t *context, + double width, + double height) +{ + return &_cairo_script_surface_create_internal (context, + width, height, + NULL)->base; +} + +cairo_surface_t * +cairo_script_surface_create_for_target (cairo_script_context_t *context, + cairo_surface_t *target) +{ + cairo_rectangle_int_t extents; - surface = (cairo_script_surface_t *) abstract_surface; - surface->ctx->mode = mode; + if (unlikely (target->status)) + return _cairo_surface_create_in_error (target->status); + + if (! _cairo_surface_get_extents (target, &extents)) + extents.width = extents.height = -1; + + return &_cairo_script_surface_create_internal (context, + extents.width, + extents.height, + target)->base; } -cairo_script_mode_t -cairo_script_surface_get_mode (cairo_surface_t *abstract_surface) +void +cairo_script_context_destroy (cairo_script_context_t *context) { - cairo_script_surface_t *surface; + cairo_status_t status_ignored; - if (! _cairo_surface_is_script (abstract_surface) || - abstract_surface->status) - { - return CAIRO_SCRIPT_MODE_ASCII; - } + if (context == NULL || context->ref < 0) + return; - surface = (cairo_script_surface_t *) abstract_surface; - return surface->ctx->mode; + status_ignored = _context_destroy (context); } diff --git a/src/cairo-script.h b/src/cairo-script.h index 397080bc..182b65da 100644 --- a/src/cairo-script.h +++ b/src/cairo-script.h @@ -42,38 +42,43 @@ CAIRO_BEGIN_DECLS -cairo_public cairo_surface_t * -cairo_script_surface_create (const char *filename, - double width, - double height); +typedef struct _cairo_script_context cairo_script_context_t; -cairo_public cairo_surface_t * -cairo_script_surface_create_for_stream (cairo_write_func_t write_func, - void *closure, - double width, - double height); +typedef enum { + CAIRO_SCRIPT_MODE_BINARY, + CAIRO_SCRIPT_MODE_ASCII +} cairo_script_mode_t; -cairo_public cairo_surface_t * -cairo_script_surface_create_for_target (cairo_surface_t *surface, - cairo_write_func_t write_func, - void *closure); +cairo_public cairo_script_context_t * +cairo_script_context_create (const char *filename); + +cairo_public cairo_script_context_t * +cairo_script_context_create_for_stream (cairo_write_func_t write_func, + void *closure); cairo_public void -cairo_script_surface_write_comment (cairo_surface_t *abstract_surface, +cairo_script_context_write_comment (cairo_script_context_t *context, const char *comment, int len); -typedef enum { - CAIRO_SCRIPT_MODE_BINARY, - CAIRO_SCRIPT_MODE_ASCII -} cairo_script_mode_t; - cairo_public void -cairo_script_surface_set_mode (cairo_surface_t *surface, +cairo_script_context_set_mode (cairo_script_context_t *context, cairo_script_mode_t mode); cairo_public cairo_script_mode_t -cairo_script_surface_get_mode (cairo_surface_t *surface); +cairo_script_context_get_mode (cairo_script_context_t *context); + +cairo_public void +cairo_script_context_destroy (cairo_script_context_t *context); + +cairo_public cairo_surface_t * +cairo_script_surface_create (cairo_script_context_t *context, + double width, + double height); + +cairo_public cairo_surface_t * +cairo_script_surface_create_for_target (cairo_script_context_t *context, + cairo_surface_t *target); CAIRO_END_DECLS diff --git a/test/cairo-test-trace.c b/test/cairo-test-trace.c index 3be54027..c35d6a7e 100644 --- a/test/cairo-test-trace.c +++ b/test/cairo-test-trace.c @@ -864,14 +864,17 @@ static void write_trace (const char *trace, struct slave *slave) { #if CAIRO_HAS_SCRIPT_SURFACE + cairo_script_context_t *ctx; cairo_surface_t *script; char *filename; cairo_status_t status; xasprintf (&filename, "%s-fail.trace", trace); - script = cairo_script_surface_create (filename, + ctx = cairo_script_context_create (filename); + script = cairo_script_surface_create (ctx, slave->width, slave->height); + cairo_script_context_destroy (ctx); free (filename); status = cairo_meta_surface_replay (slave->image, script); diff --git a/util/cairo-script/csi-trace.c b/util/cairo-script/csi-trace.c index 418a3353..d118067f 100644 --- a/util/cairo-script/csi-trace.c +++ b/util/cairo-script/csi-trace.c @@ -6,11 +6,11 @@ #include <libgen.h> static cairo_surface_t * -_similar_surface_create (void *closure, +_script_surface_create (void *closure, cairo_content_t content, double width, double height) { - return cairo_surface_create_similar (closure, content, width, height); + return cairo_script_surface_create (closure, width, height); } int @@ -18,7 +18,7 @@ main (int argc, char **argv) { cairo_script_interpreter_t *csi; cairo_script_interpreter_hooks_t hooks = { - .surface_create = _similar_surface_create, + .surface_create = _script_surface_create, }; int i; @@ -28,13 +28,12 @@ main (int argc, char **argv) char buf[4096]; snprintf (buf, sizeof (buf), "%s.trace", basename (argv[i])); - - cairo_surface_destroy (hooks.closure); - hooks.closure = cairo_script_surface_create (buf, -1, -1); + cairo_script_context_destroy (hooks.closure); + hooks.closure = cairo_script_context_create (buf); cairo_script_interpreter_install_hooks (csi, &hooks); cairo_script_interpreter_run (csi, argv[i]); } - cairo_surface_destroy (hooks.closure); + cairo_script_context_destroy (hooks.closure); return cairo_script_interpreter_destroy (csi); } diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index 365bda53..7a6219d3 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -4145,23 +4145,20 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, #if CAIRO_HAS_SCRIPT_SURFACE #include <cairo-script.h> cairo_surface_t * -cairo_script_surface_create (const char *filename, +cairo_script_surface_create (cairo_script_context_t *ctx, double width, double height) { cairo_surface_t *ret; long surface_id; - ret = DLCALL (cairo_script_surface_create, filename, width, height); + ret = DLCALL (cairo_script_surface_create, ctx, width, height); surface_id = _create_surface_id (ret); _emit_line_info (); if (_write_lock ()) { _trace_printf ("dict\n" " /type /script set\n" - " /filename "); - _emit_string_literal (filename, -1); - _trace_printf (" set\n" " /width %g set\n" " /height %g set\n" " surface dup /s%ld exch def\n", @@ -4177,28 +4174,21 @@ cairo_script_surface_create (const char *filename, } cairo_surface_t * -cairo_script_surface_create_for_stream (cairo_write_func_t write_func, - void *data, - double width, - double height) +cairo_script_surface_create_for_target (cairo_script_context_t *ctx, + cairo_surface_t *target) { cairo_surface_t *ret; long surface_id; - ret = DLCALL (cairo_script_surface_create_for_stream, - write_func, data, width, height); + ret = DLCALL (cairo_script_surface_create_for_target, ctx, target); surface_id = _create_surface_id (ret); _emit_line_info (); if (_write_lock ()) { _trace_printf ("dict\n" " /type /script set\n" - " /width %g set\n" - " /height %g set\n" " surface dup /s%ld exch def\n", - width, height, surface_id); - _surface_object_set_size (ret, width, height); _get_object (SURFACE, ret)->defined = true; _push_operand (SURFACE, ret); _write_unlock (); |