[lasem] svg_text: lame text extents support.



commit 06d821a7c2c145fbe08fd6bdfb4639fa3e5c6348
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Mon Oct 22 23:45:58 2012 +0200

    svg_text: lame text extents support.

 src/lsmsvgpathelement.c |    4 +-
 src/lsmsvgtextelement.c |   15 +++-
 src/lsmsvgview.c        |  161 +++++++++++++++++++++++++++++++----------------
 src/lsmsvgview.h        |    5 +-
 4 files changed, 120 insertions(+), 65 deletions(-)
---
diff --git a/src/lsmsvgpathelement.c b/src/lsmsvgpathelement.c
index 4643507..3f59a88 100644
--- a/src/lsmsvgpathelement.c
+++ b/src/lsmsvgpathelement.c
@@ -52,9 +52,7 @@ lsm_svg_path_element_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExte
 {
 	LsmSvgPathElement *path = LSM_SVG_PATH_ELEMENT (self);
 
-	lsm_svg_view_calculate_path_extents (view, path->d.value,
-					     &extents->x1, &extents->y1,
-					     &extents->x2, &extents->y2);
+	lsm_svg_view_path_extents (view, path->d.value, extents);
 }
 
 /* LsmSvgPathElement implementation */
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index 1ec0efc..bb647ce 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -80,15 +80,22 @@ static void
 lsm_svg_text_element_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
 {
 	LsmSvgTextElement *text = LSM_SVG_TEXT_ELEMENT (self);
+	LsmDomNode *iter;
+	GString *string = g_string_new ("");
 	double x, y;
 
+	for (iter = LSM_DOM_NODE (self)->first_child; iter != NULL; iter = iter->next_sibling) {
+		if (LSM_IS_DOM_TEXT (iter)) {
+			g_string_append (string, lsm_dom_node_get_node_value (iter));
+		}
+	}
+
 	x = lsm_svg_view_normalize_length (view, &text->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
 	y = lsm_svg_view_normalize_length (view, &text->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
 
-	extents->x1 = x;
-	extents->y1 = y;
-	extents->x2 = x;
-	extents->y2 = y;
+	lsm_svg_view_text_extents (view, g_strstrip (string->str), x, y, extents);
+
+	g_string_free (string, TRUE);
 }
 
 /* LsmSvgTextElement implementation */
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 623dbba..0cbb475 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -873,28 +873,24 @@ lsm_svg_view_show_path (LsmSvgView *view,
 }
 
 void
-lsm_svg_view_calculate_path_extents (LsmSvgView *view,
-				     const char *path,
-				     double *x1, double *y1,
-				     double *x2, double *y2)
+lsm_svg_view_path_extents (LsmSvgView *view,
+			   const char *path,
+			   LsmExtents *extents)
 {
-	double xx1, yy1, xx2, yy2;
+	double x1, y1, x2, y2;
 
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+	g_return_if_fail (extents != NULL);
 
 	cairo_new_path (view->dom_view.cairo);
 	lsm_cairo_emit_svg_path (view->dom_view.cairo, path);
-	cairo_path_extents (view->dom_view.cairo, &xx1, &yy1, &xx2, &yy2);
+	cairo_path_extents (view->dom_view.cairo, &x1, &y1, &x2, &y2);
 	cairo_new_path (view->dom_view.cairo);
 
-	if (x1 != NULL)
-		*x1 = xx1;
-	if (y1 != NULL)
-		*y1 = yy1;
-	if (x2 != NULL)
-		*x2 = xx2;
-	if (y2 != NULL)
-		*y2 = yy2;
+	extents->x1 = x1;
+	extents->x2 = x2;
+	extents->y1 = y1;
+	extents->y2 = y2;
 }
 
 void
@@ -958,10 +954,9 @@ lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
 	_show_points (view, points, TRUE);
 }
 
-void
-lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y)
+static void
+_update_pango_layout (LsmSvgView *view, char const *string, double x, double y, LsmSvgViewPathInfos *path_infos)
 {
-	LsmSvgViewPathInfos path_infos = default_path_infos;
 	const LsmSvgStyle *style;
 	PangoLayout *pango_layout;
 	PangoFontDescription *font_description;
@@ -972,28 +967,8 @@ lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y
 	int baseline;
 	double x1, y1;
 
-	if (string == NULL || string[0] == '\0')
-		return;
-
-	g_return_if_fail (LSM_IS_SVG_VIEW (view));
-
 	style = view->style;
 
-	lsm_debug_render ("[LsmSvgView::show_text] Show '%s' at %g,%g (%g px)", string, x, y, style->font_size_px);
-
-	/* A text may be painted with a text based pattern. In this case,
-	 * we take care to create a new pango layout if the current one is in use. */
-	if (view->is_pango_layout_in_use) {
-		PangoContext *pango_context;
-
-		pango_context = pango_layout_get_context (view->pango_layout);
-		view->pango_layout_stack = g_slist_prepend (view->pango_layout_stack, view->pango_layout);
-		view->pango_layout = pango_layout_new (pango_context);
-
-		lsm_debug_render ("[LsmSvgView::show_text] Create a new pango layout");
-	} else
-		view->is_pango_layout_in_use = TRUE;
-
 	pango_layout = view->pango_layout;
 	font_description = view->dom_view.font_description;
 
@@ -1070,30 +1045,42 @@ lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y
 			break;
 	}
 
