summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-08-13 17:21:05 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-08-29 08:08:36 +0100
commita9d997fecd54cea7dcd71487a24dbae14d0073a8 (patch)
tree78939c70f6411d9600630d5080871dc730e152ab
parent28887ac272c8a36a41da4d6d58044164b94da6f3 (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.c5
-rw-r--r--boilerplate/cairo-boilerplate.c26
-rw-r--r--src/cairo-script-surface.c225
-rw-r--r--src/cairo-script.h47
-rw-r--r--test/cairo-test-trace.c5
-rw-r--r--util/cairo-script/csi-trace.c13
-rw-r--r--util/cairo-trace/trace.c20
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 ();