diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2019-11-13 09:05:52 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2019-11-13 09:05:52 +0000 |
| commit | 6ae14ec71c2c005cb03ef6e0f5146bc30441acc7 (patch) | |
| tree | 8145f98d4c41cd8a1af775575fb910d0adf82b02 /src | |
| parent | Update inkscape.pot (diff) | |
| download | inkscape-6ae14ec71c2c005cb03ef6e0f5146bc30441acc7.tar.gz inkscape-6ae14ec71c2c005cb03ef6e0f5146bc30441acc7.zip | |
Fix alignment error for inline-size SVG 1.1 fallback text.
Puts white space at end of line into separate tspan when
'text-anchor' is not start.
Diffstat (limited to 'src')
| -rw-r--r-- | src/extension/internal/svg.cpp | 47 | ||||
| -rw-r--r-- | src/object/sp-tspan.cpp | 7 |
2 files changed, 50 insertions, 4 deletions
diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index 932ece46a..bc82c5692 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -384,6 +384,11 @@ static void insert_text_fallback( Inkscape::XML::Node *repr, SPDocument *origina sp_repr_css_attr_unref(css); } + // We need to put trailing white space into it's own tspan for inline size so + // it is excluded during calculation of line position in SVG 1.1 renderers. + bool trim = text->has_inline_size() && + !(text->style->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START); + // Make a list of children to delete at end: std::vector<Inkscape::XML::Node *> old_children; for (auto child = repr->firstChild(); child; child = child->next()) { @@ -408,8 +413,9 @@ static void insert_text_fallback( Inkscape::XML::Node *repr, SPDocument *origina // Create a <tspan> with 'x' and 'y' for each line. Inkscape::XML::Node *line_tspan = repr->document()->createElement("svg:tspan"); - // This could be useful if one wants to edit in an old version of Inkscape but we need to check if it breaks anything: - // line_tspan->setAttribute("sodipodi:role", "line"); + // This could be useful if one wants to edit in an old version of Inkscape but we + // need to check if it breaks anything: + line_tspan->setAttribute("sodipodi:role", "line"); Geom::Point line_anchor_point = text->layout.characterAnchorPoint(it); double line_x = line_anchor_point[Geom::X]; @@ -447,6 +453,13 @@ static void insert_text_fallback( Inkscape::XML::Node *repr, SPDocument *origina Inkscape::Text::Layout::iterator it_line_end = it; it_line_end.nextStartOfLine(); + // Find last span in line so we can put trailing whitespace in its own tspan for SVG 1.1 fallback. + Inkscape::Text::Layout::iterator it_last_span = it; + it_last_span.nextStartOfLine(); + it_last_span.prevStartOfSpan(); + + Glib::ustring trailing_whitespace; + // Loop over chunks in line while (it != it_line_end) { @@ -495,6 +508,14 @@ static void insert_text_fallback( Inkscape::XML::Node *repr, SPDocument *origina Glib::ustring new_string; while (span_text_start_iter != span_text_end_iter) new_string += *span_text_start_iter++; // grr. no substr() with iterators + + if (it == it_last_span && trim) { + // Found last span in line + const auto s = new_string.find_last_not_of(" \t"); // Any other white space characters needed? + trailing_whitespace = new_string.substr(s+1, new_string.length()); + new_string.erase(s+1); + } + Inkscape::XML::Node *new_text = repr->document()->createTextNode(new_string.c_str()); span_tspan->appendChild(new_text); Inkscape::GC::release(new_text); @@ -505,13 +526,33 @@ static void insert_text_fallback( Inkscape::XML::Node *repr, SPDocument *origina // Add tspan to document line_tspan->appendChild(span_tspan); - line_tspan->setAttribute("sodipodi:role", "line"); Inkscape::GC::release(span_tspan); } // Add line tspan to document repr->appendChild(line_tspan); Inkscape::GC::release(line_tspan); + + // For center and end justified text, we need to remove any spaces and put them + // into a separate tspan (alignment is done by "text chunk" and spaces at ends of + // line will mess this up). + if (trim && trailing_whitespace.length() != 0) { + + Inkscape::XML::Node *space_tspan = repr->document()->createElement("svg:tspan"); + // Set either 'x' or 'y' to force a new text chunk. To do: this really should + // be positioned at the end of the line (overhanging). + if (text->is_horizontal()) { + sp_repr_set_svg_double(space_tspan, "y", line_y); + } else { + sp_repr_set_svg_double(space_tspan, "x", line_x); + } + Inkscape::XML::Node *space = repr->document()->createTextNode(trailing_whitespace.c_str()); + space_tspan->appendChild(space); + Inkscape::GC::release(space); + line_tspan->appendChild(space_tspan); + Inkscape::GC::release(space_tspan); + } + } for (auto i: old_children) { diff --git a/src/object/sp-tspan.cpp b/src/object/sp-tspan.cpp index cee3f7d37..bbd8818d6 100644 --- a/src/object/sp-tspan.cpp +++ b/src/object/sp-tspan.cpp @@ -60,7 +60,12 @@ void SPTSpan::build(SPDocument *doc, Inkscape::XML::Node *repr) { this->readAttr( "dx" ); this->readAttr( "dy" ); this->readAttr( "rotate" ); - this->readAttr( "sodipodi:role" ); + + // Strip sodipodi:role from SVG 2 flowed text. + SPText* text = dynamic_cast<SPText*>(parent); + if (text && !(text->has_shape_inside() || text->has_inline_size())) { + this->readAttr( "sodipodi:role" ); + } SPItem::build(doc, repr); } |
