[libgxps] Support OpacityMask for Path elements



commit 0997fec01b99c293998de0d05be732dbbe0e03a4
Author: Jason Crain <jason aquaticape us>
Date:   Sat Nov 26 17:08:41 2011 -0600

    Support OpacityMask for Path elements
    
    https://bugzilla.gnome.org/show_bug.cgi?id=663477

 libgxps/gxps-page.c |   38 +++++++++++++++++++++++++++++++-------
 libgxps/gxps-path.c |   47 ++++++++++++++++++++++++++++++++++++++++++-----
 libgxps/gxps-path.h |    1 +
 3 files changed, 74 insertions(+), 12 deletions(-)
---
diff --git a/libgxps/gxps-page.c b/libgxps/gxps-page.c
index 1d1dc5b..dd8e824 100644
--- a/libgxps/gxps-page.c
+++ b/libgxps/gxps-page.c
@@ -737,6 +737,32 @@ render_end_element (GMarkupParseContext  *context,
 			return;
 		}
 
+		if (path->stroke_pattern) {
+			cairo_set_line_width (ctx->cr, path->line_width);
+			if (path->dash && path->dash_len > 0)
+				cairo_set_dash (ctx->cr, path->dash, path->dash_len, path->dash_offset);
+			/* FIXME: square cap doesn't work with dashed lines */
+//					cairo_set_line_cap (ctx->cr, path->line_cap);
+			cairo_set_line_join (ctx->cr, path->line_join);
+			cairo_set_miter_limit (ctx->cr, path->miter_limit);
+		}
+
+		if (path->opacity_mask) {
+			gdouble x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+			if (path->stroke_pattern)
+				cairo_stroke_extents (ctx->cr, &x1, &y1, &x2, &y2);
+			else if (path->fill_pattern)
+				cairo_fill_extents (ctx->cr, &x1, &y1, &x2, &y2);
+
+			cairo_path_t *cairo_path = cairo_copy_path (ctx->cr);
+			cairo_new_path (ctx->cr);
+			cairo_rectangle (ctx->cr, x1, y1, x2 - x1, y2 - y1);
+			cairo_clip (ctx->cr);
+			cairo_push_group (ctx->cr);
+			cairo_append_path (ctx->cr, cairo_path);
+			cairo_path_destroy (cairo_path);
+		}
+
 		if (path->fill_pattern) {
 			GXPS_DEBUG (g_message ("fill"));
 
@@ -750,16 +776,14 @@ render_end_element (GMarkupParseContext  *context,
 		if (path->stroke_pattern) {
 			GXPS_DEBUG (g_message ("stroke"));
 			cairo_set_source (ctx->cr, path->stroke_pattern);
-			cairo_set_line_width (ctx->cr, path->line_width);
-			if (path->dash && path->dash_len > 0)
-				cairo_set_dash (ctx->cr, path->dash, path->dash_len, path->dash_offset);
-			/* FIXME: square cap doesn't work with dashed lines */
-//					cairo_set_line_cap (ctx->cr, path->line_cap);
-			cairo_set_line_join (ctx->cr, path->line_join);
-			cairo_set_miter_limit (ctx->cr, path->miter_limit);
 			cairo_stroke (ctx->cr);
 		}
 
+		if (path->opacity_mask) {
+			cairo_pop_group_to_source (ctx->cr);
+			cairo_mask (ctx->cr, path->opacity_mask);
+		}
+
 		if (path->opacity != 1.0) {
 			cairo_pop_group_to_source (ctx->cr);
 			cairo_paint_with_alpha (ctx->cr, path->opacity);
diff --git a/libgxps/gxps-path.c b/libgxps/gxps-path.c
index e046ac7..80d53f4 100644
--- a/libgxps/gxps-path.c
+++ b/libgxps/gxps-path.c
@@ -74,6 +74,7 @@ gxps_path_free (GXPSPath *path)
         g_free (path->clip_data);
         cairo_pattern_destroy (path->fill_pattern);
         cairo_pattern_destroy (path->stroke_pattern);
+        cairo_pattern_destroy (path->opacity_mask);
         g_free (path->dash);
 
         g_slice_free (GXPSPath, path);
@@ -866,6 +867,30 @@ path_geometry_end_element (GMarkupParseContext  *context,
 			cairo_close_path (path->ctx->cr);
 		}
 
+		if (path->stroke_pattern) {
+			cairo_set_line_width (path->ctx->cr, path->line_width);
+			if (path->dash && path->dash_len > 0)
+				cairo_set_dash (path->ctx->cr, path->dash, path->dash_len, path->dash_offset);
+			cairo_set_line_join (path->ctx->cr, path->line_join);
+			cairo_set_miter_limit (path->ctx->cr, path->miter_limit);
+		}
+
+		if (path->opacity_mask) {
+			gdouble x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+			if (path->stroke_pattern)
+				cairo_stroke_extents (path->ctx->cr, &x1, &y1, &x2, &y2);
+			else if (path->fill_pattern)
+				cairo_fill_extents (path->ctx->cr, &x1, &y1, &x2, &y2);
+
+			cairo_path_t *cairo_path = cairo_copy_path (path->ctx->cr);
+			cairo_new_path (path->ctx->cr);
+			cairo_rectangle (path->ctx->cr, x1, y1, x2 - x1, y2 - y1);
+			cairo_clip (path->ctx->cr);
+			cairo_push_group (path->ctx->cr);
+			cairo_append_path (path->ctx->cr, cairo_path);
+			cairo_path_destroy (cairo_path);
+		}
+
 		if (path->is_filled && path->fill_pattern) {
 			GXPS_DEBUG (g_message ("fill"));
 			cairo_set_source (path->ctx->cr, path->fill_pattern);
@@ -878,13 +903,13 @@ path_geometry_end_element (GMarkupParseContext  *context,
 		if (path->stroke_pattern) {
 			GXPS_DEBUG (g_message ("stroke"));
 			cairo_set_source (path->ctx->cr, path->stroke_pattern);
-			cairo_set_line_width (path->ctx->cr, path->line_width);
-			if (path->dash && path->dash_len > 0)
-				cairo_set_dash (path->ctx->cr, path->dash, path->dash_len, path->dash_offset);
-			cairo_set_line_join (path->ctx->cr, path->line_join);
-			cairo_set_miter_limit (path->ctx->cr, path->miter_limit);
 			cairo_stroke (path->ctx->cr);
 		}
+
+		if (path->opacity_mask) {
+			cairo_pop_group_to_source (path->ctx->cr);
+			cairo_mask (path->ctx->cr, path->opacity_mask);
+		}
 	}
 }
 
@@ -969,6 +994,11 @@ path_start_element (GMarkupParseContext  *context,
 
 		matrix = gxps_matrix_new (path->ctx);
 		gxps_matrix_parser_push (context, matrix);
+	} else if (strcmp (element_name, "Path.OpacityMask") == 0) {
+		GXPSBrush *brush;
+
+		brush = gxps_brush_new (path->ctx);
+		gxps_brush_parser_push (context, brush);
 	} else {
 		GXPS_DEBUG (g_debug ("Unsupported path child %s", element_name));
 	}
@@ -1009,6 +1039,13 @@ path_end_element (GMarkupParseContext  *context,
 		cairo_transform (path->ctx->cr, &matrix->matrix);
 
 		gxps_matrix_free (matrix);
+	} else if (strcmp (element_name, "Path.OpacityMask") == 0) {
+		GXPSBrush *brush;
+
+		brush = g_markup_parse_context_pop (context);
+		if (!path->opacity_mask)
+			path->opacity_mask = cairo_pattern_reference (brush->pattern);
+		gxps_brush_free (brush);
 	} else {
 
 	}
diff --git a/libgxps/gxps-path.h b/libgxps/gxps-path.h
index 64791b3..fd21982 100644
--- a/libgxps/gxps-path.h
+++ b/libgxps/gxps-path.h
@@ -43,6 +43,7 @@ struct _GXPSPath {
         cairo_line_join_t  line_join;
         gdouble            miter_limit;
         gdouble            opacity;
+        cairo_pattern_t   *opacity_mask;
 
         gboolean           is_stroked : 1;
         gboolean           is_filled  : 1;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]