Code

Some additional Paint Bucket optimizations and cleanup
[inkscape.git] / src / sp-flowtext.cpp
index 8a39eb0b4f576fd7ed26d390d56e4f55d411d03b..daa9f808a2db1c0046de3741ef94af7094330fe9 100644 (file)
@@ -25,6 +25,7 @@
 #include "sp-use.h"
 #include "sp-rect.h"
 #include "text-tag-attributes.h"
+#include "text-chemistry.h"
 
 
 #include "livarot/Shape.h"
@@ -172,11 +173,12 @@ sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags)
 
     group->rebuildLayout();
 
-    // pass the bbox of the flowtext object as paintbox (used for paintserver fills)
     NRRect paintbox;
     sp_item_invoke_bbox(group, &paintbox, NR::identity(), TRUE);
     for (SPItemView *v = group->display; v != NULL; v = v->next) {
         group->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
+        nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object));
+        // pass the bbox of the flowtext object as paintbox (used for paintserver fills)
         group->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
     }
 }
@@ -190,6 +192,18 @@ sp_flowtext_modified(SPObject *object, guint flags)
     if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
     flags &= SP_OBJECT_MODIFIED_CASCADE;
 
+    // FIXME: the below stanza is copied over from sp_text_modified, consider factoring it out
+    if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) {
+        SPFlowtext *text = SP_FLOWTEXT(object);
+        NRRect paintbox;
+        sp_item_invoke_bbox(text, &paintbox, NR::identity(), TRUE);
+        for (SPItemView* v = text->display; v != NULL; v = v->next) {
+            text->_clearFlow(NR_ARENA_GROUP(v->arenaitem));
+            nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object));
+            text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox);
+        }
+    }
+
     for (SPObject *o = sp_object_first_child(SP_OBJECT(ft)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
         if (SP_IS_FLOWREGION(o)) {
             region = o;
@@ -278,7 +292,8 @@ static Inkscape::XML::Node *
 sp_flowtext_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 {
     if ( flags & SP_OBJECT_WRITE_BUILD ) {
-        if ( repr == NULL ) repr = sp_repr_new("svg:flowRoot");
+        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
+        if ( repr == NULL ) repr = xml_doc->createElement("svg:flowRoot");
         GSList *l = NULL;
         for (SPObject *child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) {
             Inkscape::XML::Node *c_repr = NULL;
@@ -365,6 +380,8 @@ sp_flowtext_show(SPItem *item, NRArena *arena, unsigned/* key*/, unsigned /*flag
     NRArenaGroup *flowed = NRArenaGroup::create(arena);
     nr_arena_group_set_transparent(flowed, FALSE);
 
+    nr_arena_group_set_style(flowed, group->style);
+
     // pass the bbox of the flowtext object as paintbox (used for paintserver fills)
     NRRect paintbox;
     sp_item_invoke_bbox(item, &paintbox, NR::identity(), TRUE);
@@ -499,40 +516,37 @@ void SPFlowtext::_clearFlow(NRArenaGroup *in_arena)
     }
 }
 
-void SPFlowtext::convert_to_text()
+Inkscape::XML::Node *
+SPFlowtext::getAsText()
 {
-    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-    Inkscape::Selection *selection = sp_desktop_selection(desktop);
-    SPItem *item = selection->singleItem();
-    if (!SP_IS_FLOWTEXT(item)) return;
-
-    SPFlowtext *group = SP_FLOWTEXT(item);
+    if (!this->layout.outputExists()) return NULL;
 
-    if (!group->layout.outputExists()) return;
+    SPItem *item = SP_ITEM(this);
 
-    Inkscape::XML::Node *repr = sp_repr_new("svg:text");
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(this));
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:text");
     repr->setAttribute("xml:space", "preserve");
-    repr->setAttribute("style", SP_OBJECT_REPR(group)->attribute("style"));
-    NR::Point anchor_point = group->layout.characterAnchorPoint(group->layout.begin());
+    repr->setAttribute("style", SP_OBJECT_REPR(this)->attribute("style"));
+    NR::Point anchor_point = this->layout.characterAnchorPoint(this->layout.begin());
     sp_repr_set_svg_double(repr, "x", anchor_point[NR::X]);
     sp_repr_set_svg_double(repr, "y", anchor_point[NR::Y]);
 
-    for (Inkscape::Text::Layout::iterator it = group->layout.begin() ; it != group->layout.end() ; ) {
-
-           Inkscape::XML::Node *line_tspan = sp_repr_new("svg:tspan");
+    for (Inkscape::Text::Layout::iterator it = this->layout.begin() ; it != this->layout.end() ; ) {
+        Inkscape::XML::Node *line_tspan = xml_doc->createElement("svg:tspan");
         line_tspan->setAttribute("sodipodi:role", "line");
 
         Inkscape::Text::Layout::iterator it_line_end = it;
         it_line_end.nextStartOfLine();
+
         while (it != it_line_end) {
 
-               Inkscape::XML::Node *span_tspan = sp_repr_new("svg:tspan");
-            NR::Point anchor_point = group->layout.characterAnchorPoint(it);
+            Inkscape::XML::Node *span_tspan = xml_doc->createElement("svg:tspan");
+            NR::Point anchor_point = this->layout.characterAnchorPoint(it);
             // use kerning to simulate justification and whatnot
             Inkscape::Text::Layout::iterator it_span_end = it;
             it_span_end.nextStartOfSpan();
             Inkscape::Text::Layout::OptionalTextTagAttrs attrs;
-            group->layout.simulateLayoutUsingKerning(it, it_span_end, &attrs);
+            this->layout.simulateLayoutUsingKerning(it, it_span_end, &attrs);
             // set x,y attributes only when we need to
             bool set_x = false;
             bool set_y = false;
@@ -561,9 +575,9 @@ void SPFlowtext::convert_to_text()
             SPObject *source_obj = 0;
             void *rawptr = 0;
             Glib::ustring::iterator span_text_start_iter;
-            group->layout.getSourceOfCharacter(it, &rawptr, &span_text_start_iter);
+            this->layout.getSourceOfCharacter(it, &rawptr, &span_text_start_iter);
             source_obj = SP_OBJECT (rawptr);
-            gchar *style_text = sp_style_write_difference((SP_IS_STRING(source_obj) ? source_obj->parent : source_obj)->style, group->style);
+            gchar *style_text = sp_style_write_difference((SP_IS_STRING(source_obj) ? source_obj->parent : source_obj)->style, this->style);
             if (style_text && *style_text) {
                 span_tspan->setAttribute("style", style_text);
                 g_free(style_text);
@@ -574,12 +588,12 @@ void SPFlowtext::convert_to_text()
                 SPObject *span_end_obj = 0;
                 void *rawptr = 0;
                 Glib::ustring::iterator span_text_end_iter;
-                group->layout.getSourceOfCharacter(it_span_end, &rawptr, &span_text_end_iter);
+                this->layout.getSourceOfCharacter(it_span_end, &rawptr, &span_text_end_iter);
                 span_end_obj = SP_OBJECT(rawptr);
                 if (span_end_obj != source_obj) {
-                    if (it_span_end == group->layout.end()) {
+                    if (it_span_end == this->layout.end()) {
                         span_text_end_iter = span_text_start_iter;
-                        for (int i = group->layout.iteratorToCharIndex(it_span_end) - group->layout.iteratorToCharIndex(it) ; i ; --i)
+                        for (int i = this->layout.iteratorToCharIndex(it_span_end) - this->layout.iteratorToCharIndex(it) ; i ; --i)
                             ++span_text_end_iter;
                     } else
                         span_text_end_iter = string->end();    // spans will never straddle a source boundary
@@ -589,7 +603,7 @@ void SPFlowtext::convert_to_text()
                     Glib::ustring new_string;
                     while (span_text_start_iter != span_text_end_iter)
                         new_string += *span_text_start_iter++;    // grr. no substr() with iterators
-                    Inkscape::XML::Node *new_text = sp_repr_new_text(new_string.c_str());
+                    Inkscape::XML::Node *new_text = xml_doc->createTextNode(new_string.c_str());
                     span_tspan->appendChild(new_text);
                     Inkscape::GC::release(new_text);
                 }
@@ -597,24 +611,13 @@ void SPFlowtext::convert_to_text()
             it = it_span_end;
 
             line_tspan->appendChild(span_tspan);
-               Inkscape::GC::release(span_tspan);
+            Inkscape::GC::release(span_tspan);
         }
         repr->appendChild(line_tspan);
-           Inkscape::GC::release(line_tspan);
+        Inkscape::GC::release(line_tspan);
     }
 
-    Inkscape::XML::Node *parent = SP_OBJECT_REPR(item)->parent();
-    parent->appendChild(repr);
-    SPItem *new_item = (SPItem *) sp_desktop_document(desktop)->getObjectByRepr(repr);
-    sp_item_write_transform(new_item, repr, item->transform);
-    SP_OBJECT(new_item)->updateRepr();
-
-    Inkscape::GC::release(repr);
-    selection->set(new_item);
-    item->deleteObject();
-
-    sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE, 
-                     /* TODO: annotate */ "sp-flowtext.cpp:617");
+    return repr;
 }
 
 SPItem *SPFlowtext::get_frame(SPItem *after)
@@ -667,18 +670,19 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, NR::Point p0, N
 {
     SPDocument *doc = sp_desktop_document (desktop);
 
-    Inkscape::XML::Node *root_repr = sp_repr_new("svg:flowRoot");
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+    Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot");
     root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create
     SPItem *ft_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(root_repr));
     SPObject *root_object = doc->getObjectByRepr(root_repr);
     g_assert(SP_IS_FLOWTEXT(root_object));
 
-    Inkscape::XML::Node *region_repr = sp_repr_new("svg:flowRegion");
+    Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion");
     root_repr->appendChild(region_repr);
     SPObject *region_object = doc->getObjectByRepr(region_repr);
     g_assert(SP_IS_FLOWREGION(region_object));
 
-    Inkscape::XML::Node *rect_repr = sp_repr_new("svg:rect"); // FIXME: use path!!! after rects are converted to use path
+    Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path
     region_repr->appendChild(rect_repr);
 
     SPObject *rect = doc->getObjectByRepr(rect_repr);
@@ -697,12 +701,12 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, NR::Point p0, N
     sp_rect_position_set(SP_RECT(rect), x0, y0, w, h);
     SP_OBJECT(rect)->updateRepr();
 
-    Inkscape::XML::Node *para_repr = sp_repr_new("svg:flowPara");
+    Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara");
     root_repr->appendChild(para_repr);
     SPObject *para_object = doc->getObjectByRepr(para_repr);
     g_assert(SP_IS_FLOWPARA(para_object));
 
-    Inkscape::XML::Node *text = sp_repr_new_text("");
+    Inkscape::XML::Node *text = xml_doc->createTextNode("");
     para_repr->appendChild(text);
 
     Inkscape::GC::release(root_repr);