X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ftext-editing.cpp;h=b84361324338c62735017ba15f2407bd624e9d60;hb=03edfb301b911c7a3313b58dd50193ba8e7e21ca;hp=f0cb4bd9da12967f29a32a30863485bc1154a367;hpb=226d6d28236ad91c681c13bcf1cff4c1639b153b;p=inkscape.git diff --git a/src/text-editing.cpp b/src/text-editing.cpp index f0cb4bd9d..b84361324 100644 --- a/src/text-editing.cpp +++ b/src/text-editing.cpp @@ -18,6 +18,7 @@ #include "style.h" #include "unit-constants.h" +#include "document.h" #include "xml/repr.h" #include "xml/attribute-record.h" @@ -103,9 +104,11 @@ SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layo Inkscape::Text::Layout const *layout = te_get_layout(text); if (layout == NULL) return NULL; - SPObject const *pos_obj = NULL; - layout->getSourceOfCharacter(position, (void**)&pos_obj); - if (pos_obj == NULL) pos_obj = text; + SPObject const *pos_obj = 0; + void *rawptr = 0; + layout->getSourceOfCharacter(position, &rawptr); + pos_obj = SP_OBJECT(rawptr); + if (pos_obj == 0) pos_obj = text; while (SP_OBJECT_STYLE(pos_obj) == NULL) pos_obj = SP_OBJECT_PARENT(pos_obj); // SPStrings don't have style return SP_OBJECT_STYLE(pos_obj); @@ -219,11 +222,11 @@ unsigned sp_text_get_length_upto(SPObject const *item, SPObject const *upto) return length; } -static Inkscape::XML::Node* duplicate_node_without_children(Inkscape::XML::Node const *old_node) +static Inkscape::XML::Node* duplicate_node_without_children(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node const *old_node) { switch (old_node->type()) { case Inkscape::XML::ELEMENT_NODE: { - Inkscape::XML::Node *new_node = sp_repr_new(old_node->name()); + Inkscape::XML::Node *new_node = xml_doc->createElement(old_node->name()); Inkscape::Util::List attributes = old_node->attributeList(); GQuark const id_key = g_quark_from_string("id"); for ( ; attributes ; attributes++) { @@ -234,10 +237,10 @@ static Inkscape::XML::Node* duplicate_node_without_children(Inkscape::XML::Node } case Inkscape::XML::TEXT_NODE: - return sp_repr_new_text(old_node->content()); + return xml_doc->createTextNode(old_node->content()); case Inkscape::XML::COMMENT_NODE: - return sp_repr_new_comment(old_node->content()); + return xml_doc->createComment(old_node->content()); case Inkscape::XML::DOCUMENT_NODE: return NULL; // this had better never happen @@ -273,8 +276,9 @@ parent of the first line break node encountered. */ static SPObject* split_text_object_tree_at(SPObject *split_obj, unsigned char_index) { + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(split_obj)); if (is_line_break_object(split_obj)) { - Inkscape::XML::Node *new_node = duplicate_node_without_children(SP_OBJECT_REPR(split_obj)); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); SP_OBJECT_REPR(SP_OBJECT_PARENT(split_obj))->addChild(new_node, SP_OBJECT_REPR(split_obj)); Inkscape::GC::release(new_node); split_attributes(split_obj, SP_OBJECT_NEXT(split_obj), char_index); @@ -284,7 +288,7 @@ static SPObject* split_text_object_tree_at(SPObject *split_obj, unsigned char_in unsigned char_count_before = sum_sibling_text_lengths_before(split_obj); SPObject *duplicate_obj = split_text_object_tree_at(SP_OBJECT_PARENT(split_obj), char_index + char_count_before); // copy the split node - Inkscape::XML::Node *new_node = duplicate_node_without_children(SP_OBJECT_REPR(split_obj)); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); SP_OBJECT_REPR(duplicate_obj)->appendChild(new_node); Inkscape::GC::release(new_node); @@ -318,17 +322,19 @@ Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *item, Inkscape::Text return position; Inkscape::Text::Layout const *layout = te_get_layout(item); - SPObject *split_obj; + SPObject *split_obj = 0; Glib::ustring::iterator split_text_iter; - if (position == layout->end()) - split_obj = NULL; - else - layout->getSourceOfCharacter(position, (void**)&split_obj, &split_text_iter); + if (position != layout->end()) { + void *rawptr = 0; + layout->getSourceOfCharacter(position, &rawptr, &split_text_iter); + split_obj = SP_OBJECT(rawptr); + } - if (split_obj == NULL || is_line_break_object(split_obj)) { - if (split_obj == NULL) split_obj = item->lastChild(); + if (split_obj == 0 || is_line_break_object(split_obj)) { + if (split_obj == 0) split_obj = item->lastChild(); if (split_obj) { - Inkscape::XML::Node *new_node = duplicate_node_without_children(SP_OBJECT_REPR(split_obj)); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(split_obj)); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); SP_OBJECT_REPR(SP_OBJECT_PARENT(split_obj))->addChild(new_node, SP_OBJECT_REPR(split_obj)); Inkscape::GC::release(new_node); } @@ -404,14 +410,16 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch } Inkscape::Text::Layout const *layout = te_get_layout(item); - SPObject *source_obj; + SPObject *source_obj = 0; + void *rawptr = 0; Glib::ustring::iterator iter_text; // we want to insert after the previous char, not before the current char. // it makes a difference at span boundaries Inkscape::Text::Layout::iterator it_prev_char = position; bool cursor_at_start = !it_prev_char.prevCharacter(); bool cursor_at_end = position == layout->end(); - layout->getSourceOfCharacter(it_prev_char, (void**)&source_obj, &iter_text); + layout->getSourceOfCharacter(it_prev_char, &rawptr, &iter_text); + source_obj = SP_OBJECT(rawptr); if (SP_IS_STRING(source_obj)) { // the simple case if (!cursor_at_start) iter_text++; @@ -419,6 +427,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch insert_into_spstring(string_item, cursor_at_end ? string_item->string.end() : iter_text, utf8); } else { // the not-so-simple case where we're at a line break or other control char; add to the next child/sibling SPString + Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); if (cursor_at_start) { source_obj = item; if (source_obj->hasChildren()) { @@ -431,7 +440,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch } } if (source_obj == item && SP_IS_FLOWTEXT(item)) { - Inkscape::XML::Node *para = sp_repr_new("svg:flowPara"); + Inkscape::XML::Node *para = xml_doc->createElement("svg:flowPara"); SP_OBJECT_REPR(item)->appendChild(para); source_obj = item->lastChild(); } @@ -442,7 +451,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch SPString *string_item = sp_te_seek_next_string_recursive(source_obj); if (string_item == NULL) { // need to add an SPString in this (pathological) case - Inkscape::XML::Node *rstring = sp_repr_new_text(""); + Inkscape::XML::Node *rstring = xml_doc->createTextNode(""); SP_OBJECT_REPR(source_obj)->addChild(rstring, NULL); Inkscape::GC::release(rstring); g_assert(SP_IS_STRING(source_obj->firstChild())); @@ -519,7 +528,8 @@ static SPObject* delete_line_break(SPObject *root, SPObject *item, bool *next_is

