X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-flowtext.cpp;h=daa9f808a2db1c0046de3741ef94af7094330fe9;hb=f40ff22052300eda2abcd56c08f1db16d8a3b011;hp=900a3dffc8a8bc2939805503bb108489c4dd2154;hpb=024695c271f00bba075f0825db1cbccb8f1ff324;p=inkscape.git diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 900a3dffc..daa9f808a 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -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,13 +292,14 @@ 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; if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) { c_repr = child->updateRepr(NULL, flags); - } + } if ( c_repr ) l = g_slist_prepend(l, c_repr); } while ( l ) { @@ -311,6 +326,21 @@ sp_flowtext_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, { SPFlowtext *group = SP_FLOWTEXT(item); group->layout.getBoundingBox(bbox, transform); + + // Add stroke width + SPStyle* style=SP_OBJECT_STYLE (item); + if (style->stroke.type != SP_PAINT_TYPE_NONE) { + double const scale = expansion(transform); + if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord + double const width = MAX(0.125, style->stroke_width.computed * scale); + if ( fabs(bbox->x1 - bbox->x0) > -0.00001 && fabs(bbox->y1 - bbox->y0) > -0.00001 ) { + bbox->x0-=0.5*width; + bbox->x1+=0.5*width; + bbox->y0-=0.5*width; + bbox->y1+=0.5*width; + } + } + } } static void @@ -338,9 +368,9 @@ static gchar *sp_flowtext_description(SPItem *item) Inkscape::Text::Layout const &layout = SP_FLOWTEXT(item)->layout; int const nChars = layout.iteratorToCharIndex(layout.end()); if (SP_FLOWTEXT(item)->has_internal_frame()) - return g_strdup_printf(_("Flowed text (%d characters)"), nChars); - else - return g_strdup_printf(_("Linked flowed text (%d characters)"), nChars); + return g_strdup_printf(ngettext("Flowed text (%d character)", "Flowed text (%d characters)", nChars), nChars); + else + return g_strdup_printf(ngettext("Linked flowed text (%d character)", "Linked flowed text (%d characters)", nChars), nChars); } static NRArenaItem * @@ -350,7 +380,9 @@ sp_flowtext_show(SPItem *item, NRArena *arena, unsigned/* key*/, unsigned /*flag NRArenaGroup *flowed = NRArenaGroup::create(arena); nr_arena_group_set_transparent(flowed, FALSE); - // pass the bbox of the flowtext object as paintbox (used for paintserver fills) + 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); group->layout.show(flowed, &paintbox); @@ -412,7 +444,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, } if (with_indent) layout.appendText(SP_STRING(child)->string, root->style, child, &pi); - else + else layout.appendText(SP_STRING(child)->string, root->style, child); } else if (SP_IS_FLOWREGION(child)) { std::vector const &computed = SP_FLOWREGION(child)->computed; @@ -484,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_DT_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; @@ -543,10 +572,12 @@ void SPFlowtext::convert_to_text() if (set_y) sp_repr_set_svg_double(span_tspan, "y", anchor_point[NR::Y]); - SPObject *source_obj; + SPObject *source_obj = 0; + void *rawptr = 0; Glib::ustring::iterator span_text_start_iter; - group->layout.getSourceOfCharacter(it, (void**)&source_obj, &span_text_start_iter); - gchar *style_text = sp_style_write_difference((SP_IS_STRING(source_obj) ? source_obj->parent : source_obj)->style, group->style); + 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, this->style); if (style_text && *style_text) { span_tspan->setAttribute("style", style_text); g_free(style_text); @@ -554,13 +585,15 @@ void SPFlowtext::convert_to_text() if (SP_IS_STRING(source_obj)) { Glib::ustring *string = &SP_STRING(source_obj)->string; - SPObject *span_end_obj; + SPObject *span_end_obj = 0; + void *rawptr = 0; Glib::ustring::iterator span_text_end_iter; - group->layout.getSourceOfCharacter(it_span_end, (void**)&span_end_obj, &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 @@ -570,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); } @@ -578,23 +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_DT_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_DT_DOCUMENT(desktop)); + return repr; } SPItem *SPFlowtext::get_frame(SPItem *after) @@ -645,20 +668,21 @@ bool SPFlowtext::has_internal_frame() SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, NR::Point p0, NR::Point p1) { - SPDocument *doc = SP_DT_DOCUMENT (desktop); + 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); @@ -677,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);