[libgxps] Move GXPSBrush code to a new file
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgxps] Move GXPSBrush code to a new file
- Date: Thu, 17 Nov 2011 19:23:25 +0000 (UTC)
commit 7e3635a6cac36cb8f29251d15046b477914bcab6
Author: Carlos Garcia Campos <carlosgc gnome org>
Date: Mon Nov 14 19:51:19 2011 +0100
Move GXPSBrush code to a new file
libgxps/Makefile.am | 2 +
libgxps/gxps-brush.c | 1047 ++++++++++++++++++++++++++++++++++++++++++++++++++
libgxps/gxps-brush.h | 47 +++
libgxps/gxps-page.c | 966 +---------------------------------------------
4 files changed, 1105 insertions(+), 957 deletions(-)
---
diff --git a/libgxps/Makefile.am b/libgxps/Makefile.am
index 872c678..f8ae726 100644
--- a/libgxps/Makefile.am
+++ b/libgxps/Makefile.am
@@ -2,6 +2,7 @@ lib_LTLIBRARIES = libgxps.la
NOINST_H_FILES = \
gxps-archive.h \
+ gxps-brush.h \
gxps-color.h \
gxps-debug.h \
gxps-fonts.h \
@@ -26,6 +27,7 @@ libgxpsinclude_HEADERS = $(INST_H_FILES)
libgxps_la_SOURCES = \
gxps-archive.c \
+ gxps-brush.c \
gxps-color.c \
gxps-debug.c \
gxps-document.c \
diff --git a/libgxps/gxps-brush.c b/libgxps/gxps-brush.c
new file mode 100644
index 0000000..1b4e00a
--- /dev/null
+++ b/libgxps/gxps-brush.c
@@ -0,0 +1,1047 @@
+/* GXPSBrush
+ *
+ * Copyright (C) 2011 Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "gxps-brush.h"
+#include "gxps-matrix.h"
+#include "gxps-color.h"
+#include "gxps-parse-utils.h"
+#include "gxps-debug.h"
+
+typedef struct {
+ GXPSBrush *brush;
+
+ gchar *image_uri;
+ cairo_matrix_t matrix;
+ cairo_rectangle_t viewport;
+ cairo_rectangle_t viewbox;
+ cairo_extend_t extend;
+} GXPSBrushImage;
+
+struct _GXPSBrushVisual {
+ GXPSBrush *brush;
+
+ cairo_matrix_t matrix;
+ cairo_rectangle_t viewport;
+ cairo_rectangle_t viewbox;
+ cairo_extend_t extend;
+};
+
+GXPSBrush *
+gxps_brush_new (GXPSRenderContext *ctx)
+{
+ GXPSBrush *brush;
+
+ brush = g_slice_new0 (GXPSBrush);
+ brush->ctx = ctx;
+ brush->opacity = 1.0;
+
+ return brush;
+}
+
+void
+gxps_brush_free (GXPSBrush *brush)
+{
+ if (G_UNLIKELY (!brush))
+ return;
+
+ cairo_pattern_destroy (brush->pattern);
+ g_slice_free (GXPSBrush, brush);
+}
+
+static gboolean
+hex (const gchar *spec,
+ gint len,
+ guint *c)
+{
+ const gchar *end;
+
+ *c = 0;
+ for (end = spec + len; spec != end; spec++) {
+ if (!g_ascii_isxdigit (*spec))
+ return FALSE;
+
+ *c = (*c << 4) | g_ascii_xdigit_value (*spec);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gxps_color_s_rgb_parse (const gchar *color_str,
+ GXPSColor *color)
+{
+ gsize len = strlen (color_str);
+ guint a = 255;
+ guint r, g, b;
+
+ switch (len) {
+ case 6:
+ if (!hex (color_str, 2, &r) ||
+ !hex (color_str + 2, 2, &g) ||
+ !hex (color_str + 4, 2, &b))
+ return FALSE;
+ break;
+ case 8:
+ if (!hex (color_str, 2, &a) ||
+ !hex (color_str + 2, 2, &r) ||
+ !hex (color_str + 4, 2, &g) ||
+ !hex (color_str + 6, 2, &b))
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+
+ color->alpha = a / 255.;
+ color->red = r / 255.;
+ color->green = g / 255.;
+ color->blue = b / 255.;
+
+ return TRUE;
+}
+
+static gboolean
+gxps_color_sc_rgb_parse (const gchar *color_str,
+ GXPSColor *color)
+{
+ gchar **tokens;
+ gsize len;
+ gdouble c[4];
+ guint i, start;
+
+ tokens = g_strsplit (color_str, ",", 4);
+ len = g_strv_length (tokens);
+
+ switch (len) {
+ case 4:
+ if (!gxps_value_get_double (tokens[0], &c[0])) {
+ g_strfreev (tokens);
+
+ return FALSE;
+ }
+ start = 1;
+
+ break;
+ case 3:
+ c[0] = 1.0;
+ start = 0;
+ break;
+ default:
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ for (i = start; i < len; i++) {
+ if (!gxps_value_get_double (tokens[i], &c[i])) {
+ g_strfreev (tokens);
+
+ return FALSE;
+ }
+ }
+
+ g_strfreev (tokens);
+
+ color->alpha = CLAMP (c[0], 0., 1.);
+ color->red = CLAMP (c[1], 0., 1.);
+ color->green = CLAMP (c[2], 0., 1.);
+ color->blue = CLAMP (c[3], 0., 1.);
+
+ return TRUE;
+}
+
+static gboolean
+gxps_color_icc_parse (const gchar *color_str,
+ GXPSArchive *zip,
+ GXPSColor *color)
+{
+ const gchar *p;
+ gchar *icc_profile_uri;
+ gchar **tokens;
+ gsize len;
+ gdouble alpha;
+ gdouble values[GXPS_COLOR_MAX_CHANNELS];
+ guint i, j;
+ gboolean retval;
+
+ p = strstr (color_str, " ");
+ if (!p)
+ return FALSE;
+
+ icc_profile_uri = g_strndup (color_str, strlen (color_str) - strlen (p));
+
+ tokens = g_strsplit (++p, ",", -1);
+ len = g_strv_length (tokens);
+ if (len < 2) {
+ g_strfreev (tokens);
+ g_free (icc_profile_uri);
+
+ return FALSE;
+ }
+
+ if (!gxps_value_get_double (tokens[0], &alpha)) {
+ g_strfreev (tokens);
+ g_free (icc_profile_uri);
+
+ return FALSE;
+ }
+
+ for (i = 0, j = 1; i < GXPS_COLOR_MAX_CHANNELS && j < len; i++, j++) {
+ if (!gxps_value_get_double (tokens[j], &values[i])) {
+ g_strfreev (tokens);
+ g_free (icc_profile_uri);
+
+ return FALSE;
+ }
+ }
+
+ g_strfreev (tokens);
+
+ color->alpha = CLAMP (alpha, 0., 1.);
+ retval = gxps_color_new_for_icc (zip, icc_profile_uri, values, i, color);
+ g_free (icc_profile_uri);
+
+ return retval;
+}
+
+static gboolean
+gxps_color_parse (const gchar *data,
+ GXPSArchive *zip,
+ GXPSColor *color)
+{
+ const gchar *p;
+
+ p = strstr (data, "#");
+ if (!p) {
+ p = strstr (data, "ContextColor");
+ if (p == data) {
+ p += strlen ("ContextColor");
+ return gxps_color_icc_parse (++p, zip, color);
+ }
+ GXPS_DEBUG (g_debug ("Unsupported color %s", data));
+
+ return FALSE;
+ }
+
+ if (p == data)
+ return gxps_color_s_rgb_parse (++p, color);
+
+ if (strncmp (data, "sc", 2) == 0 && p == data + 2)
+ return gxps_color_sc_rgb_parse (++p, color);
+
+ GXPS_DEBUG (g_debug ("Unsupported color %s", data));
+
+ return FALSE;
+}
+
+gboolean
+gxps_brush_solid_color_parse (const gchar *data,
+ GXPSArchive *zip,
+ gdouble alpha,
+ cairo_pattern_t **pattern)
+{
+ GXPSColor color;
+ cairo_pattern_t *retval;
+
+ if (!gxps_color_parse (data, zip, &color))
+ return FALSE;
+
+ retval = cairo_pattern_create_rgba (color.red,
+ color.green,
+ color.blue,
+ color.alpha * alpha);
+ if (cairo_pattern_status (retval)) {
+ cairo_pattern_destroy (retval);
+
+ return FALSE;
+ }
+
+ if (pattern)
+ *pattern = retval;
+
+ return TRUE;
+}
+
+static cairo_extend_t
+gxps_spread_method_parse (const gchar *spread)
+{
+ if (strcmp (spread, "Pad") == 0)
+ return CAIRO_EXTEND_PAD;
+ else if (strcmp (spread, "Reflect") == 0)
+ return CAIRO_EXTEND_REFLECT;
+ else if (strcmp (spread, "Repeat") == 0)
+ return CAIRO_EXTEND_REPEAT;
+ return CAIRO_EXTEND_NONE;
+}
+
+static cairo_extend_t
+gxps_tile_mode_parse (const gchar *tile)
+{
+ if (strcmp (tile, "Tile") == 0)
+ return CAIRO_EXTEND_REPEAT;
+ else if (strcmp (tile, "FlipX") == 0)
+ GXPS_DEBUG (g_debug ("Unsupported tile mode FlipX"));
+ else if (strcmp (tile, "FlipY") == 0)
+ GXPS_DEBUG (g_debug ("Unsupported tile mode FlipY"));
+ else if (strcmp (tile, "FlipXY") == 0)
+ GXPS_DEBUG (g_debug ("Unsupported tile mode FlipXY"));
+
+ return CAIRO_EXTEND_NONE;
+}
+
+
+static GXPSBrushImage *
+gxps_brush_image_new (GXPSBrush *brush,
+ gchar *image_uri,
+ cairo_rectangle_t *viewport,
+ cairo_rectangle_t *viewbox)
+{
+ GXPSBrushImage *image;
+
+ image = g_slice_new0 (GXPSBrushImage);
+ image->brush = brush;
+
+ cairo_matrix_init_identity (&image->matrix);
+
+ /* Required values */
+ image->image_uri = image_uri;
+ image->viewport = *viewport;
+ image->viewbox = *viewbox;
+
+ return image;
+}
+
+static void
+gxps_brush_image_free (GXPSBrushImage *image)
+{
+ if (G_UNLIKELY (!image))
+ return;
+
+ g_free (image->image_uri);
+
+ g_slice_free (GXPSBrushImage, image);
+}
+
+static void
+brush_image_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ GXPSBrushImage *image = (GXPSBrushImage *)user_data;
+
+ if (strcmp (element_name, "ImageBrush.Transform") == 0) {
+ GXPSMatrix *matrix;
+
+ matrix = gxps_matrix_new (image->brush->ctx);
+ gxps_matrix_parser_push (context, matrix);
+ } else {
+ gxps_parse_error (context,
+ image->brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ element_name, NULL, NULL, error);
+ }
+}
+
+static void
+brush_image_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ GXPSBrushImage *image = (GXPSBrushImage *)user_data;
+
+ if (strcmp (element_name, "ImageBrush.Transform") == 0) {
+ GXPSMatrix *matrix;
+
+ matrix = g_markup_parse_context_pop (context);
+ image->matrix = matrix->matrix;
+ gxps_matrix_free (matrix);
+ } else {
+ gxps_parse_error (context,
+ image->brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ element_name, NULL, NULL, error);
+ }
+}
+
+static GMarkupParser brush_image_parser = {
+ brush_image_start_element,
+ brush_image_end_element,
+ NULL,
+ NULL
+};
+
+static GXPSBrushVisual *
+gxps_brush_visual_new (GXPSBrush *brush,
+ cairo_rectangle_t *viewport,
+ cairo_rectangle_t *viewbox)
+{
+ GXPSBrushVisual *visual;
+
+ visual = g_slice_new0 (GXPSBrushVisual);
+ visual->brush = brush;
+
+ /* Default */
+ visual->extend = CAIRO_EXTEND_NONE;
+ cairo_matrix_init_identity (&visual->matrix);
+
+ /* Required values */
+ visual->viewport = *viewport;
+ visual->viewbox = *viewbox;
+
+ return visual;
+}
+
+static void
+gxps_brush_visual_free (GXPSBrushVisual *visual)
+{
+ if (G_UNLIKELY (!visual))
+ return;
+
+ g_slice_free (GXPSBrushVisual, visual);
+}
+
+static void
+brush_gradient_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ GXPSBrush *brush = (GXPSBrush *)user_data;
+
+ if (strcmp (element_name, "LinearGradientBrush.GradientStops") == 0) {
+ } else if (strcmp (element_name, "RadialGradientBrush.GradientStops") == 0) {
+ } else if (strcmp (element_name, "GradientStop") == 0) {
+ gint i;
+ GXPSColor color;
+ gboolean has_color = FALSE;
+ gdouble offset = -1;
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "Color") == 0) {
+ has_color = TRUE;
+ if (!gxps_color_parse (values[i], brush->ctx->page->priv->zip, &color)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "GradientStop", "Color",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Offset") == 0) {
+ if (!gxps_value_get_double (values[i], &offset)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "GradientStop", "Offset",
+ values[i], error);
+ return;
+ }
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ "GradientStop", names[i],
+ NULL, error);
+ return;
+ }
+ }
+
+ if (!has_color || offset == -1) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ element_name,
+ !has_color ? "Color" : "Offset",
+ NULL, error);
+ return;
+ }
+
+ cairo_pattern_add_color_stop_rgba (brush->pattern, offset,
+ color.red,
+ color.green,
+ color.blue,
+ color.alpha * brush->opacity);
+ }
+}
+
+static GMarkupParser brush_gradient_parser = {
+ brush_gradient_start_element,
+ NULL,
+ NULL,
+ NULL
+};
+
+static gboolean
+gxps_box_parse (const gchar *box,
+ cairo_rectangle_t *rect)
+{
+ gchar **tokens;
+ gdouble b[4];
+ guint i;
+
+ tokens = g_strsplit (box, ",", 4);
+ if (g_strv_length (tokens) != 4) {
+ g_strfreev (tokens);
+
+ return FALSE;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (!gxps_value_get_double (tokens[i], &b[i])) {
+ g_strfreev (tokens);
+
+ return FALSE;
+ }
+ }
+
+ rect->x = b[0];
+ rect->y = b[1];
+ rect->width = b[2];
+ rect->height = b[3];
+
+ g_strfreev (tokens);
+
+ return TRUE;
+}
+
+static void
+brush_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ GXPSBrush *brush = (GXPSBrush *)user_data;
+
+ if (strcmp (element_name, "SolidColorBrush") == 0) {
+ const gchar *color_str = NULL;
+ gint i;
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "Color") == 0) {
+ color_str = values[i];
+ } else if (strcmp (names[i], "Opacity") == 0) {
+ if (!gxps_value_get_double (values[i], &brush->opacity)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "SolidColorBrush", "Opacity",
+ values[i], error);
+ return;
+ }
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ "SolidColorBrush", names[i],
+ NULL, error);
+ return;
+ }
+ }
+
+ if (!color_str) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ "SolidColorBrush", "Color",
+ NULL, error);
+ return;
+ }
+
+ GXPS_DEBUG (g_message ("set_fill_pattern (solid)"));
+ if (!gxps_brush_solid_color_parse (color_str, brush->ctx->page->priv->zip,
+ brush->opacity, &brush->pattern)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "SolidColorBrush", "Color",
+ color_str, error);
+ return;
+ }
+ } else if (strcmp (element_name, "ImageBrush") == 0) {
+ GXPSBrushImage *image;
+ gchar *image_source = NULL;
+ cairo_rectangle_t viewport, viewbox;
+ cairo_matrix_t matrix;
+ cairo_extend_t extend = CAIRO_EXTEND_NONE;
+ gint i;
+
+ cairo_matrix_init_identity (&matrix);
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "ImageSource") == 0) {
+ image_source = gxps_resolve_relative_path (brush->ctx->page->priv->source,
+ values[i]);
+ } else if (strcmp (names[i], "Transform") == 0) {
+ if (!gxps_matrix_parse (values[i], &matrix)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "ImageBrush", "Transform",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Viewport") == 0) {
+ if (!gxps_box_parse (values[i], &viewport)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "ImageBrush", "Viewport",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ViewportUnits") == 0) {
+ } else if (strcmp (names[i], "Viewbox") == 0) {
+ if (!gxps_box_parse (values[i], &viewbox)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "ImageBrush", "Viewbox",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ViewboxUnits") == 0) {
+ } else if (strcmp (names[i], "TileMode") == 0) {
+ extend = gxps_tile_mode_parse (values[i]);
+ } else if (strcmp (names[i], "Opacity") == 0) {
+ if (!gxps_value_get_double (values[i], &brush->opacity)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "ImageBrush", "Opacity",
+ values[i], error);
+ return;
+ }
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ "ImageBrush", names[i],
+ NULL, error);
+ return;
+ }
+
+ }
+
+ if (!image_source) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ element_name, "ImageSource",
+ NULL, error);
+ return;
+ }
+
+ /* GXPSBrushImage takes ownership of image_source */
+ image = gxps_brush_image_new (brush, image_source, &viewport, &viewbox);
+ image->extend = extend;
+ image->matrix = matrix;
+ g_markup_parse_context_push (context, &brush_image_parser, image);
+ } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
+ gint i;
+ gdouble x0, y0, x1, y1;
+ cairo_extend_t extend = CAIRO_EXTEND_PAD;
+ cairo_matrix_t matrix;
+
+ x0 = y0 = x1 = y1 = -1;
+ cairo_matrix_init_identity (&matrix);
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "MappingMode") == 0) {
+ } else if (strcmp (names[i], "StartPoint") == 0) {
+ if (!gxps_point_parse (values[i], &x0, &y0)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "LinearGradientBrush", "StartPoint",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "EndPoint") == 0) {
+ if (!gxps_point_parse (values[i], &x1, &y1)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "LinearGradientBrush", "EndPoint",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "SpreadMethod") == 0) {
+ extend = gxps_spread_method_parse (values[i]);
+ } else if (strcmp (names[i], "Opacity") == 0) {
+ if (!gxps_value_get_double (values[i], &brush->opacity)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "LinearGradientBrush", "Opacity",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Transform") == 0) {
+ if (!gxps_matrix_parse (values[i], &matrix)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "LinearGradientBrush", "Transform",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ColorInterpolationMode") == 0) {
+ GXPS_DEBUG (g_debug ("Unsupported %s attribute: ColorInterpolationMode", element_name));
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ element_name, names[i],
+ NULL, error);
+ return;
+ }
+ }
+
+ if (x0 == -1 || y0 == -1 || x1 == -1 || y1 == -1) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ element_name,
+ (x0 == -1 || y0 == -1) ? "StartPoint" : "EndPoint",
+ NULL, error);
+ return;
+ }
+
+ GXPS_DEBUG (g_message ("set_fill_pattern (linear)"));
+ brush->pattern = cairo_pattern_create_linear (x0, y0, x1, y1);
+ cairo_pattern_set_matrix (brush->pattern, &matrix);
+ cairo_pattern_set_extend (brush->pattern, extend);
+ g_markup_parse_context_push (context, &brush_gradient_parser, brush);
+ } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
+ gint i;
+ gdouble cx0, cy0, r0, cx1, cy1, r1;
+ cairo_extend_t extend = CAIRO_EXTEND_PAD;
+ cairo_matrix_t matrix;
+
+ cx0 = cy0 = r0 = cx1 = cy1 = r1 = -1;
+
+ cairo_matrix_init_identity (&matrix);
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "MappingMode") == 0) {
+ } else if (strcmp (names[i], "GradientOrigin") == 0) {
+ if (!gxps_point_parse (values[i], &cx0, &cy0)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "GradientOrigin",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Center") == 0) {
+ if (!gxps_point_parse (values[i], &cx1, &cy1)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "Center",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "RadiusX") == 0) {
+ if (!gxps_value_get_double (values[i], &r0)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "RadiusX",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "RadiusY") == 0) {
+ if (!gxps_value_get_double (values[i], &r1)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "RadiusY",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "SpreadMethod") == 0) {
+ extend = gxps_spread_method_parse (values[i]);
+ } else if (strcmp (names[i], "Opacity") == 0) {
+ if (!gxps_value_get_double (values[i], &brush->opacity)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "Opacity",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Transform") == 0) {
+ if (!gxps_matrix_parse (values[i], &matrix)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "RadialGradientBrush", "Transform",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ColorInterpolationMode") == 0) {
+ GXPS_DEBUG (g_debug ("Unsupported %s attribute: ColorInterpolationMode", element_name));
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ element_name, names[i],
+ NULL, error);
+ return;
+ }
+ }
+
+ if (cx0 == -1 || cy0 == -1 || cx1 == -1 || cy1 == -1) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ element_name,
+ (cx0 == -1 || cy0 == -1) ? "GradientOrigin" : "Center",
+ NULL, error);
+ return;
+ }
+ if (r0 == -1 || r1 == -1) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_MISSING_ATTRIBUTE,
+ element_name,
+ (r0 == -1) ? "RadiusX" : "RadiusY",
+ NULL, error);
+ return;
+ }
+
+ GXPS_DEBUG (g_message ("set_fill_pattern (radial)"));
+ brush->pattern = cairo_pattern_create_radial (cx0, cy0, 0, cx1, cy1, r1);
+ cairo_pattern_set_matrix (brush->pattern, &matrix);
+ cairo_pattern_set_extend (brush->pattern, extend);
+ g_markup_parse_context_push (context, &brush_gradient_parser, brush);
+ } else if (strcmp (element_name, "VisualBrush") == 0) {
+ GXPSBrushVisual *visual;
+ GXPSRenderContext *sub_ctx;
+ cairo_rectangle_t viewport, viewbox;
+ cairo_matrix_t matrix;
+ cairo_extend_t extend = CAIRO_EXTEND_NONE;
+ gint i;
+
+ cairo_matrix_init_identity (&matrix);
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (strcmp (names[i], "TileMode") == 0) {
+ extend = gxps_tile_mode_parse (values[i]);
+ } else if (strcmp (names[i], "Transform") == 0) {
+ if (!gxps_matrix_parse (values[i], &matrix)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "VisualBrush", "Transform",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "Viewport") == 0) {
+ if (!gxps_box_parse (values[i], &viewport)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "VisualBrush", "Viewport",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ViewportUnits") == 0) {
+ } else if (strcmp (names[i], "Viewbox") == 0) {
+ if (!gxps_box_parse (values[i], &viewbox)) {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "VisualBrush", "Viewbox",
+ values[i], error);
+ return;
+ }
+ } else if (strcmp (names[i], "ViewboxUnits") == 0) {
+ } else if (strcmp (names[i], "Opacity") == 0) {
+ GXPS_DEBUG (g_debug ("Unsupported %s attribute: Opacity", element_name));
+ } else if (strcmp (names[i], "Visual") == 0) {
+ GXPS_DEBUG (g_debug ("Unsupported %s attribute: Visual", element_name));
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ element_name, names[i],
+ NULL, error);
+ return;
+ }
+ }
+
+ /* TODO: check required values */
+
+ /* Clip to viewport so that push group
+ * will create a surface with the viport size
+ */
+ cairo_save (brush->ctx->cr);
+ cairo_rectangle (brush->ctx->cr, viewbox.x, viewbox.y, viewbox.width, viewbox.height);
+ cairo_clip (brush->ctx->cr);
+ cairo_push_group (brush->ctx->cr);
+ visual = gxps_brush_visual_new (brush, &viewport, &viewbox);
+ visual->extend = extend;
+ sub_ctx = g_slice_new0 (GXPSRenderContext);
+ sub_ctx->page = brush->ctx->page;
+ sub_ctx->cr = brush->ctx->cr;
+ sub_ctx->visual = visual;
+ gxps_page_render_parser_push (context, sub_ctx);
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ element_name, NULL, NULL, error);
+ }
+}
+
+static void
+brush_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ GXPSBrush *brush = (GXPSBrush *)user_data;
+
+ if (strcmp (element_name, "SolidColorBrush") == 0) {
+ } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
+ g_markup_parse_context_pop (context);
+ } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
+ g_markup_parse_context_pop (context);
+ } else if (strcmp (element_name, "ImageBrush") == 0) {
+ GXPSBrushImage *image;
+ cairo_surface_t *surface;
+ GError *err = NULL;
+
+ image = g_markup_parse_context_pop (context);
+
+ GXPS_DEBUG (g_message ("set_fill_pattern (image)"));
+ surface = gxps_page_get_image (brush->ctx->page, image->image_uri, &err);
+ if (surface) {
+ cairo_matrix_t matrix, port_matrix;
+ gdouble x_scale, y_scale;
+
+ image->brush->pattern = cairo_pattern_create_for_surface (surface);
+ cairo_pattern_set_extend (image->brush->pattern, image->extend);
+ cairo_surface_destroy (surface);
+
+ cairo_matrix_init (&port_matrix,
+ image->viewport.width,
+ 0, 0,
+ image->viewport.height,
+ image->viewport.x,
+ image->viewport.y);
+ cairo_matrix_multiply (&port_matrix, &port_matrix, &image->matrix);
+
+ x_scale = image->viewbox.width / port_matrix.xx;
+ y_scale = image->viewbox.height / port_matrix.yy;
+ cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
+ -port_matrix.x0 * x_scale,
+ -port_matrix.y0 * y_scale);
+ cairo_pattern_set_matrix (image->brush->pattern, &matrix);
+
+ if (brush->opacity != 1.0) {
+ cairo_push_group (brush->ctx->cr);
+ cairo_set_source (brush->ctx->cr, image->brush->pattern);
+ cairo_pattern_destroy (image->brush->pattern);
+ cairo_paint_with_alpha (brush->ctx->cr, brush->opacity);
+ image->brush->pattern = cairo_pop_group (brush->ctx->cr);
+ }
+
+ if (cairo_pattern_status (image->brush->pattern)) {
+ GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (image->brush->pattern))));
+ cairo_pattern_destroy (image->brush->pattern);
+ image->brush->pattern = NULL;
+ }
+ } else if (err) {
+ GXPS_DEBUG (g_debug ("%s", err->message));
+ g_error_free (err);
+ }
+ gxps_brush_image_free (image);
+ } else if (strcmp (element_name, "VisualBrush") == 0) {
+ GXPSRenderContext *sub_ctx;
+ GXPSBrushVisual *visual;
+ cairo_matrix_t matrix, port_matrix;
+ gdouble x_scale, y_scale;
+
+ sub_ctx = g_markup_parse_context_pop (context);
+ visual = sub_ctx->visual;
+ g_slice_free (GXPSRenderContext, sub_ctx);
+
+ GXPS_DEBUG (g_message ("set_fill_pattern (visual)"));
+ visual->brush->pattern = cairo_pop_group (brush->ctx->cr);
+ /* Undo the clip */
+ cairo_restore (brush->ctx->cr);
+ cairo_pattern_set_extend (visual->brush->pattern, visual->extend);
+ cairo_matrix_init (&port_matrix,
+ visual->viewport.width,
+ 0, 0,
+ visual->viewport.height,
+ visual->viewport.x,
+ visual->viewport.y);
+ cairo_matrix_multiply (&port_matrix, &port_matrix, &visual->matrix);
+
+ x_scale = visual->viewbox.width / port_matrix.xx;
+ y_scale = visual->viewbox.height / port_matrix.yy;
+ cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
+ -port_matrix.x0 * x_scale,
+ -port_matrix.y0 * y_scale);
+
+ cairo_pattern_set_matrix (visual->brush->pattern, &matrix);
+ if (cairo_pattern_status (visual->brush->pattern)) {
+ GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (visual->brush->pattern))));
+ cairo_pattern_destroy (visual->brush->pattern);
+ visual->brush->pattern = NULL;
+ }
+
+ gxps_brush_visual_free (visual);
+ } else {
+ gxps_parse_error (context,
+ brush->ctx->page->priv->source,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ element_name, NULL, NULL, error);
+
+ }
+}
+
+static GMarkupParser brush_parser = {
+ brush_start_element,
+ brush_end_element,
+ NULL,
+ NULL
+};
+
+void
+gxps_brush_parser_push (GMarkupParseContext *context,
+ GXPSBrush *brush)
+{
+ g_markup_parse_context_push (context, &brush_parser, brush);
+}
diff --git a/libgxps/gxps-brush.h b/libgxps/gxps-brush.h
new file mode 100644
index 0000000..be3d3ff
--- /dev/null
+++ b/libgxps/gxps-brush.h
@@ -0,0 +1,47 @@
+/* GXPSBrush
+ *
+ * Copyright (C) 2011 Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GXPS_BRUSH_H__
+#define __GXPS_BRUSH_H__
+
+#include <cairo.h>
+#include "gxps-page-private.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GXPSBrush GXPSBrush;
+
+struct _GXPSBrush {
+ GXPSRenderContext *ctx;
+ cairo_pattern_t *pattern;
+ gdouble opacity;
+};
+
+GXPSBrush *gxps_brush_new (GXPSRenderContext *ctx);
+void gxps_brush_free (GXPSBrush *brush);
+gboolean gxps_brush_solid_color_parse (const gchar *data,
+ GXPSArchive *zip,
+ gdouble alpha,
+ cairo_pattern_t **pattern);
+void gxps_brush_parser_push (GMarkupParseContext *context,
+ GXPSBrush *brush);
+
+G_END_DECLS
+
+#endif /* __GXPS_BRUSH_H__ */
diff --git a/libgxps/gxps-page.c b/libgxps/gxps-page.c
index 9de1af6..b870f2a 100644
--- a/libgxps/gxps-page.c
+++ b/libgxps/gxps-page.c
@@ -24,6 +24,7 @@
#include "gxps-page-private.h"
#include "gxps-matrix.h"
+#include "gxps-brush.h"
#include "gxps-fonts.h"
#include "gxps-links.h"
#include "gxps-images.h"
@@ -745,222 +746,6 @@ path_data_parse (const gchar *data,
}
static gboolean
-hex (const gchar *spec,
- gint len,
- guint *c)
-{
- const gchar *end;
-
- *c = 0;
- for (end = spec + len; spec != end; spec++) {
- if (!g_ascii_isxdigit (*spec))
- return FALSE;
-
- *c = (*c << 4) | g_ascii_xdigit_value (*spec);
- }
-
- return TRUE;
-}
-
-static gboolean
-gxps_color_s_rgb_parse (const gchar *color_str,
- GXPSColor *color)
-{
- gsize len = strlen (color_str);
- guint a = 255;
- guint r, g, b;
-
- switch (len) {
- case 6:
- if (!hex (color_str, 2, &r) ||
- !hex (color_str + 2, 2, &g) ||
- !hex (color_str + 4, 2, &b))
- return FALSE;
- break;
- case 8:
- if (!hex (color_str, 2, &a) ||
- !hex (color_str + 2, 2, &r) ||
- !hex (color_str + 4, 2, &g) ||
- !hex (color_str + 6, 2, &b))
- return FALSE;
- break;
- default:
- return FALSE;
- }
-
- color->alpha = a / 255.;
- color->red = r / 255.;
- color->green = g / 255.;
- color->blue = b / 255.;
-
- return TRUE;
-}
-
-static gboolean
-gxps_color_sc_rgb_parse (const gchar *color_str,
- GXPSColor *color)
-{
- gchar **tokens;
- gsize len;
- gdouble c[4];
- guint i, start;
-
- tokens = g_strsplit (color_str, ",", 4);
- len = g_strv_length (tokens);
-
- switch (len) {
- case 4:
- if (!gxps_value_get_double (tokens[0], &c[0])) {
- g_strfreev (tokens);
-
- return FALSE;
- }
- start = 1;
-
- break;
- case 3:
- c[0] = 1.0;
- start = 0;
- break;
- default:
- g_strfreev (tokens);
- return FALSE;
- }
-
- for (i = start; i < len; i++) {
- if (!gxps_value_get_double (tokens[i], &c[i])) {
- g_strfreev (tokens);
-
- return FALSE;
- }
- }
-
- g_strfreev (tokens);
-
- color->alpha = CLAMP (c[0], 0., 1.);
- color->red = CLAMP (c[1], 0., 1.);
- color->green = CLAMP (c[2], 0., 1.);
- color->blue = CLAMP (c[3], 0., 1.);
-
- return TRUE;
-}
-
-static gboolean
-gxps_color_icc_parse (const gchar *color_str,
- GXPSArchive *zip,
- GXPSColor *color)
-{
- const gchar *p;
- gchar *icc_profile_uri;
- gchar **tokens;
- gsize len;
- gdouble alpha;
- gdouble values[GXPS_COLOR_MAX_CHANNELS];
- guint i, j;
- gboolean retval;
-
- p = strstr (color_str, " ");
- if (!p)
- return FALSE;
-
- icc_profile_uri = g_strndup (color_str, strlen (color_str) - strlen (p));
-
- tokens = g_strsplit (++p, ",", -1);
- len = g_strv_length (tokens);
- if (len < 2) {
- g_strfreev (tokens);
- g_free (icc_profile_uri);
-
- return FALSE;
- }
-
- if (!gxps_value_get_double (tokens[0], &alpha)) {
- g_strfreev (tokens);
- g_free (icc_profile_uri);
-
- return FALSE;
- }
-
- for (i = 0, j = 1; i < GXPS_COLOR_MAX_CHANNELS && j < len; i++, j++) {
- if (!gxps_value_get_double (tokens[j], &values[i])) {
- g_strfreev (tokens);
- g_free (icc_profile_uri);
-
- return FALSE;
- }
- }
-
- g_strfreev (tokens);
-
- color->alpha = CLAMP (alpha, 0., 1.);
- retval = gxps_color_new_for_icc (zip, icc_profile_uri, values, i, color);
- g_free (icc_profile_uri);
-
- return retval;
-}
-
-static gboolean
-gxps_color_parse (const gchar *color_str,
- GXPSArchive *zip,
- GXPSColor *color)
-{
- const gchar *p;
-
- p = strstr (color_str, "#");
- if (!p) {
- p = strstr (color_str, "ContextColor");
- if (p == color_str) {
- p += strlen ("ContextColor");
- return gxps_color_icc_parse (++p, zip, color);
- }
- GXPS_DEBUG (g_debug ("Unsupported color %s", color_str));
-
- return FALSE;
- }
-
- if (p == color_str)
- return gxps_color_s_rgb_parse (++p, color);
-
- if (strncmp (color_str, "sc", 2) == 0 && p == color_str + 2)
- return gxps_color_sc_rgb_parse (++p, color);
-
- GXPS_DEBUG (g_debug ("Unsupported color %s", color_str));
-
- return FALSE;
-}
-
-static cairo_pattern_t *
-gxps_create_solid_color_pattern_with_alpha (GXPSArchive *zip,
- const gchar *color_str,
- gdouble alpha)
-{
- cairo_pattern_t *pattern;
- GXPSColor color;
-
- if (!gxps_color_parse (color_str, zip, &color))
- return NULL;
-
- pattern = cairo_pattern_create_rgba (color.red,
- color.green,
- color.blue,
- color.alpha * alpha);
- if (cairo_pattern_status (pattern)) {
- cairo_pattern_destroy (pattern);
-
- return NULL;
- }
-
- return pattern;
-}
-
-static cairo_pattern_t *
-gxps_create_solid_color_pattern (GXPSArchive *zip,
- const gchar *color_str)
-{
- return gxps_create_solid_color_pattern_with_alpha (zip, color_str, 1.0);
-}
-
-static gboolean
gxps_boolean_parse (const gchar *value)
{
return (strcmp (value, "true") == 0);
@@ -1038,39 +823,6 @@ gxps_fill_rule_parse (const gchar *rule)
}
static gboolean
-gxps_box_parse (const gchar *box,
- cairo_rectangle_t *rect)
-{
- gchar **tokens;
- gdouble b[4];
- guint i;
-
- tokens = g_strsplit (box, ",", 4);
- if (g_strv_length (tokens) != 4) {
- g_strfreev (tokens);
-
- return FALSE;
- }
-
- for (i = 0; i < 4; i++) {
- if (!gxps_value_get_double (tokens[i], &b[i])) {
- g_strfreev (tokens);
-
- return FALSE;
- }
- }
-
- rect->x = b[0];
- rect->y = b[1];
- rect->width = b[2];
- rect->height = b[3];
-
- g_strfreev (tokens);
-
- return TRUE;
-}
-
-static gboolean
gxps_points_parse (const gchar *points,
gdouble **coords,
guint *n_points)
@@ -1115,701 +867,6 @@ gxps_points_parse (const gchar *points,
return retval;
}
-static cairo_extend_t
-gxps_spread_method_parse (const gchar *spread)
-{
- if (strcmp (spread, "Pad") == 0)
- return CAIRO_EXTEND_PAD;
- else if (strcmp (spread, "Reflect") == 0)
- return CAIRO_EXTEND_REFLECT;
- else if (strcmp (spread, "Repeat") == 0)
- return CAIRO_EXTEND_REPEAT;
- return CAIRO_EXTEND_NONE;
-}
-
-static cairo_extend_t
-gxps_tile_mode_parse (const gchar *tile)
-{
- if (strcmp (tile, "Tile") == 0)
- return CAIRO_EXTEND_REPEAT;
- else if (strcmp (tile, "FlipX") == 0)
- GXPS_DEBUG (g_debug ("Unsupported tile mode FlipX"));
- else if (strcmp (tile, "FlipY") == 0)
- GXPS_DEBUG (g_debug ("Unsupported tile mode FlipY"));
- else if (strcmp (tile, "FlipXY") == 0)
- GXPS_DEBUG (g_debug ("Unsupported tile mode FlipXY"));
-
- return CAIRO_EXTEND_NONE;
-}
-
-typedef struct {
- GXPSRenderContext *ctx;
- cairo_pattern_t *pattern;
- gdouble opacity;
-} GXPSBrush;
-
-static GXPSBrush *
-gxps_brush_new (GXPSRenderContext *ctx)
-{
- GXPSBrush *brush;
-
- brush = g_slice_new0 (GXPSBrush);
- brush->ctx = ctx;
- brush->opacity = 1.0;
-
- return brush;
-}
-
-static void
-gxps_brush_free (GXPSBrush *brush)
-{
- if (G_UNLIKELY (!brush))
- return;
-
- cairo_pattern_destroy (brush->pattern);
- g_slice_free (GXPSBrush, brush);
-}
-
-typedef struct {
- GXPSBrush *brush;
-
- gchar *image_uri;
- cairo_matrix_t matrix;
- cairo_rectangle_t viewport;
- cairo_rectangle_t viewbox;
- cairo_extend_t extend;
-} GXPSBrushImage;
-
-static GXPSBrushImage *
-gxps_brush_image_new (GXPSBrush *brush,
- gchar *image_uri,
- cairo_rectangle_t *viewport,
- cairo_rectangle_t *viewbox)
-{
- GXPSBrushImage *image;
-
- image = g_slice_new0 (GXPSBrushImage);
- image->brush = brush;
-
- cairo_matrix_init_identity (&image->matrix);
-
- /* Required values */
- image->image_uri = image_uri;
- image->viewport = *viewport;
- image->viewbox = *viewbox;
-
- return image;
-}
-
-static void
-gxps_brush_image_free (GXPSBrushImage *image)
-{
- if (G_UNLIKELY (!image))
- return;
-
- g_free (image->image_uri);
-
- g_slice_free (GXPSBrushImage, image);
-}
-
-static void
-brush_image_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **names,
- const gchar **values,
- gpointer user_data,
- GError **error)
-{
- GXPSBrushImage *image = (GXPSBrushImage *)user_data;
-
- if (strcmp (element_name, "ImageBrush.Transform") == 0) {
- GXPSMatrix *matrix;
-
- matrix = gxps_matrix_new (image->brush->ctx);
- gxps_matrix_parser_push (context, matrix);
- } else {
- gxps_parse_error (context,
- image->brush->ctx->page->priv->source,
- G_MARKUP_ERROR_UNKNOWN_ELEMENT,
- element_name, NULL, NULL, error);
- }
-}
-
-static void
-brush_image_end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- GXPSBrushImage *image = (GXPSBrushImage *)user_data;
-
- if (strcmp (element_name, "ImageBrush.Transform") == 0) {
- GXPSMatrix *matrix;
-
- matrix = g_markup_parse_context_pop (context);
- image->matrix = matrix->matrix;
- gxps_matrix_free (matrix);
- } else {
- gxps_parse_error (context,
- image->brush->ctx->page->priv->source,
- G_MARKUP_ERROR_UNKNOWN_ELEMENT,
- element_name, NULL, NULL, error);
- }
-}
-
-static GMarkupParser brush_image_parser = {
- brush_image_start_element,
- brush_image_end_element,
- NULL,
- NULL
-};
-
-struct _GXPSBrushVisual {
- GXPSBrush *brush;
-
- cairo_matrix_t matrix;
- cairo_rectangle_t viewport;
- cairo_rectangle_t viewbox;
- cairo_extend_t extend;
-};
-
-static GXPSBrushVisual *
-gxps_brush_visual_new (GXPSBrush *brush,
- cairo_rectangle_t *viewport,
- cairo_rectangle_t *viewbox)
-{
- GXPSBrushVisual *visual;
-
- visual = g_slice_new0 (GXPSBrushVisual);
- visual->brush = brush;
-
- /* Default */
- visual->extend = CAIRO_EXTEND_NONE;
- cairo_matrix_init_identity (&visual->matrix);
-
- /* Required values */
- visual->viewport = *viewport;
- visual->viewbox = *viewbox;
-
- return visual;
-}
-
-static void
-gxps_brush_visual_free (GXPSBrushVisual *visual)
-{
- if (G_UNLIKELY (!visual))
- return;
-
- g_slice_free (GXPSBrushVisual, visual);
-}
-
-static void
-brush_gradient_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **names,
- const gchar **values,
- gpointer user_data,
- GError **error)
-{
- GXPSBrush *brush = (GXPSBrush *)user_data;
-
- if (strcmp (element_name, "LinearGradientBrush.GradientStops") == 0) {
- } else if (strcmp (element_name, "RadialGradientBrush.GradientStops") == 0) {
- } else if (strcmp (element_name, "GradientStop") == 0) {
- gint i;
- GXPSColor color;
- gboolean has_color = FALSE;
- gdouble offset = -1;
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "Color") == 0) {
- has_color = TRUE;
- if (!gxps_color_parse (values[i], brush->ctx->page->priv->zip, &color)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "GradientStop", "Color",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Offset") == 0) {
- if (!gxps_value_get_double (values[i], &offset)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "GradientStop", "Offset",
- values[i], error);
- return;
- }
- }
- }
-
- if (!has_color || offset == -1) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_MISSING_ATTRIBUTE,
- element_name,
- !has_color ? "Color" : "Offset",
- NULL, error);
- return;
- }
-
- cairo_pattern_add_color_stop_rgba (brush->pattern, offset,
- color.red,
- color.green,
- color.blue,
- color.alpha * brush->opacity);
- }
-}
-
-static GMarkupParser brush_gradient_parser = {
- brush_gradient_start_element,
- NULL,
- NULL,
- NULL
-};
-
-static void
-brush_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **names,
- const gchar **values,
- gpointer user_data,
- GError **error)
-{
- GXPSBrush *brush = (GXPSBrush *)user_data;
-
- if (strcmp (element_name, "SolidColorBrush") == 0) {
- const gchar *color_str = NULL;
- gint i;
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "Color") == 0) {
- color_str = values[i];
- } else if (strcmp (names[i], "Opacity") == 0) {
- if (!gxps_value_get_double (values[i], &brush->opacity)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "SolidColorBrush", "Opacity",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "X:Key") == 0) {
- /* TODO */
- }
- }
-
- if (!color_str) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_MISSING_ATTRIBUTE,
- "SolidColorBrush", "Color",
- NULL, error);
- return;
- }
-
- brush->pattern = gxps_create_solid_color_pattern_with_alpha (brush->ctx->page->priv->zip,
- color_str, brush->opacity);
- GXPS_DEBUG (g_message ("set_fill_pattern (solid)"));
- if (!brush->pattern) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "SolidColorBrush", "Color",
- color_str, error);
- return;
- }
- } else if (strcmp (element_name, "ImageBrush") == 0) {
- GXPSBrushImage *image;
- gchar *image_source = NULL;
- cairo_rectangle_t viewport, viewbox;
- cairo_matrix_t matrix;
- cairo_extend_t extend = CAIRO_EXTEND_NONE;
- gint i;
-
- cairo_matrix_init_identity (&matrix);
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "ImageSource") == 0) {
- image_source = gxps_resolve_relative_path (brush->ctx->page->priv->source,
- values[i]);
- } else if (strcmp (names[i], "Transform") == 0) {
- if (!gxps_matrix_parse (values[i], &matrix)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "ImageBrush", "Transform",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Viewport") == 0) {
- if (!gxps_box_parse (values[i], &viewport)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "ImageBrush", "Viewport",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "ViewportUnits") == 0) {
- } else if (strcmp (names[i], "Viewbox") == 0) {
- if (!gxps_box_parse (values[i], &viewbox)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "ImageBrush", "Viewbox",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "ViewboxUnits") == 0) {
- } else if (strcmp (names[i], "TileMode") == 0) {
- extend = gxps_tile_mode_parse (values[i]);
- } else if (strcmp (names[i], "Opacity") == 0) {
- if (!gxps_value_get_double (values[i], &brush->opacity)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "ImageBrush", "Opacity",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "X:Key") == 0) {
- /* TODO */
- }
-
- }
-
- if (!image_source) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_MISSING_ATTRIBUTE,
- element_name, "ImageSource",
- NULL, error);
- return;
- }
-
- /* GXPSBrushImage takes ownership of image_source */
- image = gxps_brush_image_new (brush, image_source, &viewport, &viewbox);
- image->extend = extend;
- image->matrix = matrix;
- g_markup_parse_context_push (context, &brush_image_parser, image);
- } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
- gint i;
- gdouble x0, y0, x1, y1;
- cairo_extend_t extend = CAIRO_EXTEND_PAD;
- cairo_matrix_t matrix;
-
- cairo_matrix_init_identity (&matrix);
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "MappingMode") == 0) {
- } else if (strcmp (names[i], "StartPoint") == 0) {
- if (!gxps_point_parse (values[i], &x0, &y0)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "LinearGradientBrush", "StartPoint",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "EndPoint") == 0) {
- if (!gxps_point_parse (values[i], &x1, &y1)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "LinearGradientBrush", "EndPoint",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "SpreadMethod") == 0) {
- extend = gxps_spread_method_parse (values[i]);
- } else if (strcmp (names[i], "Opacity") == 0) {
- if (!gxps_value_get_double (values[i], &brush->opacity)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "LinearGradientBrush", "Opacity",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Transform") == 0) {
- if (!gxps_matrix_parse (values[i], &matrix)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "LinearGradientBrush", "Transform",
- values[i], error);
- return;
- }
- }
- }
-
- /* TODO: check required values */
-
- GXPS_DEBUG (g_message ("set_fill_pattern (linear)"));
- brush->pattern = cairo_pattern_create_linear (x0, y0, x1, y1);
- cairo_pattern_set_matrix (brush->pattern, &matrix);
- cairo_pattern_set_extend (brush->pattern, extend);
- g_markup_parse_context_push (context, &brush_gradient_parser, brush);
- } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
- gint i;
- gdouble cx0, cy0, r0, cx1, cy1, r1 = 0;
- cairo_extend_t extend = CAIRO_EXTEND_PAD;
- cairo_matrix_t matrix;
-
- cairo_matrix_init_identity (&matrix);
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "MappingMode") == 0) {
- } else if (strcmp (names[i], "GradientOrigin") == 0) {
- if (!gxps_point_parse (values[i], &cx0, &cy0)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "GradientOrigin",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Center") == 0) {
- if (!gxps_point_parse (values[i], &cx1, &cy1)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "Center",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "RadiusX") == 0) {
- if (!gxps_value_get_double (values[i], &r0)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "RadiusX",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "RadiusY") == 0) {
- if (!gxps_value_get_double (values[i], &r1)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "RadiusY",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "SpreadMethod") == 0) {
- extend = gxps_spread_method_parse (values[i]);
- } else if (strcmp (names[i], "Opacity") == 0) {
- if (!gxps_value_get_double (values[i], &brush->opacity)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "Opacity",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Transform") == 0) {
- if (!gxps_matrix_parse (values[i], &matrix)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "RadialGradientBrush", "Transform",
- values[i], error);
- return;
- }
- }
- }
-
- /* TODO: Check required values */
-
- GXPS_DEBUG (g_message ("set_fill_pattern (radial)"));
- brush->pattern = cairo_pattern_create_radial (cx0, cy0, 0, cx1, cy1, r1);
- cairo_pattern_set_matrix (brush->pattern, &matrix);
- cairo_pattern_set_extend (brush->pattern, extend);
- g_markup_parse_context_push (context, &brush_gradient_parser, brush);
- } else if (strcmp (element_name, "VisualBrush") == 0) {
- GXPSBrushVisual *visual;
- GXPSRenderContext *sub_ctx;
- cairo_rectangle_t viewport, viewbox;
- cairo_matrix_t matrix;
- cairo_extend_t extend = CAIRO_EXTEND_NONE;
- gint i;
-
- cairo_matrix_init_identity (&matrix);
-
- for (i = 0; names[i] != NULL; i++) {
- if (strcmp (names[i], "TileMode") == 0) {
- extend = gxps_tile_mode_parse (values[i]);
- } else if (strcmp (names[i], "Transform") == 0) {
- if (!gxps_matrix_parse (values[i], &matrix)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "VisualBrush", "Transform",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "Viewport") == 0) {
- if (!gxps_box_parse (values[i], &viewport)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "VisualBrush", "Viewport",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "ViewportUnits") == 0) {
- } else if (strcmp (names[i], "Viewbox") == 0) {
- if (!gxps_box_parse (values[i], &viewbox)) {
- gxps_parse_error (context,
- brush->ctx->page->priv->source,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "VisualBrush", "Viewbox",
- values[i], error);
- return;
- }
- } else if (strcmp (names[i], "ViewboxUnits") == 0) {
- } else if (strcmp (names[i], "Opacity") == 0) {
- } else {
- }
- }
-
- /* TODO: check required values */
-
- /* Clip to viewport so that push group
- * will create a surface with the viport size
- */
- cairo_save (brush->ctx->cr);
- cairo_rectangle (brush->ctx->cr, viewbox.x, viewbox.y, viewbox.width, viewbox.height);
- cairo_clip (brush->ctx->cr);
- cairo_push_group (brush->ctx->cr);
- visual = gxps_brush_visual_new (brush, &viewport, &viewbox);
- visual->extend = extend;
- sub_ctx = g_slice_new0 (GXPSRenderContext);
- sub_ctx->page = brush->ctx->page;
- sub_ctx->cr = brush->ctx->cr;
- sub_ctx->visual = visual;
- g_markup_parse_context_push (context, &render_parser, sub_ctx);
- } else {
- GXPS_DEBUG (g_debug ("Unsupported Brush: %s", element_name));
-
- }
-}
-
-static void
-brush_end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- GXPSBrush *brush = (GXPSBrush *)user_data;
-
- if (strcmp (element_name, "SolidColorBrush") == 0) {
- } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
- g_markup_parse_context_pop (context);
- } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
- g_markup_parse_context_pop (context);
- } else if (strcmp (element_name, "ImageBrush") == 0) {
- GXPSBrushImage *image;
- cairo_surface_t *surface;
- GError *err = NULL;
-
- image = g_markup_parse_context_pop (context);
-
- GXPS_DEBUG (g_message ("set_fill_pattern (image)"));
- surface = gxps_page_get_image (brush->ctx->page, image->image_uri, &err);
- if (surface) {
- cairo_matrix_t matrix, port_matrix;
- gdouble x_scale, y_scale;
-
- image->brush->pattern = cairo_pattern_create_for_surface (surface);
- cairo_pattern_set_extend (image->brush->pattern, image->extend);
- cairo_surface_destroy (surface);
-
- cairo_matrix_init (&port_matrix,
- image->viewport.width,
- 0, 0,
- image->viewport.height,
- image->viewport.x,
- image->viewport.y);
- cairo_matrix_multiply (&port_matrix, &port_matrix, &image->matrix);
-
- x_scale = image->viewbox.width / port_matrix.xx;
- y_scale = image->viewbox.height / port_matrix.yy;
- cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
- -port_matrix.x0 * x_scale,
- -port_matrix.y0 * y_scale);
- cairo_pattern_set_matrix (image->brush->pattern, &matrix);
-
- if (brush->opacity != 1.0) {
- cairo_push_group (brush->ctx->cr);
- cairo_set_source (brush->ctx->cr, image->brush->pattern);
- cairo_pattern_destroy (image->brush->pattern);
- cairo_paint_with_alpha (brush->ctx->cr, brush->opacity);
- image->brush->pattern = cairo_pop_group (brush->ctx->cr);
- }
-
- if (cairo_pattern_status (image->brush->pattern)) {
- GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (image->brush->pattern))));
- cairo_pattern_destroy (image->brush->pattern);
- image->brush->pattern = NULL;
- }
- } else if (err) {
- GXPS_DEBUG (g_debug ("%s", err->message));
- g_error_free (err);
- }
- gxps_brush_image_free (image);
- } else if (strcmp (element_name, "VisualBrush") == 0) {
- GXPSRenderContext *sub_ctx;
- GXPSBrushVisual *visual;
- cairo_matrix_t matrix, port_matrix;
- gdouble x_scale, y_scale;
-
- sub_ctx = g_markup_parse_context_pop (context);
- visual = sub_ctx->visual;
- g_slice_free (GXPSRenderContext, sub_ctx);
-
- GXPS_DEBUG (g_message ("set_fill_pattern (visual)"));
- visual->brush->pattern = cairo_pop_group (brush->ctx->cr);
- /* Undo the clip */
- cairo_restore (brush->ctx->cr);
- cairo_pattern_set_extend (visual->brush->pattern, visual->extend);
- cairo_matrix_init (&port_matrix,
- visual->viewport.width,
- 0, 0,
- visual->viewport.height,
- visual->viewport.x,
- visual->viewport.y);
- cairo_matrix_multiply (&port_matrix, &port_matrix, &visual->matrix);
-
- x_scale = visual->viewbox.width / port_matrix.xx;
- y_scale = visual->viewbox.height / port_matrix.yy;
- cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
- -port_matrix.x0 * x_scale,
- -port_matrix.y0 * y_scale);
-
- cairo_pattern_set_matrix (visual->brush->pattern, &matrix);
- if (cairo_pattern_status (visual->brush->pattern)) {
- GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (visual->brush->pattern))));
- cairo_pattern_destroy (visual->brush->pattern);
- visual->brush->pattern = NULL;
- }
-
- gxps_brush_visual_free (visual);
- } else {
- GXPS_DEBUG (g_debug ("Unsupported Brush: %s", element_name));
-
- }
-}
-
-static GMarkupParser brush_parser = {
- brush_start_element,
- brush_end_element,
- NULL,
- NULL
-};
-
typedef struct {
GXPSRenderContext *ctx;
@@ -1860,7 +917,7 @@ canvas_start_element (GMarkupParseContext *context,
GXPSBrush *brush;
brush = gxps_brush_new (canvas->ctx);
- g_markup_parse_context_push (context, &brush_parser, brush);
+ gxps_brush_parser_push (context, brush);
} else {
render_start_element (context,
element_name,
@@ -2185,12 +1242,12 @@ path_start_element (GMarkupParseContext *context,
GXPSBrush *brush;
brush = gxps_brush_new (path->ctx);
- g_markup_parse_context_push (context, &brush_parser, brush);
+ gxps_brush_parser_push (context, brush);
} else if (strcmp (element_name, "Path.Stroke") == 0) {
GXPSBrush *brush;
brush = gxps_brush_new (path->ctx);
- g_markup_parse_context_push (context, &brush_parser, brush);
+ gxps_brush_parser_push (context, brush);
} else if (strcmp (element_name, "Path.Data") == 0) {
} else if (strcmp (element_name, "PathGeometry") == 0) {
gint i;
@@ -2858,12 +1915,12 @@ glyphs_start_element (GMarkupParseContext *context,
GXPSBrush *brush;
brush = gxps_brush_new (glyphs->ctx);
- g_markup_parse_context_push (context, &brush_parser, brush);
+ gxps_brush_parser_push (context, brush);
} else if (strcmp (element_name, "Glyphs.OpacityMask") == 0) {
GXPSBrush *brush;
brush = gxps_brush_new (glyphs->ctx);
- g_markup_parse_context_push (context, &brush_parser, brush);
+ gxps_brush_parser_push (context, brush);
} else {
}
}
@@ -2955,9 +2012,7 @@ render_start_element (GMarkupParseContext *context,
path->clip_data = g_strdup (values[i]);
} else if (strcmp (names[i], "Fill") == 0) {
GXPS_DEBUG (g_message ("set_fill_pattern (solid)"));
- path->fill_pattern = gxps_create_solid_color_pattern (ctx->page->priv->zip,
- values[i]);
- if (!path->fill_pattern) {
+ if (!gxps_brush_solid_color_parse (values[i], ctx->page->priv->zip, 1., &path->fill_pattern)) {
gxps_parse_error (context,
ctx->page->priv->source,
G_MARKUP_ERROR_INVALID_CONTENT,
@@ -2966,9 +2021,7 @@ render_start_element (GMarkupParseContext *context,
}
} else if (strcmp (names[i], "Stroke") == 0) {
GXPS_DEBUG (g_message ("set_stroke_pattern (solid)"));
- path->stroke_pattern = gxps_create_solid_color_pattern (ctx->page->priv->zip,
- values[i]);
- if (!path->stroke_pattern) {
+ if (!gxps_brush_solid_color_parse (values[i], ctx->page->priv->zip, 1., &path->stroke_pattern)) {
gxps_parse_error (context,
ctx->page->priv->source,
G_MARKUP_ERROR_INVALID_CONTENT,
@@ -3173,8 +2226,7 @@ render_start_element (GMarkupParseContext *context,
glyphs->opacity = opacity;
if (fill_color) {
GXPS_DEBUG (g_message ("set_fill_pattern (solid)"));
- glyphs->fill_pattern = gxps_create_solid_color_pattern (ctx->page->priv->zip,
- fill_color);
+ gxps_brush_solid_color_parse (fill_color, ctx->page->priv->zip, 1., &glyphs->fill_pattern);
}
if (glyphs->opacity != 1.0)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]