diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c index b3aa69df4..9e12e575b 100644 --- a/src/cairo-script-surface.c +++ b/src/cairo-script-surface.c @@ -956,6 +956,87 @@ _emit_radial_pattern (cairo_script_surface_t *surface, 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_pattern_mesh_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 mesh-begin-patch"); + + path = cairo_pattern_mesh_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 mesh-move-to", + data[1].point.x, data[1].point.y); + break; + case CAIRO_PATH_LINE_TO: + _cairo_output_stream_printf (ctx->stream, + "\n %f %f mesh-line-to", + 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 mesh-curve-to", + 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_pattern_mesh_get_control_point (mesh, i, j, &x, &y); + if (unlikely (status)) + return status; + _cairo_output_stream_printf (ctx->stream, + "\n %d %f %f mesh-set-control-point", + j, x, y); + } + + for (j = 0; j < 4; j++) { + double r, g, b, a; + + status = cairo_pattern_mesh_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 mesh-set-corner-color", + j, r, g, b, a); + } + + _cairo_output_stream_printf (ctx->stream, "\n mesh-end-patch"); + } + + return CAIRO_STATUS_SUCCESS; +} + static cairo_status_t _emit_recording_surface_pattern (cairo_script_surface_t *surface, cairo_recording_surface_t *source) @@ -1465,6 +1546,10 @@ _emit_pattern (cairo_script_surface_t *surface, 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; diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c index 7d8297cc6..e447b2e14 100644 --- a/util/cairo-script/cairo-script-operators.c +++ b/util/cairo-script/cairo-script-operators.c @@ -3591,6 +3591,199 @@ _matrix (csi_t *ctx) return push (&matrix); } +static csi_status_t +_mesh (csi_t *ctx) +{ + csi_object_t obj; + + obj.type = CSI_OBJECT_TYPE_PATTERN; + obj.datum.pattern = cairo_pattern_create_mesh (); + return push (&obj); +} + +static csi_status_t +_mesh_begin_patch (csi_t *ctx) +{ + csi_status_t status; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (1); + + status = _csi_ostack_get_pattern (ctx, 0, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_begin_patch (pattern); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_curve_to (csi_t *ctx) +{ + csi_status_t status; + double x1, y1, x2, y2, x3, y3; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (7); + + status = _csi_ostack_get_number (ctx, 0, &y3); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &x3); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 2, &y2); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 3, &x2); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 4, &y1); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 5, &x1); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_pattern (ctx, 6, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_curve_to (pattern, x1, y1, x2, y2, x3, y3); + + pop (6); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_end_patch (csi_t *ctx) +{ + csi_status_t status; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (1); + + status = _csi_ostack_get_pattern (ctx, 0, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_end_patch (pattern); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_line_to (csi_t *ctx) +{ + csi_status_t status; + double x, y; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (3); + + status = _csi_ostack_get_number (ctx, 0, &y); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &x); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_pattern (ctx, 2, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_line_to (pattern, x, y); + + pop (2); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_move_to (csi_t *ctx) +{ + csi_status_t status; + double x, y; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (3); + + status = _csi_ostack_get_number (ctx, 0, &y); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &x); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_pattern (ctx, 2, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_move_to (pattern, x, y); + + pop (2); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_set_control_point (csi_t *ctx) +{ + csi_status_t status; + double x, y; + csi_integer_t point; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (4); + + status = _csi_ostack_get_number (ctx, 0, &y); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &x); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_integer (ctx, 2, &point); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_pattern (ctx, 3, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_set_control_point (pattern, point, x, y); + + pop (3); + return CSI_STATUS_SUCCESS; +} + +static csi_status_t +_mesh_set_corner_color (csi_t *ctx) +{ + csi_status_t status; + double r, g, b, a; + csi_integer_t corner; + cairo_pattern_t *pattern = NULL; /* silence the compiler */ + + check (6); + + status = _csi_ostack_get_number (ctx, 0, &a); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 1, &b); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 2, &g); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_number (ctx, 3, &r); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_integer (ctx, 4, &corner); + if (_csi_unlikely (status)) + return status; + status = _csi_ostack_get_pattern (ctx, 5, &pattern); + if (_csi_unlikely (status)) + return status; + + cairo_pattern_mesh_set_corner_color_rgba (pattern, corner, r, g, b, a); + + pop (5); + return CSI_STATUS_SUCCESS; +} + static csi_status_t _mod (csi_t *ctx) { @@ -6038,6 +6231,14 @@ _defs[] = { { "mark", _mark }, { "mask", _mask }, { "matrix", _matrix }, + { "mesh", _mesh }, + { "mesh-begin-patch", _mesh_begin_patch }, + { "mesh-curve-to", _mesh_curve_to }, + { "mesh-end-patch", _mesh_end_patch }, + { "mesh-line-to", _mesh_line_to }, + { "mesh-move-to", _mesh_move_to }, + { "mesh-set-control-point", _mesh_set_control_point }, + { "mesh-set-corner-color", _mesh_set_corner_color }, { "mod", _mod }, { "move-to", _move_to }, { "mul", _mul },