summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 10cc818)
raw | patch | inline | side by side (parent: 10cc818)
author | buliabyak <> | |
Mon, 21 Dec 2009 05:23:37 +0000 (01:23 -0400) | ||
committer | buliabyak <> | |
Mon, 21 Dec 2009 05:23:37 +0000 (01:23 -0400) |
index 2ee0051a4b80fd544a24670bd16db3d32cd6ac5f..33371ab1008928e1ff4751cc7054e2f224995fe8 100644 (file)
#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 {
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
index 8cd26edefd7aa0e063e49c9ba4a484a307652348..05b5103fcc1407442063b9e3db7f7eba023c86c5 100644 (file)
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.
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index 6af2f7169eaf3c9eb34ed451470c0d9ee4fa0aa1..e4259e52ca9bb0f3adf9a8cc63f5d26f49975147 100644 (file)
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
{
Inkscape::Text::Layout const &layout = SP_FLOWTEXT(item)->layout;
int const nChars = layout.iteratorToCharIndex(layout.end());
+
+ char *trunc = "";
+ if (layout.inputTruncated()) {
+ trunc = _(" [truncated]");
+ }
+
if (SP_FLOWTEXT(item)->has_internal_frame())
- return g_strdup_printf(ngettext("<b>Flowed text</b> (%d character)", "<b>Flowed text</b> (%d characters)", nChars), nChars);
+ return g_strdup_printf(ngettext("<b>Flowed text</b> (%d character%s)", "<b>Flowed text</b> (%d characters%s)", nChars), nChars, trunc);
else
- return g_strdup_printf(ngettext("<b>Linked flowed text</b> (%d character)", "<b>Linked flowed text</b> (%d characters)", nChars), nChars);
+ return g_strdup_printf(ngettext("<b>Linked flowed text</b> (%d character%s)", "<b>Linked flowed text</b> (%d characters%s)", nChars), nChars, trunc);
}
static NRArenaItem *
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index 423922b80c991a11207973b3ab800b1185a18ee3..b45f8cbb607d3a67d6aac7f7f39bc2384364a0d1 100644 (file)
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
GString *xs = SP_PX_TO_METRIC_STRING(style->font_size.computed, sp_desktop_namedview(SP_ACTIVE_DESKTOP)->getDefaultMetric());
+ char *trunc = "";
+ Inkscape::Text::Layout const *layout = te_get_layout((SPItem *) item);
+ if (layout && layout->inputTruncated()) {
+ trunc = _(" [truncated]");
+ }
+
char *ret = ( SP_IS_TEXT_TEXTPATH(item)
- ? g_strdup_printf(_("<b>Text on path</b> (%s, %s)"), n, xs->str)
- : g_strdup_printf(_("<b>Text</b> (%s, %s)"), n, xs->str) );
+ ? g_strdup_printf(_("<b>Text on path</b>%s (%s, %s)"), trunc, n, xs->str)
+ : g_strdup_printf(_("<b>Text</b>%s (%s, %s)"), trunc, n, xs->str) );
g_free(n);
return ret;
}
diff --git a/src/text-context.cpp b/src/text-context.cpp
index e6f4f083b2945b006b0496707f328f5204255aac..fc28dc8e473bd66244e1e294b5ed31447e5cb193 100644 (file)
--- a/src/text-context.cpp
+++ b/src/text-context.cpp
@@ -425,11 +425,18 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve
// find out item under mouse, disregarding groups
item_ungrouped = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), TRUE);
if (SP_IS_TEXT(item_ungrouped) || SP_IS_FLOWTEXT(item_ungrouped)) {
- sp_canvas_item_show(tc->indicator);
+
+ Inkscape::Text::Layout const *layout = te_get_layout(item_ungrouped);
+ if (layout->inputTruncated()) {
+ SP_CTRLRECT(tc->indicator)->setColor(0xff0000ff, false, 0);
+ } else {
+ SP_CTRLRECT(tc->indicator)->setColor(0x0000ff7f, false, 0);
+ }
Geom::OptRect ibbox = sp_item_bbox_desktop(item_ungrouped);
if (ibbox) {
SP_CTRLRECT(tc->indicator)->setRectangle(*ibbox);
}
+ sp_canvas_item_show(tc->indicator);
event_context->cursor_shape = cursor_text_insert_xpm;
event_context->hot_x = 7;
Inkscape::Text::Layout const *layout = te_get_layout(tc->text);
int const nChars = layout->iteratorToCharIndex(layout->end());
+ char *trunc = "";
+ bool truncated = false;
+ if (layout->inputTruncated()) {
+ truncated = true;
+ trunc = _(" [truncated]");
+ }
if (SP_IS_FLOWTEXT(tc->text)) {
SPItem *frame = SP_FLOWTEXT(tc->text)->get_frame (NULL); // first frame only
if (frame) {
+ if (truncated) {
+ SP_CTRLRECT(tc->frame)->setColor(0xff0000ff, false, 0);
+ } else {
+ SP_CTRLRECT(tc->frame)->setColor(0x0000ff7f, false, 0);
+ }
sp_canvas_item_show(tc->frame);
Geom::OptRect frame_bbox = sp_item_bbox_desktop(frame);
if (frame_bbox) {
SP_CTRLRECT(tc->frame)->setRectangle(*frame_bbox);
}
}
- SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit flowed text (%d characters); <b>Enter</b> to start new paragraph."), nChars);
+
+ SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit flowed text (%d characters%s); <b>Enter</b> to start new paragraph."), nChars, trunc);
} else {
- SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit text (%d characters); <b>Enter</b> to start new line."), nChars);
+ SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit text (%d characters%s); <b>Enter</b> to start new line."), nChars, trunc);
}
} else {
diff --git a/src/text-editing.cpp b/src/text-editing.cpp
index 2bdee4c102a643ff8302d7142fd8c8113a35cadc..e93ebdffada702e11ceb028c2c4a4f9c91b96bb9 100644 (file)
--- a/src/text-editing.cpp
+++ b/src/text-editing.cpp
@@ -1843,6 +1843,37 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta
text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
+bool is_part_of_text_subtree (SPObject *obj)
+{
+ return (SP_IS_TSPAN(obj)
+ || SP_IS_TEXT(obj)
+ || SP_IS_FLOWTEXT(obj)
+ || SP_IS_FLOWTSPAN(obj)
+ || SP_IS_FLOWDIV(obj)
+ || SP_IS_FLOWPARA(obj)
+ || SP_IS_FLOWLINE(obj)
+ || SP_IS_FLOWREGIONBREAK(obj));
+}
+
+bool is_top_level_text_object (SPObject *obj)
+{
+ return (SP_IS_TEXT(obj)
+ || SP_IS_FLOWTEXT(obj));
+}
+
+bool has_visible_text (SPObject *obj)
+{
+ if (SP_IS_STRING(obj) && !SP_STRING(obj)->string.empty())
+ return true; // maybe we should also check that it's not all whitespace?
+
+ for (SPObject const *child = obj->firstChild() ; child ; child = SP_OBJECT_NEXT(child)) {
+ if (has_visible_text((SPObject *) child))
+ return true;
+ }
+
+ return false;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/text-editing.h b/src/text-editing.h
index 83ddae77fc6e74781c8d9c78a79491e30170704e..7e845dbc905dff38e9d6d1b93ee341de6f727261 100644 (file)
--- a/src/text-editing.h
+++ b/src/text-editing.h
void sp_te_adjust_linespacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by);
void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPCSSAttr const *css);
+bool is_part_of_text_subtree (SPObject *obj);
+bool is_top_level_text_object (SPObject *obj);
+bool has_visible_text (SPObject *obj);
+
#endif