X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-item.cpp;h=33f140de24417947879a3e595e78ec74aa55be05;hb=d5b7e1b1e4973311fcc2a2530fb1f526eefca5f6;hp=fc966aff47c08f02fac16d8aa64f031f7a6fef5c;hpb=2e01c348a7462bafef5d0c6d751a4f0dc9480b18;p=inkscape.git diff --git a/src/sp-item.cpp b/src/sp-item.cpp index fc966aff4..33f140de2 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -65,12 +65,15 @@ #include "libnr/nr-convert2geom.h" #include "algorithms/find-last-if.h" #include "util/reverse-list.h" +#include <2geom/rect.h> +#include <2geom/transforms.h> #include "xml/repr.h" #include "extract-uri.h" #include "live_effects/lpeobject.h" #include "live_effects/effect.h" +#include "live_effects/lpeobject-reference.h" #define noSP_ITEM_DEBUG_IDLE @@ -81,7 +84,7 @@ static void sp_item_build(SPObject *object, SPDocument *document, Inkscape::XML: static void sp_item_release(SPObject *object); static void sp_item_set(SPObject *object, unsigned key, gchar const *value); static void sp_item_update(SPObject *object, SPCtx *ctx, guint flags); -static Inkscape::XML::Node *sp_item_write(SPObject *object, Inkscape::XML::Node *repr, guint flags); +static Inkscape::XML::Node *sp_item_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *sp_item_private_description(SPItem *item); static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p); @@ -285,7 +288,7 @@ SPItem::setExplicitlyHidden(bool const val) { */ void SPItem::setCenter(NR::Point object_centre) { - NR::Maybe bbox = getBounds(sp_item_i2d_affine(this)); + NR::Maybe bbox = getBounds(from_2geom(sp_item_i2d_affine(this))); if (bbox) { transform_center_x = object_centre[NR::X] - bbox->midpoint()[NR::X]; if (fabs(transform_center_x) < 1e-5) // rounding error @@ -307,7 +310,7 @@ bool SPItem::isCenterSet() { } NR::Point SPItem::getCenter() const { - NR::Maybe bbox = getBounds(sp_item_i2d_affine(this)); + NR::Maybe bbox = getBounds(from_2geom(sp_item_i2d_affine(this))); if (bbox) { return bbox->midpoint() + NR::Point (this->transform_center_x, this->transform_center_y); } else { @@ -653,7 +656,7 @@ sp_item_update(SPObject *object, SPCtx *ctx, guint flags) } static Inkscape::XML::Node * -sp_item_write(SPObject *const object, Inkscape::XML::Node *repr, guint flags) +sp_item_write(SPObject *const object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPItem *item = SP_ITEM(object); @@ -685,7 +688,7 @@ sp_item_write(SPObject *const 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; @@ -700,6 +703,15 @@ NR::Maybe SPItem::getBounds(NR::Matrix const &transform, return r; } +NR::Maybe +SPItem::getBounds(Geom::Matrix const &transform, SPItem::BBoxType type, unsigned int /*dkey*/) +const +{ + NR::Maybe r = NR::Nothing(); + sp_item_invoke_bbox_full(this, &r, from_2geom(transform), type, TRUE); + return NR::Maybe(to_2geom(*r)); +} + void sp_item_invoke_bbox(SPItem const *item, NR::Maybe *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type) { @@ -782,7 +794,7 @@ sp_item_invoke_bbox_full(SPItem const *item, NR::Maybe *bbox, NR::Matr } // transform the expansions by the item's transform: - NR::Matrix i2d = sp_item_i2d_affine (item); + NR::Matrix i2d = from_2geom(sp_item_i2d_affine (item)); dx0 *= NR::expansionX(i2d); dx1 *= NR::expansionX(i2d); dy0 *= NR::expansionY(i2d); @@ -803,17 +815,13 @@ sp_item_invoke_bbox_full(SPItem const *item, NR::Maybe *bbox, NR::Matr } if (temp_bbox.x0 > temp_bbox.x1 || temp_bbox.y0 > temp_bbox.y1) { - // We'll assume here that when x0 > x1 or y0 > y1, the bbox is "nothing" - // However it has never been explicitely defined this way for NRRects - // (as opposed to NR::Maybe) - *bbox = NR::Nothing(); - return; - } - - if (temp_bbox.x0 == temp_bbox.y0 == NR_HUGE && temp_bbox.x1 == temp_bbox.y1 == -NR_HUGE) { - // The bbox hasn't been touched by the SPItemClass' bbox method + // Either the bbox hasn't been touched by the SPItemClass' bbox method + // (it still has its initial values, see above: x0 = y0 = NR_HUGE and x1 = y1 = -NR_HUGE) // or it has explicitely been set to be like this (e.g. in sp_shape_bbox) - *bbox = NR::Nothing(); + + // When x0 > x1 or y0 > y1, the bbox is considered to be "nothing", although it has not been + // explicitely defined this way for NRRects (as opposed to NR::Maybe) + // So union bbox with nothing = do nothing, just return return; } @@ -896,19 +904,19 @@ sp_item_bbox_desktop(SPItem *item, NRRect *bbox, SPItem::BBoxType type) g_assert(SP_IS_ITEM(item)); g_assert(bbox != NULL); - sp_item_invoke_bbox(item, bbox, sp_item_i2d_affine(item), TRUE, type); + sp_item_invoke_bbox(item, bbox, from_2geom(sp_item_i2d_affine(item)), TRUE, type); } NR::Maybe sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type) { NR::Maybe rect = NR::Nothing(); - sp_item_invoke_bbox(item, &rect, sp_item_i2d_affine(item), TRUE, type); + sp_item_invoke_bbox(item, &rect, from_2geom(sp_item_i2d_affine(item)), TRUE, type); return rect; } static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p) { - NR::Maybe bbox = item->getBounds(sp_item_i2d_affine(item)); + NR::Maybe bbox = item->getBounds(from_2geom(sp_item_i2d_affine(item))); /* Just the corners of the bounding box suffices given that we don't yet support angled guide lines. */ @@ -1291,20 +1299,28 @@ sp_item_adjust_paint_recursive (SPItem *item, NR::Matrix advertized_transform, N void sp_item_adjust_livepatheffect (SPItem *item, NR::Matrix const &postmul, bool set) { - if ( !SP_IS_SHAPE(item) ) + if ( !SP_IS_LPE_ITEM(item) ) return; - SPShape *shape = SP_SHAPE (item); - if ( sp_shape_has_path_effect(shape) ) { - LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape); - LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary(); - if (new_lpeobj != lpeobj) { - sp_shape_set_path_effect(shape, new_lpeobj); - } - - Inkscape::LivePathEffect::Effect * effect = sp_shape_get_livepatheffect(shape); - if (effect) { - effect->transform_multiply (to_2geom(postmul), set); + SPLPEItem *lpeitem = SP_LPE_ITEM (item); + if ( sp_lpe_item_has_path_effect(lpeitem) ) { + PathEffectList effect_list = sp_lpe_item_get_effect_list(lpeitem); + for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++) + { + // If the path effect is used by 2 or more items, fork it + // so that each object has its own independent copy of the effect + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (lpeobj) { + LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary(); + if (new_lpeobj != lpeobj) { + sp_lpe_item_replace_path_effect(lpeitem, lpeobj, new_lpeobj); + } + + if (lpeobj->lpe) { + Inkscape::LivePathEffect::Effect * effect = lpeobj->lpe; + effect->transform_multiply(to_2geom(postmul), set); + } + } } } } @@ -1451,38 +1467,38 @@ sp_item_convert_item_to_guides(SPItem *item) { * \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL. * ("Ancestor (\>=)" here includes as far as \a object itself.) */ -NR::Matrix +Geom::Matrix i2anc_affine(SPObject const *object, SPObject const *const ancestor) { - NR::Matrix ret(NR::identity()); + Geom::Matrix ret(Geom::identity()); g_return_val_if_fail(object != NULL, ret); /* stop at first non-renderable ancestor */ while ( object != ancestor && SP_IS_ITEM(object) ) { if (SP_IS_ROOT(object)) { - ret *= SP_ROOT(object)->c2p; + ret *= to_2geom(SP_ROOT(object)->c2p); } - ret *= SP_ITEM(object)->transform; + ret *= to_2geom(SP_ITEM(object)->transform); object = SP_OBJECT_PARENT(object); } return ret; } -NR::Matrix +Geom::Matrix i2i_affine(SPObject const *src, SPObject const *dest) { - g_return_val_if_fail(src != NULL && dest != NULL, NR::identity()); + g_return_val_if_fail(src != NULL && dest != NULL, Geom::identity()); SPObject const *ancestor = src->nearestCommonAncestor(dest); - return i2anc_affine(src, ancestor) / i2anc_affine(dest, ancestor); + return to_2geom( from_2geom(i2anc_affine(src, ancestor)) / from_2geom(i2anc_affine(dest, ancestor)) ); } NR::Matrix SPItem::getRelativeTransform(SPObject const *dest) const { - return i2i_affine(this, dest); + return from_2geom(i2i_affine(this, dest)); } /** * Returns the accumulated transformation of the item and all its ancestors, including root's viewport. * \pre (item != NULL) and SP_IS_ITEM(item). */ -NR::Matrix sp_item_i2doc_affine(SPItem const *item) +Geom::Matrix sp_item_i2doc_affine(SPItem const *item) { return i2anc_affine(item, NULL); } @@ -1492,46 +1508,46 @@ NR::Matrix sp_item_i2doc_affine(SPItem const *item) * Used in path operations mostly. * \pre (item != NULL) and SP_IS_ITEM(item). */ -NR::Matrix sp_item_i2root_affine(SPItem const *item) +Geom::Matrix sp_item_i2root_affine(SPItem const *item) { g_assert(item != NULL); g_assert(SP_IS_ITEM(item)); - NR::Matrix ret(NR::identity()); - g_assert(ret.test_identity()); + Geom::Matrix ret(Geom::identity()); + g_assert(ret.isIdentity()); while ( NULL != SP_OBJECT_PARENT(item) ) { - ret *= item->transform; + ret *= to_2geom(item->transform); item = SP_ITEM(SP_OBJECT_PARENT(item)); } g_assert(SP_IS_ROOT(item)); - ret *= item->transform; + ret *= to_2geom(item->transform); return ret; } /* fixme: This is EVIL!!! */ - -NR::Matrix sp_item_i2d_affine(SPItem const *item) +// fix this note: why/what evil? :) +Geom::Matrix sp_item_i2d_affine(SPItem const *item) { g_assert(item != NULL); g_assert(SP_IS_ITEM(item)); - NR::Matrix const ret( sp_item_i2doc_affine(item) - * NR::scale(1, -1) - * NR::translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); + Geom::Matrix const ret( sp_item_i2doc_affine(item) + * Geom::Scale(1, -1) + * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); return ret; } // same as i2d but with i2root instead of i2doc -NR::Matrix sp_item_i2r_affine(SPItem const *item) +Geom::Matrix sp_item_i2r_affine(SPItem const *item) { g_assert(item != NULL); g_assert(SP_IS_ITEM(item)); - NR::Matrix const ret( sp_item_i2root_affine(item) - * NR::scale(1, -1) - * NR::translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); + Geom::Matrix const ret( sp_item_i2root_affine(item) + * Geom::Scale(1, -1) + * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) ); return ret; } @@ -1539,11 +1555,11 @@ NR::Matrix sp_item_i2r_affine(SPItem const *item) * Converts a matrix \a m into the desktop coords of the \a item. * Will become a noop when we eliminate the coordinate flipping. */ -NR::Matrix matrix_to_desktop(NR::Matrix const m, SPItem const *item) +Geom::Matrix matrix_to_desktop(Geom::Matrix const m, SPItem const *item) { - NR::Matrix const ret(m - * NR::translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) - * NR::scale(1, -1)); + Geom::Matrix const ret(m + * Geom::Translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) + * Geom::Scale(1, -1)); return ret; } @@ -1551,33 +1567,33 @@ NR::Matrix matrix_to_desktop(NR::Matrix const m, SPItem const *item) * Converts a matrix \a m from the desktop coords of the \a item. * Will become a noop when we eliminate the coordinate flipping. */ -NR::Matrix matrix_from_desktop(NR::Matrix const m, SPItem const *item) +Geom::Matrix matrix_from_desktop(Geom::Matrix const m, SPItem const *item) { - NR::Matrix const ret(NR::scale(1, -1) - * NR::translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) + Geom::Matrix const ret(Geom::Scale(1, -1) + * Geom::Translate(0, sp_document_height(SP_OBJECT_DOCUMENT(item))) * m); return ret; } -void sp_item_set_i2d_affine(SPItem *item, NR::Matrix const &i2dt) +void sp_item_set_i2d_affine(SPItem *item, Geom::Matrix const &i2dt) { g_return_if_fail( item != NULL ); g_return_if_fail( SP_IS_ITEM(item) ); - NR::Matrix dt2p; /* desktop to item parent transform */ + Geom::Matrix dt2p; /* desktop to item parent transform */ if (SP_OBJECT_PARENT(item)) { dt2p = sp_item_i2d_affine((SPItem *) SP_OBJECT_PARENT(item)).inverse(); } else { - dt2p = ( NR::translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) - * NR::scale(1, -1) ); + dt2p = ( Geom::Translate(0, -sp_document_height(SP_OBJECT_DOCUMENT(item))) + * Geom::Scale(1, -1) ); } - NR::Matrix const i2p( i2dt * dt2p ); - sp_item_set_item_transform(item, i2p); + Geom::Matrix const i2p( i2dt * dt2p ); + sp_item_set_item_transform(item, from_2geom(i2p)); } -NR::Matrix +Geom::Matrix sp_item_dt2i_affine(SPItem const *item) { /* fixme: Implement the right way (Lauris) */ @@ -1663,8 +1679,9 @@ sp_item_convert_to_guides(SPItem *item) { SPNamedView *nv = sp_desktop_namedview(dt); (void)nv; - gchar const *prefs_bbox = prefs_get_string_attribute("tools", "bounding_box"); - SPItem::BBoxType bbox_type = (prefs_bbox != NULL && strcmp(prefs_bbox, "geometric")==0)? SPItem::GEOMETRIC_BBOX : SPItem::RENDERING_BBOX; + int prefs_bbox = prefs_get_int_attribute("tools", "bounding_box", 0); + SPItem::BBoxType bbox_type = (prefs_bbox ==0)? + SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; NR::Maybe bbox = sp_item_bbox_desktop(item, bbox_type); if (!bbox) {