cairo/src/cairo-script-surface.c

4024 lines
106 KiB
C
Raw Normal View History

/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2008 Chris Wilson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Chris Wilson.
*
* Contributor(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
/* The script surface is one that records all operations performed on
* it in the form of a procedural script, similar in fashion to
* PostScript but using Cairo's imaging model. In essence, this is
* equivalent to the recording-surface, but as there is no impedance mismatch
* between Cairo and CairoScript, we can generate output immediately
* without having to copy and hold the data in memory.
*/
/**
* SECTION:cairo-script
* @Title: Script Surfaces
* @Short_Description: Rendering to replayable scripts
* @See_Also: #cairo_surface_t
*
* The script surface provides the ability to render to a native
* script that matches the cairo drawing model. The scripts can
* be replayed using tools under the util/cairo-script directory,
* or with cairo-perf-trace.
**/
/**
* CAIRO_HAS_SCRIPT_SURFACE:
*
* Defined if the script surface backend is available.
* The script surface backend is always built in since 1.12.
*
* Since: 1.12
**/
#include "cairoint.h"
#include "cairo-script.h"
#include "cairo-script-private.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-default-context-private.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
#include "cairo-list-inline.h"
#include "cairo-image-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-pattern-private.h"
#include "cairo-recording-surface-inline.h"
#include "cairo-scaled-font-private.h"
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
#include "cairo-surface-clipper-private.h"
#include "cairo-surface-snapshot-inline.h"
2010-04-28 09:54:56 +01:00
#include "cairo-surface-subsurface-private.h"
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
#include "cairo-surface-wrapper-private.h"
2010-04-07 22:46:38 +01:00
#if CAIRO_HAS_FT_FONT
#include "cairo-ft-private.h"
#endif
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
#include <ctype.h>
#ifdef WORDS_BIGENDIAN
#define to_be32(x) x
#else
#define to_be32(x) bswap_32(x)
#endif
#define _cairo_output_stream_puts(S, STR) \
_cairo_output_stream_write ((S), (STR), strlen (STR))
#define static cairo_warn static
typedef struct _cairo_script_context cairo_script_context_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_font cairo_script_font_t;
typedef struct _operand {
enum {
SURFACE,
DEFERRED,
} type;
cairo_list_t link;
} operand_t;
struct deferred_finish {
cairo_list_t link;
operand_t operand;
};
struct _cairo_script_context {
cairo_device_t base;
int active;
int attach_snapshots;
cairo_bool_t owns_stream;
cairo_output_stream_t *stream;
cairo_script_mode_t mode;
struct _bitmap {
unsigned long min;
unsigned long count;
unsigned int map[64];
struct _bitmap *next;
} surface_id, font_id;
cairo_list_t operands;
cairo_list_t deferred;
cairo_list_t fonts;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_list_t defines;
};
struct _cairo_script_font {
cairo_scaled_font_private_t base;
cairo_bool_t has_sfnt;
unsigned long id;
unsigned long subset_glyph_index;
cairo_list_t link;
cairo_scaled_font_t *parent;
};
struct _cairo_script_implicit_context {
cairo_operator_t current_operator;
cairo_fill_rule_t current_fill_rule;
double current_tolerance;
cairo_antialias_t current_antialias;
cairo_stroke_style_t current_style;
cairo_pattern_union_t current_source;
cairo_matrix_t current_ctm;
cairo_matrix_t current_stroke_matrix;
cairo_matrix_t current_font_matrix;
cairo_font_options_t current_font_options;
cairo_scaled_font_t *current_scaled_font;
cairo_path_fixed_t current_path;
cairo_bool_t has_clip;
};
struct _cairo_script_surface {
cairo_surface_t base;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_surface_wrapper_t wrapper;
cairo_surface_clipper_t clipper;
operand_t operand;
cairo_bool_t emitted;
cairo_bool_t defined;
cairo_bool_t active;
double width, height;
/* implicit flattened context */
cairo_script_implicit_context_t cr;
};
static const cairo_surface_backend_t _cairo_script_surface_backend;
static cairo_script_surface_t *
_cairo_script_surface_create_internal (cairo_script_context_t *ctx,
cairo_content_t content,
cairo_rectangle_t *extents,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_surface_t *passthrough);
static void
_cairo_script_scaled_font_fini (cairo_scaled_font_private_t *abstract_private,
cairo_scaled_font_t *scaled_font);
static void
_cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr);
static void
_cairo_script_implicit_context_reset (cairo_script_implicit_context_t *cr);
static void
_bitmap_release_id (struct _bitmap *b, unsigned long token)
{
struct _bitmap **prev = NULL;
do {
if (token < b->min + sizeof (b->map) * CHAR_BIT) {
unsigned int bit, elem;
token -= b->min;
elem = token / (sizeof (b->map[0]) * CHAR_BIT);
bit = token % (sizeof (b->map[0]) * CHAR_BIT);
b->map[elem] &= ~(1 << bit);
if (! --b->count && prev) {
*prev = b->next;
free (b);
}
return;
}
prev = &b->next;
b = b->next;
} while (b != NULL);
}
static cairo_status_t
_bitmap_next_id (struct _bitmap *b,
unsigned long *id)
{
struct _bitmap *bb, **prev = NULL;
unsigned long min = 0;
do {
if (b->min != min)
break;
if (b->count < sizeof (b->map) * CHAR_BIT) {
unsigned int n, m, bit;
for (n = 0; n < ARRAY_LENGTH (b->map); n++) {
if (b->map[n] == (unsigned int) -1)
continue;
for (m=0, bit=1; m<sizeof (b->map[0])*CHAR_BIT; m++, bit<<=1) {
if ((b->map[n] & bit) == 0) {
b->map[n] |= bit;
b->count++;
*id = n * sizeof (b->map[0])*CHAR_BIT + m + b->min;
return CAIRO_STATUS_SUCCESS;
}
}
}
}
min += sizeof (b->map) * CHAR_BIT;
prev = &b->next;
b = b->next;
} while (b != NULL);
assert (prev != NULL);
bb = _cairo_malloc (sizeof (struct _bitmap));
if (unlikely (bb == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
*prev = bb;
bb->next = b;
bb->min = min;
bb->count = 1;
bb->map[0] = 0x1;
memset (bb->map + 1, 0, sizeof (bb->map) - sizeof (bb->map[0]));
*id = min;
return CAIRO_STATUS_SUCCESS;
}
2010-03-23 20:08:04 +00:00
static void
_bitmap_fini (struct _bitmap *b)
{
while (b != NULL) {
struct _bitmap *next = b->next;
free (b);
b = next;
}
}
static const char *
_direction_to_string (cairo_bool_t backward)
{
static const char *names[] = {
"FORWARD",
"BACKWARD"
};
assert (backward < ARRAY_LENGTH (names));
return names[backward];
}
static const char *
_operator_to_string (cairo_operator_t op)
{
static const char *names[] = {
"CLEAR", /* CAIRO_OPERATOR_CLEAR */
"SOURCE", /* CAIRO_OPERATOR_SOURCE */
"OVER", /* CAIRO_OPERATOR_OVER */
"IN", /* CAIRO_OPERATOR_IN */
"OUT", /* CAIRO_OPERATOR_OUT */
"ATOP", /* CAIRO_OPERATOR_ATOP */
"DEST", /* CAIRO_OPERATOR_DEST */
"DEST_OVER", /* CAIRO_OPERATOR_DEST_OVER */
"DEST_IN", /* CAIRO_OPERATOR_DEST_IN */
"DEST_OUT", /* CAIRO_OPERATOR_DEST_OUT */
"DEST_ATOP", /* CAIRO_OPERATOR_DEST_ATOP */
"XOR", /* CAIRO_OPERATOR_XOR */
"ADD", /* CAIRO_OPERATOR_ADD */
2009-07-14 16:31:41 +01:00
"SATURATE", /* CAIRO_OPERATOR_SATURATE */
"MULTIPLY", /* CAIRO_OPERATOR_MULTIPLY */
"SCREEN", /* CAIRO_OPERATOR_SCREEN */
"OVERLAY", /* CAIRO_OPERATOR_OVERLAY */
"DARKEN", /* CAIRO_OPERATOR_DARKEN */
"LIGHTEN", /* CAIRO_OPERATOR_LIGHTEN */
"DODGE", /* CAIRO_OPERATOR_COLOR_DODGE */
"BURN", /* CAIRO_OPERATOR_COLOR_BURN */
"HARD_LIGHT", /* CAIRO_OPERATOR_HARD_LIGHT */
"SOFT_LIGHT", /* CAIRO_OPERATOR_SOFT_LIGHT */
"DIFFERENCE", /* CAIRO_OPERATOR_DIFFERENCE */
"EXCLUSION", /* CAIRO_OPERATOR_EXCLUSION */
"HSL_HUE", /* CAIRO_OPERATOR_HSL_HUE */
"HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */
"HSL_COLOR", /* CAIRO_OPERATOR_HSL_COLOR */
"HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */
};
assert (op < ARRAY_LENGTH (names));
return names[op];
}
static const char *
_extend_to_string (cairo_extend_t extend)
{
static const char *names[] = {
"EXTEND_NONE", /* CAIRO_EXTEND_NONE */
"EXTEND_REPEAT", /* CAIRO_EXTEND_REPEAT */
"EXTEND_REFLECT", /* CAIRO_EXTEND_REFLECT */
"EXTEND_PAD" /* CAIRO_EXTEND_PAD */
};
assert (extend < ARRAY_LENGTH (names));
return names[extend];
}
static const char *
_filter_to_string (cairo_filter_t filter)
{
static const char *names[] = {
"FILTER_FAST", /* CAIRO_FILTER_FAST */
"FILTER_GOOD", /* CAIRO_FILTER_GOOD */
"FILTER_BEST", /* CAIRO_FILTER_BEST */
"FILTER_NEAREST", /* CAIRO_FILTER_NEAREST */
"FILTER_BILINEAR", /* CAIRO_FILTER_BILINEAR */
"FILTER_GAUSSIAN", /* CAIRO_FILTER_GAUSSIAN */
};
assert (filter < ARRAY_LENGTH (names));
return names[filter];
}
static const char *
_fill_rule_to_string (cairo_fill_rule_t rule)
{
static const char *names[] = {
"WINDING", /* CAIRO_FILL_RULE_WINDING */
"EVEN_ODD" /* CAIRO_FILL_RILE_EVEN_ODD */
};
assert (rule < ARRAY_LENGTH (names));
return names[rule];
}
static const char *
_antialias_to_string (cairo_antialias_t antialias)
{
static const char *names[] = {
"ANTIALIAS_DEFAULT", /* CAIRO_ANTIALIAS_DEFAULT */
"ANTIALIAS_NONE", /* CAIRO_ANTIALIAS_NONE */
"ANTIALIAS_GRAY", /* CAIRO_ANTIALIAS_GRAY */
"ANTIALIAS_SUBPIXEL", /* CAIRO_ANTIALIAS_SUBPIXEL */
"ANTIALIAS_FAST", /* CAIRO_ANTIALIAS_FAST */
"ANTIALIAS_GOOD", /* CAIRO_ANTIALIAS_GOOD */
"ANTIALIAS_BEST" /* CAIRO_ANTIALIAS_BEST */
};
assert (antialias < ARRAY_LENGTH (names));
return names[antialias];
}
static const char *
_line_cap_to_string (cairo_line_cap_t line_cap)
{
static const char *names[] = {
"LINE_CAP_BUTT", /* CAIRO_LINE_CAP_BUTT */
"LINE_CAP_ROUND", /* CAIRO_LINE_CAP_ROUND */
"LINE_CAP_SQUARE" /* CAIRO_LINE_CAP_SQUARE */
};
assert (line_cap < ARRAY_LENGTH (names));
return names[line_cap];
}
static const char *
_line_join_to_string (cairo_line_join_t line_join)
{
static const char *names[] = {
"LINE_JOIN_MITER", /* CAIRO_LINE_JOIN_MITER */
"LINE_JOIN_ROUND", /* CAIRO_LINE_JOIN_ROUND */
"LINE_JOIN_BEVEL", /* CAIRO_LINE_JOIN_BEVEL */
};
assert (line_join < ARRAY_LENGTH (names));
return names[line_join];
}
static inline cairo_script_context_t *
to_context (cairo_script_surface_t *surface)
{
return (cairo_script_context_t *) surface->base.device;
}
static cairo_bool_t
target_is_active (cairo_script_surface_t *surface)
{
return cairo_list_is_first (&surface->operand.link,
&to_context (surface)->operands);
}
static void
target_push (cairo_script_surface_t *surface)
{
cairo_list_move (&surface->operand.link, &to_context (surface)->operands);
}
static int
target_depth (cairo_script_surface_t *surface)
{
cairo_list_t *link;
int depth = 0;
cairo_list_foreach (link, &to_context (surface)->operands) {
if (link == &surface->operand.link)
break;
depth++;
}
return depth;
}
static void
_get_target (cairo_script_surface_t *surface)
{
cairo_script_context_t *ctx = to_context (surface);
if (target_is_active (surface)) {
_cairo_output_stream_puts (ctx->stream, "dup ");
return;
}
if (surface->defined) {
_cairo_output_stream_printf (ctx->stream, "s%u ",
surface->base.unique_id);
} else {
int depth = target_depth (surface);
assert (! cairo_list_is_empty (&surface->operand.link));
assert (! target_is_active (surface));
if (ctx->active) {
_cairo_output_stream_printf (ctx->stream, "%d index ", depth);
_cairo_output_stream_puts (ctx->stream, "/target get exch pop ");
} else {
if (depth == 1) {
_cairo_output_stream_puts (ctx->stream, "exch ");
} else {
_cairo_output_stream_printf (ctx->stream,
"%d -1 roll ", depth);
}
target_push (surface);
_cairo_output_stream_puts (ctx->stream, "dup ");
}
}
}
static const char *
_content_to_string (cairo_content_t content)
{
switch (content) {
case CAIRO_CONTENT_ALPHA: return "ALPHA";
case CAIRO_CONTENT_COLOR: return "COLOR";
default:
case CAIRO_CONTENT_COLOR_ALPHA: return "COLOR_ALPHA";
}
}
static cairo_status_t
_emit_surface (cairo_script_surface_t *surface)
{
cairo_script_context_t *ctx = to_context (surface);
_cairo_output_stream_printf (ctx->stream,
"<< /content //%s",
_content_to_string (surface->base.content));
if (surface->width != -1 && surface->height != -1) {
_cairo_output_stream_printf (ctx->stream,
" /width %f /height %f",
surface->width,
surface->height);
}
if (surface->base.x_fallback_resolution !=
CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT ||
surface->base.y_fallback_resolution !=
CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT)
{
_cairo_output_stream_printf (ctx->stream,
" /fallback-resolution [%f %f]",
surface->base.x_fallback_resolution,
surface->base.y_fallback_resolution);
}
if (surface->base.device_transform.x0 != 0. ||
surface->base.device_transform.y0 != 0.)
{
/* XXX device offset is encoded into the pattern matrices etc. */
if (0) {
_cairo_output_stream_printf (ctx->stream,
" /device-offset [%f %f]",
surface->base.device_transform.x0,
surface->base.device_transform.y0);
}
}
_cairo_output_stream_puts (ctx->stream, " >> surface context\n");
surface->emitted = TRUE;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_context (cairo_script_surface_t *surface)
{
cairo_script_context_t *ctx = to_context (surface);
if (target_is_active (surface))
return CAIRO_STATUS_SUCCESS;
while (! cairo_list_is_empty (&ctx->operands)) {
operand_t *op;
cairo_script_surface_t *old;
op = cairo_list_first_entry (&ctx->operands,
operand_t,
link);
if (op->type == DEFERRED)
break;
old = cairo_container_of (op, cairo_script_surface_t, operand);
if (old == surface)
break;
if (old->active)
break;
if (! old->defined) {
assert (old->emitted);
_cairo_output_stream_printf (ctx->stream,
"/target get /s%u exch def pop\n",
old->base.unique_id);
old->defined = TRUE;
} else {
_cairo_output_stream_puts (ctx->stream, "pop\n");
}
cairo_list_del (&old->operand.link);
}
if (target_is_active (surface))
return CAIRO_STATUS_SUCCESS;
if (! surface->emitted) {
cairo_status_t status;
status = _emit_surface (surface);
if (unlikely (status))
return status;
} else if (cairo_list_is_empty (&surface->operand.link)) {
assert (surface->defined);
_cairo_output_stream_printf (ctx->stream,
"s%u context\n",
surface->base.unique_id);
_cairo_script_implicit_context_reset (&surface->cr);
_cairo_surface_clipper_reset (&surface->clipper);
} else {
int depth = target_depth (surface);
if (depth == 1) {
_cairo_output_stream_puts (ctx->stream, "exch\n");
} else {
_cairo_output_stream_printf (ctx->stream,
"%d -1 roll\n",
depth);
}
}
target_push (surface);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_operator (cairo_script_surface_t *surface,
cairo_operator_t op)
{
assert (target_is_active (surface));
if (surface->cr.current_operator == op)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_operator = op;
_cairo_output_stream_printf (to_context (surface)->stream,
"//%s set-operator\n",
_operator_to_string (op));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_fill_rule (cairo_script_surface_t *surface,
cairo_fill_rule_t fill_rule)
{
assert (target_is_active (surface));
if (surface->cr.current_fill_rule == fill_rule)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_fill_rule = fill_rule;
_cairo_output_stream_printf (to_context (surface)->stream,
"//%s set-fill-rule\n",
_fill_rule_to_string (fill_rule));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_tolerance (cairo_script_surface_t *surface,
double tolerance,
cairo_bool_t force)
{
assert (target_is_active (surface));
if ((! force ||
fabs (tolerance - CAIRO_GSTATE_TOLERANCE_DEFAULT) < 1e-5) &&
surface->cr.current_tolerance == tolerance)
{
return CAIRO_STATUS_SUCCESS;
}
surface->cr.current_tolerance = tolerance;
_cairo_output_stream_printf (to_context (surface)->stream,
"%f set-tolerance\n",
tolerance);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_antialias (cairo_script_surface_t *surface,
cairo_antialias_t antialias)
{
assert (target_is_active (surface));
if (surface->cr.current_antialias == antialias)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_antialias = antialias;
_cairo_output_stream_printf (to_context (surface)->stream,
"//%s set-antialias\n",
_antialias_to_string (antialias));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_line_width (cairo_script_surface_t *surface,
double line_width,
cairo_bool_t force)
{
assert (target_is_active (surface));
if ((! force ||
fabs (line_width - CAIRO_GSTATE_LINE_WIDTH_DEFAULT) < 1e-5) &&
surface->cr.current_style.line_width == line_width)
{
return CAIRO_STATUS_SUCCESS;
}
surface->cr.current_style.line_width = line_width;
_cairo_output_stream_printf (to_context (surface)->stream,
"%f set-line-width\n",
line_width);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_line_cap (cairo_script_surface_t *surface,
cairo_line_cap_t line_cap)
{
assert (target_is_active (surface));
if (surface->cr.current_style.line_cap == line_cap)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_style.line_cap = line_cap;
_cairo_output_stream_printf (to_context (surface)->stream,
"//%s set-line-cap\n",
_line_cap_to_string (line_cap));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_line_join (cairo_script_surface_t *surface,
cairo_line_join_t line_join)
{
assert (target_is_active (surface));
if (surface->cr.current_style.line_join == line_join)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_style.line_join = line_join;
_cairo_output_stream_printf (to_context (surface)->stream,
"//%s set-line-join\n",
_line_join_to_string (line_join));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_miter_limit (cairo_script_surface_t *surface,
double miter_limit,
cairo_bool_t force)
{
assert (target_is_active (surface));
if ((! force ||
fabs (miter_limit - CAIRO_GSTATE_MITER_LIMIT_DEFAULT) < 1e-5) &&
surface->cr.current_style.miter_limit == miter_limit)
{
return CAIRO_STATUS_SUCCESS;
}
surface->cr.current_style.miter_limit = miter_limit;
_cairo_output_stream_printf (to_context (surface)->stream,
"%f set-miter-limit\n",
miter_limit);
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_dashes_equal (const double *a, const double *b, int num_dashes)
{
while (num_dashes--) {
if (fabs (*a - *b) > 1e-5)
return FALSE;
a++, b++;
}
return TRUE;
}
static cairo_status_t
_emit_dash (cairo_script_surface_t *surface,
const double *dash,
unsigned int num_dashes,
double offset,
cairo_bool_t force)
{
unsigned int n;
assert (target_is_active (surface));
if (force &&
num_dashes == 0 &&
surface->cr.current_style.num_dashes == 0)
{
return CAIRO_STATUS_SUCCESS;
}
if (! force &&
(surface->cr.current_style.num_dashes == num_dashes &&
(num_dashes == 0 ||
(fabs (surface->cr.current_style.dash_offset - offset) < 1e-5 &&
_dashes_equal (surface->cr.current_style.dash, dash, num_dashes)))))
{
return CAIRO_STATUS_SUCCESS;
}
if (num_dashes) {
surface->cr.current_style.dash = _cairo_realloc_ab
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
(surface->cr.current_style.dash, num_dashes, sizeof (double));
if (unlikely (surface->cr.current_style.dash == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (surface->cr.current_style.dash, dash,
sizeof (double) * num_dashes);
} else {
free (surface->cr.current_style.dash);
surface->cr.current_style.dash = NULL;
}
surface->cr.current_style.num_dashes = num_dashes;
surface->cr.current_style.dash_offset = offset;
_cairo_output_stream_puts (to_context (surface)->stream, "[");
for (n = 0; n < num_dashes; n++) {
_cairo_output_stream_printf (to_context (surface)->stream, "%f", dash[n]);
if (n < num_dashes-1)
_cairo_output_stream_puts (to_context (surface)->stream, " ");
}
_cairo_output_stream_printf (to_context (surface)->stream,
"] %f set-dash\n",
offset);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_stroke_style (cairo_script_surface_t *surface,
const cairo_stroke_style_t *style,
cairo_bool_t force)
{
cairo_status_t status;
assert (target_is_active (surface));
status = _emit_line_width (surface, style->line_width, force);
if (unlikely (status))
return status;
status = _emit_line_cap (surface, style->line_cap);
if (unlikely (status))
return status;
status = _emit_line_join (surface, style->line_join);
if (unlikely (status))
return status;
status = _emit_miter_limit (surface, style->miter_limit, force);
if (unlikely (status))
return status;
status = _emit_dash (surface,
style->dash, style->num_dashes, style->dash_offset,
force);
if (unlikely (status))
return status;
return CAIRO_STATUS_SUCCESS;
}
static const char *
_format_to_string (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_RGBA128F: return "RGBA128F";
case CAIRO_FORMAT_RGB96F: return "RGB96F";
case CAIRO_FORMAT_ARGB32: return "ARGB32";
case CAIRO_FORMAT_RGB30: return "RGB30";
case CAIRO_FORMAT_RGB24: return "RGB24";
case CAIRO_FORMAT_RGB16_565: return "RGB16_565";
case CAIRO_FORMAT_A8: return "A8";
case CAIRO_FORMAT_A1: return "A1";
case CAIRO_FORMAT_INVALID: return "INVALID";
}
ASSERT_NOT_REACHED;
return "INVALID";
}
static cairo_status_t
_emit_solid_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
cairo_script_context_t *ctx = to_context (surface);
if (! CAIRO_COLOR_IS_OPAQUE (&solid->color))
{
if (! (surface->base.content & CAIRO_CONTENT_COLOR) ||
((solid->color.red_short == 0 || solid->color.red_short == 0xffff) &&
(solid->color.green_short == 0 || solid->color.green_short == 0xffff) &&
(solid->color.blue_short == 0 || solid->color.blue_short == 0xffff) ))
{
_cairo_output_stream_printf (ctx->stream,
"%f a",
solid->color.alpha);
}
else
{
_cairo_output_stream_printf (ctx->stream,
"%f %f %f %f rgba",
solid->color.red,
solid->color.green,
solid->color.blue,
solid->color.alpha);
}
}
else
{
if (solid->color.red_short == solid->color.green_short &&
solid->color.red_short == solid->color.blue_short)
{
_cairo_output_stream_printf (ctx->stream,
"%f g",
solid->color.red);
}
else
{
_cairo_output_stream_printf (ctx->stream,
"%f %f %f rgb",
solid->color.red,
solid->color.green,
solid->color.blue);
}
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_gradient_color_stops (cairo_gradient_pattern_t *gradient,
cairo_output_stream_t *output)
{
unsigned int n;
for (n = 0; n < gradient->n_stops; n++) {
_cairo_output_stream_printf (output,
"\n %f %f %f %f %f add-color-stop",
gradient->stops[n].offset,
gradient->stops[n].color.red,
gradient->stops[n].color.green,
gradient->stops[n].color.blue,
gradient->stops[n].color.alpha);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_linear_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_linear_pattern_t *linear;
linear = (cairo_linear_pattern_t *) pattern;
_cairo_output_stream_printf (ctx->stream,
"%f %f %f %f linear",
linear->pd1.x, linear->pd1.y,
linear->pd2.x, linear->pd2.y);
return _emit_gradient_color_stops (&linear->base, ctx->stream);
}
static cairo_status_t
_emit_radial_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_radial_pattern_t *radial;
radial = (cairo_radial_pattern_t *) pattern;
_cairo_output_stream_printf (ctx->stream,
"%f %f %f %f %f %f radial",
radial->cd1.center.x,
radial->cd1.center.y,
radial->cd1.radius,
radial->cd2.center.x,
radial->cd2.center.y,
radial->cd2.radius);
return _emit_gradient_color_stops (&radial->base, ctx->stream);
}
static cairo_status_t
_emit_mesh_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_pattern_t *mesh;
cairo_status_t status;
unsigned int i, n;
mesh = (cairo_pattern_t *) pattern;
status = cairo_mesh_pattern_get_patch_count (mesh, &n);
if (unlikely (status))
return status;
_cairo_output_stream_printf (ctx->stream, "mesh");
for (i = 0; i < n; i++) {
cairo_path_t *path;
cairo_path_data_t *data;
int j;
_cairo_output_stream_printf (ctx->stream, "\n begin-patch");
path = cairo_mesh_pattern_get_path (mesh, i);
if (unlikely (path->status))
return path->status;
for (j = 0; j < path->num_data; j+=data[0].header.length) {
data = &path->data[j];
switch (data->header.type) {
case CAIRO_PATH_MOVE_TO:
_cairo_output_stream_printf (ctx->stream,
"\n %f %f m",
data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
_cairo_output_stream_printf (ctx->stream,
"\n %f %f l",
data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
_cairo_output_stream_printf (ctx->stream,
"\n %f %f %f %f %f %f c",
data[1].point.x, data[1].point.y,
data[2].point.x, data[2].point.y,
data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
break;
}
}
cairo_path_destroy (path);
for (j = 0; j < 4; j++) {
double x, y;
status = cairo_mesh_pattern_get_control_point (mesh, i, j, &x, &y);
if (unlikely (status))
return status;
_cairo_output_stream_printf (ctx->stream,
"\n %d %f %f set-control-point",
j, x, y);
}
for (j = 0; j < 4; j++) {
double r, g, b, a;
status = cairo_mesh_pattern_get_corner_color_rgba (mesh, i, j, &r, &g, &b, &a);
if (unlikely (status))
return status;
_cairo_output_stream_printf (ctx->stream,
"\n %d %f %f %f %f set-corner-color",
j, r, g, b, a);
}
_cairo_output_stream_printf (ctx->stream, "\n end-patch");
}
return CAIRO_STATUS_SUCCESS;
}
struct script_snapshot {
cairo_surface_t base;
};
static cairo_status_t
script_snapshot_finish (void *abstract_surface)
{
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t script_snapshot_backend = {
CAIRO_SURFACE_TYPE_SCRIPT,
script_snapshot_finish,
};
static void
detach_snapshot (cairo_surface_t *abstract_surface)
{
cairo_script_surface_t *surface = (cairo_script_surface_t *)abstract_surface;
cairo_script_context_t *ctx = to_context (surface);
_cairo_output_stream_printf (ctx->stream,
"/s%d undef\n",
surface->base.unique_id);
}
static void
attach_snapshot (cairo_script_context_t *ctx,
cairo_surface_t *source)
{
struct script_snapshot *surface;
if (! ctx->attach_snapshots)
return;
surface = _cairo_malloc (sizeof (*surface));
if (unlikely (surface == NULL))
return;
_cairo_surface_init (&surface->base,
&script_snapshot_backend,
&ctx->base,
source->content,
source->is_vector);
_cairo_output_stream_printf (ctx->stream,
"dup /s%d exch def ",
surface->base.unique_id);
_cairo_surface_attach_snapshot (source, &surface->base, detach_snapshot);
cairo_surface_destroy (&surface->base);
}
static cairo_status_t
_emit_recording_surface_pattern (cairo_script_surface_t *surface,
2010-04-28 09:54:56 +01:00
cairo_recording_surface_t *source)
{
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_script_implicit_context_t old_cr;
cairo_script_context_t *ctx = to_context (surface);
cairo_script_surface_t *similar;
cairo_surface_t *snapshot;
cairo_rectangle_t r, *extents;
cairo_status_t status;
snapshot = _cairo_surface_has_snapshot (&source->base, &script_snapshot_backend);
if (snapshot) {
_cairo_output_stream_printf (ctx->stream, "s%d", snapshot->unique_id);
return CAIRO_INT_STATUS_SUCCESS;
}
extents = NULL;
if (_cairo_recording_surface_get_bounds (&source->base, &r))
extents = &r;
similar = _cairo_script_surface_create_internal (ctx,
source->base.content,
extents,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
NULL);
if (unlikely (similar->base.status))
return similar->base.status;
2010-03-21 20:40:19 +00:00
similar->base.is_clear = TRUE;
_cairo_output_stream_printf (ctx->stream, "//%s ",
_content_to_string (source->base.content));
if (extents) {
_cairo_output_stream_printf (ctx->stream, "[%f %f %f %f]",
extents->x, extents->y,
extents->width, extents->height);
} else
_cairo_output_stream_puts (ctx->stream, "[]");
_cairo_output_stream_puts (ctx->stream, " record\n");
attach_snapshot (ctx, &source->base);
_cairo_output_stream_puts (ctx->stream, "dup context\n");
target_push (similar);
similar->emitted = TRUE;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
old_cr = surface->cr;
_cairo_script_implicit_context_init (&surface->cr);
status = _cairo_recording_surface_replay (&source->base, &similar->base);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
surface->cr = old_cr;
if (unlikely (status)) {
cairo_surface_destroy (&similar->base);
return status;
}
cairo_list_del (&similar->operand.link);
assert (target_is_active (surface));
_cairo_output_stream_puts (ctx->stream, "pop ");
cairo_surface_destroy (&similar->base);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_script_surface_pattern (cairo_script_surface_t *surface,
2010-04-28 09:54:56 +01:00
cairo_script_surface_t *source)
{
_get_target (source);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_write_image_surface (cairo_output_stream_t *output,
const cairo_image_surface_t *image)
{
int row, width;
ptrdiff_t stride;
uint8_t row_stack[CAIRO_STACK_BUFFER_SIZE];
uint8_t *rowdata;
uint8_t *data;
stride = image->stride;
width = image->width;
data = image->data;
#if WORDS_BIGENDIAN
switch (image->format) {
case CAIRO_FORMAT_A1:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, (width+7)/8);
data += stride;
}
break;
case CAIRO_FORMAT_A8:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, width);
data += stride;
}
break;
2010-04-07 22:44:02 +01:00
case CAIRO_FORMAT_RGB16_565:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 2*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGB24:
for (row = image->height; row--; ) {
int col;
rowdata = data;
for (col = width; col--; ) {
_cairo_output_stream_write (output, rowdata, 3);
rowdata+=4;
}
data += stride;
}
break;
case CAIRO_FORMAT_ARGB32:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 4*width);
data += stride;
}
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
break;
}
#else
if (stride > ARRAY_LENGTH (row_stack)) {
rowdata = _cairo_malloc (stride);
if (unlikely (rowdata == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else
rowdata = row_stack;
switch (image->format) {
case CAIRO_FORMAT_A1:
for (row = image->height; row--; ) {
int col;
for (col = 0; col < (width + 7)/8; col++)
rowdata[col] = CAIRO_BITSWAP8 (data[col]);
_cairo_output_stream_write (output, rowdata, (width+7)/8);
data += stride;
}
break;
case CAIRO_FORMAT_A8:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, width);
data += stride;
}
break;
case CAIRO_FORMAT_RGB16_565:
for (row = image->height; row--; ) {
uint16_t *src = (uint16_t *) data;
uint16_t *dst = (uint16_t *) rowdata;
int col;
for (col = 0; col < width; col++)
dst[col] = bswap_16 (src[col]);
_cairo_output_stream_write (output, rowdata, 2*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGB24:
for (row = image->height; row--; ) {
uint8_t *src = data;
int col;
for (col = 0; col < width; col++) {
rowdata[3*col+2] = *src++;
rowdata[3*col+1] = *src++;
rowdata[3*col+0] = *src++;
src++;
}
_cairo_output_stream_write (output, rowdata, 3*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
for (row = image->height; row--; ) {
uint32_t *src = (uint32_t *) data;
uint32_t *dst = (uint32_t *) rowdata;
int col;
for (col = 0; col < width; col++)
dst[col] = bswap_32 (src[col]);
_cairo_output_stream_write (output, rowdata, 4*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGB96F:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 12*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGBA128F:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 16*width);
data += stride;
}
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
break;
}
if (rowdata != row_stack)
free (rowdata);
#endif
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_png_surface (cairo_script_surface_t *surface,
cairo_image_surface_t *image)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_output_stream_t *base85_stream;
cairo_status_t status;
const uint8_t *mime_data;
unsigned long mime_data_length;
cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_PNG,
&mime_data, &mime_data_length);
if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_output_stream_printf (ctx->stream,
"<< "
"/width %d "
"/height %d "
"/format //%s "
"/mime-type (image/png) "
"/source <~",
image->width, image->height,
_format_to_string (image->format));
base85_stream = _cairo_base85_stream_create (ctx->stream);
_cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status))
return status;
_cairo_output_stream_puts (ctx->stream, "~> >> image ");
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_image_surface (cairo_script_surface_t *surface,
cairo_image_surface_t *image)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_output_stream_t *base85_stream;
cairo_output_stream_t *zlib_stream;
cairo_int_status_t status, status2;
cairo_surface_t *snapshot;
const uint8_t *mime_data;
unsigned long mime_data_length;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
snapshot = _cairo_surface_has_snapshot (&image->base,
&script_snapshot_backend);
if (snapshot) {
_cairo_output_stream_printf (ctx->stream, "s%u ", snapshot->unique_id);
return CAIRO_INT_STATUS_SUCCESS;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
status = _emit_png_surface (surface, image);
if (_cairo_int_status_is_error (status)) {
return status;
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
cairo_image_surface_t *clone;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
uint32_t len;
if (image->format == CAIRO_FORMAT_INVALID) {
clone = _cairo_image_surface_coerce (image);
} else {
clone = (cairo_image_surface_t *)
cairo_surface_reference (&image->base);
}
_cairo_output_stream_printf (ctx->stream,
"<< "
"/width %d "
"/height %d "
"/format //%s "
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
"/source ",
clone->width, clone->height,
_format_to_string (clone->format));
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
switch (clone->format) {
case CAIRO_FORMAT_A1:
len = (clone->width + 7)/8;
break;
case CAIRO_FORMAT_A8:
len = clone->width;
break;
case CAIRO_FORMAT_RGB16_565:
len = clone->width * 2;
break;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
case CAIRO_FORMAT_RGB24:
len = clone->width * 3;
break;
case CAIRO_FORMAT_RGB30:
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
case CAIRO_FORMAT_ARGB32:
len = clone->width * 4;
break;
case CAIRO_FORMAT_RGB96F:
len = clone->width * 12;
break;
case CAIRO_FORMAT_RGBA128F:
len = clone->width * 16;
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
len = 0;
break;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
len *= clone->height;
if (len > 24) {
_cairo_output_stream_puts (ctx->stream, "<|");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
base85_stream = _cairo_base85_stream_create (ctx->stream);
len = to_be32 (len);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_output_stream_write (base85_stream, &len, sizeof (len));
zlib_stream = _cairo_deflate_stream_create (base85_stream);
status = _write_image_surface (zlib_stream, clone);
status2 = _cairo_output_stream_destroy (zlib_stream);
if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
status2 = _cairo_output_stream_destroy (base85_stream);
if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
if (unlikely (status))
return status;
} else {
_cairo_output_stream_puts (ctx->stream, "<~");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
base85_stream = _cairo_base85_stream_create (ctx->stream);
status = _write_image_surface (base85_stream, clone);
status2 = _cairo_output_stream_destroy (base85_stream);
if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (unlikely (status))
return status;
}
_cairo_output_stream_puts (ctx->stream, "~> >> image ");
cairo_surface_destroy (&clone->base);
}
cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_JPEG,
&mime_data, &mime_data_length);
if (mime_data != NULL) {
_cairo_output_stream_printf (ctx->stream,
"\n (%s) <~",
CAIRO_MIME_TYPE_JPEG);
base85_stream = _cairo_base85_stream_create (ctx->stream);
_cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status))
return status;
_cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n");
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_JP2,
&mime_data, &mime_data_length);
if (mime_data != NULL) {
_cairo_output_stream_printf (ctx->stream,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
"\n (%s) <~",
CAIRO_MIME_TYPE_JP2);
base85_stream = _cairo_base85_stream_create (ctx->stream);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status))
return status;
_cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_image_surface_pattern (cairo_script_surface_t *surface,
2010-04-28 09:54:56 +01:00
cairo_surface_t *source)
{
cairo_image_surface_t *image;
cairo_status_t status;
void *extra;
status = _cairo_surface_acquire_source_image (source, &image, &extra);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _emit_image_surface (surface, image);
_cairo_surface_release_source_image (source, image, extra);
}
return status;
}
static cairo_int_status_t
2010-04-28 09:54:56 +01:00
_emit_subsurface_pattern (cairo_script_surface_t *surface,
cairo_surface_subsurface_t *sub)
{
cairo_surface_t *source = sub->target;
cairo_int_status_t status;
2010-04-28 09:54:56 +01:00
switch ((int) source->backend->type) {
case CAIRO_SURFACE_TYPE_RECORDING:
status = _emit_recording_surface_pattern (surface, (cairo_recording_surface_t *) source);
break;
case CAIRO_SURFACE_TYPE_SCRIPT:
status = _emit_script_surface_pattern (surface, (cairo_script_surface_t *) source);
break;
default:
status = _emit_image_surface_pattern (surface, source);
break;
}
if (unlikely (status))
return status;
_cairo_output_stream_printf (to_context (surface)->stream,
"%d %d %d %d subsurface ",
sub->extents.x,
sub->extents.y,
sub->extents.width,
sub->extents.height);
return CAIRO_INT_STATUS_SUCCESS;
2010-04-28 09:54:56 +01:00
}
static cairo_int_status_t
_emit_surface_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_surface_pattern_t *surface_pattern;
cairo_surface_t *source, *snapshot, *free_me = NULL;
cairo_surface_t *take_snapshot = NULL;
cairo_int_status_t status;
surface_pattern = (cairo_surface_pattern_t *) pattern;
source = surface_pattern->surface;
if (_cairo_surface_is_snapshot (source)) {
snapshot = _cairo_surface_has_snapshot (source, &script_snapshot_backend);
if (snapshot) {
_cairo_output_stream_printf (ctx->stream,
"s%d pattern ",
snapshot->unique_id);
return CAIRO_INT_STATUS_SUCCESS;
}
if (_cairo_surface_snapshot_is_reused (source))
take_snapshot = source;
free_me = source = _cairo_surface_snapshot_get_target (source);
}
2010-04-28 09:54:56 +01:00
2010-03-21 20:40:19 +00:00
switch ((int) source->backend->type) {
case CAIRO_SURFACE_TYPE_RECORDING:
2010-04-28 09:54:56 +01:00
status = _emit_recording_surface_pattern (surface, (cairo_recording_surface_t *) source);
break;
case CAIRO_SURFACE_TYPE_SCRIPT:
2010-04-28 09:54:56 +01:00
status = _emit_script_surface_pattern (surface, (cairo_script_surface_t *) source);
break;
case CAIRO_SURFACE_TYPE_SUBSURFACE:
2010-04-28 09:54:56 +01:00
status = _emit_subsurface_pattern (surface, (cairo_surface_subsurface_t *) source);
break;
default:
2010-04-28 09:54:56 +01:00
status = _emit_image_surface_pattern (surface, source);
break;
}
cairo_surface_destroy (free_me);
2010-04-28 09:54:56 +01:00
if (unlikely (status))
return status;
if (take_snapshot)
attach_snapshot (ctx, take_snapshot);
_cairo_output_stream_puts (ctx->stream, "pattern");
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_raster_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_surface_t *source;
cairo_int_status_t status;
source = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL);
if (unlikely (source == NULL)) {
ASSERT_NOT_REACHED;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (unlikely (source->status))
return source->status;
status = _emit_image_surface_pattern (surface, source);
_cairo_raster_source_pattern_release (pattern, source);
if (unlikely (status))
return status;
_cairo_output_stream_puts (to_context(surface)->stream, "pattern");
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_int_status_t status;
cairo_bool_t is_default_extend;
cairo_bool_t need_newline = TRUE;
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
/* solid colors do not need filter/extend/matrix */
return _emit_solid_pattern (surface, pattern);
case CAIRO_PATTERN_TYPE_LINEAR:
status = _emit_linear_pattern (surface, pattern);
is_default_extend = pattern->extend == CAIRO_EXTEND_GRADIENT_DEFAULT;
break;
case CAIRO_PATTERN_TYPE_RADIAL:
status = _emit_radial_pattern (surface, pattern);
is_default_extend = pattern->extend == CAIRO_EXTEND_GRADIENT_DEFAULT;
break;
case CAIRO_PATTERN_TYPE_MESH:
status = _emit_mesh_pattern (surface, pattern);
is_default_extend = TRUE;
break;
case CAIRO_PATTERN_TYPE_SURFACE:
status = _emit_surface_pattern (surface, pattern);
is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT;
break;
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
status = _emit_raster_pattern (surface, pattern);
is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT;
break;
default:
ASSERT_NOT_REACHED;
status = CAIRO_INT_STATUS_UNSUPPORTED;
}
if (unlikely (status))
return status;
if (! _cairo_matrix_is_identity (&pattern->matrix)) {
if (need_newline) {
_cairo_output_stream_puts (ctx->stream, "\n ");
need_newline = FALSE;
}
_cairo_output_stream_printf (ctx->stream,
" [%f %f %f %f %f %f] set-matrix\n ",
pattern->matrix.xx, pattern->matrix.yx,
pattern->matrix.xy, pattern->matrix.yy,
pattern->matrix.x0, pattern->matrix.y0);
}
/* XXX need to discriminate the user explicitly setting the default */
if (pattern->filter != CAIRO_FILTER_DEFAULT) {
if (need_newline) {
_cairo_output_stream_puts (ctx->stream, "\n ");
need_newline = FALSE;
}
_cairo_output_stream_printf (ctx->stream,
" //%s set-filter\n ",
_filter_to_string (pattern->filter));
}
if (! is_default_extend ){
if (need_newline) {
_cairo_output_stream_puts (ctx->stream, "\n ");
need_newline = FALSE;
}
_cairo_output_stream_printf (ctx->stream,
" //%s set-extend\n ",
_extend_to_string (pattern->extend));
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (need_newline)
_cairo_output_stream_puts (ctx->stream, "\n ");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_identity (cairo_script_surface_t *surface,
cairo_bool_t *matrix_updated)
{
assert (target_is_active (surface));
if (_cairo_matrix_is_identity (&surface->cr.current_ctm))
return CAIRO_INT_STATUS_SUCCESS;
_cairo_output_stream_puts (to_context (surface)->stream,
"identity set-matrix\n");
*matrix_updated = TRUE;
cairo_matrix_init_identity (&surface->cr.current_ctm);
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_emit_source (cairo_script_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source)
{
cairo_bool_t matrix_updated = FALSE;
cairo_int_status_t status;
assert (target_is_active (surface));
if (op == CAIRO_OPERATOR_CLEAR) {
/* the source is ignored, so don't change it */
return CAIRO_INT_STATUS_SUCCESS;
}
if (_cairo_pattern_equal (&surface->cr.current_source.base, source))
return CAIRO_INT_STATUS_SUCCESS;
_cairo_pattern_fini (&surface->cr.current_source.base);
status = _cairo_pattern_init_copy (&surface->cr.current_source.base,
source);
if (unlikely (status))
return status;
status = _emit_identity (surface, &matrix_updated);
if (unlikely (status))
return status;
status = _emit_pattern (surface, source);
if (unlikely (status))
return status;
assert (target_is_active (surface));
_cairo_output_stream_puts (to_context (surface)->stream,
" set-source\n");
return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_status_t
_path_move_to (void *closure,
const cairo_point_t *point)
{
_cairo_output_stream_printf (closure,
" %f %f m",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_path_line_to (void *closure,
const cairo_point_t *point)
{
_cairo_output_stream_printf (closure,
" %f %f l",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_path_curve_to (void *closure,
const cairo_point_t *p1,
const cairo_point_t *p2,
const cairo_point_t *p3)
{
_cairo_output_stream_printf (closure,
" %f %f %f %f %f %f c",
_cairo_fixed_to_double (p1->x),
_cairo_fixed_to_double (p1->y),
_cairo_fixed_to_double (p2->x),
_cairo_fixed_to_double (p2->y),
_cairo_fixed_to_double (p3->x),
_cairo_fixed_to_double (p3->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_path_close (void *closure)
{
_cairo_output_stream_printf (closure,
" h");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_path_boxes (cairo_script_surface_t *surface,
const cairo_path_fixed_t *path)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_path_fixed_iter_t iter;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
struct _cairo_boxes_chunk *chunk;
cairo_boxes_t boxes;
cairo_box_t box;
int i;
_cairo_boxes_init (&boxes);
_cairo_path_fixed_iter_init (&iter, path);
while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
if (box.p1.y == box.p2.y || box.p1.x == box.p2.x)
continue;
status = _cairo_boxes_add (&boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
if (unlikely (status)) {
_cairo_boxes_fini (&boxes);
return status;
}
}
if (! _cairo_path_fixed_iter_at_end (&iter)) {
_cairo_boxes_fini (&boxes);
return CAIRO_STATUS_INVALID_PATH_DATA;
}
for (chunk = &boxes.chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
const cairo_box_t *b = &chunk->base[i];
double x1 = _cairo_fixed_to_double (b->p1.x);
double y1 = _cairo_fixed_to_double (b->p1.y);
double x2 = _cairo_fixed_to_double (b->p2.x);
double y2 = _cairo_fixed_to_double (b->p2.y);
_cairo_output_stream_printf (ctx->stream,
"\n %f %f %f %f rectangle",
x1, y1, x2 - x1, y2 - y1);
}
}
_cairo_boxes_fini (&boxes);
return status;
}
static cairo_status_t
_emit_path (cairo_script_surface_t *surface,
const cairo_path_fixed_t *path,
cairo_bool_t is_fill)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_box_t box;
cairo_int_status_t status;
assert (target_is_active (surface));
assert (_cairo_matrix_is_identity (&surface->cr.current_ctm));
if (_cairo_path_fixed_equal (&surface->cr.current_path, path))
return CAIRO_STATUS_SUCCESS;
_cairo_path_fixed_fini (&surface->cr.current_path);
_cairo_output_stream_puts (ctx->stream, "n");
if (path == NULL) {
_cairo_path_fixed_init (&surface->cr.current_path);
_cairo_output_stream_puts (ctx->stream, "\n");
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_path_fixed_init_copy (&surface->cr.current_path, path);
if (unlikely (status))
return status;
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_is_rectangle (path, &box)) {
double x1 = _cairo_fixed_to_double (box.p1.x);
double y1 = _cairo_fixed_to_double (box.p1.y);
double x2 = _cairo_fixed_to_double (box.p2.x);
double y2 = _cairo_fixed_to_double (box.p2.y);
assert (x1 > -9999);
_cairo_output_stream_printf (ctx->stream,
" %f %f %f %f rectangle",
x1, y1, x2 - x1, y2 - y1);
status = CAIRO_INT_STATUS_SUCCESS;
} else if (is_fill && _cairo_path_fixed_fill_is_rectilinear (path)) {
status = _emit_path_boxes (surface, path);
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_path_fixed_interpret (path,
_path_move_to,
_path_line_to,
_path_curve_to,
_path_close,
ctx->stream);
}
_cairo_output_stream_puts (ctx->stream, "\n");
return status;
}
static cairo_bool_t
_scaling_matrix_equal (const cairo_matrix_t *a,
const cairo_matrix_t *b)
{
return fabs (a->xx - b->xx) < 1e-5 &&
fabs (a->xy - b->xy) < 1e-5 &&
fabs (a->yx - b->yx) < 1e-5 &&
fabs (a->yy - b->yy) < 1e-5;
}
static cairo_status_t
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_emit_scaling_matrix (cairo_script_surface_t *surface,
const cairo_matrix_t *ctm,
cairo_bool_t *matrix_updated)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_bool_t was_identity;
assert (target_is_active (surface));
if (_scaling_matrix_equal (&surface->cr.current_ctm, ctm))
return CAIRO_STATUS_SUCCESS;
was_identity = _cairo_matrix_is_identity (&surface->cr.current_ctm);
*matrix_updated = TRUE;
surface->cr.current_ctm = *ctm;
surface->cr.current_ctm.x0 = 0.;
surface->cr.current_ctm.y0 = 0.;
if (_cairo_matrix_is_identity (&surface->cr.current_ctm)) {
_cairo_output_stream_puts (ctx->stream,
"identity set-matrix\n");
} else if (was_identity && fabs (ctm->yx) < 1e-5 && fabs (ctm->xy) < 1e-5) {
_cairo_output_stream_printf (ctx->stream,
"%f %f scale\n",
ctm->xx, ctm->yy);
} else {
_cairo_output_stream_printf (ctx->stream,
"[%f %f %f %f 0 0] set-matrix\n",
ctm->xx, ctm->yx,
ctm->xy, ctm->yy);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_font_matrix (cairo_script_surface_t *surface,
const cairo_matrix_t *font_matrix)
{
cairo_script_context_t *ctx = to_context (surface);
assert (target_is_active (surface));
if (memcmp (&surface->cr.current_font_matrix,
font_matrix,
sizeof (cairo_matrix_t)) == 0)
{
return CAIRO_STATUS_SUCCESS;
}
surface->cr.current_font_matrix = *font_matrix;
if (_cairo_matrix_is_identity (font_matrix)) {
_cairo_output_stream_puts (ctx->stream,
"identity set-font-matrix\n");
} else {
_cairo_output_stream_printf (ctx->stream,
"[%f %f %f %f %f %f] set-font-matrix\n",
font_matrix->xx, font_matrix->yx,
font_matrix->xy, font_matrix->yy,
font_matrix->x0, font_matrix->y0);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_script_surface_create_similar (void *abstract_surface,
cairo_content_t content,
int width,
int height)
{
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_script_surface_t *surface, *other = abstract_surface;
cairo_surface_t *passthrough = NULL;
cairo_script_context_t *ctx;
cairo_rectangle_t extents;
cairo_status_t status;
ctx = to_context (other);
status = cairo_device_acquire (&ctx->base);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
if (! other->emitted) {
status = _emit_surface (other);
if (unlikely (status)) {
cairo_device_release (&ctx->base);
return _cairo_surface_create_in_error (status);
}
target_push (other);
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&other->wrapper)) {
passthrough =
_cairo_surface_wrapper_create_similar (&other->wrapper,
content, width, height);
if (unlikely (passthrough->status)) {
cairo_device_release (&ctx->base);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
return passthrough;
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
extents.x = extents.y = 0;
extents.width = width;
extents.height = height;
surface = _cairo_script_surface_create_internal (ctx, content,
&extents, passthrough);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_surface_destroy (passthrough);
if (unlikely (surface->base.status)) {
cairo_device_release (&ctx->base);
return &surface->base;
}
_get_target (other);
_cairo_output_stream_printf (ctx->stream,
"%u %u //%s similar dup /s%u exch def context\n",
width, height,
_content_to_string (content),
surface->base.unique_id);
surface->emitted = TRUE;
surface->defined = TRUE;
2010-03-21 20:40:19 +00:00
surface->base.is_clear = TRUE;
target_push (surface);
cairo_device_release (&ctx->base);
return &surface->base;
}
static cairo_status_t
2010-03-21 20:40:19 +00:00
_device_flush (void *abstract_device)
{
cairo_script_context_t *ctx = abstract_device;
return _cairo_output_stream_flush (ctx->stream);
2010-03-21 20:40:19 +00:00
}
static void
_device_destroy (void *abstract_device)
{
cairo_script_context_t *ctx = abstract_device;
cairo_status_t status;
while (! cairo_list_is_empty (&ctx->fonts)) {
cairo_script_font_t *font;
font = cairo_list_first_entry (&ctx->fonts, cairo_script_font_t, link);
cairo_list_del (&font->base.link);
cairo_list_del (&font->link);
free (font);
}
2010-03-23 20:08:04 +00:00
_bitmap_fini (ctx->surface_id.next);
_bitmap_fini (ctx->font_id.next);
if (ctx->owns_stream)
status = _cairo_output_stream_destroy (ctx->stream);
free (ctx);
}
static cairo_surface_t *
_cairo_script_surface_source (void *abstract_surface,
cairo_rectangle_int_t *extents)
{
cairo_script_surface_t *surface = abstract_surface;
if (extents) {
extents->x = extents->y = 0;
extents->width = surface->width;
extents->height = surface->height;
}
return &surface->base;
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
static cairo_status_t
_cairo_script_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_script_surface_t *surface = abstract_surface;
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_acquire_source_image (&surface->wrapper,
image_out,
image_extra);
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static void
_cairo_script_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
cairo_script_surface_t *surface = abstract_surface;
assert (_cairo_surface_wrapper_is_active (&surface->wrapper));
_cairo_surface_wrapper_release_source_image (&surface->wrapper,
image,
image_extra);
}
static cairo_status_t
_cairo_script_surface_finish (void *abstract_surface)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_script_context_t *ctx = to_context (surface);
cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_surface_wrapper_fini (&surface->wrapper);
free (surface->cr.current_style.dash);
surface->cr.current_style.dash = NULL;
_cairo_pattern_fini (&surface->cr.current_source.base);
_cairo_path_fixed_fini (&surface->cr.current_path);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_surface_clipper_reset (&surface->clipper);
status = cairo_device_acquire (&ctx->base);
if (unlikely (status))
return status;
if (surface->emitted) {
assert (! surface->active);
if (! cairo_list_is_empty (&surface->operand.link)) {
if (! ctx->active) {
if (target_is_active (surface)) {
_cairo_output_stream_printf (ctx->stream,
"pop\n");
} else {
int depth = target_depth (surface);
if (depth == 1) {
_cairo_output_stream_printf (ctx->stream,
"exch pop\n");
} else {
_cairo_output_stream_printf (ctx->stream,
"%d -1 roll pop\n",
depth);
}
}
cairo_list_del (&surface->operand.link);
} else {
struct deferred_finish *link = _cairo_malloc (sizeof (*link));
if (link == NULL) {
status2 = _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
cairo_list_del (&surface->operand.link);
} else {
link->operand.type = DEFERRED;
cairo_list_swap (&link->operand.link,
&surface->operand.link);
cairo_list_add (&link->link, &ctx->deferred);
}
}
}
if (surface->defined) {
_cairo_output_stream_printf (ctx->stream,
"/s%u undef\n",
surface->base.unique_id);
}
}
2010-03-21 20:40:19 +00:00
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_flush (to_context (surface)->stream);
cairo_device_release (&ctx->base);
return status;
}
static cairo_int_status_t
_cairo_script_surface_copy_page (void *abstract_surface)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
status = cairo_device_acquire (surface->base.device);
if (unlikely (status))
return status;
status = _emit_context (surface);
if (unlikely (status))
goto BAIL;
_cairo_output_stream_puts (to_context (surface)->stream, "copy-page\n");
BAIL:
cairo_device_release (surface->base.device);
return status;
}
static cairo_int_status_t
_cairo_script_surface_show_page (void *abstract_surface)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
status = cairo_device_acquire (surface->base.device);
if (unlikely (status))
return status;
status = _emit_context (surface);
if (unlikely (status))
goto BAIL;
_cairo_output_stream_puts (to_context (surface)->stream, "show-page\n");
BAIL:
cairo_device_release (surface->base.device);
return status;
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
static cairo_status_t
_cairo_script_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_script_surface_t *surface = cairo_container_of (clipper,
cairo_script_surface_t,
clipper);
cairo_script_context_t *ctx = to_context (surface);
cairo_bool_t matrix_updated = FALSE;
cairo_status_t status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_box_t box;
status = _emit_context (surface);
if (unlikely (status))
return status;
if (path == NULL) {
if (surface->cr.has_clip) {
_cairo_output_stream_puts (ctx->stream, "reset-clip\n");
surface->cr.has_clip = FALSE;
}
return CAIRO_STATUS_SUCCESS;
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
/* skip the trivial clip covering the surface extents */
if (surface->width >= 0 && surface->height >= 0 &&
_cairo_path_fixed_is_box (path, &box))
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
{
if (box.p1.x <= 0 && box.p1.y <= 0 &&
box.p2.x >= _cairo_fixed_from_double (surface->width) &&
box.p2.y >= _cairo_fixed_from_double (surface->height))
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
{
return CAIRO_STATUS_SUCCESS;
}
}
status = _emit_identity (surface, &matrix_updated);
if (unlikely (status))
return status;
status = _emit_fill_rule (surface, fill_rule);
if (unlikely (status))
return status;
if (path->has_curve_to) {
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_tolerance (surface, tolerance, matrix_updated);
if (unlikely (status))
return status;
}
if (! _cairo_path_fixed_fill_maybe_region (path)) {
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_antialias (surface, antialias);
if (unlikely (status))
return status;
}
status = _emit_path (surface, path, TRUE);
if (unlikely (status))
return status;
_cairo_output_stream_puts (ctx->stream, "clip+\n");
surface->cr.has_clip = TRUE;
return CAIRO_STATUS_SUCCESS;
}
2010-03-21 20:40:19 +00:00
static cairo_status_t
active (cairo_script_surface_t *surface)
{
2010-03-21 20:40:19 +00:00
cairo_status_t status;
status = cairo_device_acquire (surface->base.device);
if (unlikely (status))
return status;
if (surface->active++ == 0)
to_context (surface)->active++;
2010-03-21 20:40:19 +00:00
return CAIRO_STATUS_SUCCESS;
}
static void
inactive (cairo_script_surface_t *surface)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_list_t sorted;
assert (surface->active > 0);
if (--surface->active)
2010-03-21 20:40:19 +00:00
goto DONE;
assert (ctx->active > 0);
if (--ctx->active)
2010-03-21 20:40:19 +00:00
goto DONE;
cairo_list_init (&sorted);
while (! cairo_list_is_empty (&ctx->deferred)) {
struct deferred_finish *df;
cairo_list_t *operand;
int depth;
df = cairo_list_first_entry (&ctx->deferred,
struct deferred_finish,
link);
depth = 0;
cairo_list_foreach (operand, &ctx->operands) {
if (operand == &df->operand.link)
break;
depth++;
}
df->operand.type = depth;
if (cairo_list_is_empty (&sorted)) {
cairo_list_move (&df->link, &sorted);
} else {
struct deferred_finish *pos;
cairo_list_foreach_entry (pos, struct deferred_finish,
&sorted,
link)
{
if (df->operand.type < pos->operand.type)
break;
}
cairo_list_move_tail (&df->link, &pos->link);
}
}
while (! cairo_list_is_empty (&sorted)) {
struct deferred_finish *df;
cairo_list_t *operand;
int depth;
df = cairo_list_first_entry (&sorted,
struct deferred_finish,
link);
depth = 0;
cairo_list_foreach (operand, &ctx->operands) {
if (operand == &df->operand.link)
break;
depth++;
}
if (depth == 0) {
_cairo_output_stream_printf (ctx->stream,
"pop\n");
} else if (depth == 1) {
_cairo_output_stream_printf (ctx->stream,
"exch pop\n");
} else {
_cairo_output_stream_printf (ctx->stream,
"%d -1 roll pop\n",
depth);
}
cairo_list_del (&df->operand.link);
cairo_list_del (&df->link);
free (df);
}
2010-03-21 20:40:19 +00:00
DONE:
cairo_device_release (surface->base.device);
}
static cairo_int_status_t
_cairo_script_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
2010-03-21 20:40:19 +00:00
status = active (surface);
if (unlikely (status))
return status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_context (surface);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_source (surface, op, source);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_operator (surface, op);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_output_stream_puts (to_context (surface)->stream,
"paint\n");
inactive (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_paint (&surface->wrapper,
op, source, clip);
}
return CAIRO_STATUS_SUCCESS;
2010-03-21 20:40:19 +00:00
BAIL:
inactive (surface);
return status;
}
static cairo_int_status_t
_cairo_script_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
2010-03-21 20:40:19 +00:00
status = active (surface);
if (unlikely (status))
return status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_context (surface);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_source (surface, op, source);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_operator (surface, op);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_pattern_equal (source, mask)) {
_cairo_output_stream_puts (to_context (surface)->stream, "/source get");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
} else {
status = _emit_pattern (surface, mask);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
assert (surface->cr.current_operator == op);
_cairo_output_stream_puts (to_context (surface)->stream,
" mask\n");
inactive (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_mask (&surface->wrapper,
op, source, mask, clip);
}
return CAIRO_STATUS_SUCCESS;
2010-03-21 20:40:19 +00:00
BAIL:
inactive (surface);
return status;
}
static cairo_int_status_t
_cairo_script_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_bool_t matrix_updated = FALSE;
cairo_status_t status;
2010-03-21 20:40:19 +00:00
status = active (surface);
if (unlikely (status))
return status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_context (surface);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_identity (surface, &matrix_updated);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_path (surface, path, FALSE);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_source (surface, op, source);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_scaling_matrix (surface, ctm, &matrix_updated);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_operator (surface, op);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
if (_scaling_matrix_equal (&surface->cr.current_ctm,
&surface->cr.current_stroke_matrix))
{
matrix_updated = FALSE;
}
else
{
matrix_updated = TRUE;
surface->cr.current_stroke_matrix = surface->cr.current_ctm;
}
status = _emit_stroke_style (surface, style, matrix_updated);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_tolerance (surface, tolerance, matrix_updated);
if (unlikely (status))
goto BAIL;
status = _emit_antialias (surface, antialias);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
_cairo_output_stream_puts (to_context (surface)->stream, "stroke+\n");
inactive (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_stroke (&surface->wrapper,
op, source, path,
style,
ctm, ctm_inverse,
tolerance, antialias,
clip);
}
return CAIRO_STATUS_SUCCESS;
2010-03-21 20:40:19 +00:00
BAIL:
inactive (surface);
return status;
}
static cairo_int_status_t
_cairo_script_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_bool_t matrix_updated = FALSE;
cairo_status_t status;
cairo_box_t box;
2010-03-21 20:40:19 +00:00
status = active (surface);
if (unlikely (status))
return status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_context (surface);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_identity (surface, &matrix_updated);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_source (surface, op, source);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
if (! _cairo_path_fixed_is_box (path, &box)) {
status = _emit_fill_rule (surface, fill_rule);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
}
if (path->has_curve_to) {
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_tolerance (surface, tolerance, matrix_updated);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
if (! _cairo_path_fixed_fill_maybe_region (path)) {
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_antialias (surface, antialias);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
status = _emit_path (surface, path, TRUE);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_operator (surface, op);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
_cairo_output_stream_puts (to_context (surface)->stream, "fill+\n");
inactive (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_fill (&surface->wrapper,
op, source, path,
fill_rule,
tolerance,
antialias,
clip);
}
return CAIRO_STATUS_SUCCESS;
2010-03-21 20:40:19 +00:00
BAIL:
inactive (surface);
return status;
}
static cairo_surface_t *
_cairo_script_surface_snapshot (void *abstract_surface)
{
cairo_script_surface_t *surface = abstract_surface;
if (_cairo_surface_wrapper_is_active (&surface->wrapper))
return _cairo_surface_wrapper_snapshot (&surface->wrapper);
return NULL;
}
static cairo_bool_t
_cairo_script_surface_has_show_text_glyphs (void *abstract_surface)
{
return TRUE;
}
static const char *
_subpixel_order_to_string (cairo_subpixel_order_t subpixel_order)
{
static const char *names[] = {
"SUBPIXEL_ORDER_DEFAULT", /* CAIRO_SUBPIXEL_ORDER_DEFAULT */
"SUBPIXEL_ORDER_RGB", /* CAIRO_SUBPIXEL_ORDER_RGB */
"SUBPIXEL_ORDER_BGR", /* CAIRO_SUBPIXEL_ORDER_BGR */
"SUBPIXEL_ORDER_VRGB", /* CAIRO_SUBPIXEL_ORDER_VRGB */
"SUBPIXEL_ORDER_VBGR" /* CAIRO_SUBPIXEL_ORDER_VBGR */
};
return names[subpixel_order];
}
static const char *
_hint_style_to_string (cairo_hint_style_t hint_style)
{
static const char *names[] = {
"HINT_STYLE_DEFAULT", /* CAIRO_HINT_STYLE_DEFAULT */
"HINT_STYLE_NONE", /* CAIRO_HINT_STYLE_NONE */
"HINT_STYLE_SLIGHT", /* CAIRO_HINT_STYLE_SLIGHT */
"HINT_STYLE_MEDIUM", /* CAIRO_HINT_STYLE_MEDIUM */
"HINT_STYLE_FULL" /* CAIRO_HINT_STYLE_FULL */
};
return names[hint_style];
}
static const char *
_hint_metrics_to_string (cairo_hint_metrics_t hint_metrics)
{
static const char *names[] = {
"HINT_METRICS_DEFAULT", /* CAIRO_HINT_METRICS_DEFAULT */
"HINT_METRICS_OFF", /* CAIRO_HINT_METRICS_OFF */
"HINT_METRICS_ON" /* CAIRO_HINT_METRICS_ON */
};
return names[hint_metrics];
}
static cairo_status_t
_emit_font_options (cairo_script_surface_t *surface,
cairo_font_options_t *font_options)
{
cairo_script_context_t *ctx = to_context (surface);
if (cairo_font_options_equal (&surface->cr.current_font_options,
font_options))
{
return CAIRO_STATUS_SUCCESS;
}
_cairo_output_stream_printf (ctx->stream, "<<");
if (font_options->antialias != surface->cr.current_font_options.antialias) {
_cairo_output_stream_printf (ctx->stream,
" /antialias //%s",
_antialias_to_string (font_options->antialias));
}
if (font_options->subpixel_order !=
surface->cr.current_font_options.subpixel_order)
{
_cairo_output_stream_printf (ctx->stream,
" /subpixel-order //%s",
_subpixel_order_to_string (font_options->subpixel_order));
}
if (font_options->hint_style !=
surface->cr.current_font_options.hint_style)
{
_cairo_output_stream_printf (ctx->stream,
" /hint-style //%s",
_hint_style_to_string (font_options->hint_style));
}
if (font_options->hint_metrics !=
surface->cr.current_font_options.hint_metrics)
{
_cairo_output_stream_printf (ctx->stream,
" /hint-metrics //%s",
_hint_metrics_to_string (font_options->hint_metrics));
}
_cairo_output_stream_printf (ctx->stream,
" >> set-font-options\n");
surface->cr.current_font_options = *font_options;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_script_scaled_font_fini (cairo_scaled_font_private_t *abstract_private,
cairo_scaled_font_t *scaled_font)
{
cairo_script_font_t *priv = (cairo_script_font_t *)abstract_private;
cairo_script_context_t *ctx = (cairo_script_context_t *)abstract_private->key;
cairo_status_t status;
status = cairo_device_acquire (&ctx->base);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
_cairo_output_stream_printf (ctx->stream,
"/f%lu undef /sf%lu undef\n",
priv->id,
priv->id);
_bitmap_release_id (&ctx->font_id, priv->id);
cairo_device_release (&ctx->base);
}
cairo_list_del (&priv->link);
cairo_list_del (&priv->base.link);
free (priv);
}
static cairo_script_font_t *
_cairo_script_font_get (cairo_script_context_t *ctx, cairo_scaled_font_t *font)
{
return (cairo_script_font_t *) _cairo_scaled_font_find_private (font, ctx);
}
static long unsigned
_cairo_script_font_id (cairo_script_context_t *ctx, cairo_scaled_font_t *font)
{
return _cairo_script_font_get (ctx, font)->id;
}
static cairo_status_t
_emit_type42_font (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_script_context_t *ctx = to_context (surface);
const cairo_scaled_font_backend_t *backend;
cairo_output_stream_t *base85_stream;
cairo_output_stream_t *zlib_stream;
cairo_status_t status, status2;
unsigned long size;
unsigned int load_flags;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
uint32_t len;
uint8_t *buf;
backend = scaled_font->backend;
if (backend->load_truetype_table == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
size = 0;
status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size);
if (unlikely (status))
return status;
buf = _cairo_malloc (size);
if (unlikely (buf == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size);
if (unlikely (status)) {
free (buf);
return status;
}
2010-04-07 22:46:38 +01:00
#if CAIRO_HAS_FT_FONT
load_flags = _cairo_ft_scaled_font_get_load_flags (scaled_font);
2010-04-07 22:46:38 +01:00
#else
load_flags = 0;
#endif
_cairo_output_stream_printf (ctx->stream,
"<< "
"/type 42 "
"/index 0 "
"/flags %d "
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
"/source <|",
load_flags);
base85_stream = _cairo_base85_stream_create (ctx->stream);
len = to_be32 (size);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_output_stream_write (base85_stream, &len, sizeof (len));
zlib_stream = _cairo_deflate_stream_create (base85_stream);
_cairo_output_stream_write (zlib_stream, buf, size);
free (buf);
status2 = _cairo_output_stream_destroy (zlib_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
status2 = _cairo_output_stream_destroy (base85_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_printf (ctx->stream,
"~> >> font dup /f%lu exch def set-font-face",
_cairo_script_font_id (ctx, scaled_font));
return status;
}
static cairo_status_t
_emit_scaled_font_init (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_script_font_t **font_out)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_script_font_t *font_private;
cairo_int_status_t status;
font_private = _cairo_malloc (sizeof (cairo_script_font_t));
if (unlikely (font_private == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_scaled_font_attach_private (scaled_font, &font_private->base, ctx,
_cairo_script_scaled_font_fini);
font_private->parent = scaled_font;
font_private->subset_glyph_index = 0;
font_private->has_sfnt = TRUE;
cairo_list_add (&font_private->link, &ctx->fonts);
status = _bitmap_next_id (&ctx->font_id,
&font_private->id);
if (unlikely (status)) {
free (font_private);
return status;
}
status = _emit_context (surface);
if (unlikely (status)) {
free (font_private);
return status;
}
status = _emit_type42_font (surface, scaled_font);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
*font_out = font_private;
return status;
}
font_private->has_sfnt = FALSE;
_cairo_output_stream_printf (ctx->stream,
"dict\n"
" /type 3 set\n"
" /metrics [%f %f %f %f %f] set\n"
" /glyphs array set\n"
" font dup /f%lu exch def set-font-face",
scaled_font->fs_extents.ascent,
scaled_font->fs_extents.descent,
scaled_font->fs_extents.height,
scaled_font->fs_extents.max_x_advance,
scaled_font->fs_extents.max_y_advance,
font_private->id);
*font_out = font_private;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_scaled_font (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_matrix_t matrix;
cairo_font_options_t options;
cairo_bool_t matrix_updated = FALSE;
cairo_status_t status;
cairo_script_font_t *font_private;
cairo_scaled_font_get_ctm (scaled_font, &matrix);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_scaling_matrix (surface, &matrix, &matrix_updated);
if (unlikely (status))
return status;
if (! matrix_updated && surface->cr.current_scaled_font == scaled_font)
return CAIRO_STATUS_SUCCESS;
surface->cr.current_scaled_font = scaled_font;
font_private = _cairo_script_font_get (ctx, scaled_font);
if (font_private == NULL) {
cairo_scaled_font_get_font_matrix (scaled_font, &matrix);
status = _emit_font_matrix (surface, &matrix);
if (unlikely (status))
return status;
cairo_scaled_font_get_font_options (scaled_font, &options);
status = _emit_font_options (surface, &options);
if (unlikely (status))
return status;
status = _emit_scaled_font_init (surface, scaled_font, &font_private);
if (unlikely (status))
return status;
assert (target_is_active (surface));
_cairo_output_stream_printf (ctx->stream,
" /scaled-font get /sf%lu exch def\n",
font_private->id);
} else {
_cairo_output_stream_printf (ctx->stream,
"sf%lu set-scaled-font\n",
font_private->id);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_scaled_glyph_vector (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_script_font_t *font_private,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_script_implicit_context_t old_cr;
cairo_status_t status;
unsigned long index;
index = ++font_private->subset_glyph_index;
scaled_glyph->dev_private_key = ctx;
scaled_glyph->dev_private = (void *) index;
_cairo_output_stream_printf (ctx->stream,
"%lu <<\n"
" /metrics [%f %f %f %f %f %f]\n"
" /render {\n",
index,
scaled_glyph->fs_metrics.x_bearing,
scaled_glyph->fs_metrics.y_bearing,
scaled_glyph->fs_metrics.width,
scaled_glyph->fs_metrics.height,
scaled_glyph->fs_metrics.x_advance,
scaled_glyph->fs_metrics.y_advance);
if (! _cairo_matrix_is_identity (&scaled_font->scale_inverse)) {
_cairo_output_stream_printf (ctx->stream,
"[%f %f %f %f %f %f] transform\n",
scaled_font->scale_inverse.xx,
scaled_font->scale_inverse.yx,
scaled_font->scale_inverse.xy,
scaled_font->scale_inverse.yy,
scaled_font->scale_inverse.x0,
scaled_font->scale_inverse.y0);
}
old_cr = surface->cr;
_cairo_script_implicit_context_init (&surface->cr);
status = _cairo_recording_surface_replay (scaled_glyph->recording_surface,
&surface->base);
surface->cr = old_cr;
_cairo_output_stream_puts (ctx->stream, "} >> set\n");
return status;
}
static cairo_status_t
_emit_scaled_glyph_bitmap (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_script_font_t *font_private,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_status_t status;
unsigned long index;
index = ++font_private->subset_glyph_index;
scaled_glyph->dev_private_key = ctx;
scaled_glyph->dev_private = (void *) index;
_cairo_output_stream_printf (ctx->stream,
"%lu <<\n"
" /metrics [%f %f %f %f %f %f]\n"
" /render {\n"
"%f %f translate\n",
index,
scaled_glyph->fs_metrics.x_bearing,
scaled_glyph->fs_metrics.y_bearing,
scaled_glyph->fs_metrics.width,
scaled_glyph->fs_metrics.height,
scaled_glyph->fs_metrics.x_advance,
scaled_glyph->fs_metrics.y_advance,
scaled_glyph->fs_metrics.x_bearing,
scaled_glyph->fs_metrics.y_bearing);
status = _emit_image_surface (surface, scaled_glyph->surface);
if (unlikely (status))
return status;
2010-04-28 09:54:56 +01:00
_cairo_output_stream_puts (ctx->stream, "pattern ");
if (! _cairo_matrix_is_identity (&scaled_font->font_matrix)) {
_cairo_output_stream_printf (ctx->stream,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
"\n [%f %f %f %f %f %f] set-matrix\n",
scaled_font->font_matrix.xx,
scaled_font->font_matrix.yx,
scaled_font->font_matrix.xy,
scaled_font->font_matrix.yy,
scaled_font->font_matrix.x0,
scaled_font->font_matrix.y0);
}
_cairo_output_stream_puts (ctx->stream,
"mask\n} >> set\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_scaled_glyph_prologue (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_script_context_t *ctx = to_context (surface);
_cairo_output_stream_printf (ctx->stream, "f%lu /glyphs get\n",
_cairo_script_font_id (ctx, scaled_font));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_emit_scaled_glyphs (cairo_script_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
unsigned int num_glyphs)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_script_font_t *font_private;
cairo_status_t status;
unsigned int n;
cairo_bool_t have_glyph_prologue = FALSE;
if (num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
font_private = _cairo_script_font_get (ctx, scaled_font);
if (font_private->has_sfnt)
return CAIRO_STATUS_SUCCESS;
_cairo_scaled_font_freeze_cache (scaled_font);
for (n = 0; n < num_glyphs; n++) {
cairo_scaled_glyph_t *scaled_glyph;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (unlikely (status))
break;
if (scaled_glyph->dev_private_key == ctx)
continue;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
&scaled_glyph);
if (_cairo_status_is_error (status))
break;
if (status == CAIRO_STATUS_SUCCESS) {
if (! have_glyph_prologue) {
status = _emit_scaled_glyph_prologue (surface, scaled_font);
if (unlikely (status))
break;
have_glyph_prologue = TRUE;
}
status = _emit_scaled_glyph_vector (surface,
scaled_font, font_private,
scaled_glyph);
if (unlikely (status))
break;
continue;
}
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (_cairo_status_is_error (status))
break;
if (status == CAIRO_STATUS_SUCCESS) {
if (! have_glyph_prologue) {
status = _emit_scaled_glyph_prologue (surface, scaled_font);
if (unlikely (status))
break;
have_glyph_prologue = TRUE;
}
status = _emit_scaled_glyph_bitmap (surface,
scaled_font,
font_private,
scaled_glyph);
if (unlikely (status))
break;
continue;
}
}
_cairo_scaled_font_thaw_cache (scaled_font);
if (have_glyph_prologue) {
_cairo_output_stream_puts (to_context (surface)->stream, "pop pop\n");
}
return status;
}
static void
to_octal (int value, char *buf, size_t size)
{
do {
buf[--size] = '0' + (value & 7);
value >>= 3;
} while (size);
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
static void
_emit_string_literal (cairo_script_surface_t *surface,
const char *utf8, int len)
{
cairo_script_context_t *ctx = to_context (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
char c;
const char *end;
_cairo_output_stream_puts (ctx->stream, "(");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (utf8 == NULL) {
end = utf8;
} else {
if (len < 0)
len = strlen (utf8);
end = utf8 + len;
}
while (utf8 < end) {
switch ((c = *utf8++)) {
case '\n':
c = 'n';
goto ESCAPED_CHAR;
case '\r':
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:
_cairo_output_stream_printf (ctx->stream, "\\%c", c);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
break;
default:
if (isprint (c) || isspace (c)) {
_cairo_output_stream_printf (ctx->stream, "%c", c);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
} else {
char buf[4] = { '\\' };
to_octal (c, buf+1, 3);
_cairo_output_stream_write (ctx->stream, buf, 4);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
break;
}
}
_cairo_output_stream_puts (ctx->stream, ")");
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
static cairo_int_status_t
_cairo_script_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_text_cluster_flags_t backward,
cairo_scaled_font_t *scaled_font,
const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_script_context_t *ctx = to_context (surface);
cairo_script_font_t *font_private;
cairo_scaled_glyph_t *scaled_glyph;
cairo_matrix_t matrix;
cairo_status_t status;
double x, y, ix, iy;
int n;
cairo_output_stream_t *base85_stream = NULL;
2010-03-21 20:40:19 +00:00
status = active (surface);
if (unlikely (status))
return status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_context (surface);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_source (surface, op, source);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
status = _emit_scaled_font (surface, scaled_font);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_operator (surface, op);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
status = _emit_scaled_glyphs (surface, scaled_font, glyphs, num_glyphs);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
/* (utf8) [cx cy [glyphs]] [clusters] backward show_text_glyphs */
/* [cx cy [glyphs]] show_glyphs */
if (utf8 != NULL && clusters != NULL) {
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_emit_string_literal (surface, utf8, utf8_len);
_cairo_output_stream_puts (ctx->stream, " ");
}
matrix = surface->cr.current_ctm;
status = cairo_matrix_invert (&matrix);
assert (status == CAIRO_STATUS_SUCCESS);
ix = x = glyphs[0].x;
iy = y = glyphs[0].y;
cairo_matrix_transform_point (&matrix, &ix, &iy);
ix -= scaled_font->font_matrix.x0;
iy -= scaled_font->font_matrix.y0;
_cairo_scaled_font_freeze_cache (scaled_font);
font_private = _cairo_script_font_get (ctx, scaled_font);
_cairo_output_stream_printf (ctx->stream,
"[%f %f ",
ix, iy);
for (n = 0; n < num_glyphs; n++) {
if (font_private->has_sfnt) {
if (glyphs[n].index > 256)
break;
} else {
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (unlikely (status)) {
_cairo_scaled_font_thaw_cache (scaled_font);
2010-03-21 20:40:19 +00:00
goto BAIL;
}
if ((long unsigned) scaled_glyph->dev_private > 256)
break;
}
}
if (n == num_glyphs) {
_cairo_output_stream_puts (ctx->stream, "<~");
base85_stream = _cairo_base85_stream_create (ctx->stream);
} else
_cairo_output_stream_puts (ctx->stream, "[");
for (n = 0; n < num_glyphs; n++) {
double dx, dy;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (unlikely (status)) {
_cairo_scaled_font_thaw_cache (scaled_font);
2010-03-21 20:40:19 +00:00
goto BAIL;
}
if (fabs (glyphs[n].x - x) > 1e-5 || fabs (glyphs[n].y - y) > 1e-5) {
if (fabs (glyphs[n].y - y) < 1e-5) {
if (base85_stream != NULL) {
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status)) {
base85_stream = NULL;
break;
}
_cairo_output_stream_printf (ctx->stream,
"~> %f <~", glyphs[n].x - x);
base85_stream = _cairo_base85_stream_create (ctx->stream);
} else {
_cairo_output_stream_printf (ctx->stream,
" ] %f [ ", glyphs[n].x - x);
}
x = glyphs[n].x;
} else {
ix = x = glyphs[n].x;
iy = y = glyphs[n].y;
cairo_matrix_transform_point (&matrix, &ix, &iy);
ix -= scaled_font->font_matrix.x0;
iy -= scaled_font->font_matrix.y0;
if (base85_stream != NULL) {
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status)) {
base85_stream = NULL;
break;
}
_cairo_output_stream_printf (ctx->stream,
"~> %f %f <~",
ix, iy);
base85_stream = _cairo_base85_stream_create (ctx->stream);
} else {
_cairo_output_stream_printf (ctx->stream,
" ] %f %f [ ",
ix, iy);
}
}
}
if (base85_stream != NULL) {
uint8_t c;
if (font_private->has_sfnt)
c = glyphs[n].index;
else
c = (uint8_t) (long unsigned) scaled_glyph->dev_private;
_cairo_output_stream_write (base85_stream, &c, 1);
} else {
if (font_private->has_sfnt)
_cairo_output_stream_printf (ctx->stream, " %lu",
glyphs[n].index);
else
_cairo_output_stream_printf (ctx->stream, " %lu",
(long unsigned) scaled_glyph->dev_private);
}
dx = scaled_glyph->metrics.x_advance;
dy = scaled_glyph->metrics.y_advance;
cairo_matrix_transform_distance (&scaled_font->ctm, &dx, &dy);
x += dx;
y += dy;
}
_cairo_scaled_font_thaw_cache (scaled_font);
if (base85_stream != NULL) {
cairo_status_t status2;
status2 = _cairo_output_stream_destroy (base85_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_printf (ctx->stream, "~>");
} else {
_cairo_output_stream_puts (ctx->stream, " ]");
}
if (unlikely (status))
return status;
if (utf8 != NULL && clusters != NULL) {
for (n = 0; n < num_clusters; n++) {
if (clusters[n].num_bytes > UCHAR_MAX ||
clusters[n].num_glyphs > UCHAR_MAX)
{
break;
}
}
if (n < num_clusters) {
_cairo_output_stream_puts (ctx->stream, "] [ ");
for (n = 0; n < num_clusters; n++) {
_cairo_output_stream_printf (ctx->stream,
"%d %d ",
clusters[n].num_bytes,
clusters[n].num_glyphs);
}
_cairo_output_stream_puts (ctx->stream, "]");
}
else
{
_cairo_output_stream_puts (ctx->stream, "] <~");
base85_stream = _cairo_base85_stream_create (ctx->stream);
for (n = 0; n < num_clusters; n++) {
uint8_t c[2];
c[0] = clusters[n].num_bytes;
c[1] = clusters[n].num_glyphs;
_cairo_output_stream_write (base85_stream, c, 2);
}
status = _cairo_output_stream_destroy (base85_stream);
if (unlikely (status))
2010-03-21 20:40:19 +00:00
goto BAIL;
_cairo_output_stream_puts (ctx->stream, "~>");
}
_cairo_output_stream_printf (ctx->stream,
" //%s show-text-glyphs\n",
_direction_to_string (backward));
} else {
_cairo_output_stream_puts (ctx->stream,
"] show-glyphs\n");
}
inactive (surface);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)){
return _cairo_surface_wrapper_show_text_glyphs (&surface->wrapper,
op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font,
clip);
}
return CAIRO_STATUS_SUCCESS;
2010-03-21 20:40:19 +00:00
BAIL:
inactive (surface);
return status;
}
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
static cairo_bool_t
_cairo_script_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
{
cairo_script_surface_t *surface = abstract_surface;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
return _cairo_surface_wrapper_get_extents (&surface->wrapper,
rectangle);
}
if (surface->width < 0 || surface->height < 0)
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
return FALSE;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
return TRUE;
}
static const cairo_surface_backend_t
_cairo_script_surface_backend = {
CAIRO_SURFACE_TYPE_SCRIPT,
_cairo_script_surface_finish,
_cairo_default_context_create,
_cairo_script_surface_create_similar,
NULL, /* create similar image */
NULL, /* map to image */
NULL, /* unmap image */
_cairo_script_surface_source,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_script_surface_acquire_source_image,
_cairo_script_surface_release_source_image,
_cairo_script_surface_snapshot,
_cairo_script_surface_copy_page,
_cairo_script_surface_show_page,
_cairo_script_surface_get_extents,
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
_cairo_script_surface_paint,
_cairo_script_surface_mask,
_cairo_script_surface_stroke,
_cairo_script_surface_fill,
NULL, /* fill/stroke */
NULL, /* glyphs */
_cairo_script_surface_has_show_text_glyphs,
_cairo_script_surface_show_text_glyphs
};
static void
_cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr)
{
cr->current_operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
cr->current_fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT;
cr->current_tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
cr->current_antialias = CAIRO_ANTIALIAS_DEFAULT;
_cairo_stroke_style_init (&cr->current_style);
_cairo_pattern_init_solid (&cr->current_source.solid,
CAIRO_COLOR_BLACK);
_cairo_path_fixed_init (&cr->current_path);
cairo_matrix_init_identity (&cr->current_ctm);
cairo_matrix_init_identity (&cr->current_stroke_matrix);
cairo_matrix_init_identity (&cr->current_font_matrix);
_cairo_font_options_init_default (&cr->current_font_options);
cr->current_scaled_font = NULL;
cr->has_clip = FALSE;
}
static void
_cairo_script_implicit_context_reset (cairo_script_implicit_context_t *cr)
{
free (cr->current_style.dash);
cr->current_style.dash = NULL;
_cairo_pattern_fini (&cr->current_source.base);
_cairo_path_fixed_fini (&cr->current_path);
_cairo_script_implicit_context_init (cr);
}
static cairo_script_surface_t *
_cairo_script_surface_create_internal (cairo_script_context_t *ctx,
cairo_content_t content,
cairo_rectangle_t *extents,
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
cairo_surface_t *passthrough)
{
cairo_script_surface_t *surface;
if (unlikely (ctx == NULL))
return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
surface = _cairo_malloc (sizeof (cairo_script_surface_t));
if (unlikely (surface == NULL))
return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base,
&_cairo_script_surface_backend,
&ctx->base,
content,
TRUE); /* is_vector */
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
_cairo_surface_wrapper_init (&surface->wrapper, passthrough);
_cairo_surface_clipper_init (&surface->clipper,
_cairo_script_surface_clipper_intersect_clip_path);
surface->width = surface->height = -1;
if (extents) {
surface->width = extents->width;
surface->height = extents->height;
cairo_surface_set_device_offset (&surface->base,
-extents->x, -extents->y);
}
surface->emitted = FALSE;
surface->defined = FALSE;
surface->active = FALSE;
surface->operand.type = SURFACE;
cairo_list_init (&surface->operand.link);
_cairo_script_implicit_context_init (&surface->cr);
return surface;
}
static const cairo_device_backend_t _cairo_script_device_backend = {
CAIRO_DEVICE_TYPE_SCRIPT,
NULL, NULL, /* lock, unlock */
2010-03-21 20:40:19 +00:00
_device_flush, /* flush */
NULL, /* finish */
_device_destroy
};
cairo_device_t *
_cairo_script_context_create_internal (cairo_output_stream_t *stream)
{
cairo_script_context_t *ctx;
ctx = _cairo_malloc (sizeof (cairo_script_context_t));
if (unlikely (ctx == NULL))
return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
memset (ctx, 0, sizeof (cairo_script_context_t));
_cairo_device_init (&ctx->base, &_cairo_script_device_backend);
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);
ctx->attach_snapshots = TRUE;
return &ctx->base;
}
void
_cairo_script_context_attach_snapshots (cairo_device_t *device,
cairo_bool_t enable)
{
cairo_script_context_t *ctx;
ctx = (cairo_script_context_t *) device;
ctx->attach_snapshots = enable;
}
static cairo_device_t *
_cairo_script_context_create (cairo_output_stream_t *stream)
{
cairo_script_context_t *ctx;
ctx = (cairo_script_context_t *)
_cairo_script_context_create_internal (stream);
if (unlikely (ctx->base.status))
return &ctx->base;
ctx->owns_stream = TRUE;
_cairo_output_stream_puts (ctx->stream, "%!CairoScript\n");
return &ctx->base;
}
/**
* cairo_script_create:
* @filename: the name (path) of the file to write the script to
*
* Creates a output device for emitting the script, used when
* creating the individual surfaces.
*
* Return value: a pointer to the newly created device. The caller
* owns the surface and should call cairo_device_destroy() when done
* with it.
*
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" device if an error such as out of memory
* occurs. You can use cairo_device_status() to check for this.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_device_t *
cairo_script_create (const char *filename)
{
cairo_output_stream_t *stream;
cairo_status_t status;
stream = _cairo_output_stream_create_for_filename (filename);
if ((status = _cairo_output_stream_get_status (stream)))
return _cairo_device_create_in_error (status);
return _cairo_script_context_create (stream);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
/**
* cairo_script_create_for_stream:
* @write_func: callback function passed the bytes written to the script
* @closure: user data to be passed to the callback
*
* Creates a output device for emitting the script, used when
* creating the individual surfaces.
*
* Return value: a pointer to the newly created device. The caller
* owns the surface and should call cairo_device_destroy() when done
* with it.
*
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" device if an error such as out of memory
* occurs. You can use cairo_device_status() to check for this.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_device_t *
cairo_script_create_for_stream (cairo_write_func_t write_func,
void *closure)
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
{
cairo_output_stream_t *stream;
cairo_status_t status;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
stream = _cairo_output_stream_create (write_func, NULL, closure);
if ((status = _cairo_output_stream_get_status (stream)))
return _cairo_device_create_in_error (status);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
return _cairo_script_context_create (stream);
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
}
/**
* cairo_script_write_comment:
* @script: the script (output device)
* @comment: the string to emit
* @len:the length of the string to write, or -1 to use strlen()
*
* Emit a string verbatim into the script.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
void
cairo_script_write_comment (cairo_device_t *script,
const char *comment,
int len)
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
{
cairo_script_context_t *context = (cairo_script_context_t *) script;
Remove clip handling from generic surface layer. Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
2009-07-23 15:32:13 +01:00
if (len < 0)
len = strlen (comment);
_cairo_output_stream_puts (context->stream, "% ");
_cairo_output_stream_write (context->stream, comment, len);
_cairo_output_stream_puts (context->stream, "\n");
}
/**
* cairo_script_set_mode:
* @script: The script (output device)
* @mode: the new mode
*
* Change the output mode of the script
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
void
cairo_script_set_mode (cairo_device_t *script,
cairo_script_mode_t mode)
{
cairo_script_context_t *context = (cairo_script_context_t *) script;
context->mode = mode;
}
/**
* cairo_script_get_mode:
* @script: The script (output device) to query
*
* Queries the script for its current output mode.
*
* Return value: the current output mode of the script
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_script_mode_t
cairo_script_get_mode (cairo_device_t *script)
{
cairo_script_context_t *context = (cairo_script_context_t *) script;
return context->mode;
}
/**
* cairo_script_surface_create:
* @script: the script (output device)
* @content: the content of the surface
* @width: width in pixels
* @height: height in pixels
*
* Create a new surface that will emit its rendering through @script
*
* Return value: a pointer to the newly created surface. The caller
* owns the surface and should call cairo_surface_destroy() when done
* with it.
*
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" surface if an error such as out of memory
* occurs. You can use cairo_surface_status() to check for this.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_surface_t *
cairo_script_surface_create (cairo_device_t *script,
cairo_content_t content,
double width,
double height)
{
cairo_rectangle_t *extents, r;
if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
if (unlikely (script->status))
return _cairo_surface_create_in_error (script->status);
extents = NULL;
if (width > 0 && height > 0) {
r.x = r.y = 0;
r.width = width;
r.height = height;
extents = &r;
}
return &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
content, extents,
NULL)->base;
}
slim_hidden_def (cairo_script_surface_create);
/**
* cairo_script_surface_create_for_target:
* @script: the script (output device)
* @target: a target surface to wrap
*
* Create a pxoy surface that will render to @target and record
* the operations to @device.
*
* Return value: a pointer to the newly created surface. The caller
* owns the surface and should call cairo_surface_destroy() when done
* with it.
*
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" surface if an error such as out of memory
* occurs. You can use cairo_surface_status() to check for this.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_surface_t *
cairo_script_surface_create_for_target (cairo_device_t *script,
cairo_surface_t *target)
{
cairo_rectangle_int_t extents;
cairo_rectangle_t rect, *r;
if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
if (unlikely (script->status))
return _cairo_surface_create_in_error (script->status);
if (unlikely (target->status))
return _cairo_surface_create_in_error (target->status);
r = NULL;
if (_cairo_surface_get_extents (target, &extents)) {
rect.x = rect.y = 0;
rect.width = extents.width;
rect.height = extents.height;
r= &rect;
}
return &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
target->content, r,
target)->base;
}
/**
* cairo_script_from_recording_surface:
* @script: the script (output device)
* @recording_surface: the recording surface to replay
*
* Converts the record operations in @recording_surface into a script.
*
* Return value: #CAIRO_STATUS_SUCCESS on successful completion or an error code.
doc: Add "since" tag to documentation The following Python script was used to compute "Since: 1.X" tags, based on the first version where a symbol became officially supported. This script requires a concatenation of the the cairo public headers for the officially supported beckends to be available as "../../includes/1.X.0.h". from sys import argv import re syms = {} def stripcomments(text): def replacer(match): s = match.group(0) if s.startswith('/'): return "" else: return s pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub(pattern, replacer, text) for minor in range(12,-2,-2): version = "1.%d" % minor names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read())) for s in names: syms[s] = version for filename in argv[1:]: is_public = False lines = open(filename, "r").read().split("\n") newlines = [] for i in range(len(lines)): if lines[i] == "/**": last_sym = lines[i+1][2:].strip().replace(":", "") is_public = last_sym.lower().startswith("cairo") elif is_public and lines[i] == " **/": if last_sym in syms: v = syms[last_sym] if re.search("Since", newlines[-1]): newlines = newlines[:-1] if newlines[-1].strip() != "*": newlines.append(" *") newlines.append(" * Since: %s" % v) else: print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym) newlines.append(lines[i]) out = open(filename, "w") out.write("\n".join(newlines)) out.close()
2012-03-27 11:48:19 +02:00
*
* Since: 1.12
**/
cairo_status_t
cairo_script_from_recording_surface (cairo_device_t *script,
cairo_surface_t *recording_surface)
{
cairo_rectangle_t r, *extents;
cairo_surface_t *surface;
cairo_status_t status;
if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
return _cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
if (unlikely (script->status))
return _cairo_error (script->status);
if (unlikely (recording_surface->status))
return recording_surface->status;
if (unlikely (! _cairo_surface_is_recording (recording_surface)))
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
extents = NULL;
if (_cairo_recording_surface_get_bounds (recording_surface, &r))
extents = &r;
surface = &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
recording_surface->content,
extents,
NULL)->base;
if (unlikely (surface->status))
return surface->status;
status = _cairo_recording_surface_replay (recording_surface, surface);
cairo_surface_destroy (surface);
return status;
}