-	path_infos.is_text_path = TRUE;
-	path_infos.is_extents_defined = TRUE;
-	path_infos.extents.x1 = x1;
-	path_infos.extents.y1 = y1;
-	path_infos.extents.x2 = x1 + pango_units_to_double (rectangle.width);
-	path_infos.extents.y2 = y1 + pango_units_to_double (rectangle.height);
-	path_infos.pango_layout = pango_layout;
+	path_infos->is_text_path = TRUE;
+	path_infos->is_extents_defined = TRUE;
+	path_infos->extents.x1 = x1;
+	path_infos->extents.y1 = y1;
+	path_infos->extents.x2 = x1 + pango_units_to_double (rectangle.width);
+	path_infos->extents.y2 = y1 + pango_units_to_double (rectangle.height);
+	path_infos->pango_layout = pango_layout;
+}
 
-	if (style->writing_mode->value == LSM_SVG_WRITING_MODE_TB ||
-	    style->writing_mode->value == LSM_SVG_WRITING_MODE_TB_RL) {
+static gboolean
+_lock_pango_layout (LsmSvgView *view)
+{
+	/* A text may be painted with a text based pattern. In this case,
+	 * we take care to create a new pango layout if the current one is in use. */
+	if (view->is_pango_layout_in_use) {
+		PangoContext *pango_context;
 
-		cairo_save (view->dom_view.cairo);
-		cairo_rotate (view->dom_view.cairo, M_PI / 2.0);
-		cairo_move_to (view->dom_view.cairo, x1, y1);
+		pango_context = pango_layout_get_context (view->pango_layout);
+		view->pango_layout_stack = g_slist_prepend (view->pango_layout_stack, view->pango_layout);
+		view->pango_layout = pango_layout_new (pango_context);
 
-		process_path (view, &path_infos);
+		lsm_debug_render ("[LsmSvgView::show_text] Create a new pango layout");
 
-		cairo_restore (view->dom_view.cairo);
-	} else {
-		cairo_move_to (view->dom_view.cairo, x1, y1);
-		process_path (view, &path_infos);
+		return TRUE;
 	}
 
-	if (pango_layout != view->pango_layout) {
+	view->is_pango_layout_in_use = TRUE;
+
+	return FALSE;
+}
+
+static void
+_unlock_pango_layout (LsmSvgView *view, gboolean need_pop)
+{
+
+	if (need_pop) {
 		lsm_debug_render ("[LsmSvgView::show_text] Free the child pango layout");
 
 		if (view->pango_layout != NULL) {
@@ -1110,6 +1097,70 @@ lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y
 }
 
 void
+lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y)
+{
+	LsmSvgViewPathInfos path_infos = default_path_infos;
+	const LsmSvgStyle *style;
+	gboolean need_pop;
+
+	if (string == NULL || string[0] == '\0')
+		return;
+
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+
+	style = view->style;
+
+	lsm_debug_render ("[LsmSvgView::show_text] Show '%s' at %g,%g (%g px)", string, x, y, style->font_size_px);
+
+	need_pop = _lock_pango_layout (view);
+
+	_update_pango_layout (view, string, x, y, &path_infos);
+
+	if (style->writing_mode->value == LSM_SVG_WRITING_MODE_TB ||
+	    style->writing_mode->value == LSM_SVG_WRITING_MODE_TB_RL) {
+
+		cairo_save (view->dom_view.cairo);
+		cairo_rotate (view->dom_view.cairo, M_PI / 2.0);
+		cairo_move_to (view->dom_view.cairo, path_infos.extents.x1, path_infos.extents.y1);
+
+		process_path (view, &path_infos);
+
+		cairo_restore (view->dom_view.cairo);
+	} else {
+		cairo_move_to (view->dom_view.cairo, path_infos.extents.x1, path_infos.extents.y1);
+		process_path (view, &path_infos);
+	}
+
+	_unlock_pango_layout (view, need_pop);
+}
+
+void
+lsm_svg_view_text_extents (LsmSvgView *view, char const *string, double x, double y, LsmExtents *extents)
+{
+	LsmSvgViewPathInfos path_infos = default_path_infos;
+	gboolean need_pop;
+
+	g_return_if_fail (LSM_IS_SVG_VIEW (view));
+	g_return_if_fail (extents != NULL);
+
+	if (string == NULL ||
+	    string[0] == '\0') {
+		extents->x1 = 0;
+		extents->y1 = 0;
+		extents->y1 = 0;
+		extents->y2 = 0;
+	}
+
+	need_pop = _lock_pango_layout (view);
+
+	_update_pango_layout (view, string, x, y, &path_infos);
+
+	_unlock_pango_layout (view, need_pop);
+
+	*extents = path_infos.extents;
+}
+
+void
 lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
 {
 	g_return_if_fail (LSM_IS_SVG_VIEW (view));
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index c553776..a0c3e33 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -95,9 +95,7 @@ const LsmBox *	lsm_svg_view_get_pattern_extents	(LsmSvgView *view);
 const LsmBox * 	lsm_svg_view_get_object_extents 	(LsmSvgView *view);
 const LsmBox *	lsm_svg_view_get_clip_extents		(LsmSvgView *view);
 
-void		lsm_svg_view_calculate_path_extents	(LsmSvgView *view, const char *path,
-							 double *x1, double *y1,
-							 double *x2, double *y2);
+void		lsm_svg_view_path_extents		(LsmSvgView *view, const char *path, LsmExtents *extents);
 
 void 		lsm_svg_view_create_radial_gradient 	(LsmSvgView *view, double cx, double cy,
 							                   double r, double fx, double fy);
@@ -125,6 +123,7 @@ void 		lsm_svg_view_show_line 		(LsmSvgView *view, double x1, double y1, double
 void 		lsm_svg_view_show_polyline	(LsmSvgView *view, const char *points);
 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_text_extents 	(LsmSvgView *view, char const *string, double x, double y, LsmExtents *extents);
 void		lsm_svg_view_show_pixbuf	(LsmSvgView *view, GdkPixbuf *pixbuf);
 
 void 		lsm_svg_view_push_viewbox 		(LsmSvgView *view, const LsmBox *viewbox);



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