X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-flowtext.cpp;h=6af2f7169eaf3c9eb34ed451470c0d9ee4fa0aa1;hb=1bc4dd6dd6f59d7b59bc923ea565ebd1321684ae;hp=ec6fd04279c1d82555f0a7b59d36705e6c405321;hpb=e7a5f3e4a4758ac8353e070265e9bf03ed7228c9;p=inkscape.git diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index ec6fd0427..6af2f7169 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -5,6 +5,8 @@ # include "config.h" #endif #include +#include +#include #include "attributes.h" #include "xml/repr.h" @@ -14,7 +16,6 @@ #include "selection.h" #include "desktop-handles.h" #include "desktop.h" -#include "desktop-affine.h" #include "xml/repr.h" @@ -41,11 +42,11 @@ static void sp_flowtext_child_added(SPObject *object, Inkscape::XML::Node *child static void sp_flowtext_remove_child(SPObject *object, Inkscape::XML::Node *child); static void sp_flowtext_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_flowtext_modified(SPObject *object, guint flags); -static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::Node *repr, guint flags); +static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static void sp_flowtext_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static void sp_flowtext_set(SPObject *object, unsigned key, gchar const *value); -static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags); +static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_flowtext_description(SPItem *item); static NRArenaItem *sp_flowtext_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags); @@ -173,11 +174,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); + sp_item_invoke_bbox(group, &paintbox, Geom::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); } } @@ -195,7 +197,7 @@ sp_flowtext_modified(SPObject *object, guint flags) if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) { SPFlowtext *text = SP_FLOWTEXT(object); NRRect paintbox; - sp_item_invoke_bbox(text, &paintbox, NR::identity(), TRUE); + sp_item_invoke_bbox(text, &paintbox, Geom::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)); @@ -288,15 +290,15 @@ sp_flowtext_set(SPObject *object, unsigned key, gchar const *value) } static Inkscape::XML::Node * -sp_flowtext_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) +sp_flowtext_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { if ( flags & SP_OBJECT_WRITE_BUILD ) { - if ( repr == NULL ) repr = sp_repr_new("svg:flowRoot"); + 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); + c_repr = child->updateRepr(xml_doc, NULL, flags); } if ( c_repr ) l = g_slist_prepend(l, c_repr); } @@ -314,21 +316,21 @@ sp_flowtext_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) } if (((SPObjectClass *) (parent_class))->write) - ((SPObjectClass *) (parent_class))->write(object, repr, flags); + ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags); return repr; } static void -sp_flowtext_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const /*flags*/) +sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) { 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 ( !style->stroke.isNone() ) { + double const scale = transform.descrim(); 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 ) { @@ -347,15 +349,20 @@ sp_flowtext_print(SPItem *item, SPPrintContext *ctx) SPFlowtext *group = SP_FLOWTEXT(item); NRRect pbox; - sp_item_invoke_bbox(item, &pbox, NR::identity(), TRUE); + sp_item_invoke_bbox(item, &pbox, Geom::identity(), TRUE); NRRect bbox; - sp_item_bbox_desktop(item, &bbox); + Geom::OptRect bbox_maybe = sp_item_bbox_desktop(item); + if (!bbox_maybe) { + return; + } + bbox = NRRect(from_2geom(*bbox_maybe)); + NRRect dbox; dbox.x0 = 0.0; dbox.y0 = 0.0; dbox.x1 = sp_document_width(SP_OBJECT_DOCUMENT(item)); dbox.y1 = sp_document_height(SP_OBJECT_DOCUMENT(item)); - NR::Matrix const ctm = sp_item_i2d_affine(item); + Geom::Matrix const ctm (sp_item_i2d_affine(item)); group->layout.print(ctx, &pbox, &dbox, &bbox, ctm); } @@ -378,9 +385,11 @@ 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); + sp_item_invoke_bbox(item, &paintbox, Geom::identity(), TRUE); group->layout.show(flowed, &paintbox); return flowed; @@ -406,7 +415,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, if (SP_IS_FLOWPARA(root)) { // emulate par-indent with the first char's kern SPObject *t = root; - for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = SP_OBJECT_PARENT(t)); + for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = SP_OBJECT_PARENT(t)){}; if (SP_IS_FLOWTEXT(t)) { double indent = SP_FLOWTEXT(t)->par_indent; if (indent != 0) { @@ -453,7 +462,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, layout.appendWrapShape(&shapes->back()); } } - else if (!SP_IS_FLOWREGIONEXCLUDE(child)) + else if (!SP_IS_FLOWREGIONEXCLUDE(child) && !sp_repr_is_meta_element(child->repr)) _buildLayoutInput(child, exclusion_shape, shapes, pending_line_break_object); } @@ -519,15 +528,16 @@ SPFlowtext::getAsText() 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(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]); + Geom::Point anchor_point = this->layout.characterAnchorPoint(this->layout.begin()); + sp_repr_set_svg_double(repr, "x", anchor_point[Geom::X]); + sp_repr_set_svg_double(repr, "y", anchor_point[Geom::Y]); for (Inkscape::Text::Layout::iterator it = this->layout.begin() ; it != this->layout.end() ; ) { - Inkscape::XML::Node *line_tspan = sp_repr_new("svg:tspan"); + Inkscape::XML::Node *line_tspan = xml_doc->createElement("svg:tspan"); line_tspan->setAttribute("sodipodi:role", "line"); Inkscape::Text::Layout::iterator it_line_end = it; @@ -535,8 +545,8 @@ SPFlowtext::getAsText() while (it != it_line_end) { - Inkscape::XML::Node *span_tspan = sp_repr_new("svg:tspan"); - NR::Point anchor_point = this->layout.characterAnchorPoint(it); + Inkscape::XML::Node *span_tspan = xml_doc->createElement("svg:tspan"); + Geom::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(); @@ -545,7 +555,7 @@ SPFlowtext::getAsText() // set x,y attributes only when we need to bool set_x = false; bool set_y = false; - if (!item->transform.test_identity()) { + if (!item->transform.isIdentity()) { set_x = set_y = true; } else { Inkscape::Text::Layout::iterator it_chunk_start = it; @@ -563,9 +573,13 @@ SPFlowtext::getAsText() attrs.dx[0] = 0.0; TextTagAttributes(attrs).writeTo(span_tspan); if (set_x) - sp_repr_set_svg_double(span_tspan, "x", anchor_point[NR::X]); // FIXME: this will pick up the wrong end of counter-directional runs + sp_repr_set_svg_double(span_tspan, "x", anchor_point[Geom::X]); // FIXME: this will pick up the wrong end of counter-directional runs if (set_y) - sp_repr_set_svg_double(span_tspan, "y", anchor_point[NR::Y]); + sp_repr_set_svg_double(span_tspan, "y", anchor_point[Geom::Y]); + if (line_tspan->childCount() == 0) { + sp_repr_set_svg_double(line_tspan, "x", anchor_point[Geom::X]); // FIXME: this will pick up the wrong end of counter-directional runs + sp_repr_set_svg_double(line_tspan, "y", anchor_point[Geom::Y]); + } SPObject *source_obj = 0; void *rawptr = 0; @@ -598,7 +612,7 @@ SPFlowtext::getAsText() 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); } @@ -661,46 +675,47 @@ bool SPFlowtext::has_internal_frame() } -SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, NR::Point p0, NR::Point p1) +SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { 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); - p0 = sp_desktop_dt2root_xy_point(desktop, p0); - p1 = sp_desktop_dt2root_xy_point(desktop, p1); - using NR::X; - using NR::Y; - NR::Coord const x0 = MIN(p0[X], p1[X]); - NR::Coord const y0 = MIN(p0[Y], p1[Y]); - NR::Coord const x1 = MAX(p0[X], p1[X]); - NR::Coord const y1 = MAX(p0[Y], p1[Y]); - NR::Coord const w = x1 - x0; - NR::Coord const h = y1 - y0; + p0 *= desktop->dt2doc(); + p1 *= desktop->dt2doc(); + using Geom::X; + using Geom::Y; + Geom::Coord const x0 = MIN(p0[X], p1[X]); + Geom::Coord const y0 = MIN(p0[Y], p1[Y]); + Geom::Coord const x1 = MAX(p0[X], p1[X]); + Geom::Coord const y1 = MAX(p0[Y], p1[Y]); + Geom::Coord const w = x1 - x0; + Geom::Coord const h = y1 - y0; 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); @@ -708,6 +723,8 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, NR::Point p0, N Inkscape::GC::release(para_repr); Inkscape::GC::release(rect_repr); + ft_item->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse(); + return ft_item; }