summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMenner <mik@gmx.org>2016-01-02 09:42:53 +0100
committerFederico Mena Quintero <federico@gnome.org>2016-01-05 19:36:06 -0600
commite804fb1adcf564ce4bae661cc595a8d4df55efd3 (patch)
tree47ae3ba21f06a5b2f27f82e34186ddfe0cad3554
parent1fc06fe6def169920f4032e348040c38be320fb1 (diff)
downloadlibrsvg-e804fb1adcf564ce4bae661cc595a8d4df55efd3.tar.gz
bgo#340047 - Add support for the "baseline-shift" text attribute
This commit adds support for the baseline-shift attribute for tags "sub/super/baseline". We don't support percentages of the font size or explicit lengths yet. https://bugzilla.gnome.org/show_bug.cgi?id=340047
-rw-r--r--rsvg-css.c24
-rw-r--r--rsvg-private.h2
-rw-r--r--rsvg-styles.c21
-rw-r--r--rsvg-styles.h2
-rw-r--r--rsvg-text.c16
-rw-r--r--tests/fixtures/reftests/bugs/340047-ref.pngbin0 -> 4855 bytes
-rw-r--r--tests/fixtures/reftests/bugs/340047.svg43
7 files changed, 101 insertions, 7 deletions
diff --git a/rsvg-css.c b/rsvg-css.c
index a7cd199e..5b359a20 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -204,6 +204,7 @@ _rsvg_css_parse_length (const char *str)
return out;
}
+/* Recursive evaluation of all parent elements regarding absolute font size */
double
_rsvg_css_normalize_font_size (RsvgState * state, RsvgDrawingCtx * ctx)
{
@@ -213,7 +214,7 @@ _rsvg_css_normalize_font_size (RsvgState * state, RsvgDrawingCtx * ctx)
case 'p':
case 'm':
case 'x':
- parent= rsvg_state_parent (state);
+ parent = rsvg_state_parent (state);
if (parent) {
double parent_size;
parent_size = _rsvg_css_normalize_font_size (parent, ctx);
@@ -263,6 +264,27 @@ _rsvg_css_normalize_length (const RsvgLength * in, RsvgDrawingCtx * ctx, char di
return 0;
}
+/* Recursive evaluation of all parent elements regarding basline-shift */
+double
+_rsvg_css_accumulate_baseline_shift (RsvgState * state, RsvgDrawingCtx * ctx)
+{
+ RsvgState *parent;
+ double shift = 0.;
+
+ parent = rsvg_state_parent (state);
+ if (parent) {
+ if (state->has_baseline_shift) {
+ double parent_font_size;
+ parent_font_size = _rsvg_css_normalize_font_size (parent, ctx); /* font size from here */
+ shift = parent_font_size * state->baseline_shift;
+ }
+ shift += _rsvg_css_accumulate_baseline_shift (parent, ctx); /* baseline-shift for parent element */
+ }
+
+ return shift;
+}
+
+
double
_rsvg_css_hand_normalize_length (const RsvgLength * in, gdouble pixels_per_inch,
gdouble width_or_height, gdouble font_size)
diff --git a/rsvg-private.h b/rsvg-private.h
index 17457f9f..6921bc31 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -394,6 +394,8 @@ double _rsvg_css_hand_normalize_length (const RsvgLength * in, gdouble pixels_p
gdouble width_or_height, gdouble font_size);
double _rsvg_css_normalize_font_size (RsvgState * state, RsvgDrawingCtx * ctx);
G_GNUC_INTERNAL
+double _rsvg_css_accumulate_baseline_shift (RsvgState * state, RsvgDrawingCtx * ctx);
+G_GNUC_INTERNAL
RsvgLength _rsvg_css_parse_length (const char *str);
G_GNUC_INTERNAL
void _rsvg_push_view_box (RsvgDrawingCtx * ctx, double w, double h);
diff --git a/rsvg-styles.c b/rsvg-styles.c
index 9a918ee2..6aea8844 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -118,6 +118,7 @@ rsvg_state_init (RsvgState * state)
cairo_matrix_init_identity (&state->personal_affine);
state->mask = NULL;
state->opacity = 0xff;
+ state->baseline_shift = 0.;
state->fill = rsvg_paint_server_parse (NULL, "#000");
state->fill_opacity = 0xff;
state->stroke_opacity = 0xff;
@@ -153,6 +154,7 @@ rsvg_state_init (RsvgState * state)
state->middleMarker = NULL;
state->endMarker = NULL;
+ state->has_baseline_shift = FALSE;
state->has_current_color = FALSE;
state->has_flood_color = FALSE;
state->has_flood_opacity = FALSE;
@@ -253,6 +255,8 @@ rsvg_state_inherit_run (RsvgState * dst, const RsvgState * src,
{
gint i;
+ if (function (dst->has_baseline_shift, src->has_baseline_shift))
+ dst->baseline_shift = src->baseline_shift;
if (function (dst->has_current_color, src->has_current_color))
dst->current_color = src->current_color;
if (function (dst->has_flood_color, src->has_flood_color))
@@ -513,6 +517,22 @@ rsvg_parse_style_pair (RsvgHandle * ctx,
} else if (g_str_equal (name, "mask")) {
g_free (state->mask);
state->mask = rsvg_get_url_string (value);
+ } else if (g_str_equal (name, "baseline-shift")) {
+ /* These values come from Inkscape's SP_CSS_BASELINE_SHIFT_(SUB/SUPER/BASELINE);
+ * see sp_style_merge_baseline_shift_from_parent()
+ */
+ if (g_str_equal (value, "sub")) {
+ state->has_baseline_shift = TRUE;
+ state->baseline_shift = -0.2;
+ } else if (g_str_equal (value, "super")) {
+ state->has_baseline_shift = TRUE;
+ state->baseline_shift = 0.4;
+ } else if (g_str_equal (value, "baseline")) {
+ state->has_baseline_shift = TRUE;
+ state->baseline_shift = 0.;
+ } else {
+ g_warning ("value \'%s\' for attribute \'baseline-shift\' is not supported; only 'sub', 'super', and 'baseline' are supported\n", value);
+ }
} else if (g_str_equal (name, "clip-path")) {
g_free (state->clip_path);
state->clip_path = rsvg_get_url_string (value);
@@ -862,6 +882,7 @@ void
rsvg_parse_style_pairs (RsvgHandle * ctx, RsvgState * state, RsvgPropertyBag * atts)
{
rsvg_lookup_parse_style_pair (ctx, state, "a:adobe-blending-mode", atts);
+ rsvg_lookup_parse_style_pair (ctx, state, "baseline-shift", atts);
rsvg_lookup_parse_style_pair (ctx, state, "clip-path", atts);
rsvg_lookup_parse_style_pair (ctx, state, "clip-rule", atts);
rsvg_lookup_parse_style_pair (ctx, state, "color", atts);
diff --git a/rsvg-styles.h b/rsvg-styles.h
index bd2b5cfa..a044d3f3 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -83,6 +83,8 @@ struct _RsvgState {
char *mask;
char *clip_path;
guint8 opacity; /* 0..255 */
+ double baseline_shift;
+ gboolean has_baseline_shift;
RsvgPaintServer *fill;
gboolean has_fill_server;
diff --git a/rsvg-text.c b/rsvg-text.c
index 6fb20075..52e52c35 100644
--- a/rsvg-text.c
+++ b/rsvg-text.c
@@ -163,6 +163,7 @@ static void
gdouble * x, gdouble * y, gboolean * lastwasspace,
gboolean usetextonly);
+/* This function is responsible of selecting render for a text element including its children and giving it the drawing context */
static void
_rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
gdouble * x, gdouble * y, gboolean * lastwasspace,
@@ -598,7 +599,8 @@ rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdou
PangoLayout *layout;
PangoLayoutIter *iter;
RsvgState *state;
- gint w, h, offsetX, offsetY;
+ gint w, h;
+ double offset_x, offset_y, offset;
state = rsvg_current_state (ctx);
@@ -610,15 +612,17 @@ rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdou
layout = rsvg_text_create_layout (ctx, state, text, context);
pango_layout_get_size (layout, &w, &h);
iter = pango_layout_get_iter (layout);
+ offset = pango_layout_iter_get_baseline (iter) / (double) PANGO_SCALE;
+ offset += _rsvg_css_accumulate_baseline_shift (state, ctx);
if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity)) {
- offsetX = -pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE;
- offsetY = 0;
+ offset_x = -offset;
+ offset_y = 0;
} else {
- offsetX = 0;
- offsetY = pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE;
+ offset_x = 0;
+ offset_y = offset;
}
pango_layout_iter_free (iter);
- ctx->render->render_pango_layout (ctx, layout, *x - offsetX, *y - offsetY);
+ ctx->render->render_pango_layout (ctx, layout, *x - offset_x, *y - offset_y);
if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity))
*y += w / (double)PANGO_SCALE;
else
diff --git a/tests/fixtures/reftests/bugs/340047-ref.png b/tests/fixtures/reftests/bugs/340047-ref.png
new file mode 100644
index 00000000..58957724
--- /dev/null
+++ b/tests/fixtures/reftests/bugs/340047-ref.png
Binary files differ
diff --git a/tests/fixtures/reftests/bugs/340047.svg b/tests/fixtures/reftests/bugs/340047.svg
new file mode 100644
index 00000000..4e0ee31a
--- /dev/null
+++ b/tests/fixtures/reftests/bugs/340047.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="New document 1">
+
+ <g fill = "navy">
+ <text x = "10" y = "25" font-size = "20">
+ <tspan>
+ e = mc
+ <tspan baseline-shift = "super">
+ 2
+ </tspan>
+ </tspan>
+ <tspan x = "10" y = "60">
+ T
+ <tspan baseline-shift = "sub">
+ i+2
+ </tspan>
+ =T
+ <tspan baseline-shift = "sub">
+ i
+ </tspan>
+ + T
+ <tspan baseline-shift = "sub">
+ i+1
+ </tspan>
+ </tspan>
+ </text>
+ </g>
+</svg>