summaryrefslogtreecommitdiffstats
path: root/src/libnrtype
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnrtype')
-rw-r--r--src/libnrtype/Layout-TNG-Input.cpp69
-rw-r--r--src/libnrtype/Layout-TNG-OutIter.cpp29
-rw-r--r--src/libnrtype/Layout-TNG.h6
3 files changed, 102 insertions, 2 deletions
diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp
index 2ee0051a4..33371ab10 100644
--- a/src/libnrtype/Layout-TNG-Input.cpp
+++ b/src/libnrtype/Layout-TNG-Input.cpp
@@ -16,8 +16,11 @@
#include "style.h"
#include "svg/svg-length.h"
#include "sp-object.h"
+#include "sp-string.h"
#include "FontFactory.h"
+#include "text-editing.h" // for inputTruncated()
+
namespace Inkscape {
namespace Text {
@@ -321,5 +324,71 @@ Layout::InputStreamTextSource::~InputStreamTextSource()
sp_style_unref(style);
}
+bool
+Layout::inputTruncated() const
+{
+ if (!inputExists())
+ return false;
+
+ // Find out the SPObject to which the last visible character corresponds:
+ Layout::iterator last = end();
+ if (last == begin()) {
+ // FIXME: this returns a wrong "not truncated" when a flowtext is entirely
+ // truncated, so there are no visible characters. But how can I find out the
+ // originator SPObject without having anything to do getSourceOfCharacter
+ // from?
+ return false;
+ }
+ last.prevCharacter();
+ void *source;
+ Glib::ustring::iterator offset;
+ getSourceOfCharacter(last, &source, &offset);
+ SPObject *obj = SP_OBJECT(source);
+
+ // if that is SPString, see if it has further characters beyond the last visible
+ if (obj && SP_IS_STRING(obj)) {
+ Glib::ustring::iterator offset_next = offset;
+ offset_next ++;
+ if (offset_next != SP_STRING(obj)->string.end()) {
+ // truncated: source SPString has next char
+ return true;
+ }
+ }
+
+ // otherwise, see if the SPObject at end() or any of its text-tree ancestors
+ // (excluding top-level SPText or SPFlowText) have a text-tree next sibling with
+ // visible text
+ if (obj) {
+ for (SPObject *ascend = obj;
+ ascend && (is_part_of_text_subtree (ascend) && !is_top_level_text_object(ascend));
+ ascend = SP_OBJECT_PARENT(ascend)) {
+ if (SP_OBJECT_NEXT(ascend)) {
+ SPObject *next = SP_OBJECT_NEXT(ascend);
+ if (next && is_part_of_text_subtree(next) && has_visible_text(next)) {
+ // truncated: source text object has next text sibling
+ return true;
+ }
+ }
+ }
+ }
+
+ // the above works for flowed text, but not for text on path.
+ // so now, we also check if the last of the _characters, if coming from a TEXT_SOURCE,
+ // has in_glyph different from -1
+ unsigned last_char = _characters.size() - 1;
+ unsigned span_index = _characters[last_char].in_span;
+ Glib::ustring::const_iterator iter_char = _spans[span_index].input_stream_first_character;
+
+ if (_input_stream[_spans[span_index].in_input_stream_item]->Type() == TEXT_SOURCE) {
+ if (_characters[last_char].in_glyph == -1) {
+ //truncated: last char has no glyph
+ return true;
+ }
+ }
+
+ // not truncated
+ return false;
+}
+
}//namespace Text
}//namespace Inkscape
diff --git a/src/libnrtype/Layout-TNG-OutIter.cpp b/src/libnrtype/Layout-TNG-OutIter.cpp
index 0fc061bfc..f4e8e4031 100644
--- a/src/libnrtype/Layout-TNG-OutIter.cpp
+++ b/src/libnrtype/Layout-TNG-OutIter.cpp
@@ -221,6 +221,31 @@ Geom::Point Layout::characterAnchorPoint(iterator const &it) const
}
}
+boost::optional<Geom::Point> Layout::baselineAnchorPoint() const
+{
+ iterator pos = this->begin();
+ Geom::Point left_pt = this->characterAnchorPoint(pos);
+ pos.thisEndOfLine();
+ Geom::Point right_pt = this->characterAnchorPoint(pos);
+ Geom::Point mid_pt = (left_pt + right_pt)/2;
+
+ switch (this->paragraphAlignment(pos)) {
+ case LEFT:
+ case FULL:
+ return left_pt;
+ break;
+ case CENTER:
+ return mid_pt;
+ break;
+ case RIGHT:
+ return right_pt;
+ break;
+ default:
+ return boost::optional<Geom::Point>();
+ break;
+ }
+}
+
Geom::Point Layout::chunkAnchorPoint(iterator const &it) const
{
unsigned chunk_index;
@@ -705,7 +730,7 @@ bool Layout::iterator::nextLineCursor(int n)
unsigned line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line;
if (line_index == _parent_layout->_lines.size() - 1)
return false; // nowhere to go
- else
+ else
n = MIN (n, static_cast<int>(_parent_layout->_lines.size() - 1 - line_index));
if (_parent_layout->_lines[line_index + n].in_shape != _parent_layout->_lines[line_index].in_shape) {
// switching between shapes: adjust the stored x to compensate
@@ -728,7 +753,7 @@ bool Layout::iterator::prevLineCursor(int n)
line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line;
if (line_index == 0)
return false; // nowhere to go
- else
+ else
n = MIN (n, static_cast<int>(line_index));
if (_parent_layout->_lines[line_index - n].in_shape != _parent_layout->_lines[line_index].in_shape) {
// switching between shapes: adjust the stored x to compensate
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index 19680b140..05b5103fc 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -212,6 +212,8 @@ public:
bool inputExists() const
{return !_input_stream.empty();}
+ bool inputTruncated() const;
+
/** adds a new piece of text to the end of the current list of text to
be processed. This method can only add text of a consistent style.
To add lots of different styles, call it lots of times.
@@ -480,6 +482,10 @@ public:
/** For latin text, the left side of the character, on the baseline */
Geom::Point characterAnchorPoint(iterator const &it) const;
+ /** For left aligned text, the leftmost end of the baseline
+ For rightmost text, the rightmost... you probably got it by now ;-)*/
+ boost::optional<Geom::Point> baselineAnchorPoint() const;
+
/** This is that value to apply to the x,y attributes of tspan role=line
elements, and hence it takes alignment into account. */
Geom::Point chunkAnchorPoint(iterator const &it) const;