diff options
author | Menner <mik@gmx.org> | 2016-01-02 09:42:53 +0100 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2016-01-05 19:36:06 -0600 |
commit | e804fb1adcf564ce4bae661cc595a8d4df55efd3 (patch) | |
tree | 47ae3ba21f06a5b2f27f82e34186ddfe0cad3554 | |
parent | 1fc06fe6def169920f4032e348040c38be320fb1 (diff) | |
download | librsvg-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.c | 24 | ||||
-rw-r--r-- | rsvg-private.h | 2 | ||||
-rw-r--r-- | rsvg-styles.c | 21 | ||||
-rw-r--r-- | rsvg-styles.h | 2 | ||||
-rw-r--r-- | rsvg-text.c | 16 | ||||
-rw-r--r-- | tests/fixtures/reftests/bugs/340047-ref.png | bin | 0 -> 4855 bytes | |||
-rw-r--r-- | tests/fixtures/reftests/bugs/340047.svg | 43 |
7 files changed, 101 insertions, 7 deletions
@@ -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 Binary files differnew file mode 100644 index 00000000..58957724 --- /dev/null +++ b/tests/fixtures/reftests/bugs/340047-ref.png 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> |