*text

*text

*/ - Inkscape::XML::Node *new_span_repr = sp_repr_new(span_name_for_text_object(root)); + Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); + Inkscape::XML::Node *new_span_repr = xml_doc->createElement(span_name_for_text_object(root)); if (gchar const *a = this_repr->attribute("dx")) new_span_repr->setAttribute("dx", a); @@ -624,15 +634,18 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inksc last = start; } Inkscape::Text::Layout const *layout = te_get_layout(item); - SPObject *start_item, *end_item; + SPObject *start_item = 0, *end_item = 0; + void *rawptr = 0; Glib::ustring::iterator start_text_iter, end_text_iter; - layout->getSourceOfCharacter(first, (void**)&start_item, &start_text_iter); - layout->getSourceOfCharacter(last, (void**)&end_item, &end_text_iter); - if (start_item == NULL) + layout->getSourceOfCharacter(first, &rawptr, &start_text_iter); + start_item = SP_OBJECT(rawptr); + layout->getSourceOfCharacter(last, &rawptr, &end_text_iter); + end_item = SP_OBJECT(rawptr); + if (start_item == 0) return first; // start is at end of text if (is_line_break_object(start_item)) move_to_end_of_paragraph(&start_item, &start_text_iter); - if (end_item == NULL) { + if (end_item == 0) { end_item = item->lastChild(); move_to_end_of_paragraph(&end_item, &end_text_iter); } @@ -748,9 +761,11 @@ sp_te_get_string_multiline (SPItem const *text, Inkscape::Text::Layout::iterator Glib::ustring result; // not a particularly fast piece of code. I'll optimise it if people start to notice. for ( ; first < last ; first.nextCharacter()) { - SPObject *char_item; + SPObject *char_item = 0; + void *rawptr = 0; Glib::ustring::iterator text_iter; - layout->getSourceOfCharacter(first, (void**)&char_item, &text_iter); + layout->getSourceOfCharacter(first, &rawptr, &text_iter); + char_item = SP_OBJECT(rawptr); if (SP_IS_STRING(char_item)) result += *text_iter; else @@ -765,6 +780,7 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) g_return_if_fail (text != NULL); g_return_if_fail (SP_IS_TEXT(text) || SP_IS_FLOWTEXT(text)); + Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(text)->document(); Inkscape::XML::Node *repr; SPObject *object; bool is_textpath = false; @@ -798,12 +814,12 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) if (e) *e = '\0'; Inkscape::XML::Node *rtspan; if (SP_IS_TEXT(text)) { // create a tspan for each line - rtspan = sp_repr_new ("svg:tspan"); + rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); } else { // create a flowPara for each line - rtspan = sp_repr_new ("svg:flowPara"); + rtspan = xml_doc->createElement("svg:flowPara"); } - Inkscape::XML::Node *rstr = sp_repr_new_text(p); + Inkscape::XML::Node *rstr = xml_doc->createTextNode(p); rtspan->addChild(rstr, NULL); Inkscape::GC::release(rstr); repr->appendChild(rtspan); @@ -812,7 +828,7 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) p = (e) ? e + 1 : NULL; } if (is_textpath) { - Inkscape::XML::Node *rstr = sp_repr_new_text(content); + Inkscape::XML::Node *rstr = xml_doc->createTextNode(content); repr->addChild(rstr, NULL); Inkscape::GC::release(rstr); } @@ -832,9 +848,11 @@ text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator c return NULL; // flowtext doesn't support kerning yet SPText *text = SP_TEXT(item); - SPObject *source_item; + SPObject *source_item = 0; + void *rawptr = 0; Glib::ustring::iterator source_text_iter; - text->layout.getSourceOfCharacter(position, (void**)&source_item, &source_text_iter); + text->layout.getSourceOfCharacter(position, &rawptr, &source_text_iter); + source_item = SP_OBJECT(rawptr); if (!SP_IS_STRING(source_item)) return NULL; Glib::ustring *string = &SP_STRING(source_item)->string; @@ -875,11 +893,13 @@ sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator cons gdouble factor = 1 / desktop->current_zoom(); NR::Matrix t = sp_item_i2doc_affine(text); factor = factor / NR::expansion(t); - SPObject *source_item; Inkscape::Text::Layout const *layout = te_get_layout(text); if (layout == NULL) return; - layout->getSourceOfCharacter(std::min(start, end), (void**)&source_item); - if (source_item == NULL) return; + SPObject *source_item = 0; + void *rawptr = 0; + layout->getSourceOfCharacter(std::min(start, end), &rawptr); + source_item = SP_OBJECT(rawptr); + if (source_item == 0) return; gdouble degrees = (180/M_PI) * atan2(pixels, SP_OBJECT_PARENT(source_item)->style->font_size.computed / factor); sp_te_adjust_rotation(text, start, end, desktop, degrees); @@ -913,11 +933,13 @@ sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::it Inkscape::Text::Layout const *layout = te_get_layout(text); gdouble val; - SPObject *source_obj; + SPObject *source_obj = 0; + void *rawptr = 0; unsigned nb_let; - layout->getSourceOfCharacter(std::min(start, end), (void**)&source_obj); + layout->getSourceOfCharacter(std::min(start, end), &rawptr); + source_obj = SP_OBJECT(rawptr); - if (source_obj == NULL) { // end of text + if (source_obj == 0) { // end of text source_obj = text->lastChild(); } if (SP_IS_STRING(source_obj)) { @@ -1183,7 +1205,8 @@ name of the xml for a text span (ie tspan or flowspan). */ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const *css, SPObject *start_item, Glib::ustring::iterator start_text_iter, SPObject *end_item, Glib::ustring::iterator end_text_iter, char const *span_object_name) { bool passed_start = start_item == NULL ? true : false; - + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(common_ancestor)); + for (SPObject *child = common_ancestor->firstChild() ; child != NULL ; child = SP_OBJECT_NEXT(child)) { if (start_item == child) passed_start = true; @@ -1201,7 +1224,7 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * SPString *string_item = SP_STRING(child); bool surround_entire_string = true; - Inkscape::XML::Node *child_span = sp_repr_new(span_object_name); + Inkscape::XML::Node *child_span = xml_doc->createElement(span_object_name); sp_repr_css_set(child_span, const_cast(css), "style"); // better hope that prototype wasn't nonconst for a good reason SPObject *prev_item = SP_OBJECT_PREV(child); Inkscape::XML::Node *prev_repr = prev_item ? SP_OBJECT_REPR(prev_item) : NULL; @@ -1213,11 +1236,11 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * unsigned start_char_index = char_index_of_iterator(string_item->string, start_text_iter); unsigned end_char_index = char_index_of_iterator(string_item->string, end_text_iter); - Inkscape::XML::Node *text_before = sp_repr_new_text(string_item->string.substr(0, start_char_index).c_str()); + Inkscape::XML::Node *text_before = xml_doc->createTextNode(string_item->string.substr(0, start_char_index).c_str()); SP_OBJECT_REPR(common_ancestor)->addChild(text_before, prev_repr); SP_OBJECT_REPR(common_ancestor)->addChild(child_span, text_before); Inkscape::GC::release(text_before); - Inkscape::XML::Node *text_in_span = sp_repr_new_text(string_item->string.substr(start_char_index, end_char_index - start_char_index).c_str()); + Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(start_char_index, end_char_index - start_char_index).c_str()); child_span->appendChild(text_in_span); Inkscape::GC::release(text_in_span); SP_OBJECT_REPR(child)->setContent(string_item->string.substr(end_char_index).c_str()); @@ -1229,7 +1252,7 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * unsigned end_char_index = char_index_of_iterator(string_item->string, end_text_iter); SP_OBJECT_REPR(common_ancestor)->addChild(child_span, prev_repr); - Inkscape::XML::Node *text_in_span = sp_repr_new_text(string_item->string.substr(0, end_char_index).c_str()); + Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(0, end_char_index).c_str()); child_span->appendChild(text_in_span); Inkscape::GC::release(text_in_span); SP_OBJECT_REPR(child)->setContent(string_item->string.substr(end_char_index).c_str()); @@ -1238,11 +1261,11 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * // eg "abcDEF" -> "abc""DEF" unsigned start_char_index = char_index_of_iterator(string_item->string, start_text_iter); - Inkscape::XML::Node *text_before = sp_repr_new_text(string_item->string.substr(0, start_char_index).c_str()); + Inkscape::XML::Node *text_before = xml_doc->createTextNode(string_item->string.substr(0, start_char_index).c_str()); SP_OBJECT_REPR(common_ancestor)->addChild(text_before, prev_repr); SP_OBJECT_REPR(common_ancestor)->addChild(child_span, text_before); Inkscape::GC::release(text_before); - Inkscape::XML::Node *text_in_span = sp_repr_new_text(string_item->string.substr(start_char_index).c_str()); + Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(start_char_index).c_str()); child_span->appendChild(text_in_span); Inkscape::GC::release(text_in_span); child->deleteObject(); @@ -1486,7 +1509,8 @@ static bool redundant_semi_nesting_processor(SPObject **item, SPObject *child, b sp_repr_css_attr_unref(css_child_only); if (!equal) return false; - Inkscape::XML::Node *new_span = sp_repr_new(SP_OBJECT_REPR(*item)->name()); + Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(*item)->document(); + Inkscape::XML::Node *new_span = xml_doc->createElement(SP_OBJECT_REPR(*item)->name()); if (prepend) { SPObject *prev = SP_OBJECT_PREV(*item); SP_OBJECT_REPR(SP_OBJECT_PARENT(*item))->addChild(new_span, prev ? SP_OBJECT_REPR(prev) : NULL); @@ -1645,17 +1669,20 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta last = start; } Inkscape::Text::Layout const *layout = te_get_layout(text); - SPObject *start_item, *end_item; + SPObject *start_item = 0, *end_item = 0; + void *rawptr = 0; Glib::ustring::iterator start_text_iter, end_text_iter; - layout->getSourceOfCharacter(first, (void**)&start_item, &start_text_iter); - layout->getSourceOfCharacter(last, (void**)&end_item, &end_text_iter); - if (start_item == NULL) + layout->getSourceOfCharacter(first, &rawptr, &start_text_iter); + start_item = SP_OBJECT(rawptr); + layout->getSourceOfCharacter(last, &rawptr, &end_text_iter); + end_item = SP_OBJECT(rawptr); + if (start_item == 0) return; // start is at end of text if (is_line_break_object(start_item)) start_item = SP_OBJECT_NEXT(start_item); if (is_line_break_object(end_item)) end_item = SP_OBJECT_NEXT(end_item); - if (end_item == NULL) end_item = text; + if (end_item == 0) end_item = text; /* stage 1: applying the style. Go up to the closest common ancestor of start and end and then semi-recursively apply the style to all the