diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2011-08-27 09:04:37 +0000 |
|---|---|---|
| committer | Krzysztof Kosinski <tweenk.pl@gmail.com> | 2011-08-27 09:04:37 +0000 |
| commit | 72cc39b9f0b340548f395c7f61ca9662b34aea09 (patch) | |
| tree | 34a0853cff6c6040bc2a0572dfa365280fce2601 /src | |
| parent | Fix "snap guides" toggle (diff) | |
| download | inkscape-72cc39b9f0b340548f395c7f61ca9662b34aea09.tar.gz inkscape-72cc39b9f0b340548f395c7f61ca9662b34aea09.zip | |
Refactor SPItem bounding box methods: remove NRRect usage and make code
using them more obvious. Fix filter region computation.
(bzr r10582.1.1)
Diffstat (limited to 'src')
81 files changed, 789 insertions, 1042 deletions
diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index fad11bb89..331865254 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -394,7 +394,7 @@ Geom::Point SPAvoidRef::getConnectionPointPos(const int type, const int id) if ( type == ConnPointDefault ) { // For now, just default to the centre of the item - Geom::OptRect bbox = item->getBounds(item->i2doc_affine()); + Geom::OptRect bbox = item->documentVisualBounds(); pos = (bbox) ? bbox->midpoint() : Geom::Point(0, 0); } else diff --git a/src/desktop.cpp b/src/desktop.cpp index ca5fdc63b..b622d1080 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -577,16 +577,16 @@ bool SPDesktop::isLayer(SPObject *object) const { } /** - * True if desktop viewport fully contains \a item's bbox. + * True if desktop viewport intersects \a item's bbox. */ bool SPDesktop::isWithinViewport (SPItem *item) const { Geom::Rect const viewport = get_display_area(); - Geom::OptRect const bbox = item->getBboxDesktop(); + Geom::OptRect const bbox = item->desktopVisualBounds(); if (bbox) { - return viewport.contains(*bbox); + return viewport.intersects(*bbox); } else { - return true; + return false; } } @@ -957,7 +957,7 @@ SPDesktop::zoom_quick (bool enable) } if (!zoomed) { - Geom::OptRect const d = selection->bounds(); + Geom::OptRect const d = selection->visualBounds(); if (d && d->area() * 2.0 < _quick_zoom_stored_area.area()) { set_display_area(*d, true); zoomed = true; @@ -1109,7 +1109,7 @@ SPDesktop::zoom_page_width() void SPDesktop::zoom_selection() { - Geom::OptRect const d = selection->bounds(); + Geom::OptRect const d = selection->visualBounds(); if ( !d || d->minExtent() < 0.1 ) { return; @@ -1137,7 +1137,7 @@ SPDesktop::zoom_drawing() SPItem *docitem = doc()->getRoot(); g_return_if_fail (docitem != NULL); - Geom::OptRect d = docitem->getBboxDesktop(); + Geom::OptRect d = docitem->desktopVisualBounds(); /* Note that the second condition here indicates that ** there are no items in the drawing. diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp index 109b235d0..a92b6392e 100644 --- a/src/dialogs/clonetiler.cpp +++ b/src/dialogs/clonetiler.cpp @@ -1170,10 +1170,9 @@ static void clonetiler_apply(GtkWidget */*widget*/, void *) y0 = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-y0", 0); } else { bool prefs_bbox = prefs->getBool("/tools/bounding_box", false); - SPItem::BBoxType bbox_type = ( prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX ); - Geom::OptRect r = item->getBounds(item->i2doc_affine(), - bbox_type); + SPItem::BBoxType bbox_type = ( !prefs_bbox ? + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX ); + Geom::OptRect r = item->documentBounds(bbox_type); if (r) { w = r->dimensions()[Geom::X]; h = r->dimensions()[Geom::Y]; diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp index 0c2bc5adc..a19f9b60f 100644 --- a/src/dialogs/export.cpp +++ b/src/dialogs/export.cpp @@ -783,20 +783,22 @@ sp_export_selection_modified ( Inkscape::Application */*inkscape*/, if ( SP_ACTIVE_DESKTOP ) { SPDocument *doc; doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - Geom::OptRect bbox = doc->getRoot()->getBboxDesktop(SPItem::RENDERING_BBOX); + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); if (bbox) { - sp_export_set_area (base, bbox->min()[Geom::X], - bbox->min()[Geom::Y], - bbox->max()[Geom::X], - bbox->max()[Geom::Y]); + sp_export_set_area (base, bbox->left(), + bbox->top(), + bbox->right(), + bbox->bottom()); } } break; case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { - NRRect bbox; - (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox, SPItem::RENDERING_BBOX); - sp_export_set_area (base, bbox.x0, bbox.y0, bbox.x1, bbox.y1); + Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->visualBounds(); + sp_export_set_area (base, bbox->left(), + bbox->top(), + bbox->right(), + bbox->bottom()); } break; default: @@ -852,7 +854,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { - bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds(SPItem::RENDERING_BBOX); + bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->visualBounds(); /* Only if there is a selection that we can set do we break, otherwise we fall through to the drawing */ @@ -864,7 +866,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) /** \todo * This returns wrong values if the document has a viewBox. */ - bbox = doc->getRoot()->getBboxDesktop(SPItem::RENDERING_BBOX); + bbox = doc->getRoot()->desktopVisualBounds(); /* If the drawing is valid, then we'll use it and break otherwise we drop through to the page settings */ if (bbox) { @@ -1129,8 +1131,7 @@ sp_export_export_clicked (GtkButton */*button*/, GtkObject *base) dpi = DPI_BASE; } - Geom::OptRect area; - item->invoke_bbox( area, item->i2dt_affine(), TRUE ); + Geom::OptRect area = item->desktopVisualBounds(); if (area) { gint width = (gint) (area->width() * dpi / PX_PER_IN + 0.5); gint height = (gint) (area->height() * dpi / PX_PER_IN + 0.5); @@ -1493,7 +1494,7 @@ sp_export_detect_size(GtkObject * base) { switch (this_test[i]) { case SELECTION_SELECTION: if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) { - Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(SPItem::RENDERING_BBOX); + Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(SPItem::VISUAL_BBOX); //std::cout << "Selection " << bbox; if ( bbox && sp_export_bbox_equal(*bbox,current_bbox)) { @@ -1504,7 +1505,7 @@ sp_export_detect_size(GtkObject * base) { case SELECTION_DRAWING: { SPDocument *doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - Geom::OptRect bbox = doc->getRoot()->getBboxDesktop(SPItem::RENDERING_BBOX); + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); // std::cout << "Drawing " << bbox2; if ( bbox && sp_export_bbox_equal(*bbox,current_bbox) ) { diff --git a/src/dialogs/spellcheck.cpp b/src/dialogs/spellcheck.cpp index d0de6ad20..bd8381d8c 100644 --- a/src/dialogs/spellcheck.cpp +++ b/src/dialogs/spellcheck.cpp @@ -243,8 +243,8 @@ gint compare_text_bboxes (gconstpointer a, gconstpointer b) SPItem *i1 = SP_ITEM(a); SPItem *i2 = SP_ITEM(b); - Geom::OptRect bbox1 = i1->getBounds(i1->i2dt_affine()); - Geom::OptRect bbox2 = i2->getBounds(i2->i2dt_affine()); + Geom::OptRect bbox1 = i1->desktopVisualBounds(); + Geom::OptRect bbox2 = i2->desktopVisualBounds(); if (!bbox1 || !bbox2) { return 0; } diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp index a22d23548..5911f5908 100644 --- a/src/display/nr-filter-image.cpp +++ b/src/display/nr-filter-image.cpp @@ -74,7 +74,7 @@ void FilterImage::render_cairo(FilterSlot &slot) document->ensureUpToDate(); Drawing drawing; - Geom::OptRect optarea = SVGElem->getBounds(Geom::identity()); + Geom::OptRect optarea = SVGElem->visualBounds(); if (!optarea) return; unsigned const key = SPItem::display_key_new(1); diff --git a/src/document.cpp b/src/document.cpp index 72f92bd17..cf2474fe5 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1086,7 +1086,7 @@ static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, s = find_items_in_area(s, SP_GROUP(o), dkey, area, test); } else { SPItem *child = SP_ITEM(o); - Geom::OptRect box = child->getBboxDesktop(); + Geom::OptRect box = child->desktopVisualBounds(); if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { s = g_slist_append(s, child); } diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp index de6c7d86f..11b150aa0 100644 --- a/src/eraser-context.cpp +++ b/src/eraser-context.cpp @@ -748,7 +748,7 @@ set_to_accumulated(SPEraserContext *dc) Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); SPItem* acid = SP_ITEM(desktop->doc()->getObjectByRepr(dc->repr)); - Geom::OptRect eraserBbox = acid->getBounds(Geom::identity()); + Geom::OptRect eraserBbox = acid->visualBounds(); Geom::Rect bounds = (*eraserBbox) * desktop->doc2dt(); std::vector<SPItem*> remainingItems; GSList* toWorkOn = 0; @@ -770,7 +770,7 @@ set_to_accumulated(SPEraserContext *dc) for (GSList *i = toWorkOn ; i ; i = i->next ) { SPItem *item = SP_ITEM(i->data); if ( eraserMode ) { - Geom::OptRect bbox = item->getBounds(Geom::identity()); + Geom::OptRect bbox = item->visualBounds(); if (bbox && bbox->intersects(*eraserBbox)) { Inkscape::XML::Node* dup = dc->repr->duplicate(xml_doc); dc->repr->parent()->appendChild(dup); diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 1e6577173..b4f42a37d 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -157,16 +157,14 @@ desktop_ensure_active (SPDesktop* desk) { gdouble selection_get_center_x (Inkscape::Selection *sel){ - NRRect *box = g_new(NRRect, 1);; - box = sel->boundsInDocument(box); - return box->x0 + ((box->x1 - box->x0)/2); + Geom::OptRect box = sel->documentBounds(SPItem::GEOMETRIC_BBOX); + return box ? box->midpoint()[Geom::X] : 0; } gdouble selection_get_center_y (Inkscape::Selection *sel){ - NRRect *box = g_new(NRRect, 1);; - box = sel->boundsInDocument(box); - return box->y0 + ((box->y1 - box->y0)/2); + Geom::OptRect box = sel->documentBounds(SPItem::GEOMETRIC_BBOX); + return box ? box->midpoint()[Geom::X] : 0; } /* diff --git a/src/extension/internal/bitmap/crop.cpp b/src/extension/internal/bitmap/crop.cpp index 23e31b510..2ad75a0dc 100644 --- a/src/extension/internal/bitmap/crop.cpp +++ b/src/extension/internal/bitmap/crop.cpp @@ -38,7 +38,7 @@ Crop::postEffect(Magick::Image *image, SPItem *item) { sp_item_scale_rel (item, scale); // Translate proportionaly to the image/bbox ratio - Geom::OptRect bbox(item->getBboxDesktop()); + Geom::OptRect bbox(item->desktopGeometricBounds()); //g_warning("bbox. W:%f, H:%f, X:%f, Y:%f", bbox->dimensions()[Geom::X], bbox->dimensions()[Geom::Y], bbox->min()[Geom::X], bbox->min()[Geom::Y]); Geom::Translate translate (0,0); diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index c3a8a790b..a0573d9ff 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -682,12 +682,12 @@ CairoRenderContext::popLayer(void) // copy the correct CTM to mask context /* if (_state->parent_has_userspace) - mask_ctx->setTransform(&getParentState()->transform); + mask_ctx->setTransform(getParentState()->transform); else - mask_ctx->setTransform(&_state->transform); + mask_ctx->setTransform(_state->transform); */ // This is probably not correct... but it seems to do the trick. - mask_ctx->setTransform(&_state->item_transform); + mask_ctx->setTransform(_state->item_transform); // render mask contents to mask_ctx _renderer->applyMask(mask_ctx, mask); @@ -915,7 +915,7 @@ CairoRenderContext::finish(void) } void -CairoRenderContext::transform(Geom::Affine const *transform) +CairoRenderContext::transform(Geom::Affine const &transform) { g_assert( _is_valid ); @@ -924,42 +924,44 @@ CairoRenderContext::transform(Geom::Affine const *transform) cairo_transform(_cr, &matrix); // store new CTM - getTransform(&_state->transform); + _state->transform = getTransform(); } void -CairoRenderContext::setTransform(Geom::Affine const *transform) +CairoRenderContext::setTransform(Geom::Affine const &transform) { g_assert( _is_valid ); cairo_matrix_t matrix; _initCairoMatrix(&matrix, transform); cairo_set_matrix(_cr, &matrix); - _state->transform = *transform; + _state->transform = transform; } -void -CairoRenderContext::getTransform(Geom::Affine *copy) const +Geom::Affine +CairoRenderContext::getTransform() const { g_assert( _is_valid ); cairo_matrix_t ctm; cairo_get_matrix(_cr, &ctm); - (*copy)[0] = ctm.xx; - (*copy)[1] = ctm.yx; - (*copy)[2] = ctm.xy; - (*copy)[3] = ctm.yy; - (*copy)[4] = ctm.x0; - (*copy)[5] = ctm.y0; + Geom::Affine ret; + ret[0] = ctm.xx; + ret[1] = ctm.yx; + ret[2] = ctm.xy; + ret[3] = ctm.yy; + ret[4] = ctm.x0; + ret[5] = ctm.y0; + return ret; } -void -CairoRenderContext::getParentTransform(Geom::Affine *copy) const +Geom::Affine +CairoRenderContext::getParentTransform() const { g_assert( _is_valid ); CairoRenderState *parent_state = getParentState(); - memcpy(copy, &parent_state->transform, sizeof(Geom::Affine)); + return parent_state->transform; } void @@ -1002,7 +1004,7 @@ static bool pattern_hasItemChildren(SPPattern *pat) } cairo_pattern_t* -CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver, NRRect const *pbox) +CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox) { g_assert( SP_IS_PATTERN(paintserver) ); @@ -1023,10 +1025,10 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver if (pbox && pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { //Geom::Affine bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); - bbox_width_scaler = pbox->x1 - pbox->x0; - bbox_height_scaler = pbox->y1 - pbox->y0; - ps2user[4] = x * bbox_width_scaler + pbox->x0; - ps2user[5] = y * bbox_height_scaler + pbox->y0; + bbox_width_scaler = pbox->width(); + bbox_height_scaler = pbox->height(); + ps2user[4] = x * bbox_width_scaler + pbox->left(); + ps2user[5] = y * bbox_height_scaler + pbox->top(); } else { bbox_width_scaler = 1.0; bbox_height_scaler = 1.0; @@ -1059,8 +1061,8 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver pcs2dev[4] = x - view_box->x0 * pcs2dev[0]; pcs2dev[5] = y - view_box->y0 * pcs2dev[3]; } else if (pbox && pattern_patternContentUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - pcs2dev[0] = pbox->x1 - pbox->x0; - pcs2dev[3] = pbox->y1 - pbox->y0; + pcs2dev[0] = pbox->width(); + pcs2dev[3] = pbox->height(); } @@ -1089,7 +1091,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver ps2user[4] = ori[Geom::X]; ps2user[5] = ori[Geom::Y]; - pattern_ctx->setTransform(&pcs2dev); + pattern_ctx->setTransform(pcs2dev); pattern_ctx->pushState(); // create drawing and group @@ -1119,7 +1121,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver // set pattern transformation cairo_matrix_t pattern_matrix; - _initCairoMatrix(&pattern_matrix, &ps2user); + _initCairoMatrix(&pattern_matrix, ps2user); cairo_matrix_invert(&pattern_matrix); cairo_pattern_set_matrix(result, &pattern_matrix); @@ -1142,7 +1144,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver cairo_pattern_t* CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const paintserver, - NRRect const *pbox, float alpha) + Geom::OptRect const &pbox, float alpha) { cairo_pattern_t *pattern = NULL; bool apply_bbox2user = FALSE; @@ -1157,7 +1159,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain Geom::Point p2 (lg->x2.computed, lg->y2.computed); if (pbox && SP_GRADIENT(lg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { // convert to userspace - Geom::Affine bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); + Geom::Affine bbox2user(pbox->width(), 0, 0, pbox->height(), pbox->left(), pbox->top()); p1 *= bbox2user; p2 *= bbox2user; } @@ -1237,7 +1239,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain if (apply_bbox2user) { // convert to userspace cairo_matrix_t bbox2user; - cairo_matrix_init (&bbox2user, pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); + cairo_matrix_init (&bbox2user, pbox->width(), 0, 0, pbox->height(), pbox->left(), pbox->top()); cairo_matrix_multiply (&pattern_matrix, &bbox2user, &pattern_matrix); } cairo_matrix_invert(&pattern_matrix); // because Cairo expects a userspace->patternspace matrix @@ -1248,7 +1250,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain } void -CairoRenderContext::_setFillStyle(SPStyle const *const style, NRRect const *pbox) +CairoRenderContext::_setFillStyle(SPStyle const *const style, Geom::OptRect const &pbox) { g_return_if_fail( !style->fill.set || style->fill.isColor() @@ -1284,7 +1286,7 @@ CairoRenderContext::_setFillStyle(SPStyle const *const style, NRRect const *pbox } void -CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox) +CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &pbox) { float alpha = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); if (_state->merge_opacity) @@ -1351,7 +1353,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox) } bool -CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, NRRect const *pbox) +CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, Geom::OptRect const &pbox) { g_assert( _is_valid ); @@ -1419,7 +1421,7 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con } bool CairoRenderContext::renderImage(GdkPixbuf *pb, - Geom::Affine const *image_transform, SPStyle const * /*style*/) + Geom::Affine const &image_transform, SPStyle const * /*style*/) { g_assert( _is_valid ); @@ -1442,8 +1444,7 @@ bool CairoRenderContext::renderImage(GdkPixbuf *pb, cairo_save(_cr); // scaling by width & height is not needed because it will be done by Cairo - if (image_transform) - transform(image_transform); + transform(image_transform); cairo_set_source_surface(_cr, image_surface, 0.0, 0.0); @@ -1507,7 +1508,7 @@ unsigned int CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont * /*font*/, } bool -CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const *font_matrix, +CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_matrix, std::vector<CairoGlyphInfo> const &glyphtext, SPStyle const *style) { // create a cairo_font_face from PangoFont @@ -1575,7 +1576,7 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const *font_ma stroke = true; } if (fill) { - _setFillStyle(style, NULL); + _setFillStyle(style, Geom::OptRect()); if (_is_texttopath) { _showGlyphs(_cr, font, glyphtext, true); have_path = true; @@ -1586,7 +1587,7 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const *font_ma } } if (stroke) { - _setStrokeStyle(style, NULL); + _setStrokeStyle(style, Geom::OptRect()); if (!have_path) _showGlyphs(_cr, font, glyphtext, true); cairo_stroke(_cr); } @@ -1625,22 +1626,22 @@ CairoRenderContext::_concatTransform(cairo_t *cr, double xx, double yx, double x } void -CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform) +CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const &transform) { - matrix->xx = (*transform)[0]; - matrix->yx = (*transform)[1]; - matrix->xy = (*transform)[2]; - matrix->yy = (*transform)[3]; - matrix->x0 = (*transform)[4]; - matrix->y0 = (*transform)[5]; + matrix->xx = transform[0]; + matrix->yx = transform[1]; + matrix->xy = transform[2]; + matrix->yy = transform[3]; + matrix->x0 = transform[4]; + matrix->y0 = transform[5]; } void -CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Affine const *transform) +CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Affine const &transform) { - _concatTransform(cr, (*transform)[0], (*transform)[1], - (*transform)[2], (*transform)[3], - (*transform)[4], (*transform)[5]); + _concatTransform(cr, transform[0], transform[1], + transform[2], transform[3], + transform[4], transform[5]); } static cairo_status_t diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index d4117ff7e..94c7bb294 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -128,20 +128,20 @@ public: CairoRenderState *getParentState(void) const; void setStateForStyle(SPStyle const *style); - void transform(Geom::Affine const *transform); - void setTransform(Geom::Affine const *transform); - void getTransform(Geom::Affine *copy) const; - void getParentTransform(Geom::Affine *copy) const; + void transform(Geom::Affine const &transform); + void setTransform(Geom::Affine const &transform); + Geom::Affine getTransform() const; + Geom::Affine getParentTransform() const; /* Clipping methods */ void addClipPath(Geom::PathVector const &pv, SPIEnum const *fill_rule); void addClippingRect(double x, double y, double width, double height); /* Rendering methods */ - bool renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, NRRect const *pbox); + bool renderPathVector(Geom::PathVector const &pathv, SPStyle const *style, Geom::OptRect const &pbox); bool renderImage(GdkPixbuf *pb, - Geom::Affine const *image_transform, SPStyle const *style); - bool renderGlyphtext(PangoFont *font, Geom::Affine const *font_matrix, + Geom::Affine const &image_transform, SPStyle const *style); + bool renderGlyphtext(PangoFont *font, Geom::Affine const &font_matrix, std::vector<CairoGlyphInfo> const &glyphtext, SPStyle const *style); /* More general rendering methods will have to be added (like fill, stroke) */ @@ -183,18 +183,18 @@ protected: CairoClipMode _clip_mode; cairo_pattern_t *_createPatternForPaintServer(SPPaintServer const *const paintserver, - NRRect const *pbox, float alpha); - cairo_pattern_t *_createPatternPainter(SPPaintServer const *const paintserver, NRRect const *pbox); + Geom::OptRect const &pbox, float alpha); + cairo_pattern_t *_createPatternPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox); unsigned int _showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoGlyphInfo> const &glyphtext, bool is_stroke); bool _finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t *ctm = NULL); - void _setFillStyle(SPStyle const *style, NRRect const *pbox); - void _setStrokeStyle(SPStyle const *style, NRRect const *pbox); + void _setFillStyle(SPStyle const *style, Geom::OptRect const &pbox); + void _setStrokeStyle(SPStyle const *style, Geom::OptRect const &pbox); - void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform); + void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const &transform); void _concatTransform(cairo_t *cr, double xx, double yx, double xy, double yy, double x0, double y0); - void _concatTransform(cairo_t *cr, Geom::Affine const *transform); + void _concatTransform(cairo_t *cr, Geom::Affine const &transform); GHashTable *font_table; static void font_data_free(gpointer data); diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 5e7fb991a..adfa0421d 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -181,15 +181,13 @@ static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affi static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) { - NRRect pbox; - SPShape *shape = SP_SHAPE(item); if (!shape->curve) { return; } - item->invoke_bbox( &pbox, Geom::identity(), TRUE); + Geom::OptRect pbox = item->geometricBounds(); SPStyle* style = item->style; @@ -198,7 +196,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) return; } - ctx->renderPathVector(pathv, style, &pbox); + ctx->renderPathVector(pathv, style, pbox); // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START @@ -316,7 +314,7 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx) if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed)); ctx->pushState(); - ctx->transform(&tp); + ctx->transform(tp); translated = true; } @@ -372,7 +370,7 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx) Geom::Scale s(width / (double)w, height / (double)h); Geom::Affine t(s * tp); - ctx->renderImage (image->pixbuf, &t, item->style); + ctx->renderImage (image->pixbuf, t, item->style); } static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) @@ -384,7 +382,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) /* Cloned <symbol> is actually renderable */ ctx->pushState(); - ctx->transform(&symbol->c2p); + ctx->transform(symbol->c2p); // apply viewbox if set if (0 /*symbol->viewBox_set*/) { @@ -409,7 +407,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) vb2user[4] = x - symbol->viewBox.x0 * vb2user[0]; vb2user[5] = y - symbol->viewBox.y0 * vb2user[3]; - ctx->transform(&vb2user); + ctx->transform(vb2user); } sp_group_render(item, ctx); @@ -425,8 +423,7 @@ static void sp_root_render(SPRoot *root, CairoRenderContext *ctx) ctx->pushState(); renderer->setStateForItem(ctx, root); - Geom::Affine tempmat (root->c2p); - ctx->transform(&tempmat); + ctx->transform(root->c2p); sp_group_render(root, ctx); ctx->popState(); } @@ -450,9 +447,8 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) } TRACE(("sp_asbitmap_render: resolution: %f\n", res )); - // Get the bounding box of the selection in document coordinates. - Geom::OptRect bbox = - item->getBounds(item->i2dt_affine(), SPItem::RENDERING_BBOX); + // Get the bounding box of the selection in desktop coordinates. + Geom::OptRect bbox = item->desktopVisualBounds(); // no bbox, e.g. empty group if (!bbox) { @@ -460,12 +456,7 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) } Geom::Rect docrect(Geom::Rect(Geom::Point(0, 0), item->document->getDimensions())); - Geom::Rect bboxrect(Geom::Rect(Geom::Point(bbox->min()[Geom::X], bbox->min()[Geom::Y]), Geom::Point(bbox->max()[Geom::X], bbox->max()[Geom::Y]))); - - Geom::OptRect _bbox = Geom::intersect(docrect, bboxrect); - - // assign the object dimension clipped on the document, no need to draw on area not on canvas - bbox = _bbox; + bbox &= docrect; // no bbox, e.g. empty group if (!bbox) { @@ -473,14 +464,14 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) } // The width and height of the bitmap in pixels - unsigned width = ceil((bbox->max()[Geom::X] - bbox->min()[Geom::X]) * (res / PX_PER_IN)); - unsigned height = ceil((bbox->max()[Geom::Y] - bbox->min()[Geom::Y]) * (res / PX_PER_IN)); + unsigned width = ceil(bbox->width() * (res / PX_PER_IN)); + unsigned height = ceil(bbox->height() * (res / PX_PER_IN)); if (width == 0 || height == 0) return; // Scale to exactly fit integer bitmap inside bounding box - double scale_x = (bbox->max()[Geom::X] - bbox->min()[Geom::X]) / width; - double scale_y = (bbox->max()[Geom::Y] - bbox->min()[Geom::Y]) / height; + double scale_x = bbox->width() / width; + double scale_y = bbox->height() / height; // Location of bounding box in document coordinates. double shift_x = bbox->min()[Geom::X]; @@ -516,7 +507,7 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) TEST(gdk_pixbuf_save( pb, "bitmap.png", "png", NULL, NULL )); // TODO this is stupid - we just converted to pixbuf format when generating the bitmap! convert_pixbuf_normal_to_argb32(pb); - ctx->renderImage(pb, &t, item->style); + ctx->renderImage(pb, t, item->style); gdk_pixbuf_unref(pb); pb = 0; } @@ -604,8 +595,7 @@ void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) state->merge_opacity = FALSE; ctx->pushLayer(); } - Geom::Affine tempmat (item->transform); - ctx->transform(&tempmat); + ctx->transform(item->transform); sp_item_invoke_render(item, ctx); if (state->need_layer) @@ -625,25 +615,25 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page base = doc->getRoot(); } - NRRect d; + Geom::Rect d; if (pageBoundingBox) { - d.x0 = d.y0 = 0; - d.x1 = doc->getWidth(); - d.y1 = doc->getHeight(); + d = Geom::Rect::from_xywh(Geom::Point(0,0), doc->getDimensions()); } else { - base->invoke_bbox( &d, base->i2dt_affine(), TRUE, SPItem::RENDERING_BBOX); + Geom::OptRect bbox = base->desktopVisualBounds(); + if (!bbox) { + g_message("CairoRenderer: empty bounding box."); + return false; + } + d = *bbox; } if (ctx->_vector_based_target) { // convert from px to pt - d.x0 *= PT_PER_PX; - d.x1 *= PT_PER_PX; - d.y0 *= PT_PER_PX; - d.y1 *= PT_PER_PX; + d *= Geom::Scale(PT_PER_PX); } - ctx->_width = d.x1-d.x0; - ctx->_height = d.y1-d.y0; + ctx->_width = d.width(); + ctx->_height = d.height(); TRACE(("setupDocument: %f x %f\n", ctx->_width, ctx->_height)); @@ -655,11 +645,12 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page if (ctx->_vector_based_target) high *= PT_PER_PX; - Geom::Affine tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), - (d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); - ctx->transform(&tp); + /// @fixme hardcoded dt2doc transform? + Geom::Affine tp(Geom::Translate(-d.left() * (ctx->_vector_based_target ? PX_PER_PT : 1.0), + (d.bottom() - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); + ctx->transform(tp); } - + return ret; } @@ -685,8 +676,8 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) t[4] = clip_bbox.x0; t[5] = clip_bbox.y0; t *= ctx->getCurrentState()->transform; - ctx->getTransform(&saved_ctm); - ctx->setTransform(&t); + saved_ctm = ctx->getTransform(); + ctx->setTransform(t); } TRACE(("BEGIN clip\n")); @@ -696,12 +687,11 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) SPItem const *item = SP_ITEM(child); // combine transform of the item in clippath and the item using clippath: - Geom::Affine tempmat (item->transform); - tempmat = tempmat * (ctx->getCurrentState()->item_transform); + Geom::Affine tempmat = item->transform * ctx->getCurrentState()->item_transform; // render this item in clippath ctx->pushState(); - ctx->transform(&tempmat); + ctx->transform(tempmat); setStateForItem(ctx, item); // TODO fix this call to accept const items sp_item_invoke_render(const_cast<SPItem *>(item), ctx); @@ -716,7 +706,7 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) cairo_clip(ctx->_cr); if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) - ctx->setTransform(&saved_ctm); + ctx->setTransform(saved_ctm); ctx->setRenderMode(saved_mode); } @@ -738,7 +728,7 @@ CairoRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask) t[4] = mask_bbox.x0; t[5] = mask_bbox.y0; t *= ctx->getCurrentState()->transform; - ctx->setTransform(&t); + ctx->setTransform(t); } // Clip mask contents... but... diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index 7ed0f6fcf..be5bf96c3 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -135,25 +135,22 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc) _width = doc->getWidth(); _height = doc->getHeight(); - NRRect d; bool pageBoundingBox; pageBoundingBox = mod->get_param_bool("pageBoundingBox"); + + Geom::Rect d; if (pageBoundingBox) { - d.x0 = d.y0 = 0; - d.x1 = _width; - d.y1 = _height; + d = Geom::Rect::from_xywh(0, 0, _width, _height); } else { SPItem* doc_item = doc->getRoot(); - doc_item->invoke_bbox(&d, doc_item->i2dt_affine(), TRUE); + Geom::OptRect bbox = doc_item->desktopVisualBounds(); + if (bbox) d = *bbox; } - d.x0 *= IN_PER_PX; - d.y0 *= IN_PER_PX; - d.x1 *= IN_PER_PX; - d.y1 *= IN_PER_PX; + d *= IN_PER_PX; - float dwInchesX = (d.x1 - d.x0); - float dwInchesY = (d.y1 - d.y0); + float dwInchesX = d.width(); + float dwInchesY = d.height(); // dwInchesX x dwInchesY in .01mm units SetRect( &rc, 0, 0, (int) ceil(dwInchesX*2540), (int) ceil(dwInchesY*2540) ); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 6436624fd..da5ea6d9e 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -90,7 +90,7 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc bounding_area = Geom::Rect( Geom::Point(0,0), Geom::Point(doc->getWidth(), doc->getHeight()) ); } else { - Geom::OptRect bounds = selection->bounds(); + Geom::OptRect bounds = selection->visualBounds(); if (bounds) { bounding_area = *bounds; } diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 02f0823d9..0da048a17 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -588,27 +588,27 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * base = doc->getRoot(); } - Geom::OptRect d; + Geom::Rect d; if (pageBoundingBox) { - d = Geom::Rect( Geom::Point(0,0), - Geom::Point(doc->getWidth(), doc->getHeight()) ); + d = Geom::Rect::from_xywh(Geom::Point(0,0), doc->getDimensions()); } else { - base->invoke_bbox( d, base->i2dt_affine(), TRUE, SPItem::RENDERING_BBOX); - } - if (!d) { - g_message("LaTeXTextRenderer: could not retrieve boundingbox."); - return false; + Geom::OptRect bbox = base->desktopVisualBounds(); + if (!bbox) { + g_message("CairoRenderer: empty bounding box."); + return false; + } + d = *bbox; } // scale all coordinates, such that the width of the image is 1, this is convenient for scaling the image in LaTeX - double scale = 1/(d->width()); - double _width = d->width() * scale; - double _height = d->height() * scale; + double scale = 1/(d.width()); + double _width = d.width() * scale; + double _height = d.height() * scale; push_transform( Geom::Scale(scale, scale) ); if (!pageBoundingBox) { - push_transform( Geom::Translate( - d->min() ) ); + push_transform( Geom::Translate( -d.min() ) ); } // flip y-axis @@ -621,7 +621,7 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * // scaling of the image when including it in LaTeX os << " \\ifx\\svgwidth\\undefined%\n"; - os << " \\setlength{\\unitlength}{" << d->width() * PT_PER_PX << "bp}%\n"; // note: 'bp' is the Postscript pt unit in LaTeX, see LP bug #792384 + os << " \\setlength{\\unitlength}{" << d.width() * PT_PER_PX << "bp}%\n"; // note: 'bp' is the Postscript pt unit in LaTeX, see LP bug #792384 os << " \\ifx\\svgscale\\undefined%\n"; os << " \\relax%\n"; os << " \\else%\n"; diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index 568c804a0..735c57798 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -573,7 +573,7 @@ void SingularValueDecomposition::calculate() //double eps = pow(2.0,-52.0); //double tiny = pow(2.0,-966.0); //let's just calculate these now - //a double can be e ± 308.25, so this is safe + //a double can be e ± 308.25, so this is safe double eps = 2.22e-16; double tiny = 1.6e-291; while (p > 0) { @@ -965,15 +965,10 @@ static Geom::Affine getODFTransform(const SPItem *item) */ static Geom::OptRect getODFBoundingBox(const SPItem *item) { - Geom::OptRect bbox_temp = ((SPItem *)item)->getBboxDesktop(); - Geom::OptRect bbox; - if (bbox_temp) { - bbox = *bbox_temp; - double doc_height = SP_ACTIVE_DOCUMENT->getHeight(); - Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0)); - doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height)); - bbox = *bbox * doc2dt_tf; - bbox = *bbox * Geom::Affine(Geom::Scale(pxToCm)); + // TODO: geometric or visual? + Geom::OptRect bbox = ((SPItem *)item)->documentVisualBounds(); + if (bbox) { + *bbox *= Geom::Affine(Geom::Scale(pxToCm)); } return bbox; } diff --git a/src/file.cpp b/src/file.cpp index c6d43fa51..350281dee 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1056,7 +1056,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, // move to mouse pointer { sp_desktop_document(desktop)->ensureUpToDate(); - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); if (sel_bbox) { Geom::Point m( desktop->point() - sel_bbox->midpoint() ); sp_selection_move_relative(selection, m, false); diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp index 9ea9407b1..1b63bf6f9 100644 --- a/src/filter-chemistry.cpp +++ b/src/filter-chemistry.cpp @@ -317,7 +317,7 @@ new_filter_blend_gaussian_blur (SPDocument *document, const char *blendmode, gdo SPFilter * new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble radius) { - Geom::OptRect const r = item->getBboxDesktop(SPItem::GEOMETRIC_BBOX); + Geom::OptRect const r = item->desktopGeometricBounds(); double width; double height; @@ -370,7 +370,7 @@ SPFilter *modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *it stdDeviation /= expansion; // Get the object size - Geom::OptRect const r = item->getBboxDesktop(SPItem::GEOMETRIC_BBOX); + Geom::OptRect const r = item->desktopGeometricBounds(); double width; double height; if (r) { diff --git a/src/flood-context.cpp b/src/flood-context.cpp index 8603f8b66..9e8705862 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -778,7 +778,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even document->ensureUpToDate(); - Geom::OptRect bbox = document->getRoot()->getBounds(Geom::identity()); + Geom::OptRect bbox = document->getRoot()->visualBounds(); if (!bbox) { desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("<b>Area is not bounded</b>, cannot fill.")); diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index f803d7bf8..5a8b20850 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -296,7 +296,7 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) // calculate the bbox of the item item->document->ensureUpToDate(); - Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine + Geom::OptRect bbox = item->visualBounds(); // we need "true" bbox without item_i2d_affine if (!bbox) return gr; @@ -363,7 +363,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar // calculate the bbox of the item item->document->ensureUpToDate(); Geom::Affine bbox2user; - Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine + Geom::OptRect bbox = item->visualBounds(); // we need "true" bbox without item_i2d_affine if ( bbox ) { bbox2user = Geom::Affine(bbox->dimensions()[Geom::X], 0, 0, bbox->dimensions()[Geom::Y], @@ -1063,7 +1063,7 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po if (SP_GRADIENT(gradient)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { item->document->ensureUpToDate(); - Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine + Geom::OptRect bbox = item->visualBounds(); // we need "true" bbox without item_i2d_affine if (bbox) { p *= Geom::Affine(bbox->dimensions()[Geom::X], 0, 0, bbox->dimensions()[Geom::Y], diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 142ae2a98..1275bf995 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -1788,15 +1788,15 @@ GrDrag::updateLevels () for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) { SPItem *item = SP_ITEM(i->data); - Geom::OptRect rect = item->getBboxDesktop (); + Geom::OptRect rect = item->desktopVisualBounds(); if (rect) { // Remember the edges of the bbox and the center axis hor_levels.push_back(rect->min()[Geom::Y]); hor_levels.push_back(rect->max()[Geom::Y]); - hor_levels.push_back(0.5 * (rect->min()[Geom::Y] + rect->max()[Geom::Y])); + hor_levels.push_back(rect->midpoint()[Geom::Y]); vert_levels.push_back(rect->min()[Geom::X]); vert_levels.push_back(rect->max()[Geom::X]); - vert_levels.push_back(0.5 * (rect->min()[Geom::X] + rect->max()[Geom::X])); + vert_levels.push_back(rect->midpoint()[Geom::X]); } } } diff --git a/src/graphlayout.cpp b/src/graphlayout.cpp index 57002bfb6..6197be9f7 100644 --- a/src/graphlayout.cpp +++ b/src/graphlayout.cpp @@ -128,7 +128,7 @@ void graphlayout(GSList const *const items) { ++i) { SPItem *u=*i; - Geom::OptRect const item_box(u->getBboxDesktop()); + Geom::OptRect const item_box = u->desktopVisualBounds(); if(item_box) { Geom::Point ll(item_box->min()); Geom::Point ur(item_box->max()); @@ -231,8 +231,8 @@ void graphlayout(GSList const *const items) { map<string,unsigned>::iterator i=nodelookup.find(u->getId()); if(i!=nodelookup.end()) { Rectangle* r=rs[i->second]; - Geom::OptRect item_box(u->getBboxDesktop()); - if(item_box) { + Geom::OptRect item_box = u->desktopVisualBounds(); + if (item_box) { Geom::Point const curr(item_box->midpoint()); Geom::Point const dest(r->getCentreX(),r->getCentreY()); sp_item_move_rel(u, Geom::Translate(dest - curr)); diff --git a/src/interface.cpp b/src/interface.cpp index a981424fa..fb0d23e1b 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1425,7 +1425,7 @@ sp_ui_drag_data_received(GtkWidget *widget, // move to mouse pointer { sp_desktop_document(desktop)->ensureUpToDate(); - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); if (sel_bbox) { Geom::Point m( desktop->point() - sel_bbox->midpoint() ); sp_selection_move_relative(selection, m, false); diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index a72fa0180..fa1a07414 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -81,7 +81,7 @@ void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) con } } -void Layout::show(DrawingGroup *in_arena, NRRect const *paintbox) const +void Layout::show(DrawingGroup *in_arena, Geom::OptRect const &paintbox) const { int glyph_index = 0; for (unsigned span_index = 0 ; span_index < _spans.size() ; span_index++) { @@ -99,13 +99,14 @@ void Layout::show(DrawingGroup *in_arena, NRRect const *paintbox) const } glyph_index++; } - nr_text->setPaintBox(paintbox ? paintbox->upgrade_2geom() : Geom::OptRect()); + nr_text->setPaintBox(paintbox); in_arena->prependChild(nr_text); } } -void Layout::getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start, int length) const +Geom::OptRect Layout::bounds(Geom::Affine const &transform, int start, int length) const { + Geom::OptRect bbox; for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; glyph_index++) { if (_characters[_glyphs[glyph_index].in_character].in_glyph == -1) continue; if (start != -1 && (int) _glyphs[glyph_index].in_character < start) continue; @@ -122,26 +123,15 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, if(_glyphs[glyph_index].span(this).font) { Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph); if (glyph_rect) { - Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max(); - Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]); - tlp *= total_transform; - trp *= total_transform; - blp *= total_transform; - brp *= total_transform; - *glyph_rect = Geom::Rect(tlp,trp); - glyph_rect->expandTo(blp); - glyph_rect->expandTo(brp); - if ( (glyph_rect->min())[0] < bounding_box->x0 ) bounding_box->x0=(glyph_rect->min())[0]; - if ( (glyph_rect->max())[0] > bounding_box->x1 ) bounding_box->x1=(glyph_rect->max())[0]; - if ( (glyph_rect->min())[1] < bounding_box->y0 ) bounding_box->y0=(glyph_rect->min())[1]; - if ( (glyph_rect->max())[1] > bounding_box->y1 ) bounding_box->y1=(glyph_rect->max())[1]; + bbox.unionWith(*glyph_rect * total_transform); } } } + return bbox; } void Layout::print(SPPrintContext *ctx, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, + Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox, Geom::Affine const &ctm) const { if (_input_stream.empty()) return; @@ -240,7 +230,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const if (pathv) { Geom::PathVector pathv_trans = (*pathv) * glyph_matrix; SPStyle const *style = text_source->style; - ctx->renderPathVector(pathv_trans, style, NULL); + ctx->renderPathVector(pathv_trans, style, Geom::OptRect()); } glyph_index++; continue; @@ -302,7 +292,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const ctx->pushLayer(); } if (glyph_index - first_index > 0) - ctx->renderGlyphtext(span.font->pFont, &font_matrix, glyphtext, style); + ctx->renderGlyphtext(span.font->pFont, font_matrix, glyphtext, style); if (opacity != 1.0) { ctx->popLayer(); ctx->popState(); @@ -388,9 +378,9 @@ Glib::ustring Layout::dumpAsText() const for (unsigned char_index = 0 ; char_index < _characters.size() ; char_index++) { if (_characters[char_index].in_span != span_index) continue; if (_input_stream[_spans[span_index].in_input_stream_item]->Type() != TEXT_SOURCE) { - snprintf(line, sizeof(line), " %d: control x=%f flags=%03x glyph=%d\n", char_index, _characters[char_index].x, *(unsigned*)&_characters[char_index].char_attributes, _characters[char_index].in_glyph); + snprintf(line, sizeof(line), " %d: control x=%f flags=%03x glyph=%d\n", char_index, _characters[char_index].x, *(unsigned*) &_characters[char_index].char_attributes, _characters[char_index].in_glyph); } else { - snprintf(line, sizeof(line), " %d: '%c' x=%f flags=%03x glyph=%d\n", char_index, *iter_char, _characters[char_index].x, *(unsigned*)&_characters[char_index].char_attributes, _characters[char_index].in_glyph); + snprintf(line, sizeof(line), " %d: '%c' x=%f flags=%03x glyph=%d\n", char_index, *iter_char, _characters[char_index].x, *(unsigned*) &_characters[char_index].char_attributes, _characters[char_index].in_glyph); iter_char++; } result += line; diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index 25f80e9e9..a8852ed8a 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -328,7 +328,7 @@ public: \param in_arena The arena to add the glyphs group to \param paintbox The current rendering tile */ - void show(DrawingGroup *in_arena, NRRect const *paintbox) const; + void show(DrawingGroup *in_arena, Geom::OptRect const &paintbox) const; /** Calculates the smallest rectangle completely enclosing all the glyphs. @@ -336,7 +336,7 @@ public: \param transform The transform to be applied to the entire object prior to calculating its bounds. */ - void getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start = -1, int length = -1) const; + Geom::OptRect bounds(Geom::Affine const &transform, int start = -1, int length = -1) const; /** Sends all the glyphs to the given print context. \param ctx I have @@ -345,7 +345,7 @@ public: \param bbox parameters \param ctm do yet */ - void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Affine const &ctm) const; + void print(SPPrintContext *ctx, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox, Geom::Affine const &ctm) const; #ifdef HAVE_CAIRO_PDF /** Renders all the glyphs to the given Cairo rendering context. diff --git a/src/live_effects/lpe-extrude.cpp b/src/live_effects/lpe-extrude.cpp index 96d465569..8b5badf5f 100644 --- a/src/live_effects/lpe-extrude.cpp +++ b/src/live_effects/lpe-extrude.cpp @@ -174,10 +174,10 @@ LPEExtrude::resetDefaults(SPItem * item) using namespace Geom; - Geom::OptRect bbox = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = item->geometricBounds(); if (bbox) { - Interval boundingbox_X = (*bbox)[Geom::X]; - Interval boundingbox_Y = (*bbox)[Geom::Y]; + Interval const &boundingbox_X = (*bbox)[Geom::X]; + Interval const &boundingbox_Y = (*bbox)[Geom::Y]; extrude_vector.set_and_write_new_values( Geom::Point(boundingbox_X.middle(), boundingbox_Y.middle()), (boundingbox_X.extent() + boundingbox_Y.extent())*Geom::Point(-0.05,0.2) ); } diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index 02d24752b..2d043ca91 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -45,8 +45,10 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem *lpeitem) { using namespace Geom; + // fixme: what happens if the bbox is empty? + // fixme: this is probably wrong Geom::Affine t = lpeitem->i2dt_affine(); - Geom::Rect bbox = *lpeitem->getBounds(t); // fixme: what happens if getBounds does not return a valid rect? + Geom::Rect bbox = *lpeitem->desktopVisualBounds(); Point A(bbox.left(), bbox.bottom()); Point B(bbox.left(), bbox.top()); diff --git a/src/live_effects/lpe-rough-hatches.cpp b/src/live_effects/lpe-rough-hatches.cpp index 671d88a8b..87e3dbe5c 100644 --- a/src/live_effects/lpe-rough-hatches.cpp +++ b/src/live_effects/lpe-rough-hatches.cpp @@ -557,7 +557,7 @@ LPERoughHatches::resetDefaults(SPItem * item) { Effect::resetDefaults(item); - Geom::OptRect bbox = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = item->geometricBounds(); Geom::Point origin(0.,0.); Geom::Point vector(50.,0.); if (bbox) { diff --git a/src/live_effects/lpegroupbbox.cpp b/src/live_effects/lpegroupbbox.cpp index 382231378..c241b9a4c 100644 --- a/src/live_effects/lpegroupbbox.cpp +++ b/src/live_effects/lpegroupbbox.cpp @@ -34,7 +34,7 @@ GroupBBoxEffect::original_bbox(SPLPEItem *lpeitem, bool absolute) transform = Geom::identity(); } - Geom::OptRect bbox = lpeitem->getBounds(transform, SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = lpeitem->geometricBounds(transform); if (bbox) { boundingbox_X = (*bbox)[Geom::X]; boundingbox_Y = (*bbox)[Geom::Y]; diff --git a/src/main.cpp b/src/main.cpp index ace99f519..501a3e5d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1195,8 +1195,8 @@ do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const g doc->ensureUpToDate(); SPItem *item = ((SPItem *) o); - // "true" SVG bbox for scripting - Geom::OptRect area = item->getBounds(item->i2doc_affine()); + // visual bbox in document coords for scripting + Geom::OptRect area = item->documentVisualBounds(); if (area) { Inkscape::SVGOStringStream os; if (extent) { @@ -1226,7 +1226,7 @@ do_query_all_recurse (SPObject *o) { SPItem *item = ((SPItem *) o); if (o->getId() && SP_IS_ITEM(item)) { - Geom::OptRect area = item->getBounds(item->i2doc_affine()); + Geom::OptRect area = item->documentVisualBounds(); if (area) { Inkscape::SVGOStringStream os; os << o->getId(); @@ -1320,8 +1320,7 @@ sp_do_export_png(SPDocument *doc) // write object bbox to area doc->ensureUpToDate(); - Geom::OptRect areaMaybe; - static_cast<SPItem *>(o_area)->invoke_bbox( areaMaybe, static_cast<SPItem *>(o_area)->i2dt_affine(), TRUE); + Geom::OptRect areaMaybe = static_cast<SPItem *>(o_area)->desktopVisualBounds(); if (areaMaybe) { area = *areaMaybe; } else { diff --git a/src/marker.cpp b/src/marker.cpp index c8fa9218d..9db5cfdc1 100644 --- a/src/marker.cpp +++ b/src/marker.cpp @@ -45,7 +45,7 @@ static Inkscape::XML::Node *sp_marker_write (SPObject *object, Inkscape::XML::Do static Inkscape::DrawingItem *sp_marker_private_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); static void sp_marker_private_hide (SPItem *item, unsigned int key); -static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_marker_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_marker_print (SPItem *item, SPPrintContext *ctx); static void sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destroyitems); @@ -541,10 +541,11 @@ sp_marker_private_hide (SPItem */*item*/, unsigned int /*key*/) /** * This routine is disabled to break propagation. */ -static void -sp_marker_bbox(SPItem const *, NRRect *, Geom::Affine const &, unsigned const) +static Geom::OptRect +sp_marker_bbox(SPItem const *, Geom::Affine const &, SPItem::BBoxType) { - /* Break propagation */ + /* Break propagation */ + return Geom::OptRect(); } /** diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index fd8ef0c7c..07d690ce0 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -135,15 +135,14 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, if (SP_IS_GROUP(o)) { _findCandidates(o, it, false, bbox_to_snap, clip_or_mask, additional_affine); } else { - Geom::OptRect bbox_of_item = Geom::Rect(); + Geom::OptRect bbox_of_item; if (clip_or_mask) { // Oh oh, this will get ugly. We cannot use sp_item_i2d_affine directly because we need to // insert an additional transformation in document coordinates (code copied from sp_item_i2d_affine) - item->invoke_bbox(bbox_of_item, - item->i2doc_affine() * additional_affine * _snapmanager->getDesktop()->doc2dt(), - true); + bbox_of_item = item->visualBounds(item->i2doc_affine() * additional_affine * + _snapmanager->getDesktop()->doc2dt()); } else { - item->invoke_bbox( bbox_of_item, item->i2dt_affine(), true); + bbox_of_item = item->desktopVisualBounds(); } if (bbox_of_item) { // See if the item is within range @@ -188,7 +187,7 @@ void Inkscape::ObjectSnapper::_collectNodes(SnapSourceType const &t, Preferences *prefs = Preferences::get(); bool prefs_bbox = prefs->getBool("/tools/bounding_box"); bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; } // Consider the page border for snapping to @@ -255,7 +254,7 @@ void Inkscape::ObjectSnapper::_collectNodes(SnapSourceType const &t, // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox // of the item AND the bbox of the clipping path at the same time if (!(*i).clip_or_mask) { - Geom::OptRect b = root_item->getBboxDesktop(bbox_type); + Geom::OptRect b = root_item->desktopBounds(bbox_type); getBBoxPoints(b, _points_to_snap_to, true, _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_BBOX_CORNER), _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_BBOX_EDGE_MIDPOINT), @@ -370,7 +369,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, Preferences *prefs = Preferences::get(); int prefs_bbox = prefs->getBool("/tools/bounding_box", 0); bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; } // Consider the page border for snapping @@ -449,11 +448,10 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox // of the item AND the bbox of the clipping path at the same time if (!(*i).clip_or_mask) { - Geom::OptRect rect; - root_item->invoke_bbox( rect, i2doc, TRUE, bbox_type); + Geom::OptRect rect = root_item->bounds(bbox_type, i2doc); if (rect) { Geom::PathVector *path = _getPathvFromRect(*rect); - rect = root_item->getBboxDesktop(bbox_type); + rect = root_item->desktopBounds(bbox_type); _paths_to_snap_to->push_back(SnapCandidatePath(path, SNAPTARGET_BBOX_EDGE, rect)); } } diff --git a/src/print.cpp b/src/print.cpp index 2eadf0fa9..3e477c976 100644 --- a/src/print.cpp +++ b/src/print.cpp @@ -56,16 +56,18 @@ sp_print_comment(SPPrintContext *ctx, char const *comment) unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) + Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) { - return ctx->module->fill(pathv, ctm, style, pbox, dbox, bbox); + NRRect nrpbox(pbox), nrdbox(dbox), nrbbox(bbox); + return ctx->module->fill(pathv, ctm, style, &nrpbox, &nrdbox, &nrbbox); } unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) + Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) { - return ctx->module->stroke(pathv, ctm, style, pbox, dbox, bbox); + NRRect nrpbox(pbox), nrdbox(dbox), nrbbox(bbox); + return ctx->module->stroke(pathv, ctm, style, &nrpbox, &nrdbox, &nrbbox); } unsigned int diff --git a/src/print.h b/src/print.h index 6bdbe4b82..34c85d901 100644 --- a/src/print.h +++ b/src/print.h @@ -27,9 +27,9 @@ unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const *transform, f unsigned int sp_print_release(SPPrintContext *ctx); unsigned int sp_print_comment(SPPrintContext *ctx, char const *comment); unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); + Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox); unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *transform, SPStyle const *style, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); + Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox); unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx, guchar *px, unsigned int w, unsigned int h, unsigned int rs, diff --git a/src/removeoverlap.cpp b/src/removeoverlap.cpp index a503fea35..6dd8d6a79 100644 --- a/src/removeoverlap.cpp +++ b/src/removeoverlap.cpp @@ -50,7 +50,7 @@ void removeoverlap(GSList const *const items, double const xGap, double const yG ++it) { using Geom::X; using Geom::Y; - Geom::OptRect item_box((*it)->getBboxDesktop()); + Geom::OptRect item_box((*it)->desktopVisualBounds()); if (item_box) { Geom::Point min(item_box->min() - .5*gap); Geom::Point max(item_box->max() + .5*gap); diff --git a/src/selcue.cpp b/src/selcue.cpp index c647c1f96..dbcaf4cc3 100644 --- a/src/selcue.cpp +++ b/src/selcue.cpp @@ -68,8 +68,6 @@ void Inkscape::SelCue::_updateItemBboxes() g_return_if_fail(_selection != NULL); int prefs_bbox = prefs->getBool("/tools/bounding_box"); - SPItem::BBoxType bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; GSList const *items = _selection->itemList(); if (_item_bboxes.size() != g_slist_length((GSList *) items)) { @@ -83,7 +81,8 @@ void Inkscape::SelCue::_updateItemBboxes() SPCanvasItem* box = _item_bboxes[bcount ++]; if (box) { - Geom::OptRect const b = item->getBboxDesktop(bbox_type); + Geom::OptRect const b = (prefs_bbox == 0) ? + item->desktopVisualBounds() : item->desktopGeometricBounds(); if (b) { sp_canvas_item_show(box); @@ -118,13 +117,12 @@ void Inkscape::SelCue::_newItemBboxes() g_return_if_fail(_selection != NULL); int prefs_bbox = prefs->getBool("/tools/bounding_box"); - SPItem::BBoxType bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; for (GSList const *l = _selection->itemList(); l != NULL; l = l->next) { SPItem *item = (SPItem *) l->data; - Geom::OptRect const b = item->getBboxDesktop(bbox_type); + Geom::OptRect const b = (prefs_bbox == 0) ? + item->desktopVisualBounds() : item->desktopGeometricBounds(); SPCanvasItem* box = NULL; diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 23991bfb6..75745f4af 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -777,7 +777,7 @@ enclose_items(GSList const *items) Geom::OptRect r; for (GSList const *i = items; i; i = i->next) { - r.unionWith(((SPItem *) i->data)->getBboxDesktop()); + r.unionWith(((SPItem *) i->data)->desktopVisualBounds()); } return r; } @@ -829,7 +829,7 @@ sp_selection_raise(SPDesktop *desktop) for (SPObject *newref = child->next; newref; newref = newref->next) { // if the sibling is an item AND overlaps our selection, if (SP_IS_ITEM(newref)) { - Geom::OptRect newref_bbox = SP_ITEM(newref)->getBboxDesktop(); + Geom::OptRect newref_bbox = SP_ITEM(newref)->desktopVisualBounds(); if ( newref_bbox && selected->intersects(*newref_bbox) ) { // AND if it's not one of our selected objects, if (!g_slist_find((GSList *) items, newref)) { @@ -924,7 +924,7 @@ sp_selection_lower(SPDesktop *desktop) for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) { // if the sibling is an item AND overlaps our selection, if (SP_IS_ITEM(newref)) { - Geom::OptRect ref_bbox = SP_ITEM(newref)->getBboxDesktop(); + Geom::OptRect ref_bbox = SP_ITEM(newref)->desktopVisualBounds(); if ( ref_bbox && selected->intersects(*ref_bbox) ) { // AND if it's not one of our selected objects, if (!g_slist_find((GSList *) items, newref)) { @@ -1481,7 +1481,7 @@ sp_selection_scale_absolute(Inkscape::Selection *selection, if (selection->isEmpty()) return; - Geom::OptRect const bbox(selection->bounds()); + Geom::OptRect bbox = selection->visualBounds(); if ( !bbox ) { return; } @@ -1503,7 +1503,7 @@ void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point con if (selection->isEmpty()) return; - Geom::OptRect const bbox(selection->bounds()); + Geom::OptRect bbox = selection->visualBounds(); if ( !bbox ) { return; @@ -1621,7 +1621,7 @@ sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle) if (selection->isEmpty()) return; - Geom::OptRect const bbox(selection->bounds()); + Geom::OptRect bbox = selection->visualBounds(); boost::optional<Geom::Point> center = selection->center(); if ( !bbox || !center ) { @@ -1650,7 +1650,7 @@ sp_selection_scale(Inkscape::Selection *selection, gdouble grow) if (selection->isEmpty()) return; - Geom::OptRect const bbox(selection->bounds()); + Geom::OptRect bbox = selection->visualBounds(); if (!bbox) { return; } @@ -1687,7 +1687,7 @@ sp_selection_scale_times(Inkscape::Selection *selection, gdouble times) if (selection->isEmpty()) return; - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); if (!sel_bbox) { return; @@ -2014,7 +2014,7 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, void scroll_to_show_item(SPDesktop *desktop, SPItem *item) { Geom::Rect dbox = desktop->get_display_area(); - Geom::OptRect sbox = item->getBboxDesktop(); + Geom::OptRect sbox = item->desktopVisualBounds(); if ( sbox && dbox.contains(*sbox) == false ) { Geom::Point const s_dt = sbox->midpoint(); @@ -2248,8 +2248,8 @@ sp_select_clone_original(SPDesktop *desktop) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool highlight = prefs->getBool("/options/highlightoriginal/value"); if (highlight) { - Geom::OptRect a = item->getBounds(item->i2dt_affine()); - Geom::OptRect b = original->getBounds(original->i2dt_affine()); + Geom::OptRect a = item->desktopVisualBounds(); + Geom::OptRect b = original->desktopVisualBounds(); if ( a && b ) { // draw a flashing line between the objects SPCurve *curve = new SPCurve(); @@ -2291,7 +2291,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) } doc->ensureUpToDate(); - Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX); + Geom::OptRect r = selection->visualBounds(); boost::optional<Geom::Point> c = selection->center(); if ( !r || !c ) { return; @@ -2322,7 +2322,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) repr_copies = g_slist_prepend(repr_copies, dup); } - Geom::Rect bounds(desktop->dt2doc(r->min()), desktop->dt2doc(r->max())); + Geom::Rect bbox(desktop->dt2doc(r->min()), desktop->dt2doc(r->max())); if (apply) { // delete objects so that their clones don't get alerted; this object will be restored shortly @@ -2339,7 +2339,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); - gchar const *mark_id = generate_marker(repr_copies, bounds, doc, + gchar const *mark_id = generate_marker(repr_copies, bbox, doc, ( Geom::Affine(Geom::Translate(desktop->dt2doc( Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) @@ -2416,7 +2416,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) } doc->ensureUpToDate(); - Geom::OptRect r = selection->bounds(SPItem::RENDERING_BBOX); + Geom::OptRect r = selection->visualBounds(); if ( !r ) { return; } @@ -2447,7 +2447,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) // restore the z-order after prepends repr_copies = g_slist_reverse(repr_copies); - Geom::Rect bounds(desktop->dt2doc(r->min()), desktop->dt2doc(r->max())); + Geom::Rect bbox(desktop->dt2doc(r->min()), desktop->dt2doc(r->max())); if (apply) { // delete objects so that their clones don't get alerted; this object will be restored shortly @@ -2464,7 +2464,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); - gchar const *pat_id = pattern_tile(repr_copies, bounds, doc, + gchar const *pat_id = pattern_tile(repr_copies, bbox, doc, ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) * parent_transform.inverse() ), @@ -2477,8 +2477,8 @@ sp_selection_tile(SPDesktop *desktop, bool apply) Inkscape::XML::Node *rect = xml_doc->createElement("svg:rect"); rect->setAttribute("style", g_strdup_printf("stroke:none;fill:url(#%s)", pat_id)); - Geom::Point min = bounds.min() * parent_transform.inverse(); - Geom::Point max = bounds.max() * parent_transform.inverse(); + Geom::Point min = bbox.min() * parent_transform.inverse(); + Geom::Point max = bbox.max() * parent_transform.inverse(); sp_repr_set_svg_double(rect, "width", max[Geom::X] - min[Geom::X]); sp_repr_set_svg_double(rect, "height", max[Geom::Y] - min[Geom::Y]); @@ -2663,7 +2663,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) // Get the bounding box of the selection document->ensureUpToDate(); - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (!bbox) { desktop->clearWaitingCursor(); return; // exceptional situation, so not bother with a translatable error message, just quit quietly @@ -3200,7 +3200,7 @@ fit_canvas_to_selection(SPDesktop *desktop, bool with_margins) desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to fit canvas to.")); return false; } - Geom::OptRect const bbox(desktop->selection->bounds(SPItem::RENDERING_BBOX)); + Geom::OptRect const bbox(desktop->selection->visualBounds()); if (bbox) { doc->fitToRect(*bbox, with_margins); return true; @@ -3232,7 +3232,7 @@ fit_canvas_to_drawing(SPDocument *doc, bool with_margins) doc->ensureUpToDate(); SPItem const *const root = doc->getRoot(); - Geom::OptRect const bbox(root->getBounds(root->i2dt_affine(), SPItem::RENDERING_BBOX)); + Geom::OptRect bbox = root->desktopVisualBounds(); if (bbox) { doc->fitToRect(*bbox, with_margins); return true; diff --git a/src/selection.cpp b/src/selection.cpp index 677e57d5f..92b35bce7 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -362,50 +362,48 @@ Inkscape::XML::Node *Selection::singleRepr() { return obj ? obj->getRepr() : NULL; } -NRRect *Selection::bounds(NRRect *bbox, SPItem::BBoxType type) const +Geom::OptRect Selection::bounds(SPItem::BBoxType type) const { - g_return_val_if_fail (bbox != NULL, NULL); - *bbox = NRRect(bounds(type)); - return bbox; + return (type == SPItem::GEOMETRIC_BBOX) ? + geometricBounds() : visualBounds(); } -Geom::OptRect Selection::bounds(SPItem::BBoxType type) const +Geom::OptRect Selection::geometricBounds() const { GSList const *items = const_cast<Selection *>(this)->itemList(); Geom::OptRect bbox; for ( GSList const *i = items ; i != NULL ; i = i->next ) { - bbox.unionWith(SP_ITEM(i->data)->getBboxDesktop(type)); + bbox.unionWith(SP_ITEM(i->data)->desktopGeometricBounds()); } return bbox; } -NRRect *Selection::boundsInDocument(NRRect *bbox, SPItem::BBoxType type) const { - g_return_val_if_fail (bbox != NULL, NULL); +Geom::OptRect Selection::visualBounds() const +{ + GSList const *items = const_cast<Selection *>(this)->itemList(); - GSList const *items=const_cast<Selection *>(this)->itemList(); - if (!items) { - bbox->x0 = bbox->y0 = bbox->x1 = bbox->y1 = 0.0; - return bbox; + Geom::OptRect bbox; + for ( GSList const *i = items ; i != NULL ; i = i->next ) { + bbox.unionWith(SP_ITEM(i->data)->desktopVisualBounds()); } + return bbox; +} - bbox->x0 = bbox->y0 = 1e18; - bbox->x1 = bbox->y1 = -1e18; +Geom::OptRect Selection::documentBounds(SPItem::BBoxType type) const +{ + Geom::OptRect bbox; + GSList const *items = const_cast<Selection *>(this)->itemList(); + if (!items) return bbox; for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) { - SPItem *item=SP_ITEM(iter->data); - Geom::Affine i2doc(item->i2doc_affine()); - item->invoke_bbox( bbox, i2doc, FALSE, type); + SPItem *item = SP_ITEM(iter->data); + bbox |= item->documentBounds(type); } return bbox; } -Geom::OptRect Selection::boundsInDocument(SPItem::BBoxType type) const { - NRRect r; - return to_2geom(boundsInDocument(&r, type)); -} - /** Extract the position of the center from the first selected object */ // If we have a selection of multiple items, then the center of the first item // will be returned; this is also the case in SelTrans::centerRequest() @@ -418,9 +416,9 @@ boost::optional<Geom::Point> Selection::center() const { return first->getCenter(); } } - Geom::OptRect bbox = bounds(); + Geom::OptRect bbox = visualBounds(); if (bbox) { - return bounds()->midpoint(); + return bbox->midpoint(); } else { return boost::optional<Geom::Point>(); } diff --git a/src/selection.h b/src/selection.h index 00572a1c5..af0facc3d 100644 --- a/src/selection.h +++ b/src/selection.h @@ -244,25 +244,12 @@ public: guint numberOfParents(); /** @brief Returns the bounding rectangle of the selection */ - NRRect *bounds(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; - /** @brief Returns the bounding rectangle of the selection */ - Geom::OptRect bounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; - - /** - * @brief Returns the bounding rectangle of the selection - * - * Gives the coordinates in internal format, does not match onscreen guides. - * (0,0 is the upper left corner, not the lower left corner) - */ - NRRect *boundsInDocument(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; + Geom::OptRect bounds(SPItem::BBoxType type) const; + Geom::OptRect visualBounds() const; + Geom::OptRect geometricBounds() const; - /** - * @brief Returns the bounding rectangle of the selection - * - * Gives the coordinates in internal format, does not match onscreen guides. - * (0,0 is the upper left corner, not the lower left corner) - */ - Geom::OptRect boundsInDocument(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; + /// Returns the bounding rectangle of the selectionin document coordinates. + Geom::OptRect documentBounds(SPItem::BBoxType type) const; /** * @brief Returns the rotation/skew center of the selection diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 3a204a49e..0e5e533fc 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -90,7 +90,7 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) : _grabbed(false), _show_handles(true), _bbox(), - _approximate_bbox(), + _visual_bbox(), _absolute_affine(Geom::Scale(1,1)), _opposite(Geom::Point(0,0)), _opposite_for_specpoints(Geom::Point(0,0)), @@ -104,7 +104,7 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) : Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int prefs_bbox = prefs->getBool("/tools/bounding_box"); _snap_bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; g_return_if_fail(desktop != NULL); @@ -279,8 +279,8 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s // First, determine the bounding box _bbox = selection->bounds(_snap_bbox_type); - _approximate_bbox = selection->bounds(SPItem::APPROXIMATE_BBOX); // Used for correctly scaling the strokewidth - _geometric_bbox = selection->bounds(SPItem::GEOMETRIC_BBOX); + _visual_bbox = selection->visualBounds(); // Used for correctly scaling the strokewidth + _geometric_bbox = selection->geometricBounds(); _point = p; if (_geometric_bbox) { @@ -336,7 +336,8 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s // More than 50 items will produce at least 200 bbox points, which might make Inkscape crawl // (see the comment a few lines above). In that case we will use the bbox of the selection as a whole for (unsigned i = 0; i < _items.size(); i++) { - getBBoxPoints(_items[i]->getBboxDesktop(_snap_bbox_type), &_bbox_points_for_translating, false, c, emp, mp); + Geom::OptRect b = _items[i]->desktopBounds(_snap_bbox_type); + getBBoxPoints(b, &_bbox_points_for_translating, false, c, emp, mp); } } else { _bbox_points_for_translating = _bbox_points; // use the bbox points of the selection as a whole @@ -696,7 +697,7 @@ void Inkscape::SelTrans::_updateVolatileState() //Update the bboxes _bbox = selection->bounds(_snap_bbox_type); - _approximate_bbox = selection->bounds(SPItem::APPROXIMATE_BBOX); + _visual_bbox = selection->visualBounds(); if (!_bbox) { _empty = true; @@ -898,8 +899,7 @@ void Inkscape::SelTrans::_selChanged(Inkscape::Selection */*selection*/) // reread in case it changed on the fly: int prefs_bbox = prefs->getBool("/tools/bounding_box"); _snap_bbox_type = !prefs_bbox ? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; - //SPItem::APPROXIMATE_BBOX will be replaced by SPItem::VISUAL_BBOX, as soon as the latter is implemented properly + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; _updateVolatileState(); _current_relative_affine.setIdentity(); @@ -1602,8 +1602,8 @@ Geom::Scale Inkscape::calcScaleFactors(Geom::Point const &initial_point, Geom::P Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_scale) { Geom::Affine abs_affine = Geom::Translate(-_origin) * Geom::Affine(default_scale) * Geom::Translate(_origin); - Geom::Point new_bbox_min = _approximate_bbox->min() * abs_affine; - Geom::Point new_bbox_max = _approximate_bbox->max() * abs_affine; + Geom::Point new_bbox_min = _visual_bbox->min() * abs_affine; + Geom::Point new_bbox_max = _visual_bbox->max() * abs_affine; bool transform_stroke = false; gdouble strokewidth = 0; @@ -1614,7 +1614,7 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_ strokewidth = _strokewidth; } - _absolute_affine = get_scale_transform_with_uniform_stroke (*_approximate_bbox, strokewidth, transform_stroke, + _absolute_affine = get_scale_transform_with_uniform_stroke (*_visual_bbox, strokewidth, transform_stroke, new_bbox_min[Geom::X], new_bbox_min[Geom::Y], new_bbox_max[Geom::X], new_bbox_max[Geom::Y]); // return the new handle position diff --git a/src/seltrans.h b/src/seltrans.h index dd890ee9b..9d14fda26 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -136,7 +136,7 @@ private: SPItem::BBoxType _snap_bbox_type; Geom::OptRect _bbox; - Geom::OptRect _approximate_bbox; + Geom::OptRect _visual_bbox; Geom::OptRect _geometric_bbox; gdouble _strokewidth; diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 0b3320e59..2213443a5 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -34,7 +34,7 @@ struct SPClipPathView { SPClipPathView *next; unsigned int key; Inkscape::DrawingItem *arenaitem; - NRRect bbox; + Geom::OptRect bbox; }; SPClipPathView *sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, Inkscape::DrawingItem *arenaitem); @@ -193,10 +193,9 @@ void SPClipPath::update(SPObject *object, SPCtx *ctx, guint flags) SPClipPath *cp = SP_CLIPPATH(object); for (SPClipPathView *v = cp->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); - t[4] = v->bbox.x0; - t[5] = v->bbox.y0; + if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX && v->bbox) { + Geom::Affine t = Geom::Scale(v->bbox->dimensions()); + t.setTranslation(v->bbox->min()); g->setChildTransform(t); } else { g->setChildTransform(Geom::identity()); @@ -257,10 +256,9 @@ Inkscape::DrawingItem *SPClipPath::show(Inkscape::Drawing &drawing, unsigned int } } - if (clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0)); - t[4] = display->bbox.x0; - t[5] = display->bbox.y0; + if (clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX && display->bbox) { + Geom::Affine t = Geom::Scale(display->bbox->dimensions()); + t.setTranslation(display->bbox->min()); ai->setChildTransform(t); } ai->setStyle(this->style); @@ -287,42 +285,26 @@ void SPClipPath::hide(unsigned int key) g_assert_not_reached(); } -void SPClipPath::setBBox(unsigned int key, NRRect *bbox) +void SPClipPath::setBBox(unsigned int key, Geom::OptRect const &bbox) { for (SPClipPathView *v = display; v != NULL; v = v->next) { if (v->key == key) { - if (!Geom::are_near(v->bbox.x0, bbox->x0) || - !Geom::are_near(v->bbox.y0, bbox->y0) || - !Geom::are_near(v->bbox.x1, bbox->x1) || - !Geom::are_near(v->bbox.y1, bbox->y1)) { - v->bbox = *bbox; - } + v->bbox = bbox; break; } } } -void SPClipPath::getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) +Geom::OptRect SPClipPath::geometricBounds(Geom::Affine const &transform) { SPObject *i = 0; - for (i = firstChild(); i && !SP_IS_ITEM(i); i = i->getNext()) { - } - if (!i) { - return; - } - - SP_ITEM(i)->invoke_bbox_full( bbox, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); - SPObject *i_start = i; - - while (i != NULL) { - if (i != i_start) { - NRRect i_box; - SP_ITEM(i)->invoke_bbox_full( &i_box, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); - nr_rect_d_union (bbox, bbox, &i_box); - } - i = i->getNext(); - for (; i && !SP_IS_ITEM(i); i = i->getNext()){}; + Geom::OptRect bbox; + for (i = firstChild(); i; i = i->getNext()) { + if (!SP_IS_ITEM(i)) continue; + Geom::OptRect tmp = SP_ITEM(i)->geometricBounds(Geom::Affine(SP_ITEM(i)->transform) * transform); + bbox.unionWith(tmp); } + return bbox; } /* ClipPath views */ @@ -335,8 +317,7 @@ sp_clippath_view_new_prepend(SPClipPathView *list, unsigned int key, Inkscape::D new_path_view->next = list; new_path_view->key = key; new_path_view->arenaitem = arenaitem; - new_path_view->bbox.x0 = new_path_view->bbox.x1 = 0.0; - new_path_view->bbox.y0 = new_path_view->bbox.y1 = 0.0; + new_path_view->bbox = Geom::OptRect(); return new_path_view; } diff --git a/src/sp-clippath.h b/src/sp-clippath.h index 11817eb77..c151851d3 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -43,8 +43,8 @@ public: Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key); void hide(unsigned int key); - void setBBox(unsigned int key, NRRect *bbox); - void getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags); + void setBBox(unsigned int key, Geom::OptRect const &bbox); + Geom::OptRect geometricBounds(Geom::Affine const &transform); private: static void init(SPClipPath *clippath); diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index ea8079bba..bd73a65c9 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -46,7 +46,7 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D 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, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_flowtext_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_flowtext_description(SPItem *item); static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); @@ -176,20 +176,19 @@ static void sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags) group->rebuildLayout(); - NRRect paintbox; - group->invoke_bbox( &paintbox, Geom::identity(), TRUE); + Geom::OptRect pbox = group->geometricBounds(); for (SPItemView *v = group->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); group->_clearFlow(g); g->setStyle(object->style); // pass the bbox of the flowtext object as paintbox (used for paintserver fills) - group->layout.show(g, &paintbox); + group->layout.show(g, pbox); } } static void sp_flowtext_modified(SPObject *object, guint flags) { - SPObject *ft = SP_FLOWTEXT (object); + SPObject *ft = object; SPObject *region = NULL; if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; @@ -198,13 +197,12 @@ static void sp_flowtext_modified(SPObject *object, guint flags) // 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; - text->invoke_bbox( &paintbox, Geom::identity(), TRUE); + Geom::OptRect pbox = text->geometricBounds(); for (SPItemView* v = text->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); text->_clearFlow(g); g->setStyle(object->style); - text->layout.show(g, &paintbox); + text->layout.show(g, pbox); } } @@ -329,53 +327,33 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D return repr; } -static void -sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) +static Geom::OptRect +sp_flowtext_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { SPFlowtext *group = SP_FLOWTEXT(item); - group->layout.getBoundingBox(bbox, transform); + Geom::OptRect bbox = group->layout.bounds(transform); // Add stroke width - SPStyle* style = item->style; - 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 ) { - bbox->x0-=0.5*width; - bbox->x1+=0.5*width; - bbox->y0-=0.5*width; - bbox->y1+=0.5*width; - } - } + // FIXME this code is incorrect + if (type == SPItem::VISUAL_BBOX && !item->style->stroke.isNone()) { + double scale = transform.descrim(); + bbox->expandBy(0.5 * item->style->stroke_width.computed * scale); } + return bbox; } static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx) { SPFlowtext *group = SP_FLOWTEXT(item); + Geom::OptRect pbox, bbox, dbox; - NRRect pbox; - item->invoke_bbox( &pbox, Geom::identity(), TRUE); - NRRect bbox; - Geom::OptRect bbox_maybe = item->getBboxDesktop(); - if (!bbox_maybe) { - return; - } - bbox.x0 = bbox_maybe->min()[Geom::X]; - bbox.y0 = bbox_maybe->min()[Geom::Y]; - bbox.x1 = bbox_maybe->max()[Geom::X]; - bbox.y1 = bbox_maybe->max()[Geom::Y]; - - NRRect dbox; - dbox.x0 = 0.0; - dbox.y0 = 0.0; - dbox.x1 = item->document->getWidth(); - dbox.y1 = item->document->getHeight(); + pbox = item->geometricBounds(); + bbox = item->desktopVisualBounds(); + dbox = Geom::Rect::from_xywh(Geom::Point(0,0), item->document->getDimensions()); Geom::Affine const ctm (item->i2dt_affine()); - group->layout.print(ctx, &pbox, &dbox, &bbox, ctm); + group->layout.print(ctx, pbox, dbox, bbox, ctm); } @@ -417,9 +395,8 @@ sp_flowtext_show(SPItem *item, Inkscape::Drawing &drawing, unsigned/* key*/, uns flowed->setStyle(group->style); // pass the bbox of the flowtext object as paintbox (used for paintserver fills) - NRRect paintbox; - item->invoke_bbox( &paintbox, Geom::identity(), TRUE); - group->layout.show(flowed, &paintbox); + Geom::OptRect bbox = group->geometricBounds(); + group->layout.show(flowed, bbox); return flowed; } diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 5f398b10e..3ae2b6e63 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -80,7 +80,7 @@ static void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags); static void sp_image_modified (SPObject *object, unsigned int flags); static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_image_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_image_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_image_description (SPItem * item); static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); @@ -1062,21 +1062,16 @@ static Inkscape::XML::Node *sp_image_write( SPObject *object, Inkscape::XML::Doc return repr; } -static void sp_image_bbox( SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/ ) +static Geom::OptRect sp_image_bbox( SPItem const *item,Geom::Affine const &transform, SPItem::BBoxType type ) { SPImage const &image = *SP_IMAGE(item); + Geom::OptRect bbox; if ((image.width.computed > 0.0) && (image.height.computed > 0.0)) { - double const x0 = image.x.computed; - double const y0 = image.y.computed; - double const x1 = x0 + image.width.computed; - double const y1 = y0 + image.height.computed; - - nr_rect_union_pt(bbox, Geom::Point(x0, y0) * transform); - nr_rect_union_pt(bbox, Geom::Point(x1, y0) * transform); - nr_rect_union_pt(bbox, Geom::Point(x1, y1) * transform); - nr_rect_union_pt(bbox, Geom::Point(x0, y1) * transform); + bbox = Geom::Rect::from_xywh(image.x.computed, image.y.computed, image.width.computed, image.height.computed); + *bbox *= transform; } + return bbox; } static void sp_image_print( SPItem *item, SPPrintContext *ctx ) @@ -1499,10 +1494,8 @@ static void sp_image_set_curve( SPImage *image ) image->curve = image->curve->unref(); } } else { - NRRect rect; - sp_image_bbox(image, &rect, Geom::identity(), 0); - Geom::Rect rect2 = *to_2geom(&rect); - SPCurve *c = SPCurve::new_from_rect(rect2, true); + Geom::OptRect rect = sp_image_bbox(image, Geom::identity(), SPItem::VISUAL_BBOX); + SPCurve *c = SPCurve::new_from_rect(*rect, true); if (image->curve) { image->curve = image->curve->unref(); diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index f8ab0460a..ada980b3e 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -65,7 +65,7 @@ static void sp_group_modified (SPObject *object, guint flags); static Inkscape::XML::Node *sp_group_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static void sp_group_set(SPObject *object, unsigned key, char const *value); -static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_group_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_group_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_group_description (SPItem * item); static Inkscape::DrawingItem *sp_group_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); @@ -274,10 +274,10 @@ static Inkscape::XML::Node * sp_group_write(SPObject *object, Inkscape::XML::Doc return repr; } -static void -sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) +static Geom::OptRect +sp_group_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { - SP_GROUP(item)->group->calculateBBox(bbox, transform, flags); + return SP_GROUP(item)->group->bounds(type, transform); } static void @@ -696,9 +696,9 @@ void CGroup::onModified(guint flags) { } } -void CGroup::calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { - - Geom::OptRect dummy_bbox; +Geom::OptRect CGroup::bounds(SPItem::BBoxType type, Geom::Affine const &transform) +{ + Geom::OptRect bbox; GSList *l = _group->childList(false, SPObject::ActionBBox); while (l) { @@ -706,12 +706,11 @@ void CGroup::calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned if (SP_IS_ITEM(o) && !SP_ITEM(o)->isHidden()) { SPItem *child = SP_ITEM(o); Geom::Affine const ct(child->transform * transform); - child->invoke_bbox_full( dummy_bbox, ct, flags, FALSE); + bbox |= child->bounds(type, transform); } l = g_slist_remove (l, o); } - - *bbox = NRRect(dummy_bbox); + return bbox; } void CGroup::onPrint(SPPrintContext *ctx) { diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 99f375e44..f56192925 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -69,7 +69,7 @@ public: virtual void onChildRemoved(Inkscape::XML::Node *child); virtual void onUpdate(SPCtx *ctx, unsigned int flags); virtual void onModified(guint flags); - virtual void calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags); + virtual Geom::OptRect bounds(SPItem::BBoxType type, Geom::Affine const &transform); virtual void onPrint(SPPrintContext *ctx); virtual void onOrderChanged(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref); virtual gchar *getDescription(); diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp index 9f166e718..749a32d52 100644 --- a/src/sp-item-transform.cpp +++ b/src/sp-item-transform.cpp @@ -39,7 +39,7 @@ sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation) void sp_item_scale_rel (SPItem *item, Geom::Scale const &scale) { - Geom::OptRect bbox = item->getBboxDesktop(); + Geom::OptRect bbox = item->desktopVisualBounds(); if (bbox) { Geom::Translate const s(bbox->midpoint()); // use getCenter? item->set_i2d_affine(item->i2dt_affine() * s.inverse() * scale * s); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 07ce73c4b..a2a603c68 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -253,7 +253,7 @@ bool SPItem::isExplicitlyHidden() const * Sets the display CSS property to `hidden' if \a val is true, * otherwise makes it unset */ -void SPItem::setExplicitlyHidden(bool const val) { +void SPItem::setExplicitlyHidden(bool val) { style->display.set = val; style->display.value = ( val ? SP_CSS_DISPLAY_NONE : SP_CSS_DISPLAY_INLINE ); style->display.computed = style->display.value; @@ -263,17 +263,17 @@ void SPItem::setExplicitlyHidden(bool const val) { /** * Sets the transform_center_x and transform_center_y properties to retain the rotation centre */ -void SPItem::setCenter(Geom::Point object_centre) { - // for getBounds() to work +void SPItem::setCenter(Geom::Point const &object_centre) { document->ensureUpToDate(); - Geom::OptRect bbox = getBounds(i2dt_affine()); + // FIXME this is seriously wrong + Geom::OptRect bbox = desktopGeometricBounds(); if (bbox) { transform_center_x = object_centre[Geom::X] - bbox->midpoint()[Geom::X]; - if (fabs(transform_center_x) < 1e-5) // rounding error + if (Geom::are_near(transform_center_x, 0)) // rounding error transform_center_x = 0; transform_center_y = object_centre[Geom::Y] - bbox->midpoint()[Geom::Y]; - if (fabs(transform_center_y) < 1e-5) // rounding error + if (Geom::are_near(transform_center_y, 0)) // rounding error transform_center_y = 0; } } @@ -289,10 +289,10 @@ bool SPItem::isCenterSet() { } Geom::Point SPItem::getCenter() const { - // for getBounds() to work document->ensureUpToDate(); - Geom::OptRect bbox = getBounds(i2dt_affine()); + // FIXME this is seriously wrong + Geom::OptRect bbox = desktopGeometricBounds(); if (bbox) { return bbox->midpoint() + Geom::Point (transform_center_x, transform_center_y); } else { @@ -515,8 +515,7 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item) } } if (SP_IS_CLIPPATH(clip)) { - NRRect bbox; - item->invoke_bbox( &bbox, Geom::identity(), TRUE); + Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { if (!v->arenaitem->key()) { v->arenaitem->setKey(SPItem::display_key_new(3)); @@ -525,7 +524,7 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item) v->arenaitem->drawing(), v->arenaitem->key()); v->arenaitem->setClip(ai); - SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), &bbox); + SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), bbox); clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } @@ -540,8 +539,7 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item) } } if (SP_IS_MASK(mask)) { - NRRect bbox; - item->invoke_bbox( &bbox, Geom::identity(), TRUE); + Geom::OptRect bbox = item->geometricBounds(); for (SPItemView *v = item->display; v != NULL; v = v->next) { if (!v->arenaitem->key()) { v->arenaitem->setKey(SPItem::display_key_new(3)); @@ -550,7 +548,7 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item) v->arenaitem->drawing(), v->arenaitem->key()); v->arenaitem->setMask(ai); - sp_mask_set_bbox(SP_MASK(mask), v->arenaitem->key(), &bbox); + sp_mask_set_bbox(SP_MASK(mask), v->arenaitem->key(), bbox); mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } @@ -575,16 +573,15 @@ void SPItem::sp_item_update(SPObject *object, SPCtx *ctx, guint flags) SPMask *mask = item->mask_ref ? item->mask_ref->getObject() : NULL; if ( clip_path || mask ) { - NRRect bbox; - item->invoke_bbox( &bbox, Geom::identity(), TRUE); + Geom::OptRect bbox = item->geometricBounds(); if (clip_path) { for (SPItemView *v = item->display; v != NULL; v = v->next) { - clip_path->setBBox(v->arenaitem->key(), &bbox); + clip_path->setBBox(v->arenaitem->key(), bbox); } } if (mask) { for (SPItemView *v = item->display; v != NULL; v = v->next) { - sp_mask_set_bbox(mask, v->arenaitem->key(), &bbox); + sp_mask_set_bbox(mask, v->arenaitem->key(), bbox); } } } @@ -599,8 +596,7 @@ void SPItem::sp_item_update(SPObject *object, SPCtx *ctx, guint flags) /* Update bounding box data used by filters */ if (item->style->filter.set && item->display) { - Geom::OptRect item_bbox; - item->invoke_bbox( item_bbox, Geom::identity(), TRUE, SPItem::GEOMETRIC_BBOX); + Geom::OptRect item_bbox = item->geometricBounds(); SPItemView *itemview = item->display; do { @@ -677,169 +673,132 @@ Inkscape::XML::Node *SPItem::sp_item_write(SPObject *const object, Inkscape::XML return repr; } -/** - * \return There is no guarantee that the return value will contain a rectangle. - If this item does not have a boundingbox, it might well be empty. - */ -Geom::OptRect SPItem::getBounds(Geom::Affine const &transform, - SPItem::BBoxType type, - unsigned int /*dkey*/) const -{ - Geom::OptRect r; - invoke_bbox_full( r, transform, type, TRUE); - return r; -} - -void SPItem::invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type) -{ - invoke_bbox_full( bbox, transform, type, clear); -} - -// DEPRECATED to phase out the use of NRRect in favor of Geom::OptRect -void SPItem::invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type) +/** @brief Get item's geometric bounding box in this item's coordinate system. + * The geometric bounding box includes only the path, disregarding all style attributes. */ +Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const { - invoke_bbox_full( bbox, transform, type, clear); + Geom::OptRect bbox; + // call the subclass method + if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) { + bbox = ((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox(this, transform, SPItem::GEOMETRIC_BBOX); + } + return bbox; } -/** Calls \a item's subclass' bounding box method; clips it by the bbox of clippath, if any; and - * unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the - * transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups, - * clones), in turn, call this function in their bbox methods. - * \retval bbox Note that there is no guarantee that bbox will contain a rectangle when the - * function returns. If this item does not have a boundingbox, this might well be empty. - */ -void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const +/** @brief Get item's visual bounding box in this item's coordinate system. + * The visual bounding box includes the stroke and the filter region. */ +Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const { - if (clear) { - bbox = Geom::OptRect(); - } - - // TODO: replace NRRect by Geom::Rect, for all SPItemClasses, and for SP_CLIPPATH + using Geom::X; + using Geom::Y; - NRRect temp_bbox; - temp_bbox.x0 = temp_bbox.y0 = Geom::infinity(); - temp_bbox.x1 = temp_bbox.y1 = -Geom::infinity(); + Geom::OptRect bbox; - // call the subclass method - if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) { - ((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox(this, &temp_bbox, transform, flags); - } - - // unless this is geometric bbox, extend by filter area and crop the bbox by clip path, if any - if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) { - if ( style && style->filter.href) { - SPObject *filter = style->getFilter(); - if (filter && SP_IS_FILTER(filter)) { - // default filer area per the SVG spec: - double x = -0.1; - double y = -0.1; - double w = 1.2; - double h = 1.2; - - // if area is explicitly set, override: - if (SP_FILTER(filter)->x._set) - x = SP_FILTER(filter)->x.computed; - if (SP_FILTER(filter)->y._set) - y = SP_FILTER(filter)->y.computed; - if (SP_FILTER(filter)->width._set) - w = SP_FILTER(filter)->width.computed; - if (SP_FILTER(filter)->height._set) - h = SP_FILTER(filter)->height.computed; - - double dx0 = 0; - double dx1 = 0; - double dy0 = 0; - double dy1 = 0; - if (filter_is_single_gaussian_blur(SP_FILTER(filter))) { - // if this is a single blur, use 2.4*radius - // which may be smaller than the default area; - // see set_filter_area for why it's 2.4 - double r = get_single_gaussian_blur_radius (SP_FILTER(filter)); - dx0 = -2.4 * r; - dx1 = 2.4 * r; - dy0 = -2.4 * r; - dy1 = 2.4 * r; - } else { - // otherwise, calculate expansion from relative to absolute units: - dx0 = x * (temp_bbox.x1 - temp_bbox.x0); - dx1 = (w + x - 1) * (temp_bbox.x1 - temp_bbox.x0); - dy0 = y * (temp_bbox.y1 - temp_bbox.y0); - dy1 = (h + y - 1) * (temp_bbox.y1 - temp_bbox.y0); - } + if ( style && style->filter.href && style->getFilter() && SP_IS_FILTER(style->getFilter())) { + // call the subclass method + if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) { + bbox = ((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox(this, Geom::identity(), SPItem::VISUAL_BBOX); + } - // transform the expansions by the item's transform: - Geom::Affine i2dt(i2dt_affine ()); - dx0 *= i2dt.expansionX(); - dx1 *= i2dt.expansionX(); - dy0 *= i2dt.expansionY(); - dy1 *= i2dt.expansionY(); - - // expand the bbox - temp_bbox.x0 += dx0; - temp_bbox.x1 += dx1; - temp_bbox.y0 += dy0; - temp_bbox.y1 += dy1; - } + SPFilter *filter = SP_FILTER(style->getFilter()); + // default filer area per the SVG spec: + SVGLength x, y, w, h; + Geom::Point minp, maxp; + x.set(SVGLength::PERCENT, -0.10, 0); + y.set(SVGLength::PERCENT, -0.10, 0); + w.set(SVGLength::PERCENT, 1.20, 0); + h.set(SVGLength::PERCENT, 1.20, 0); + + // if area is explicitly set, override: + if (filter->x._set) + x = filter->x; + if (filter->y._set) + y = filter->y; + if (filter->width._set) + w = filter->width; + if (filter->height._set) + h = filter->height; + + double len_x = bbox ? bbox->width() : 0; + double len_y = bbox ? bbox->height() : 0; + + x.update(12, 6, len_x); + y.update(12, 6, len_y); + w.update(12, 6, len_x); + h.update(12, 6, len_y); + + if (filter->filterUnits == SP_FILTER_UNITS_OBJECTBOUNDINGBOX && bbox) { + minp[X] = bbox->left() + x.computed * (x.unit == SVGLength::PERCENT ? 1.0 : len_x); + maxp[X] = minp[X] + w.computed * (w.unit == SVGLength::PERCENT ? 1.0 : len_x); + minp[Y] = bbox->top() + y.computed * (y.unit == SVGLength::PERCENT ? 1.0 : len_y); + maxp[Y] = minp[Y] + h.computed * (h.unit == SVGLength::PERCENT ? 1.0 : len_y); + } else if (filter->filterUnits == SP_FILTER_UNITS_USERSPACEONUSE) { + minp[X] = x.computed; + maxp[X] = minp[X] + w.computed; + minp[Y] = y.computed; + maxp[Y] = minp[Y] + h.computed; } - if (clip_ref->getObject()) { - NRRect b; - SP_CLIPPATH(clip_ref->getObject())->getBBox(&b, transform, flags); - nr_rect_d_intersect (&temp_bbox, &temp_bbox, &b); + bbox = Geom::OptRect(minp, maxp); + *bbox *= transform; + } else { + // call the subclass method + if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) { + bbox = ((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox(this, transform, SPItem::VISUAL_BBOX); } } - - if (temp_bbox.x0 > temp_bbox.x1 || temp_bbox.y0 > temp_bbox.y1) { - // Either the bbox hasn't been touched by the SPItemClass' bbox method - // (it still has its initial values, see above: x0 = y0 = Geom::infinity() and x1 = y1 = -Geom::infinity()) - // or it has explicitely been set to be like this (e.g. in sp_shape_bbox) - - // 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 Geom::OptRect) - // So union bbox with nothing = do nothing, just return - return; + if (clip_ref->getObject()) { + bbox.intersectWith(SP_CLIPPATH(clip_ref->getObject())->geometricBounds(transform)); } - // Do not use temp_bbox.upgrade() here, because it uses a test that returns an empty Geom::OptRect() - // for any rectangle with zero area. The geometrical bbox of for example a vertical line - // would therefore be translated into empty Geom::OptRect() (see bug https://bugs.launchpad.net/inkscape/+bug/168684) - Geom::OptRect temp_bbox_new = Geom::Rect(Geom::Point(temp_bbox.x0, temp_bbox.y0), Geom::Point(temp_bbox.x1, temp_bbox.y1)); - - bbox.unionWith(temp_bbox_new); + return bbox; } - -// DEPRECATED to phase out the use of NRRect in favor of Geom::OptRect -/** Calls \a item's subclass' bounding box method; clips it by the bbox of clippath, if any; and - * unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the - * transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups, - * clones), in turn, call this function in their bbox methods. */ -void SPItem::invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) +Geom::OptRect SPItem::bounds(BBoxType type, Geom::Affine const &transform) const { - g_assert(bbox != NULL); - - if (clear) { - bbox->x0 = bbox->y0 = 1e18; - bbox->x1 = bbox->y1 = -1e18; - } - - NRRect this_bbox; - this_bbox.x0 = this_bbox.y0 = 1e18; - this_bbox.x1 = this_bbox.y1 = -1e18; - - // call the subclass method - if (((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox) { - ((SPItemClass *) G_OBJECT_GET_CLASS(this))->bbox(this, &this_bbox, transform, flags); + if (type == GEOMETRIC_BBOX) { + return geometricBounds(transform); + } else { + return visualBounds(transform); } +} - // unless this is geometric bbox, crop the bbox by clip path, if any - if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX && clip_ref->getObject()) { - NRRect b; - SP_CLIPPATH(clip_ref->getObject())->getBBox(&b, transform, flags); - nr_rect_d_intersect (&this_bbox, &this_bbox, &b); +/** Get item's geometric bbox in document coordinate system. + * Document coordinates are the default coordinates of the root element: + * the origin is at the top left, X grows to the right and Y grows downwards. */ +Geom::OptRect SPItem::documentGeometricBounds() const +{ + return geometricBounds(i2doc_affine()); +} +/// Get item's visual bbox in document coordinate system. +Geom::OptRect SPItem::documentVisualBounds() const +{ + return visualBounds(i2doc_affine()); +} +Geom::OptRect SPItem::documentBounds(BBoxType type) const +{ + if (type == GEOMETRIC_BBOX) { + return documentGeometricBounds(); + } else { + return documentVisualBounds(); } - - // if non-empty (with some tolerance - ?) union this_bbox with the bbox we've got passed - if ( fabs(this_bbox.x1-this_bbox.x0) > -0.00001 && fabs(this_bbox.y1-this_bbox.y0) > -0.00001 ) { - nr_rect_d_union (bbox, bbox, &this_bbox); +} +/** Get item's geometric bbox in desktop coordinate system. + * Desktop coordinates should be user defined. Currently they are hardcoded: + * origin is at bottom left, X grows to the right and Y grows upwards. */ +Geom::OptRect SPItem::desktopGeometricBounds() const +{ + return geometricBounds(i2dt_affine()); +} +/// Get item's visual bbox in desktop coordinate system. +Geom::OptRect SPItem::desktopVisualBounds() const +{ + return visualBounds(i2dt_affine()); +} +Geom::OptRect SPItem::desktopBounds(BBoxType type) const +{ + if (type == GEOMETRIC_BBOX) { + return desktopGeometricBounds(); + } else { + return desktopVisualBounds(); } } @@ -864,20 +823,6 @@ unsigned SPItem::pos_in_parent() return 0; } -void SPItem::getBboxDesktop(NRRect *bbox, SPItem::BBoxType type) -{ - g_assert(bbox != NULL); - - invoke_bbox( bbox, i2dt_affine(), TRUE, type); -} - -Geom::OptRect SPItem::getBboxDesktop(SPItem::BBoxType type) -{ - Geom::OptRect rect = Geom::OptRect(); - invoke_bbox( rect, i2dt_affine(), TRUE, type); - return rect; -} - void SPItem::sp_item_private_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { /* This will only be called if the derived class doesn't override this. @@ -1011,6 +956,8 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned } if (ai != NULL) { + Geom::OptRect item_bbox = geometricBounds(); + display = sp_item_view_new_prepend(display, this, flags, key, ai); ai->setTransform(transform); ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value)); @@ -1029,9 +976,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned ai->setClip(ac); // Update bbox, in case the clip uses bbox units - NRRect bbox; - invoke_bbox( &bbox, Geom::identity(), TRUE); - SP_CLIPPATH(cp)->setBBox(clip_key, &bbox); + SP_CLIPPATH(cp)->setBBox(clip_key, item_bbox); cp->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } if (mask_ref->getObject()) { @@ -1047,14 +992,10 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned ai->setMask(ac); // Update bbox, in case the mask uses bbox units - NRRect bbox; - invoke_bbox( &bbox, Geom::identity(), TRUE); - sp_mask_set_bbox(SP_MASK(mask), mask_key, &bbox); + sp_mask_set_bbox(SP_MASK(mask), mask_key, item_bbox); mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } ai->setData(this); - Geom::OptRect item_bbox; - invoke_bbox( item_bbox, Geom::identity(), TRUE, SPItem::GEOMETRIC_BBOX); ai->setItemBounds(item_bbox); } @@ -1544,10 +1485,8 @@ SPItem *sp_item_first_item_child(SPObject *obj) void SPItem::convert_to_guides() { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int prefs_bbox = prefs->getInt("/tools/bounding_box", 0); - SPItem::BBoxType bbox_type = (prefs_bbox ==0)? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; - Geom::OptRect bbox = getBboxDesktop(bbox_type); + Geom::OptRect bbox = (prefs_bbox == 0) ? desktopVisualBounds() : desktopGeometricBounds(); if (!bbox) { g_warning ("Cannot determine item's bounding box during conversion to guides.\n"); return; diff --git a/src/sp-item.h b/src/sp-item.h index 633deb508..62336e3c8 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -112,7 +112,7 @@ public: // includes only the bare path bbox, no stroke, no nothing GEOMETRIC_BBOX, // includes everything: correctly done stroke (with proper miters and caps), markers, filter margins (e.g. blur) - RENDERING_BBOX + VISUAL_BBOX }; unsigned int sensitive : 1; @@ -151,7 +151,7 @@ public: void setExplicitlyHidden(bool val); - void setCenter(Geom::Point object_centre); + void setCenter(Geom::Point const &object_centre); void unsetCenter(); bool isCenterSet(); Geom::Point getCenter() const; @@ -167,15 +167,19 @@ public: void raiseToTop(); void lowerToBottom(); - Geom::OptRect getBounds(Geom::Affine const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const; - sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) { return _transformed_signal.connect(slot); } - void invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); - void invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); - void invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const; - void invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated)); + + Geom::OptRect geometricBounds(Geom::Affine const &transform = Geom::identity()) const; + Geom::OptRect visualBounds(Geom::Affine const &transform = Geom::identity()) const; + Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform = Geom::identity()) const; + Geom::OptRect documentGeometricBounds() const; + Geom::OptRect documentVisualBounds() const; + Geom::OptRect documentBounds(BBoxType type) const; + Geom::OptRect desktopGeometricBounds() const; + Geom::OptRect desktopVisualBounds() const; + Geom::OptRect desktopBounds(BBoxType type) const; unsigned pos_in_parent(); gchar *description(); @@ -195,8 +199,7 @@ public: void convert_item_to_guides(); gint emitEvent (SPEvent &event); Inkscape::DrawingItem *get_arenaitem(unsigned int key); - void getBboxDesktop(NRRect *bbox, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); - Geom::OptRect getBboxDesktop(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + Geom::Affine i2doc_affine() const; Geom::Affine i2dt_affine() const; void set_i2d_affine(Geom::Affine const &transform); @@ -237,7 +240,7 @@ public: SPObjectClass parent_class; /** BBox union in given coordinate system */ - void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); + Geom::OptRect (* bbox) (SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); /** Printing method. Assumes ctm is set to item affine matrix */ /* \todo Think about it, and maybe implement generic export method instead (Lauris) */ diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index f23172a17..f955e5428 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -31,7 +31,7 @@ struct SPMaskView { SPMaskView *next; unsigned int key; Inkscape::DrawingItem *arenaitem; - NRRect bbox; + Geom::OptRect bbox; }; static void sp_mask_class_init (SPMaskClass *klass); @@ -216,10 +216,9 @@ static void sp_mask_update(SPObject *object, SPCtx *ctx, guint flags) SPMask *mask = SP_MASK(object); for (SPMaskView *v = mask->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); - t[4] = v->bbox.x0; - t[5] = v->bbox.y0; + if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX && v->bbox) { + Geom::Affine t = Geom::Scale(v->bbox->dimensions()); + t.setTranslation(v->bbox->min()); g->setChildTransform(t); } else { g->setChildTransform(Geom::identity()); @@ -314,11 +313,10 @@ Inkscape::DrawingItem *sp_mask_show(SPMask *mask, Inkscape::Drawing &drawing, un } } - if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Affine t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0)); - t[4] = mask->display->bbox.x0; - t[5] = mask->display->bbox.y0; - ai->setChildTransform(t); + if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX && mask->display->bbox) { + Geom::Affine t = Geom::Scale(mask->display->bbox->dimensions()); + t.setTranslation(mask->display->bbox->min()); + ai->setChildTransform(t); } return ai; @@ -347,17 +345,12 @@ void sp_mask_hide(SPMask *cp, unsigned int key) } void -sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox) +sp_mask_set_bbox (SPMask *mask, unsigned int key, Geom::OptRect const &bbox) { for (SPMaskView *v = mask->display; v != NULL; v = v->next) { if (v->key == key) { - if (!Geom::are_near(v->bbox.x0, bbox->x0) || - !Geom::are_near(v->bbox.y0, bbox->y0) || - !Geom::are_near(v->bbox.x1, bbox->x1) || - !Geom::are_near(v->bbox.y1, bbox->y1)) { - v->bbox = *bbox; - } - break; + v->bbox = bbox; + break; } } } @@ -372,8 +365,7 @@ sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, Inkscape::DrawingI new_mask_view->next = list; new_mask_view->key = key; new_mask_view->arenaitem = arenaitem; - new_mask_view->bbox.x0 = new_mask_view->bbox.x1 = 0.0; - new_mask_view->bbox.y0 = new_mask_view->bbox.y1 = 0.0; + new_mask_view->bbox = Geom::OptRect(); return new_mask_view; } diff --git a/src/sp-mask.h b/src/sp-mask.h index b1048e6be..d493c2dc7 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -13,6 +13,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <2geom/rect.h> +#include "display/display-forward.h" +#include "libnr/nr-forward.h" +#include "sp-object-group.h" +#include "uri-references.h" +#include "xml/node.h" + #define SP_TYPE_MASK (sp_mask_get_type ()) #define SP_MASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_MASK, SPMask)) #define SP_MASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_MASK, SPMaskClass)) @@ -23,12 +30,6 @@ class SPMask; class SPMaskClass; class SPMaskView; -#include "display/display-forward.h" -#include "libnr/nr-forward.h" -#include "sp-object-group.h" -#include "uri-references.h" -#include "xml/node.h" - struct SPMask : public SPObjectGroup { unsigned int maskUnits_set : 1; unsigned int maskUnits : 1; @@ -93,7 +94,7 @@ protected: Inkscape::DrawingItem *sp_mask_show (SPMask *mask, Inkscape::Drawing &drawing, unsigned int key); void sp_mask_hide (SPMask *mask, unsigned int key); -void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox); +void sp_mask_set_bbox (SPMask *mask, unsigned int key, Geom::OptRect const &bbox); const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index 5187ff027..8617c096a 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -514,7 +514,7 @@ sp_offset_set_shape(SPShape *shape) theRes->ConvertToForme (orig, 1, originaux); SPItem *item = shape; - Geom::OptRect bbox = item->getBboxDesktop (); + Geom::OptRect bbox = item->desktopVisualBounds(); if ( bbox ) { gdouble size = L2(bbox->dimensions()); gdouble const exp = item->transform.descrim(); diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 4fd1deb69..15fa76d65 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -502,212 +502,158 @@ void SPShape::sp_shape_modified(SPObject *object, unsigned int flags) * Calculates the bounding box for item, storing it into bbox. * This also includes the bounding boxes of any markers included in the shape. */ -void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) +Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType bboxtype) { SPShape const *shape = SP_SHAPE (item); - SPItem::BBoxType bboxtype = (SPItem::BBoxType) flags; - - if (shape->curve) { - Geom::OptRect geombbox = bounds_exact_transformed(shape->curve->get_pathvector(), transform); - if (geombbox) { - NRRect cbbox; - cbbox.x0 = (*geombbox)[0][0]; - cbbox.y0 = (*geombbox)[1][0]; - cbbox.x1 = (*geombbox)[0][1]; - cbbox.y1 = (*geombbox)[1][1]; - - switch (bboxtype) { - case SPItem::GEOMETRIC_BBOX: { - // do nothing - break; - } - case SPItem::RENDERING_BBOX: { - // convert the stroke to a path and calculate that path's geometric bbox - SPStyle* style = item->style; - if (!style->stroke.isNone()) { - Geom::PathVector *pathv = item_outline(item); - if (pathv) { - Geom::OptRect geomstrokebbox = bounds_exact_transformed(*pathv, transform); - if (geomstrokebbox) { - NRRect strokebbox; - strokebbox.x0 = (*geomstrokebbox)[0][0]; - strokebbox.y0 = (*geomstrokebbox)[1][0]; - strokebbox.x1 = (*geomstrokebbox)[0][1]; - strokebbox.y1 = (*geomstrokebbox)[1][1]; - nr_rect_d_union (&cbbox, &cbbox, &strokebbox); - } - delete pathv; + Geom::OptRect bbox; + + if (!shape->curve) return bbox; + bbox = bounds_exact_transformed(shape->curve->get_pathvector(), transform); + if (!bbox) return bbox; + + if (bboxtype == SPItem::VISUAL_BBOX) { + // convert the stroke to a path and calculate that path's geometric bbox + SPStyle* style = item->style; + if (!style->stroke.isNone()) { + Geom::PathVector *pathv = item_outline(item); + if (pathv) { + bbox |= bounds_exact_transformed(*pathv, transform); + delete pathv; + } + } + // Union with bboxes of the markers, if any + if ( shape->hasMarkers() && !shape->curve->get_pathvector().empty() ) { + /** \todo make code prettier! */ + Geom::PathVector const & pathv = shape->curve->get_pathvector(); + // START marker + for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (shape->marker[i]); + SPItem* marker_item = sp_item_first_item_child( marker ); + + if (marker_item) { + Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; } + + // total marker transform + tr = marker_item->transform * marker->c2p * tr * transform; + + // get bbox of the marker with that transform + bbox |= marker_item->visualBounds(tr); } - break; } - default: - case SPItem::APPROXIMATE_BBOX: { - SPStyle* style = item->style; - 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(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) { - cbbox.x0-=0.5*width; - cbbox.x1+=0.5*width; - cbbox.y0-=0.5*width; - cbbox.y1+=0.5*width; - } + } + // MID marker + for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID + SPMarker* marker = SP_MARKER (shape->marker[i]); + if ( !shape->marker[i] ) continue; + SPItem* marker_item = sp_item_first_item_child( marker ); + if ( !marker_item ) continue; + + for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { + // START position + if ( path_it != pathv.begin() + && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there + { + Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } + tr = marker_item->transform * marker->c2p * tr * transform; + bbox |= marker_item->visualBounds(tr); } + // MID position + if ( path_it->size_default() > 1) { + Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve + Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve + while (curve_it2 != path_it->end_default()) + { + /* Put marker between curve_it1 and curve_it2. + * Loop to end_default (so including closing segment), because when a path is closed, + * there should be a midpoint marker between last segment and closing straight line segment */ - // Union with bboxes of the markers, if any - if ( shape->hasMarkers() && !shape->curve->get_pathvector().empty() ) { - /** \todo make code prettier! */ - Geom::PathVector const & pathv = shape->curve->get_pathvector(); - // START marker - for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START - if ( shape->marker[i] ) { - SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child( marker ); - - if (marker_item) { - Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - - // total marker transform - tr = marker_item->transform * marker->c2p * tr * transform; - - // get bbox of the marker with that transform - NRRect marker_bbox; - marker_item->invoke_bbox ( &marker_bbox, tr, true); - // union it with the shape bbox - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); - } - } - } - // MID marker - for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID SPMarker* marker = SP_MARKER (shape->marker[i]); - if ( !shape->marker[i] ) continue; SPItem* marker_item = sp_item_first_item_child( marker ); - if ( !marker_item ) continue; - - for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { - // START position - if ( path_it != pathv.begin() - && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there - { - Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - marker_item->invoke_bbox ( &marker_bbox, tr, true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); - } - // MID position - if ( path_it->size_default() > 1) { - Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - while (curve_it2 != path_it->end_default()) - { - /* Put marker between curve_it1 and curve_it2. - * Loop to end_default (so including closing segment), because when a path is closed, - * there should be a midpoint marker between last segment and closing straight line segment */ - - SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child( marker ); - - if (marker_item) { - Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - marker_item->invoke_bbox ( &marker_bbox, tr, true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); - } - - ++curve_it1; - ++curve_it2; - } + + if (marker_item) { + Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); } - // END position - if ( path_it != (pathv.end()-1) && !path_it->empty()) { - Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - tr = marker_item->transform * marker->c2p * tr * transform; - NRRect marker_bbox; - marker_item->invoke_bbox ( &marker_bbox, tr, true); - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; } + tr = marker_item->transform * marker->c2p * tr * transform; + bbox |= marker_item->visualBounds(tr); } + + ++curve_it1; + ++curve_it2; } - // END marker - for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END - if ( shape->marker[i] ) { - SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child( marker ); - - if (marker_item) { - /* Get reference to last curve in the path. - * For moveto-only path, this returns the "closing line segment". */ - Geom::Path const &path_last = pathv.back(); - unsigned int index = path_last.size_default(); - if (index > 0) { - index--; - } - Geom::Curve const &lastcurve = path_last[index]; - - Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); - if (!marker->orient_auto) { - Geom::Point transl = tr.translation(); - tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); - } - if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { - tr = Geom::Scale(style->stroke_width.computed) * tr; - } - - // total marker transform - tr = marker_item->transform * marker->c2p * tr * transform; - - // get bbox of the marker with that transform - NRRect marker_bbox; - marker_item->invoke_bbox ( &marker_bbox, tr, true); - // union it with the shape bbox - nr_rect_d_union (&cbbox, &cbbox, &marker_bbox); - } - } + } + // END position + if ( path_it != (pathv.end()-1) && !path_it->empty()) { + Geom::Curve const &lastcurve = path_it->back_default(); + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; } + tr = marker_item->transform * marker->c2p * tr * transform; + bbox |= marker_item->visualBounds(); } - break; - } // end case approximate bbox type - } // end switch bboxtype + } + } + // END marker + for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END + if ( shape->marker[i] ) { + SPMarker* marker = SP_MARKER (shape->marker[i]); + SPItem* marker_item = sp_item_first_item_child( marker ); + + if (marker_item) { + /* Get reference to last curve in the path. + * For moveto-only path, this returns the "closing line segment". */ + Geom::Path const &path_last = pathv.back(); + unsigned int index = path_last.size_default(); + if (index > 0) { + index--; + } + Geom::Curve const &lastcurve = path_last[index]; + + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); + if (!marker->orient_auto) { + Geom::Point transl = tr.translation(); + tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); + } + if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { + tr = Geom::Scale(style->stroke_width.computed) * tr; + } - // copy our bbox to the variable we're given - *bbox = cbbox; + // total marker transform + tr = marker_item->transform * marker->c2p * tr * transform; + + // get bbox of the marker with that transform + bbox |= marker_item->visualBounds(tr); + } + } + } } } + return bbox; } static void @@ -736,7 +682,7 @@ sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Affine tr, SPStyle* s void sp_shape_print (SPItem *item, SPPrintContext *ctx) { - NRRect pbox, dbox, bbox; + Geom::OptRect pbox, dbox, bbox; SPShape *shape = SP_SHAPE(item); @@ -755,22 +701,19 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) } /* fixme: Think (Lauris) */ - item->invoke_bbox( &pbox, Geom::identity(), TRUE); - dbox.x0 = 0.0; - dbox.y0 = 0.0; - dbox.x1 = item->document->getWidth(); - dbox.y1 = item->document->getHeight(); - item->getBboxDesktop (&bbox); + pbox = item->geometricBounds(); + bbox = item->desktopVisualBounds(); + dbox = Geom::Rect::from_xywh(Geom::Point(0,0), item->document->getDimensions()); Geom::Affine const i2dt(item->i2dt_affine()); SPStyle* style = item->style; if (!style->fill.isNone()) { - sp_print_fill (ctx, pathv, &i2dt, style, &pbox, &dbox, &bbox); + sp_print_fill (ctx, pathv, &i2dt, style, pbox, dbox, bbox); } if (!style->stroke.isNone()) { - sp_print_stroke (ctx, pathv, &i2dt, style, &pbox, &dbox, &bbox); + sp_print_stroke (ctx, pathv, &i2dt, style, pbox, dbox, bbox); } /** \todo make code prettier */ @@ -1184,7 +1127,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap Geom::Affine const i2dt (item->i2dt_affine ()); if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_OBJECT_MIDPOINT)) { - Geom::OptRect bbox = item->getBounds(i2dt); + Geom::OptRect bbox = item->desktopVisualBounds(); if (bbox) { p.push_back(Inkscape::SnapCandidatePoint(bbox->midpoint(), Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); } diff --git a/src/sp-shape.h b/src/sp-shape.h index 355d8e7cc..06bd704ad 100644 --- a/src/sp-shape.h +++ b/src/sp-shape.h @@ -66,7 +66,7 @@ private: static void sp_shape_modified (SPObject *object, unsigned int flags); static Inkscape::XML::Node *sp_shape_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); - static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); + static Geom::OptRect sp_shape_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static Inkscape::DrawingItem *sp_shape_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); static void sp_shape_hide (SPItem *item, unsigned int key); static void sp_shape_snappoints (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp index bee28f8e3..71de619c1 100644 --- a/src/sp-symbol.cpp +++ b/src/sp-symbol.cpp @@ -39,7 +39,7 @@ static Inkscape::XML::Node *sp_symbol_write (SPObject *object, Inkscape::XML::Do static Inkscape::DrawingItem *sp_symbol_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); static void sp_symbol_hide (SPItem *item, unsigned int key); -static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_symbol_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_symbol_print (SPItem *item, SPPrintContext *ctx); static SPGroupClass *parent_class; @@ -399,18 +399,20 @@ static void sp_symbol_hide(SPItem *item, unsigned int key) } } -static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) +static Geom::OptRect sp_symbol_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { SPSymbol const *symbol = SP_SYMBOL(item); + Geom::OptRect bbox; if (symbol->cloned) { // Cloned <symbol> is actually renderable if (((SPItemClass *) (parent_class))->bbox) { Geom::Affine const a( symbol->c2p * transform ); - ((SPItemClass *) (parent_class))->bbox(item, bbox, a, flags); + bbox = ((SPItemClass *) (parent_class))->bbox(item, a, type); } } + return bbox; } static void sp_symbol_print(SPItem *item, SPPrintContext *ctx) diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 9bb674843..fc248824d 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -71,7 +71,7 @@ static void sp_text_update (SPObject *object, SPCtx *ctx, guint flags); static void sp_text_modified (SPObject *object, guint flags); static Inkscape::XML::Node *sp_text_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_text_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static Inkscape::DrawingItem *sp_text_show (SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags); static void sp_text_hide (SPItem *item, unsigned key); static char *sp_text_description (SPItem *item); @@ -248,14 +248,13 @@ static void sp_text_update(SPObject *object, SPCtx *ctx, guint flags) /* fixme: So check modification flag everywhere immediate state is used */ text->rebuildLayout(); - NRRect paintbox; - text->invoke_bbox( &paintbox, Geom::identity(), TRUE); + Geom::OptRect paintbox = text->geometricBounds(); for (SPItemView* v = text->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); text->_clearFlow(g); g->setStyle(object->style); // pass the bbox of the text object as paintbox (used for paintserver fills) - text->layout.show(g, &paintbox); + text->layout.show(g, paintbox); } } } @@ -277,13 +276,12 @@ static void sp_text_modified(SPObject *object, guint flags) // and create new ones. This is probably quite wasteful. if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) { SPText *text = SP_TEXT (object); - NRRect paintbox; - text->invoke_bbox( &paintbox, Geom::identity(), TRUE); + Geom::OptRect paintbox = text->geometricBounds(); for (SPItemView* v = text->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); text->_clearFlow(g); g->setStyle(object->style); - text->layout.show(g, &paintbox); + text->layout.show(g, paintbox); } } @@ -363,25 +361,17 @@ static Inkscape::XML::Node *sp_text_write(SPObject *object, Inkscape::XML::Docum return repr; } -static void -sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) +static Geom::OptRect +sp_text_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { - SP_TEXT(item)->layout.getBoundingBox(bbox, transform); - - // Add stroke width - SPStyle* style = item->style; - 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 ) { - bbox->x0-=0.5*width; - bbox->x1+=0.5*width; - bbox->y0-=0.5*width; - bbox->y1+=0.5*width; - } - } + Geom::OptRect bbox = SP_TEXT(item)->layout.bounds(transform); + + // FIXME this code is incorrect + if (type == SPItem::VISUAL_BBOX && !item->style->stroke.isNone()) { + double scale = transform.descrim(); + bbox->expandBy(0.5 * item->style->stroke_width.computed * scale); } + return bbox; } @@ -395,9 +385,7 @@ sp_text_show(SPItem *item, Inkscape::Drawing &drawing, unsigned /* key*/, unsign flowed->setStyle(group->style); // pass the bbox of the text object as paintbox (used for paintserver fills) - NRRect paintbox; - item->invoke_bbox( &paintbox, Geom::identity(), TRUE); - group->layout.show(flowed, &paintbox); + group->layout.show(flowed, group->geometricBounds()); return flowed; } @@ -509,18 +497,15 @@ sp_text_set_transform (SPItem *item, Geom::Affine const &xform) static void sp_text_print (SPItem *item, SPPrintContext *ctx) { - NRRect pbox, dbox, bbox; SPText *group = SP_TEXT (item); + Geom::OptRect pbox, bbox, dbox; - item->invoke_bbox( &pbox, Geom::identity(), TRUE); - item->getBboxDesktop (&bbox); - dbox.x0 = 0.0; - dbox.y0 = 0.0; - dbox.x1 = item->document->getWidth(); - dbox.y1 = item->document->getHeight(); + pbox = item->geometricBounds(); + bbox = item->desktopVisualBounds(); + dbox = Geom::Rect::from_xywh(Geom::Point(0,0), item->document->getDimensions()); Geom::Affine const ctm (item->i2dt_affine()); - group->layout.print(ctx,&pbox,&dbox,&bbox,ctm); + group->layout.print(ctx,pbox,dbox,bbox,ctm); } /* diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index dcf46f6ac..ac20ce098 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -63,7 +63,7 @@ static void sp_tref_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_tref_modified(SPObject *object, guint flags); static Inkscape::XML::Node *sp_tref_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_tref_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static gchar *sp_tref_description(SPItem *item); static void sp_tref_href_changed(SPObject *old_ref, SPObject *ref, SPTRef *tref); @@ -314,39 +314,33 @@ sp_tref_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML: return repr; } -/** +/* * The code for this function is swiped from the tspan bbox code, since tref should work pretty much the same way */ -static void -sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) +static Geom::OptRect +sp_tref_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { + Geom::OptRect bbox; // find out the ancestor text which holds our layout SPObject const *parent_text = item; while ( parent_text && !SP_IS_TEXT(parent_text) ) { parent_text = parent_text->parent; } if (parent_text == NULL) { - return; + return bbox; } // get the bbox of our portion of the layout - SP_TEXT(parent_text)->layout.getBoundingBox( - bbox, transform, sp_text_get_length_upto(parent_text, item), sp_text_get_length_upto(item, NULL) - 1); + bbox = SP_TEXT(parent_text)->layout.bounds(transform, + sp_text_get_length_upto(parent_text, item), sp_text_get_length_upto(item, NULL) - 1); // Add stroke width - SPStyle* style = item->style; - 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 ) { - bbox->x0-=0.5*width; - bbox->x1+=0.5*width; - bbox->y0-=0.5*width; - bbox->y1+=0.5*width; - } - } + // FIXME this code is incorrect + if (type == SPItem::VISUAL_BBOX && !item->style->stroke.isNone()) { + double scale = transform.descrim(); + bbox->expandBy(0.5 * item->style->stroke_width.computed * scale); } + return bbox; } diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp index 199d82e1b..f4e79f7d5 100644 --- a/src/sp-tspan.cpp +++ b/src/sp-tspan.cpp @@ -56,7 +56,7 @@ static void sp_tspan_release(SPObject *object); static void sp_tspan_set(SPObject *object, unsigned key, gchar const *value); static void sp_tspan_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_tspan_modified(SPObject *object, unsigned flags); -static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_tspan_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static Inkscape::XML::Node *sp_tspan_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static char *sp_tspan_description (SPItem *item); @@ -203,34 +203,30 @@ static void sp_tspan_modified(SPObject *object, unsigned flags) } } -static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) +static Geom::OptRect +sp_tspan_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { + Geom::OptRect bbox; // find out the ancestor text which holds our layout SPObject const *parent_text = item; while (parent_text && !SP_IS_TEXT(parent_text)) { parent_text = parent_text->parent; } if (parent_text == NULL) { - return; + return bbox; } // get the bbox of our portion of the layout - SP_TEXT(parent_text)->layout.getBoundingBox(bbox, transform, sp_text_get_length_upto(parent_text, item), sp_text_get_length_upto(item, NULL) - 1); + bbox = SP_TEXT(parent_text)->layout.bounds(transform, sp_text_get_length_upto(parent_text, item), sp_text_get_length_upto(item, NULL) - 1); + if (!bbox) return bbox; // Add stroke width - SPStyle* style = item->style; - 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 ) { - bbox->x0-=0.5*width; - bbox->x1+=0.5*width; - bbox->y0-=0.5*width; - bbox->y1+=0.5*width; - } - } + // FIXME this code is incorrect + if (type == SPItem::VISUAL_BBOX && !item->style->stroke.isNone()) { + double scale = transform.descrim(); + bbox->expandBy(0.5 * item->style->stroke_width.computed * scale); } + return bbox; } static Inkscape::XML::Node * @@ -592,8 +588,7 @@ sp_textpath_to_text(SPObject *tp) { SPObject *text = tp->parent; - Geom::OptRect bbox; - SP_ITEM(text)->invoke_bbox(bbox, SP_ITEM(text)->i2doc_affine(), TRUE); + Geom::OptRect bbox = SP_ITEM(text)->geometricBounds(SP_ITEM(text)->i2doc_affine()); if (!bbox) return; Geom::Point xy = bbox->min(); diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 89df9130d..057c01ef1 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -49,7 +49,7 @@ static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Docume static void sp_use_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_use_modified(SPObject *object, guint flags); -static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); +static Geom::OptRect sp_use_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); static void sp_use_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); static void sp_use_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_use_description(SPItem *item); @@ -276,10 +276,11 @@ sp_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:: return repr; } -static void -sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) +static Geom::OptRect +sp_use_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) { SPUse const *use = SP_USE(item); + Geom::OptRect bbox; if (use->child && SP_IS_ITEM(use->child)) { SPItem *child = SP_ITEM(use->child); @@ -287,15 +288,9 @@ sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, uns * Geom::Translate(use->x.computed, use->y.computed) * transform ); - Geom::OptRect optbbox; - child->invoke_bbox_full( optbbox, ct, flags, FALSE); - if (optbbox) { - bbox->x0 = (*optbbox)[0][0]; - bbox->y0 = (*optbbox)[1][0]; - bbox->x1 = (*optbbox)[0][1]; - bbox->y1 = (*optbbox)[1][1]; - } + bbox = child->bounds(type, ct); } + return bbox; } static void diff --git a/src/splivarot.cpp b/src/splivarot.cpp index d3d6c3db7..28d6f90be 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -1942,7 +1942,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop, bool didSomething = false; - Geom::OptRect selectionBbox = selection->bounds(); + Geom::OptRect selectionBbox = selection->visualBounds(); if (!selectionBbox) { return false; } @@ -1963,7 +1963,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop, continue; if (simplifyIndividualPaths) { - Geom::OptRect itemBbox = item->getBounds(item->i2dt_affine()); + Geom::OptRect itemBbox = item->desktopVisualBounds(); if (itemBbox) { simplifySize = L2(itemBbox->dimensions()); } else { diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 33fffb01f..68b71b21f 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -444,7 +444,7 @@ bool sp_spray_recursive(SPDesktop *desktop, dr=dr*radius; if (mode == SPRAY_MODE_COPY) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { SPItem *item_copied; if(_fid <= population) @@ -496,7 +496,7 @@ bool sp_spray_recursive(SPDesktop *desktop, Inkscape::XML::Node *old_repr = father->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); - Geom::OptRect a = father->getBounds(father->i2doc_affine()); + Geom::OptRect a = father->documentVisualBounds(); if (a) { if (i == 2) { Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc); @@ -534,7 +534,7 @@ bool sp_spray_recursive(SPDesktop *desktop, } } } else if (mode == SPRAY_MODE_CLONE) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { if(_fid <= population) { SPItem *item_copied; diff --git a/src/text-chemistry.cpp b/src/text-chemistry.cpp index d64fa749a..a4a6b231a 100644 --- a/src/text-chemistry.cpp +++ b/src/text-chemistry.cpp @@ -432,8 +432,7 @@ text_unflow () /* Set style */ rtext->setAttribute("style", flowtext->getRepr()->attribute("style")); // fixme: transfer style attrs too; and from descendants - Geom::OptRect bbox; - flowtext->invoke_bbox(bbox, flowtext->i2doc_affine(), TRUE); + Geom::OptRect bbox = flowtext->geometricBounds(flowtext->i2doc_affine()); if (bbox) { Geom::Point xy = bbox->min(); sp_repr_set_svg_double(rtext, "x", xy[Geom::X]); diff --git a/src/text-context.cpp b/src/text-context.cpp index 1468984a1..d2bf8c5f5 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -432,7 +432,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve } else { SP_CTRLRECT(tc->indicator)->setColor(0x0000ff7f, false, 0); } - Geom::OptRect ibbox = item_ungrouped->getBboxDesktop(); + Geom::OptRect ibbox = item_ungrouped->desktopVisualBounds(); if (ibbox) { SP_CTRLRECT(tc->indicator)->setRectangle(*ibbox); } @@ -1635,7 +1635,7 @@ sp_text_context_update_cursor(SPTextContext *tc, bool scroll_to_see) SP_CTRLRECT(tc->frame)->setColor(0x0000ff7f, false, 0); } sp_canvas_item_show(tc->frame); - Geom::OptRect frame_bbox = frame->getBboxDesktop(); + Geom::OptRect frame_bbox = frame->desktopVisualBounds(); if (frame_bbox) { SP_CTRLRECT(tc->frame)->setRectangle(*frame_bbox); } diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 83598d8da..5d592b83d 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -442,7 +442,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else { if (mode == TWEAK_MODE_MOVE) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; @@ -455,7 +455,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else if (mode == TWEAK_MODE_MOVE_IN_OUT) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; @@ -469,7 +469,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else if (mode == TWEAK_MODE_MOVE_JITTER) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double dp = g_random_double_range(0, M_PI*2); double dr = g_random_double_range(0, radius); @@ -484,7 +484,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else if (mode == TWEAK_MODE_SCALE) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; @@ -497,7 +497,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else if (mode == TWEAK_MODE_ROTATE) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; @@ -510,7 +510,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } else if (mode == TWEAK_MODE_MORELESS) { - Geom::OptRect a = item->getBounds(item->i2doc_affine()); + Geom::OptRect a = item->documentVisualBounds(); if (a) { double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; @@ -562,7 +562,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } // skip those paths whose bboxes are entirely out of reach with our radius - Geom::OptRect bbox = item->getBounds(item->i2doc_affine()); + Geom::OptRect bbox = item->documentVisualBounds(); if (bbox) { bbox->expandBy(radius); if (!bbox->contains(p)) { @@ -946,8 +946,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, if (!style) { return false; } - Geom::OptRect bbox = item->getBounds(item->i2doc_affine(), - SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = item->documentGeometricBounds(); if (!bbox) { return false; } @@ -976,8 +975,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, if (this_force > 0.002) { if (do_blur) { - Geom::OptRect bbox = item->getBounds(item->i2doc_affine(), - SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = item->documentGeometricBounds(); if (!bbox) { return did; } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 60379a966..adec1de5d 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -467,7 +467,7 @@ bool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool a if (separately) { for (GSList *i = const_cast<GSList*>(selection->itemList()) ; i ; i = i->next) { SPItem *item = SP_ITEM(i->data); - Geom::OptRect obj_size = item->getBboxDesktop(); + Geom::OptRect obj_size = item->desktopVisualBounds(); if ( !obj_size ) { continue; } @@ -476,7 +476,7 @@ bool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool a } // resize the selection as a whole else { - Geom::OptRect sel_size = selection->bounds(); + Geom::OptRect sel_size = selection->visualBounds(); if ( sel_size ) { sp_selection_scale_relative(selection, sel_size->midpoint(), _getScale(desktop, min, max, *sel_size, apply_x, apply_y)); @@ -636,7 +636,7 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection) } } - Geom::OptRect size = selection->bounds(); + Geom::OptRect size = selection->visualBounds(); if (size) { sp_repr_set_point(_clipnode, "min", size->min()); sp_repr_set_point(_clipnode, "max", size->max()); @@ -852,7 +852,7 @@ void ClipboardManagerImpl::_pasteDocument(SPDesktop *desktop, SPDocument *clipdo target_document->ensureUpToDate(); // move selection either to original position (in_place) or to mouse pointer - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); if (sel_bbox) { // get offset of selection to original position of copied elements Geom::Point pos_original; diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 8728e2ef4..36d5a20d0 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -155,7 +155,7 @@ private : selected.erase(master); /*}*/ //Compute the anchor point - Geom::OptRect b = thing->getBboxDesktop (); + Geom::OptRect b = thing->desktopVisualBounds(); if (b) { mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X], a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]); @@ -172,7 +172,7 @@ private : case AlignAndDistribute::DRAWING: { - Geom::OptRect b = sp_desktop_document(desktop)->getRoot()->getBboxDesktop(); + Geom::OptRect b = sp_desktop_document(desktop)->getRoot()->desktopVisualBounds(); if (b) { mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X], a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]); @@ -184,7 +184,7 @@ private : case AlignAndDistribute::SELECTION: { - Geom::OptRect b = selection->bounds(); + Geom::OptRect b = selection->visualBounds(); if (b) { mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X], a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]); @@ -211,7 +211,7 @@ private : bool changed = false; Geom::OptRect b; if (sel_as_group) - b = selection->bounds(); + b = selection->visualBounds(); //Move each item in the selected list separately for (std::list<SPItem *>::iterator it(selected.begin()); @@ -220,7 +220,7 @@ private : { sp_desktop_document (desktop)->ensureUpToDate(); if (!sel_as_group) - b = (*it)->getBboxDesktop(); + b = (*it)->desktopVisualBounds(); if (b) { Geom::Point const sp(a.sx0 * b->min()[Geom::X] + a.sx1 * b->max()[Geom::X], a.sy0 * b->min()[Geom::Y] + a.sy1 * b->max()[Geom::Y]); @@ -261,7 +261,7 @@ ActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = { {0., 0., 1., 0., 0., 0., 0., 1.} }; -BBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) : +BBoxSort::BBoxSort(SPItem *pItem, Geom::Rect const &bounds, Geom::Dim2 orientation, double kBegin, double kEnd) : item(pItem), bbox (bounds) { @@ -324,7 +324,7 @@ private : it != selected.end(); ++it) { - Geom::OptRect bbox = (*it)->getBboxDesktop(); + Geom::OptRect bbox = (*it)->desktopVisualBounds(); if (bbox) { sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd)); } @@ -699,7 +699,7 @@ private : //Check 2 or more selected objects if (selected.size() < 2) return; - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); if (!sel_bbox) { return; } @@ -721,7 +721,7 @@ private : ++it) { sp_desktop_document (desktop)->ensureUpToDate(); - Geom::OptRect item_box = (*it)->getBboxDesktop (); + Geom::OptRect item_box = (*it)->desktopVisualBounds(); if (item_box) { // find new center, staying within bbox double x = _dialog.randomize_bbox->min()[Geom::X] + (*item_box)[Geom::X].extent() /2 + @@ -1245,7 +1245,7 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem { gdouble max = -1e18; for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) { - Geom::OptRect b = (*it)->getBboxDesktop (); + Geom::OptRect b = (*it)->desktopVisualBounds(); if (b) { gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent(); if (dim > max) { @@ -1262,7 +1262,7 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem { gdouble max = 1e18; for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) { - Geom::OptRect b = (*it)->getBboxDesktop (); + Geom::OptRect b = (*it)->desktopVisualBounds(); if (b) { gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent(); if (dim < max) { diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index 99b96463c..22227cb60 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -120,7 +120,7 @@ struct BBoxSort SPItem *item; float anchor; Geom::Rect bbox; - BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd); + BBoxSort(SPItem *pItem, Geom::Rect const &bounds, Geom::Dim2 orientation, double kBegin, double kEnd); BBoxSort(const BBoxSort &rhs); }; bool operator< (const BBoxSort &a, const BBoxSort &b); diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 4f4093a99..0d7a0c687 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -992,10 +992,8 @@ bool FileOpenDialogImplWin32::set_svg_preview() NRRectL bbox = {0, 0, scaledSvgWidth, scaledSvgHeight}; // write object bbox to area - Geom::OptRect maybeArea(area); svgDoc->ensureUpToDate(); - svgDoc->getRoot()->invoke_bbox( maybeArea, - svgDoc->getRoot()->i2dt_affine(), TRUE); + Geom::OptRect maybeArea = area | svgDoc->getRoot()->desktopVisualBounds(); NRArena *const arena = NRArena::create(); diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp index 68ad9393c..5f19a2613 100644 --- a/src/ui/dialog/tile.cpp +++ b/src/ui/dialog/tile.cpp @@ -47,8 +47,8 @@ sp_compare_x_position(SPItem *first, SPItem *second) using Geom::X; using Geom::Y; - Geom::OptRect a = first->getBounds(first->i2doc_affine()); - Geom::OptRect b = second->getBounds(second->i2doc_affine()); + Geom::OptRect a = first->documentVisualBounds(); + Geom::OptRect b = second->documentVisualBounds(); if ( !a || !b ) { // FIXME? @@ -87,8 +87,8 @@ sp_compare_x_position(SPItem *first, SPItem *second) int sp_compare_y_position(SPItem *first, SPItem *second) { - Geom::OptRect a = first->getBounds(first->i2doc_affine()); - Geom::OptRect b = second->getBounds(second->i2doc_affine()); + Geom::OptRect a = first->documentVisualBounds(); + Geom::OptRect b = second->documentVisualBounds(); if ( !a || !b ) { // FIXME? @@ -167,7 +167,7 @@ void TileDialog::Grid_Arrange () cnt=0; for (; items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); - Geom::OptRect b = item->getBounds(item->i2doc_affine()); + Geom::OptRect b = item->documentVisualBounds(); if (!b) { continue; } @@ -210,7 +210,7 @@ void TileDialog::Grid_Arrange () const GSList *sizes = sorted; for (; sizes != NULL; sizes = sizes->next) { SPItem *item = SP_ITEM(sizes->data); - Geom::OptRect b = item->getBounds(item->i2doc_affine()); + Geom::OptRect b = item->documentVisualBounds(); if (b) { width = b->dimensions()[Geom::X]; height = b->dimensions()[Geom::Y]; @@ -267,7 +267,7 @@ void TileDialog::Grid_Arrange () } - Geom::OptRect sel_bbox = selection->bounds(); + Geom::OptRect sel_bbox = selection->visualBounds(); // Fit to bbox, calculate padding between rows accordingly. if ( sel_bbox && !SpaceManualRadioButton.get_active() ){ #ifdef DEBUG_GRID_ARRANGE @@ -317,7 +317,7 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h for (; current_row != NULL; current_row = current_row->next) { SPItem *item=SP_ITEM(current_row->data); Inkscape::XML::Node *repr = item->getRepr(); - Geom::OptRect b = item->getBounds(item->i2doc_affine()); + Geom::OptRect b = item->documentVisualBounds(); Geom::Point min; if (b) { width = b->dimensions()[Geom::X]; diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 92c8bd349..029a83ea5 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -467,7 +467,7 @@ Transformation::updatePageMove(Inkscape::Selection *selection) { if (selection && !selection->isEmpty()) { if (!_check_move_relative.get_active()) { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { double x = bbox->min()[Geom::X]; double y = bbox->min()[Geom::Y]; @@ -489,7 +489,7 @@ void Transformation::updatePageScale(Inkscape::Selection *selection) { if (selection && !selection->isEmpty()) { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { double w = bbox->dimensions()[Geom::X]; double h = bbox->dimensions()[Geom::Y]; @@ -519,7 +519,7 @@ void Transformation::updatePageSkew(Inkscape::Selection *selection) { if (selection && !selection->isEmpty()) { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { double w = bbox->dimensions()[Geom::X]; double h = bbox->dimensions()[Geom::Y]; @@ -616,7 +616,7 @@ Transformation::applyPageMove(Inkscape::Selection *selection) if (_check_move_relative.get_active()) { sp_selection_move_relative(selection, x, y); } else { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { sp_selection_move_relative(selection, x - bbox->min()[Geom::X], y - bbox->min()[Geom::Y]); @@ -637,7 +637,7 @@ Transformation::applyPageMove(Inkscape::Selection *selection) it != selected.end(); ++it) { - Geom::OptRect bbox = (*it)->getBboxDesktop(); + Geom::OptRect bbox = (*it)->desktopVisualBounds(); if (bbox) { sorted.push_back(BBoxSort(*it, *bbox, Geom::X, x > 0? 1. : 0., x > 0? 0. : 1.)); } @@ -661,7 +661,7 @@ Transformation::applyPageMove(Inkscape::Selection *selection) it != selected.end(); ++it) { - Geom::OptRect bbox = (*it)->getBboxDesktop(); + Geom::OptRect bbox = (*it)->desktopVisualBounds(); if (bbox) { sorted.push_back(BBoxSort(*it, *bbox, Geom::Y, y > 0? 1. : 0., y > 0? 0. : 1.)); } @@ -680,7 +680,7 @@ Transformation::applyPageMove(Inkscape::Selection *selection) } } } else { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { sp_selection_move_relative(selection, x - bbox->min()[Geom::X], y - bbox->min()[Geom::Y]); @@ -705,7 +705,7 @@ Transformation::applyPageScale(Inkscape::Selection *selection) Geom::Scale scale (0,0); // the values are increments! if (_units_scale.isAbsolute()) { - Geom::OptRect bbox(item->getBboxDesktop()); + Geom::OptRect bbox = item->desktopVisualBounds(); if (bbox) { double new_width = scaleX; if (fabs(new_width) < 1e-6) new_width = 1e-6; // not 0, as this would result in a nasty no-bbox object @@ -723,7 +723,7 @@ Transformation::applyPageScale(Inkscape::Selection *selection) sp_item_scale_rel (item, scale); } } else { - Geom::OptRect bbox(selection->bounds()); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { Geom::Point center(bbox->midpoint()); // use rotation center? Geom::Scale scale (0,0); @@ -792,7 +792,7 @@ Transformation::applyPageSkew(Inkscape::Selection *selection) } else { // absolute displacement double skewX = _scalar_skew_horizontal.getValue("px"); double skewY = _scalar_skew_vertical.getValue("px"); - Geom::OptRect bbox(item->getBboxDesktop()); + Geom::OptRect bbox = item->desktopVisualBounds(); if (bbox) { double width = bbox->dimensions()[Geom::X]; double height = bbox->dimensions()[Geom::Y]; @@ -801,7 +801,7 @@ Transformation::applyPageSkew(Inkscape::Selection *selection) } } } else { // transform whole selection - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); boost::optional<Geom::Point> center = selection->center(); if ( bbox && center ) { @@ -886,7 +886,7 @@ Transformation::onMoveRelativeToggled() //g_message("onMoveRelativeToggled: %f, %f px\n", x, y); - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { if (_check_move_relative.get_active()) { @@ -1026,7 +1026,7 @@ Transformation::onClear() _scalar_move_horizontal.setValue(0); _scalar_move_vertical.setValue(0); } else { - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { _scalar_move_horizontal.setValue(bbox->min()[Geom::X], "px"); _scalar_move_vertical.setValue(bbox->min()[Geom::Y], "px"); diff --git a/src/ui/widget/style-subject.cpp b/src/ui/widget/style-subject.cpp index f4780896b..f3a8478ea 100644 --- a/src/ui/widget/style-subject.cpp +++ b/src/ui/widget/style-subject.cpp @@ -147,7 +147,7 @@ StyleSubject::iterator StyleSubject::CurrentLayer::begin() { Geom::OptRect StyleSubject::CurrentLayer::getBounds(SPItem::BBoxType type) { SPObject *layer = _getLayer(); if (layer && SP_IS_ITEM(layer)) { - return SP_ITEM(layer)->getBboxDesktop(type); + return SP_ITEM(layer)->desktopBounds(type); } else { return Geom::OptRect(); } diff --git a/src/ui/widget/style-subject.h b/src/ui/widget/style-subject.h index 6d5c96350..73f818516 100644 --- a/src/ui/widget/style-subject.h +++ b/src/ui/widget/style-subject.h @@ -45,7 +45,7 @@ public: virtual iterator begin() = 0; virtual iterator end() { return iterator(NULL); } - virtual Geom::OptRect getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) = 0; + virtual Geom::OptRect getBounds(SPItem::BBoxType type) = 0; virtual int queryStyle(SPStyle *query, int property) = 0; virtual void setCSS(SPCSSAttr *css) = 0; @@ -68,7 +68,7 @@ public: ~Selection(); virtual iterator begin(); - virtual Geom::OptRect getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + virtual Geom::OptRect getBounds(SPItem::BBoxType type); virtual int queryStyle(SPStyle *query, int property); virtual void setCSS(SPCSSAttr *css); @@ -89,7 +89,7 @@ public: ~CurrentLayer(); virtual iterator begin(); - virtual Geom::OptRect getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + virtual Geom::OptRect getBounds(SPItem::BBoxType type); virtual int queryStyle(SPStyle *query, int property); virtual void setCSS(SPCSSAttr *css); diff --git a/src/unclump.cpp b/src/unclump.cpp index e570e8fa7..6b9a8c574 100644 --- a/src/unclump.cpp +++ b/src/unclump.cpp @@ -34,7 +34,7 @@ unclump_center (SPItem *item) return i->second; } - Geom::OptRect r = item->getBounds(item->i2dt_affine()); + Geom::OptRect r = item->desktopVisualBounds(); if (r) { Geom::Point const c = r->midpoint(); c_cache[item->getId()] = c; @@ -53,7 +53,7 @@ unclump_wh (SPItem *item) if ( i != wh_cache.end() ) { wh = i->second; } else { - Geom::OptRect r = item->getBounds(item->i2dt_affine()); + Geom::OptRect r = item->desktopVisualBounds(); if (r) { wh = r->dimensions(); wh_cache[item->getId()] = wh; diff --git a/src/verbs.cpp b/src/verbs.cpp index e443e9917..ac8699654 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1325,7 +1325,7 @@ ObjectVerb::perform( SPAction *action, void *data, void */*pdata*/ ) if (sel->isEmpty()) return; - Geom::OptRect bbox = sel->bounds(); + Geom::OptRect bbox = sel->visualBounds(); if (!bbox) { return; } diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 08f0eadfb..fff9c0a5c 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1881,7 +1881,7 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) Geom::Rect darea ( Geom::Point(-doc->getWidth(), -doc->getHeight()), Geom::Point(2 * doc->getWidth(), 2 * doc->getHeight()) ); - Geom::OptRect deskarea = darea | doc->getRoot()->getBboxDesktop(); + Geom::OptRect deskarea = darea | doc->getRoot()->desktopVisualBounds(); /* Canvas region we always show unconditionally */ Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64), diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index a57b56b5c..9540b59d6 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -1102,8 +1102,7 @@ sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing, if (object && SP_IS_ITEM(object)) { SPItem *item = SP_ITEM(object); // Find bbox in document - Geom::Affine const i2doc(item->i2doc_affine()); - Geom::OptRect dbox = item->getBounds(i2doc); + Geom::OptRect dbox = item->documentVisualBounds(); if ( object->parent == NULL ) { diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index 260c09c69..5f90a8997 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -70,7 +70,7 @@ sp_selection_layout_widget_update(SPWidget *spw, Inkscape::Selection *sel) if ( sel && !sel->isEmpty() ) { int prefs_bbox = prefs->getInt("/tools/bounding_box", 0); SPItem::BBoxType bbox_type = (prefs_bbox ==0)? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; Geom::OptRect const bbox(sel->bounds(bbox_type)); if ( bbox ) { UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(G_OBJECT(spw), "tracker")); @@ -160,12 +160,12 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) document->ensureUpToDate (); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Geom::OptRect bbox_vis = selection->bounds(SPItem::APPROXIMATE_BBOX); - Geom::OptRect bbox_geom = selection->bounds(SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox_vis = selection->visualBounds(); + Geom::OptRect bbox_geom = selection->geometricBounds(); int prefs_bbox = prefs->getInt("/tools/bounding_box"); SPItem::BBoxType bbox_type = (prefs_bbox == 0)? - SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; Geom::OptRect bbox_user = selection->bounds(bbox_type); if ( !bbox_user ) { @@ -247,10 +247,10 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) int transform_stroke = prefs->getBool("/options/transform/stroke", true) ? 1 : 0; Geom::Affine scaler; - if (bbox_type == SPItem::APPROXIMATE_BBOX) { + if (bbox_type == SPItem::VISUAL_BBOX) { scaler = get_scale_transform_with_unequal_stroke (*bbox_vis, *bbox_geom, transform_stroke, x0, y0, x1, y1); } else { - // get_scale_transform_with_stroke() is intended for VISUAL (or APPROXIMATE) bounding boxes, not geometrical ones! + // get_scale_transform_with_stroke() is intended for visual bounding boxes, not geometrical ones! // we'll trick it into using a geometric bounding box though, by setting the stroke width to zero scaler = get_scale_transform_with_uniform_stroke (*bbox_user, 0, false, x0, y0, x1, y1); } diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 8d9b9b429..bb9391c78 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -191,8 +191,7 @@ sp_marker_prev_new(unsigned psize, gchar const *mname, SPItem *item = SP_ITEM(object); // Find object's bbox in document - Geom::Affine const i2doc(item->i2doc_affine()); - Geom::OptRect dbox = item->getBounds(i2doc); + Geom::OptRect dbox = item->documentVisualBounds(); if (!dbox) { return NULL; diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 26947979d..61c7c8e88 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -5951,7 +5951,7 @@ static void lpetool_toggle_set_bbox(GtkToggleAction *act, gpointer data) SPDesktop *desktop = static_cast<SPDesktop *>(data); Inkscape::Selection *selection = desktop->selection; - Geom::OptRect bbox = selection->bounds(); + Geom::OptRect bbox = selection->visualBounds(); if (bbox) { Geom::Point A(bbox->min()); @@ -6799,8 +6799,7 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) axis = Geom::Y; } - Geom::OptRect bbox - = item->getBounds(Geom::identity(), SPItem::GEOMETRIC_BBOX); + Geom::OptRect bbox = item->geometricBounds(); if (!bbox) continue; double width = bbox->dimensions()[axis]; |
