[lasem] [LsmSvgView] Avoid if mpossible push_group for opacity handling.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Subject: [lasem] [LsmSvgView] Avoid if mpossible push_group for opacity handling.
- Date: Mon, 22 Jun 2009 17:17:57 -0400 (EDT)
commit b5f08ae879db00815cbf27b750bd6d876e2622dd
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date: Mon Jun 22 23:15:20 2009 +0200
[LsmSvgView] Avoid if mpossible push_group for opacity handling.
Push group create a new big surface, which is not efficient when
global opacity only applies to a graphical element.
src/lsmsvgcircleelement.c | 1 +
src/lsmsvgellipseelement.c | 1 +
src/lsmsvggraphic.c | 8 ++--
src/lsmsvggraphic.h | 2 +
src/lsmsvglineelement.c | 1 +
src/lsmsvgpathelement.c | 1 +
src/lsmsvgpolygonelement.c | 1 +
src/lsmsvgpolylineelement.c | 1 +
src/lsmsvgrectelement.c | 1 +
src/lsmsvgtextelement.c | 1 +
src/lsmsvgview.c | 72 ++++++++++++++++++++++++++++++++++++++----
src/lsmsvgview.h | 5 ++-
12 files changed, 82 insertions(+), 13 deletions(-)
---
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index 5371a7d..b0a333b 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -111,6 +111,7 @@ lsm_svg_circle_element_class_init (LsmSvgCircleElementClass *s_rect_class)
s_element_class->update = lsm_svg_circle_element_update;
s_graphic_class->graphic_render = lsm_svg_circle_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index 17f7783..e26fc78 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -112,6 +112,7 @@ lsm_svg_ellipse_element_class_init (LsmSvgEllipseElementClass *s_rect_class)
s_element_class->update = lsm_svg_ellipse_element_update;
s_graphic_class->graphic_render = lsm_svg_ellipse_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index e381e37..d32abb8 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -159,8 +159,8 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
if (graphic->transform != NULL)
lsm_svg_view_push_matrix (view, &graphic->transform->transform.matrix);
- if (graphic->opacity.value < 1.0)
- lsm_svg_view_push_group (view);
+ lsm_svg_view_push_opacity (view, graphic->opacity.value,
+ LSM_SVG_GRAPHIC_GET_CLASS (graphic)->late_opacity_handling);
if (graphic->fill != NULL) {
lsm_svg_view_push_fill_attributes (view, graphic->fill);
@@ -190,8 +190,7 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_pop_fill_attributes (view);
}
- if (graphic->opacity.value < 1.0)
- lsm_svg_view_paint_group (view, graphic->opacity.value);
+ lsm_svg_view_pop_opacity (view);
if (graphic->transform != NULL)
lsm_svg_view_pop_matrix (view);
@@ -276,6 +275,7 @@ lsm_svg_graphic_class_init (LsmSvgGraphicClass *s_graphic_class)
s_graphic_class->graphic_render = _graphic_render;
s_graphic_class->graphic_get_extents = _graphic_get_extents;
+ s_graphic_class->late_opacity_handling = FALSE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvggraphic.h b/src/lsmsvggraphic.h
index 4c23a17..4127964 100644
--- a/src/lsmsvggraphic.h
+++ b/src/lsmsvggraphic.h
@@ -57,6 +57,8 @@ struct _LsmSvgGraphicClass {
void (*graphic_render) (LsmSvgElement *element, LsmSvgView *view);
void (*graphic_get_extents) (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
+
+ gboolean late_opacity_handling;
};
GType lsm_svg_graphic_get_type (void);
diff --git a/src/lsmsvglineelement.c b/src/lsmsvglineelement.c
index a272bb3..3924c7d 100644
--- a/src/lsmsvglineelement.c
+++ b/src/lsmsvglineelement.c
@@ -107,6 +107,7 @@ lsm_svg_line_element_class_init (LsmSvgLineElementClass *s_rect_class)
s_element_class->update = lsm_svg_line_element_update;
s_graphic_class->graphic_render = lsm_svg_line_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgpathelement.c b/src/lsmsvgpathelement.c
index e7e55d1..408f8cb 100644
--- a/src/lsmsvgpathelement.c
+++ b/src/lsmsvgpathelement.c
@@ -82,6 +82,7 @@ lsm_svg_path_element_class_init (LsmSvgPathElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_path_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_path_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgpolygonelement.c b/src/lsmsvgpolygonelement.c
index a560e6f..b30071c 100644
--- a/src/lsmsvgpolygonelement.c
+++ b/src/lsmsvgpolygonelement.c
@@ -71,6 +71,7 @@ lsm_svg_polygon_element_class_init (LsmSvgPolygonElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_polygon_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_polygon_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgpolylineelement.c b/src/lsmsvgpolylineelement.c
index 0facb9a..37ff4f4 100644
--- a/src/lsmsvgpolylineelement.c
+++ b/src/lsmsvgpolylineelement.c
@@ -71,6 +71,7 @@ lsm_svg_polyline_element_class_init (LsmSvgPolylineElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_polyline_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_polyline_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index b039e9c..4e1388b 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -152,6 +152,7 @@ lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_class)
s_graphic_class->graphic_render = lsm_svg_rect_element_graphic_render;
s_graphic_class->graphic_get_extents = lsm_svg_rect_element_graphic_get_extents;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index f89c44e..845c552 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -124,6 +124,7 @@ lsm_svg_text_element_class_init (LsmSvgTextElementClass *s_rect_class)
s_element_class->update = lsm_svg_text_element_update;
s_graphic_class->graphic_render = lsm_svg_text_element_graphic_render;
+ s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 826e0e7..03a6d66 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -36,6 +36,11 @@
static GObjectClass *parent_class;
+typedef struct {
+ double opacity;
+ gboolean late_opacity_handling;
+} LsmSvgViewOpacityData;
+
struct _LsmSvgViewPatternData {
cairo_t *old_cairo;
@@ -1074,6 +1079,8 @@ paint (LsmSvgView *view)
LsmSvgFillAttributeBag *fill;
LsmSvgStrokeAttributeBag *stroke;
cairo_t *cairo;
+ gboolean use_group;
+ double global_opacity;
g_return_if_fail (view->fill_stack != NULL);
g_return_if_fail (view->stroke_stack != NULL);
@@ -1082,15 +1089,37 @@ paint (LsmSvgView *view)
fill = view->fill_stack->data;
stroke = view->stroke_stack->data;
+ if (view->opacity_stack != NULL) {
+ LsmSvgViewOpacityData *opacity_data;
+
+ opacity_data = view->opacity_stack->data;
+ global_opacity = opacity_data->opacity;
+
+ use_group = fill->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
+ stroke->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
+ global_opacity < 1.0;
+
+ if (!opacity_data->late_opacity_handling)
+ g_warning ("[LsmSvgView::paint] Missing late_opacity_handling declaration in"
+ " caller element");
+ } else {
+ use_group = FALSE;
+ global_opacity = 1.0;
+ }
+
+ /* FIXME Instead of push_group, restrict to the current path bounding box */
+ if (use_group)
+ cairo_push_group (cairo);
+
if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_FILL,
- &fill->paint.paint, fill->opacity.value)) {
+ &fill->paint.paint, fill->opacity.value * global_opacity)) {
cairo_set_fill_rule (cairo, fill->rule.value == LSM_SVG_FILL_RULE_EVEN_ODD ?
CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_fill_preserve (cairo);
}
if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_STROKE,
- &stroke->paint.paint, stroke->opacity.value)) {
+ &stroke->paint.paint, stroke->opacity.value * global_opacity)) {
double line_width;
switch (stroke->line_join.value) {
@@ -1148,6 +1177,11 @@ paint (LsmSvgView *view)
}
cairo_new_path (cairo);
+
+ if (use_group) {
+ cairo_pop_group_to_source (cairo);
+ cairo_paint_with_alpha (cairo, global_opacity);
+ }
}
static void
@@ -1362,20 +1396,38 @@ lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
}
void
-lsm_svg_view_push_group (LsmSvgView *view)
+lsm_svg_view_push_opacity (LsmSvgView *view, double opacity, gboolean late_opacity_handling)
{
+ LsmSvgViewOpacityData *opacity_data;
+
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- cairo_push_group (view->dom_view.cairo);
+ opacity_data = g_new (LsmSvgViewOpacityData, 1);
+ opacity_data->opacity = opacity;
+ opacity_data->late_opacity_handling = late_opacity_handling;
+
+ if (opacity < 1.0 && !late_opacity_handling)
+ cairo_push_group (view->dom_view.cairo);
+
+ view->opacity_stack = g_slist_prepend (view->opacity_stack, opacity_data);
}
void
-lsm_svg_view_paint_group (LsmSvgView *view, double opacity)
+lsm_svg_view_pop_opacity (LsmSvgView *view)
{
+ LsmSvgViewOpacityData *opacity_data;
+
g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->opacity_stack != NULL);
- cairo_pop_group_to_source (view->dom_view.cairo);
- cairo_paint_with_alpha (view->dom_view.cairo, opacity);
+ opacity_data = view->opacity_stack->data;
+
+ if (opacity_data->opacity < 1.0 && !opacity_data->late_opacity_handling) {
+ cairo_pop_group_to_source (view->dom_view.cairo);
+ cairo_paint_with_alpha (view->dom_view.cairo, opacity_data->opacity);
+ }
+
+ view->opacity_stack = g_slist_delete_link (view->opacity_stack, view->opacity_stack);
}
static void
@@ -1409,6 +1461,7 @@ lsm_svg_view_render (LsmDomView *view)
svg_view->viewbox_stack = NULL;
svg_view->fill_stack = NULL;
svg_view->stroke_stack = NULL;
+ svg_view->opacity_stack = NULL;
svg_view->text_stack = NULL;
svg_view->matrix_stack = NULL;
@@ -1431,6 +1484,11 @@ lsm_svg_view_render (LsmDomView *view)
g_slist_free (svg_view->viewbox_stack);
svg_view->viewbox_stack = NULL;
}
+ if (svg_view->opacity_stack != NULL) {
+ g_warning ("[LsmSvgView::render] Dangling opacity data in stack");
+ g_slist_free (svg_view->opacity_stack);
+ svg_view->opacity_stack = NULL;
+ }
if (svg_view->fill_stack != NULL) {
g_warning ("[LsmSvgView::render] Dangling fill attribute in stack");
g_slist_free (svg_view->fill_stack);
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 0bff515..72a0b3a 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -49,6 +49,7 @@ struct _LsmSvgView {
GSList *viewbox_stack;
GSList *fill_stack;
GSList *stroke_stack;
+ GSList *opacity_stack;
GSList *text_stack;
GSList *matrix_stack;
@@ -120,8 +121,8 @@ void lsm_svg_view_show_polygon (LsmSvgView *view, const char *points);
void lsm_svg_view_show_text (LsmSvgView *view, char const *text, double x, double y);
void lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf);
-void lsm_svg_view_push_group (LsmSvgView *view);
-void lsm_svg_view_paint_group (LsmSvgView *view, double opacity);
+void lsm_svg_view_push_opacity (LsmSvgView *view, double opacity, gboolean late_opacity_handling);
+void lsm_svg_view_pop_opacity (LsmSvgView *view);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]