diff --git a/src/document.cpp b/src/document.cpp index f2be81612759a1149c90da51d45c71017e59ccc2..cba919ceecc3f635f1f0ebf90e3e7284b855ab92 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -819,7 +819,7 @@ Geom::OptRect SPDocument::preferredBounds() const * Given a Geom::Rect that may, for example, correspond to the bbox of an object, * this function fits the canvas to that rect by resizing the canvas * and translating the document root into position. - * \param rect fit document size to this + * \param rect fit document size to this, in document coordinates * \param with_margins add margins to rect, by taking margins from this * document's namedview ( "fit-margin-..." * attributes, and "units") @@ -829,7 +829,6 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double const w = rect.width(); double const h = rect.height(); - double const old_height = getHeight().value("px"); Inkscape::Util::Unit const *nv_units = unit_table.getUnit("px"); if (root->height.unit && (root->height.unit != SVGLength::PERCENT)) nv_units = unit_table.getUnit(root->height.unit); @@ -856,26 +855,26 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins) double y_dir = yaxisdir(); - if (y_dir > 0) { - std::swap(margin_top, margin_bottom); - } - Geom::Rect const rect_with_margins( - rect.min() - Geom::Point(margin_left, margin_bottom), - rect.max() + Geom::Point(margin_right, margin_top)); + rect.min() - Geom::Point(margin_left, margin_top), + rect.max() + Geom::Point(margin_right, margin_bottom)); + + // rect in desktop coordinates before changing document dimensions + auto rect_with_margins_dt_old = rect_with_margins * doc2dt(); setWidthAndHeight( Inkscape::Util::Quantity(Inkscape::Util::Quantity::convert(rect_with_margins.width(), "px", nv_units), nv_units), Inkscape::Util::Quantity(Inkscape::Util::Quantity::convert(rect_with_margins.height(), "px", nv_units), nv_units) ); - Geom::Translate const tr( - Geom::Point(0, (y_dir > 0) ? 0 : old_height - rect_with_margins.height()) - - rect_with_margins.min()); + // rect in desktop coordinates after changing document dimensions + auto rect_with_margins_dt_new = rect_with_margins * doc2dt(); + + Geom::Translate const tr(-rect_with_margins_dt_new.min()); root->translateChildItems(tr); if(nv) { - Geom::Translate tr2(-rect_with_margins.min()); + Geom::Translate tr2(-rect_with_margins_dt_old.min()); nv->translateGuides(tr2); nv->translateGrids(tr2); @@ -1308,6 +1307,9 @@ static bool overlaps(Geom::Rect const &area, Geom::Rect const &box) return area.intersects(box); } +/** + * @param area Area in document coordinates + */ static std::vector &find_items_in_area(std::vector &s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, @@ -1330,7 +1332,7 @@ static std::vector &find_items_in_area(std::vector &s, continue; } } - Geom::OptRect box = item->desktopVisualBounds(); + Geom::OptRect box = item->documentVisualBounds(); if (box && test(area, *box) && (take_insensitive || !item->isLocked()) && (take_hidden || !item->isHidden())) @@ -1488,11 +1490,10 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin } -/* +/** * Return list of items, contained in box * - * Assumes box is normalized (and g_asserts it!) - * + * @param box area to find items, in document coordinates */ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden, bool take_insensitive, bool take_groups, bool enter_groups) const @@ -1501,10 +1502,10 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_hidden, take_insensitive, take_groups, enter_groups); } -/* - * Assumes box is normalized (and g_asserts it!) +/** + * Get items whose bounding box overlaps with given area. * @param dkey desktop view in use - * @param box area to find items + * @param box area to find items, in document coordinates * @param take_hidden get hidden items * @param take_insensitive get insensitive items * @param take_groups get also the groups diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index 1f2150cf139539ac2c2c12410493a35d9e30467c..802d1372d70b905db1c89f10a5fa7eb6888c83d7 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -407,6 +407,11 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename, width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only, interlace, color_type, bit_depth, zlib, antialiasing); } +/** + * Export an area to a PNG file + * + * @param area Area in document coordinates + */ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename, Geom::Rect const &area, unsigned long width, unsigned long height, double xdpi, double ydpi, @@ -430,7 +435,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename, doc->ensureUpToDate(); /* Calculate translation by transforming to document coordinates (flipping Y)*/ - Geom::Point translation = -(area * doc->dt2doc()).min(); + Geom::Point translation = -area.min(); /* This calculation is only valid when assumed that (x0,y0)= area.corner(0) and (x1,y1) = area.corner(2) * 1) a[0] * x0 + a[2] * y1 + a[4] = 0.0 diff --git a/src/io/file-export-cmd.cpp b/src/io/file-export-cmd.cpp index 82ca0807da253f18701511eb7d8233a4b7bec9ca..9af2d61ac0ee6ec0335313add59150d20c4ef7a2 100644 --- a/src/io/file-export-cmd.cpp +++ b/src/io/file-export-cmd.cpp @@ -480,7 +480,7 @@ InkFileExportCmd::do_export_png(SPDocument *doc, std::string filename_in) } else { // Export area drawing (explicit or if object is given). - Geom::OptRect areaMaybe = static_cast(object)->desktopVisualBounds(); + Geom::OptRect areaMaybe = static_cast(object)->documentVisualBounds(); if (areaMaybe) { area = *areaMaybe; } else { diff --git a/src/object/sp-offset.cpp b/src/object/sp-offset.cpp index 667fdf9c3bce52515b2452cb80d8a68faa716fb5..b837d785560a3ec2de64414207c4b5221fe08e3e 100644 --- a/src/object/sp-offset.cpp +++ b/src/object/sp-offset.cpp @@ -412,7 +412,7 @@ void SPOffset::set_shape() { theRes->ConvertToForme (orig, 1, originaux); - Geom::OptRect bbox = this->desktopVisualBounds(); + Geom::OptRect bbox = this->documentVisualBounds(); if ( bbox ) { gdouble size = L2(bbox->dimensions()); diff --git a/src/rubberband.cpp b/src/rubberband.cpp index e6db06efa0d107a1c31771eebff45780890005a8..83b5e7a3534edb834409cf09a9f98e990fced253 100644 --- a/src/rubberband.cpp +++ b/src/rubberband.cpp @@ -126,6 +126,9 @@ void Inkscape::Rubberband::setMode(int mode) _mode = mode; } +/** + * @return Rectangle in desktop coordinates + */ Geom::OptRect Inkscape::Rubberband::getRectangle() const { if (!_started) { diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 39b70eb2905e5a7fc4fde85224a606e873a60114..2423198091e2ba2f47af16e32fe20e072f5ea508 100755 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -3611,7 +3611,7 @@ void ObjectSet::createBitmapCopy() // Get the bounding box of the selection doc->ensureUpToDate(); - Geom::OptRect bbox = visualBounds(); + Geom::OptRect bbox = documentBounds(SPItem::VISUAL_BBOX); if (!bbox) { if(desktop()) desktop()->clearWaitingCursor(); @@ -3727,9 +3727,8 @@ void ObjectSet::createBitmapCopy() } Geom::Affine t; - auto bbox_doc = (*bbox) * doc->dt2doc(); - double shift_x = bbox_doc.left(); - double shift_y = bbox_doc.top(); + double shift_x = bbox->left(); + double shift_y = bbox->top(); if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid shift_x = round(shift_x); shift_y = round(shift_y); @@ -4247,7 +4246,7 @@ bool ObjectSet::fitCanvas(bool with_margins, bool skip_undo) desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to fit canvas to.")); return false; } - Geom::OptRect const bbox(visualBounds()); + Geom::OptRect const bbox = documentBounds(SPItem::VISUAL_BBOX); if (bbox) { document()->fitToRect(*bbox, with_margins); if(!skip_undo) @@ -4340,7 +4339,7 @@ fit_canvas_to_drawing(SPDocument *doc, bool with_margins) doc->ensureUpToDate(); SPItem const *const root = doc->getRoot(); - Geom::OptRect bbox = root->desktopVisualBounds(); + Geom::OptRect bbox = root->documentVisualBounds(); if (bbox) { doc->fitToRect(*bbox, with_margins); return true; diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 23895fe642381477820cd2af188e61a693d7192b..7719a707118489efa50f8c24a68948d68f48dfdc 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -2241,7 +2241,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop, continue; if (simplifyIndividualPaths) { - Geom::OptRect itemBbox = item->desktopVisualBounds(); + Geom::OptRect itemBbox = item->documentVisualBounds(); if (itemBbox) { simplifySize = L2(itemBbox->dimensions()); } else { diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index b33653bfd37a0813075e769c2d888ececaa9b7e3..2b281a096b7d7886ca233b267db8988b0c3ace47 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -88,7 +88,8 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : } AddSeparator(); /* Lock/Unock Hide/Unhide*/ - Geom::Rect b(_desktop->point(),_desktop->point() + Geom::Point(1,1)); + auto point_doc = _desktop->point() * _desktop->dt2doc(); + Geom::Rect b(point_doc, point_doc + Geom::Point(1, 1)); std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true, true, true); bool has_down_hidden = false; bool has_down_locked = false; diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 160f83965025c9dfba13076f9d4d75849c437a05..2c1ebb45dc31a2b6a332b39017322ea43cdfff55 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -1050,7 +1050,7 @@ void Export::onExport () } pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : dpi; - Geom::OptRect area = item->desktopVisualBounds(); + Geom::OptRect area = item->documentVisualBounds(); if (area) { gint width = (gint) (area->width() * dpi / DPI_BASE + 0.5); gint height = (gint) (area->height() * dpi / DPI_BASE + 0.5); @@ -1154,11 +1154,13 @@ void Export::onExport () prog_dlg->set_data("current", GINT_TO_POINTER(0)); prog_dlg->set_data("total", GINT_TO_POINTER(0)); + auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + /* Do export */ std::vector x; std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); ExportResult status = sp_export_png_file(desktop->getDocument(), path.c_str(), - Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)), width, height, pHYs, pHYs, //previously xdpi, ydpi. + area, width, height, pHYs, pHYs, //previously xdpi, ydpi. nv->pagecolor, onProgressCallback, (void*)prog_dlg, FALSE, diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index ab0282298d6fdf24d15175d0723da96a19e6e045..eb32d224527cc6a25bb54ca49fc7bfbfe587613f 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -252,15 +252,14 @@ bool SpellCheck::compareTextBboxes (gconstpointer a, gconstpointer b)//returns a SPItem *i1 = SP_ITEM(a); SPItem *i2 = SP_ITEM(b); - Geom::OptRect bbox1 = i1->desktopVisualBounds(); - Geom::OptRect bbox2 = i2->desktopVisualBounds(); + Geom::OptRect bbox1 = i1->documentVisualBounds(); + Geom::OptRect bbox2 = i2->documentVisualBounds(); if (!bbox1 || !bbox2) { return false; } // vector between top left corners - Geom::Point diff = Geom::Point(bbox2->min()[Geom::X], bbox2->max()[Geom::Y]) - - Geom::Point(bbox1->min()[Geom::X], bbox1->max()[Geom::Y]); + Geom::Point diff = bbox1->min() - bbox2->min(); return diff[Geom::Y] == 0 ? (diff[Geom::X] < 0) : (diff[Geom::Y] < 0); } diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp index 3ea8a960e5052493edde6631d11ee57b3d07861d..ed307acc5561ee5ffa10a013890040007466fa64 100644 --- a/src/ui/tools/eraser-tool.cpp +++ b/src/ui/tools/eraser-tool.cpp @@ -670,7 +670,7 @@ void EraserTool::set_to_accumulated() { Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc(); SPItem* acid = SP_ITEM(this->desktop->doc()->getObjectByRepr(this->repr)); - eraserBbox = acid->desktopVisualBounds(); + eraserBbox = acid->documentVisualBounds(); std::vector remainingItems; std::vector toWorkOn; if (selection->isEmpty()) { @@ -709,7 +709,7 @@ void EraserTool::set_to_accumulated() { } else if (SP_IS_GROUP(item) || use ) { /*Do nothing*/ } else { - Geom::OptRect bbox = item->desktopVisualBounds(); + Geom::OptRect bbox = item->documentVisualBounds(); if (bbox && bbox->intersects(*eraserBbox)) { Inkscape::XML::Node* dup = this->repr->duplicate(xml_doc); this->repr->parent()->appendChild(dup); @@ -758,7 +758,7 @@ void EraserTool::set_to_accumulated() { for (std::vector::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){ selection->clear(); SPItem *item = *i; - Geom::OptRect bbox = item->desktopVisualBounds(); + Geom::OptRect bbox = item->documentVisualBounds(); Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc(); Inkscape::XML::Node* dup = this->repr->duplicate(xml_doc); this->repr->parent()->appendChild(dup); @@ -800,7 +800,8 @@ void EraserTool::set_to_accumulated() { SPRect * rect = SP_RECT(item_repr->parent->appendChildRepr(rect_repr)); Inkscape::GC::release(rect_repr); rect->setPosition (bbox->left(), bbox->top(), bbox->width(), bbox->height()); - rect->transform = SP_ITEM(rect->parent)->i2dt_affine().inverse(); + rect->transform = SP_ITEM(rect->parent)->i2doc_affine().inverse(); + rect->updateRepr(); rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); selection->raiseToTop(true); diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 6633cdd6483334d8f03bce5fc933f93d71a6eddb..568d8c542dca520d863318564416e959da174f1d 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -1260,8 +1260,10 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, dimension_offset = 70; Geom::PathVector lineseg; Geom::Path p; - p.start(desktop->dt2doc(start_p)); - p.appendNew(desktop->dt2doc(end_p)); + Geom::Point start_p_doc = start_p * desktop->dt2doc(); + Geom::Point end_p_doc = end_p * desktop->dt2doc(); + p.start(start_p_doc); + p.appendNew(end_p_doc); lineseg.push_back(p); double angle = atan2(end_p - start_p); @@ -1274,7 +1276,7 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, std::vector items; SPDocument *doc = desktop->getDocument(); - Geom::Rect rect(start_p, end_p); + Geom::Rect rect(start_p_doc, end_p_doc); items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true, false, true); Inkscape::LayerModel *layer_model = nullptr; SPObject *current_layer = nullptr; diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index a14114cb71ddf7b99b715bb036b058155b83cf0e..63161b3cd8fcd74197b53667b6e8d31da324a87d 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -723,13 +723,17 @@ void NodeTool::update_tip(GdkEvent *event) { } } +/** + * @param sel Area in desktop coordinates + */ void NodeTool::select_area(Geom::Rect const &sel, GdkEventButton *event) { using namespace Inkscape::UI; if (this->_multipath->empty()) { // if multipath is empty, select rubberbanded items rather than nodes Inkscape::Selection *selection = this->desktop->selection; - std::vector items = this->desktop->getDocument()->getItemsInBox(this->desktop->dkey, sel); + auto sel_doc = desktop->dt2doc() * sel; + std::vector items = this->desktop->getDocument()->getItemsInBox(this->desktop->dkey, sel_doc); selection->setList(items); } else { if (!held_shift(*event)) { diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 88b432004e82e373559fa627faea83ce50b8195e..9bd97fabc4682e4cbe94d4a09f1c9100ea3ef886 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -721,7 +721,7 @@ bool SelectTool::root_handler(GdkEvent* event) { if (r->getMode() == RUBBERBAND_MODE_RECT) { Geom::OptRect const b = r->getRectangle(); - items = desktop->getDocument()->getItemsInBox(desktop->dkey, *b); + items = desktop->getDocument()->getItemsInBox(desktop->dkey, (*b) * desktop->dt2doc()); } else if (r->getMode() == RUBBERBAND_MODE_TOUCHPATH) { items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints()); } diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp index c910607a9d33c87581d07f25bce570d2ddc8afbf..c8dce398600a7c6c9b7fae962de87ed7fd041c10 100644 --- a/src/ui/tools/spray-tool.cpp +++ b/src/ui/tools/spray-tool.cpp @@ -527,7 +527,6 @@ static bool fit_item(SPDesktop *desktop, sp_spray_transform_path(item, path, Geom::Scale(scale), center); sp_spray_transform_path(item, path, Geom::Rotate(angle), center); path *= Geom::Translate(move); - path *= desktop->doc2dt(); bbox_procesed = path.boundsFast(); double bbox_left_main = bbox_procesed->left(); double bbox_right_main = bbox_procesed->right(); @@ -535,7 +534,7 @@ static bool fit_item(SPDesktop *desktop, double bbox_bottom_main = bbox_procesed->bottom(); double width_transformed = bbox_procesed->width(); double height_transformed = bbox_procesed->height(); - Geom::Point mid_point = desktop->d2w(bbox_procesed->midpoint()); + Geom::Point mid_point = desktop->d2w(bbox_procesed->midpoint() * desktop->doc2dt()); Geom::IntRect area = Geom::IntRect::from_xywh(floor(mid_point[Geom::X]), floor(mid_point[Geom::Y]), 1, 1); guint32 rgba = getPickerData(area); guint32 rgba2 = 0xffffff00;