From 644fcc3dc6937101ece71d2a08e5ec148e8f358f Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Thu, 29 Oct 2020 15:33:24 +0100 Subject: [PATCH 1/2] NEED HELP: Canvas scale prerender The goal of this MR is scale current canvas to the next zoom position making "instant" previews while finish drawing. Currently it store files to disk for debug that slow. You need a complex draw to see better and in a big screen with small tile size and debug mode for test in badest position and take time to compare results visualy. Working except a gap when zoom is not from canvas center, I try to fix in a try/carch but finaly get desesperarted, so I leave for other to finish. --- src/desktop.cpp | 57 ++++++++++++-- src/desktop.h | 20 ++++- src/ui/tools/zoom-tool.cpp | 6 +- src/ui/widget/canvas.cpp | 154 ++++++++++++++++++++++++++++++++++++- src/ui/widget/canvas.h | 4 +- 5 files changed, 226 insertions(+), 15 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index bff5a8348a..aca1fb993d 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -665,6 +665,9 @@ SPDesktop::prev_transform() return; } + // Set the previous affine + _prev_affine = _current_affine; + // Push current transform into future transforms list. transforms_future.push_front( _current_affine ); @@ -673,6 +676,7 @@ SPDesktop::prev_transform() // restore previous transform _current_affine = transforms_past.front(); + set_display_area (false); } @@ -687,6 +691,9 @@ void SPDesktop::next_transform() this->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No next transform.")); return; } + + // Set the previous affine + _prev_affine = _current_affine; // restore next transform _current_affine = transforms_future.front(); @@ -719,7 +726,8 @@ SPDesktop::clear_transform_history() void SPDesktop::set_display_area (bool log) { - // Save the transform + Geom::Affine advert_transform = _prev_affine.w2d().inverse() * _current_affine.w2d(); + if (log) { transforms_past.push_front( _current_affine ); // if we do a logged transform, our transform-forward list is invalidated, so delete it @@ -730,9 +738,8 @@ SPDesktop::set_display_area (bool log) // Scroll Geom::Point offset = _current_affine.getOffset(); - canvas->scroll_to(offset, true); + canvas->scroll_to(offset, true, advert_transform); canvas->set_affine(_current_affine.d2w()); // For CanvasItem's. - // To do: if transform unchanged call with 'false' (redraw only newly exposed areas). /* Update perspective lines if we are in the 3D box tool (so that infinite ones are shown * correctly) */ @@ -755,10 +762,13 @@ SPDesktop::set_display_area (bool log) * is a point on the canvas and 'w' is position in window in screen pixels. */ void -SPDesktop::set_display_area (Geom::Point const &c, Geom::Point const &w, bool log) +SPDesktop::set_display_area (Geom::Point const &c, Geom::Point const &w, bool log, bool from_rect) { // The relative offset needed to keep c at w. Geom::Point offset = d2w(c) - w; + if (!from_rect) { + _prev_affine.setOffset(_current_affine.getOffset()); + } _current_affine.addOffset( offset ); set_display_area( log ); } @@ -789,11 +799,12 @@ SPDesktop::set_display_area( Geom::Rect const &r, double border, bool log) zoom = w.height() / r.height(); } zoom = CLAMP(zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + _prev_affine = _current_affine; _current_affine.setScale( Geom::Scale(zoom, yaxisdir() * zoom) ); // Zero offset, actual offset calculated later. _current_affine.setOffset( Geom::Point( 0, 0 ) ); - set_display_area( r.midpoint(), w.midpoint(), log ); + set_display_area( r.midpoint(), w.midpoint(), log, true); } @@ -824,6 +835,7 @@ SPDesktop::zoom_absolute(Geom::Point const ¢er, double zoom, bool keep_point w = canvas->get_area_world().midpoint(); } zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + _prev_affine = _current_affine; _current_affine.setScale( Geom::Scale(zoom, yaxisdir() * zoom) ); set_display_area( center, w ); } @@ -988,6 +1000,7 @@ void SPDesktop::zoom_quick(bool enable) zoom_relative(midpoint, 2.0, false); } } else { + _prev_affine = _current_affine; _current_affine = _quick_zoom_affine; set_display_area( false ); } @@ -1017,6 +1030,7 @@ void SPDesktop::rotate_absolute_keep_point (Geom::Point const &c, double rotate) { Geom::Point w = d2w( c ); // Must be before rotate changed. + _prev_affine = _current_affine; _current_affine.setRotate( rotate ); set_display_area( c, w ); } @@ -1032,6 +1046,7 @@ void SPDesktop::rotate_relative_keep_point (Geom::Point const &c, double rotate) { Geom::Point w = d2w( c ); // Must be before rotate changed. + _prev_affine = _current_affine; _current_affine.addRotate( rotate ); set_display_area( c, w ); } @@ -1046,6 +1061,7 @@ SPDesktop::rotate_relative_keep_point (Geom::Point const &c, double rotate) void SPDesktop::rotate_absolute_center_point (Geom::Point const &c, double rotate) { + _prev_affine = _current_affine; _current_affine.setRotate( rotate ); Geom::Rect viewbox = canvas->get_area_world(); set_display_area(c, viewbox.midpoint()); @@ -1061,6 +1077,7 @@ SPDesktop::rotate_absolute_center_point (Geom::Point const &c, double rotate) void SPDesktop::rotate_relative_center_point (Geom::Point const &c, double rotate) { + _prev_affine = _current_affine; _current_affine.addRotate( rotate ); Geom::Rect viewbox = canvas->get_area_world(); set_display_area(c, viewbox.midpoint()); @@ -1077,6 +1094,7 @@ void SPDesktop::flip_absolute_keep_point (Geom::Point const &c, CanvasFlip flip) { Geom::Point w = d2w(c); // Must be before flip. + _prev_affine = _current_affine; _current_affine.setFlip(flip); set_display_area(c, w); } @@ -1092,6 +1110,7 @@ void SPDesktop::flip_relative_keep_point (Geom::Point const &c, CanvasFlip flip) { Geom::Point w = d2w(c); // Must be before flip. + _prev_affine = _current_affine; _current_affine.addFlip(flip); set_display_area(c, w); } @@ -1106,6 +1125,7 @@ SPDesktop::flip_relative_keep_point (Geom::Point const &c, CanvasFlip flip) void SPDesktop::flip_absolute_center_point (Geom::Point const &c, CanvasFlip flip) { + _prev_affine = _current_affine; _current_affine.setFlip(flip); Geom::Rect viewbox = canvas->get_area_world(); set_display_area(c, viewbox.midpoint()); @@ -1121,6 +1141,7 @@ SPDesktop::flip_absolute_center_point (Geom::Point const &c, CanvasFlip flip) void SPDesktop::flip_relative_center_point (Geom::Point const &c, CanvasFlip flip) { + _prev_affine = _current_affine; _current_affine.addFlip(flip); Geom::Rect viewbox = canvas->get_area_world(); set_display_area(c, viewbox.midpoint()); @@ -1140,6 +1161,7 @@ void SPDesktop::scroll_absolute (Geom::Point const &point, bool is_scrolling) { canvas->scroll_to(point, false); + _prev_affine.setOffset(_current_affine.getOffset()); _current_affine.setOffset( point ); /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ @@ -1851,6 +1873,11 @@ Geom::Affine SPDesktop::w2d() const return _current_affine.w2d(); } +Geom::Affine SPDesktop::d2w() const +{ + return _current_affine.d2w(); +} + Geom::Point SPDesktop::w2d(Geom::Point const &p) const { return p * _current_affine.w2d(); @@ -1861,6 +1888,26 @@ Geom::Point SPDesktop::d2w(Geom::Point const &p) const return p * _current_affine.d2w(); } +Geom::Affine SPDesktop::prev_w2d() const +{ + return _prev_affine.w2d(); +} + +Geom::Affine SPDesktop::prev_d2w() const +{ + return _prev_affine.d2w(); +} + +Geom::Point SPDesktop::prev_w2d(Geom::Point const &p) const +{ + return p * _prev_affine.w2d(); +} + +Geom::Point SPDesktop::prev_d2w(Geom::Point const &p) const +{ + return p * _prev_affine.d2w(); +} + const Geom::Affine &SPDesktop::doc2dt() const { g_assert(doc() != nullptr); diff --git a/src/desktop.h b/src/desktop.h index b6375b5b0b..78636fd805 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -309,7 +309,7 @@ public: void clear_transform_history(); void set_display_area (bool log = true); - void set_display_area (Geom::Point const &c, Geom::Point const &w, bool log = true); + void set_display_area (Geom::Point const &c, Geom::Point const &w, bool log = true, bool from_rect = false); void set_display_area (Geom::Rect const &a, Geom::Coord border, bool log = true); Geom::Parallelogram get_display_area(bool use_integer_viewbox = false) const; @@ -415,10 +415,13 @@ public: // TODO return const ref instead of copy Geom::Affine w2d() const; //transformation from window to desktop coordinates (zoom/rotate). + Geom::Affine d2w() const; /// Transformation from desktop to window coordinates Geom::Point w2d(Geom::Point const &p) const; - /// Transformation from desktop to window coordinates - Geom::Affine d2w() const { return _current_affine.d2w(); } Geom::Point d2w(Geom::Point const &p) const; + Geom::Affine prev_w2d() const; + Geom::Point prev_w2d(Geom::Point const &p) const; + Geom::Affine prev_d2w() const; + Geom::Point prev_d2w(Geom::Point const &p) const; const Geom::Affine& doc2dt() const; Geom::Affine dt2doc() const; Geom::Point doc2dt(Geom::Point const &p) const; @@ -519,7 +522,15 @@ private: Geom::Point getOffset() { return _offset; } - + DesktopAffine &operator=(const DesktopAffine &other) { + _w2d = other._w2d; + _d2w = other._d2w; + _rotate = other._rotate; + _scale = other._scale; + _flip = other._flip; + _offset = other._offset; + return *this; + } private: void _update() { _d2w = _scale * _rotate * _flip; @@ -534,6 +545,7 @@ private: }; DesktopAffine _current_affine; + DesktopAffine _prev_affine; std::list transforms_past; std::list transforms_future; bool _split_canvas; diff --git a/src/ui/tools/zoom-tool.cpp b/src/ui/tools/zoom-tool.cpp index 612051dcda..8f3e7811a2 100644 --- a/src/ui/tools/zoom-tool.cpp +++ b/src/ui/tools/zoom-tool.cpp @@ -133,7 +133,7 @@ bool ZoomTool::root_handler(GdkEvent* event) { if ( event->button.button == 1 && !this->space_panning) { Geom::OptRect const b = Inkscape::Rubberband::get(desktop)->getRectangle(); - + Inkscape::Rubberband::get(desktop)->stop(); if (b && !within_tolerance && !(GDK_SHIFT_MASK & event->button.state) ) { desktop->set_display_area(*b, 10); } else if (!escaped) { @@ -145,9 +145,11 @@ bool ZoomTool::root_handler(GdkEvent* event) { } ret = true; + } else { + Inkscape::Rubberband::get(desktop)->stop(); } - Inkscape::Rubberband::get(desktop)->stop(); + ungrabCanvasEvents(); diff --git a/src/ui/widget/canvas.cpp b/src/ui/widget/canvas.cpp index 9bbd255eb5..ed37ed450a 100644 --- a/src/ui/widget/canvas.cpp +++ b/src/ui/widget/canvas.cpp @@ -30,6 +30,7 @@ #include "display/control/canvas-item-group.h" #include "ui/tools/tool-base.h" // Default cursor +#include /* * The canvas is responsible for rendering the SVG drawing with various "control" @@ -289,11 +290,14 @@ Canvas::request_update() * Complete redraw if 'clear' is true. */ void -Canvas::scroll_to(Geom::Point const &c, bool clear) +Canvas::scroll_to(Geom::Point const &c, bool clear, Geom::Affine advert_transform) { int old_x0 = _x0; int old_y0 = _y0; - + int _prev_old_x0 = _prev_x0; + int _prev_old_y0 = _prev_y0; + _prev_x0 = _x0; + _prev_y0 = _y0; // This is the only place the _x0 and _y0 are set! _x0 = (int) round(c[Geom::X]); // cx might be negative, so (int)(cx + 0.5) will not do! _y0 = (int) round(c[Geom::Y]); @@ -322,8 +326,152 @@ Canvas::scroll_to(Geom::Point const &c, bool clear) expanded.expandBy(expansion); _drawing->setCacheLimit(expanded, false); } - if (clear || !overlap) { + // Save the transform + if (_desktop && clear && !Geom::are_near(Geom::identity(), advert_transform)) { + // Paint background + if (_backing_store) { + cairo_surface_write_to_png (_backing_store->cobj(), "/home/jtx/Development/hello3.png"); + Cairo::RefPtr<::Cairo::ImageSurface> new_store = + Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, + _allocation.get_width() * _device_scale, + _allocation.get_height() * _device_scale); + + cairo_surface_set_device_scale(new_store->cobj(), _device_scale, _device_scale); // No C++ API! + + // Copy the old store contents to new backing store. + auto cr = Cairo::Context::create(new_store); + /* Geom::Rect w(Geom::Point(), get_area_world().dimensions()); + Geom::Rect w1(Geom::Point(old_x0,old_y0), get_area_world().dimensions()); + Geom::Rect w2(Geom::Point(_x0,_y0), get_area_world().dimensions()); + Geom::Point res = _desktop->prev_w2d(Geom::Point(_x0,_y0) + w.midpoint()) - _desktop->prev_w2d(Geom::Point(old_x0,old_y0) + w.midpoint());; + */ + /* std::cout << 0 << res << std::endl; + res = _desktop->prev_w2d(Geom::Point(_x0,_y0) + w.midpoint()); + std::cout << 0 << res << std::endl; + res = _desktop->prev_w2d(Geom::Point(old_x0,old_y0) + w.midpoint()); + std::cout << 0 << res << std::endl; + res = _desktop->prev_w2d(Geom::Point(_prev_old_x0,_prev_old_y0) + w.midpoint()); + std::cout << 0 << res << std::endl; + + res = _desktop->prev_w2d(Geom::Point(old_x0,old_y0) + w.midpoint()); + std::cout << "0-0" << res << std::endl; + std::cout << 1 << (Geom::Point(old_x0,old_y0)) << std::endl; + std::cout << 2 << (Geom::Point(_x0,_y0)) << std::endl; + std::cout << 3 << (Geom::Point(dx, dy)) << std::endl; + std::cout << "3-1" << (w1.midpoint()) << std::endl; + std::cout << "3-2" << (w2.midpoint()) << std::endl; + std::cout << 4 << (_desktop->d2w(Geom::Point(old_x0,old_y0))) << std::endl; + std::cout << 5 << (_desktop->d2w(Geom::Point(_x0,_y0))) << std::endl; + std::cout << 6 << (_desktop->d2w(Geom::Point(dx, dy))) << std::endl; + std::cout << "6-1" << (_desktop->d2w(w1.midpoint())) << std::endl; + std::cout << "6-2" << (_desktop->d2w(w2.midpoint())) << std::endl; + std::cout << 7 << (_desktop->w2d(Geom::Point(old_x0,old_y0))) << std::endl; + std::cout << 8 << (_desktop->w2d(Geom::Point(_x0,_y0))) << std::endl; + std::cout << 9 << (_desktop->w2d(Geom::Point(dx, dy))) << std::endl; + std::cout << "9-1" << (_desktop->w2d(w1.midpoint())) << std::endl; + std::cout << "9-2" << (_desktop->w2d(w2.midpoint())) << std::endl; + std::cout << 10 << (Geom::Point(old_x0,old_y0) * advert_transform.inverse()) << std::endl; + std::cout << 11 << (Geom::Point(_x0,_y0) * advert_transform.inverse()) << std::endl; + std::cout << 12 << (Geom::Point(dx, dy) * advert_transform.inverse()) << std::endl; + std::cout << "12-1" << (w1.midpoint() * advert_transform.inverse()) << std::endl; + std::cout << "12-1" << (w2.midpoint() * advert_transform.inverse()) << std::endl; + std::cout << 13 << (_desktop->d2w(Geom::Point(old_x0,old_y0)) * advert_transform.inverse()) << std::endl; + std::cout << 14 << (_desktop->d2w(Geom::Point(_x0,_y0)) * advert_transform.inverse()) << std::endl; + std::cout << 15 << (_desktop->d2w(Geom::Point(dx, dy)) * advert_transform.inverse()) << std::endl; + std::cout << "15-1" << (_desktop->d2w(w1.midpoint()) * advert_transform.inverse()) << std::endl; + std::cout << "15-2" << (_desktop->d2w(w2.midpoint()) * advert_transform.inverse()) << std::endl; + std::cout << 16 << (_desktop->w2d(Geom::Point(old_x0,old_y0)) * advert_transform.inverse()) << std::endl; + std::cout << 17 << (_desktop->w2d(Geom::Point(_x0,_y0)) * advert_transform.inverse()) << std::endl; + std::cout << 18 << (_desktop->w2d(Geom::Point(dx, dy)) * advert_transform.inverse()) << std::endl; + std::cout << "18-1" << (_desktop->w2d(w1.midpoint()) * advert_transform.inverse()) << std::endl; + std::cout << "18-2" << (_desktop->w2d(w2.midpoint()) * advert_transform.inverse()) << std::endl; + std::cout << 19 << (Geom::Point(old_x0,old_y0) * advert_transform) << std::endl; + std::cout << 20 << (Geom::Point(_x0,_y0) * advert_transform) << std::endl; + std::cout << 21 << (Geom::Point(dx, dy) * advert_transform) << std::endl; + std::cout << "21-1" << (w1.midpoint() * advert_transform) << std::endl; + std::cout << "21-2" << (w2.midpoint() * advert_transform) << std::endl; + std::cout << 22 << (_desktop->d2w(Geom::Point(old_x0,old_y0)) * advert_transform) << std::endl; + std::cout << 23 << (_desktop->d2w(Geom::Point(_x0,_y0)) * advert_transform) << std::endl; + std::cout << 24 << (_desktop->d2w(Geom::Point(dx, dy)) * advert_transform) << std::endl; + std::cout << "24-1" << (_desktop->d2w(w1.midpoint()) * advert_transform) << std::endl; + std::cout << "24-2" << (_desktop->d2w(w2.midpoint()) * advert_transform) << std::endl; + std::cout << 25 << (_desktop->w2d(Geom::Point(old_x0,old_y0)) * advert_transform) << std::endl; + std::cout << 26 << (_desktop->w2d(Geom::Point(_x0,_y0)) * advert_transform) << std::endl; + std::cout << 27 << (_desktop->w2d(Geom::Point(dx, dy)) * advert_transform) << std::endl; + std::cout << "27-1" << (_desktop->w2d(w1.midpoint()) * advert_transform) << std::endl; + std::cout << "27-2" << (_desktop->w2d(w2.midpoint()) * advert_transform) << std::endl; + std::cout << 28 << (w.midpoint()) << std::endl; + */ + Geom::Point gap = Geom::Point(); + Geom::Point middle = w.midpoint(); + advert_transform = Geom::Translate(middle).inverse() * Geom::Translate(gap) * advert_transform.inverse() * Geom::Translate(middle); + Cairo::Matrix matrix; + matrix.xx = advert_transform[0]; + matrix.yx = advert_transform[1]; + matrix.xy = advert_transform[2]; + matrix.yy = advert_transform[3]; + matrix.x0 = advert_transform[4]; + matrix.y0 = advert_transform[5]; + cr->set_matrix(matrix); + // cr->translate(middle[Geom::X], middle[Geom::Y]); + // Paint background + cr->set_operator(Cairo::Operator::OPERATOR_SOURCE); + cr->set_source(_background); + cr->paint(); + //cr->translate(_allocation.get_width()/2, _allocation.get_height()/2); + cr->set_source(_backing_store, 0, 0); // ((prev_transform.expansionX() * -1 * _allocation.get_width()) - _allocation.get_width())/2, ((prev_transform.expansionY() * -1 * _allocation.get_height()) - _allocation.get_height())/2); + cr->paint(); + + //cr->translate(middle[Geom::X], middle[Geom::Y]); + + /* cr->rectangle(dx, dy, _allocation.get_width(), _allocation.get_height()); + cr->clip(); + cr->paint(); */ + //prev_transform = prev_transform.inverse(); + // Copy old background unshifted (reduces sensation of flicker while waiting for rendering newly exposed area). + /* cr->save(); + cr->set_operator(Cairo::Operator::OPERATOR_SOURCE); + cr->set_source(_backing_store, 0, 0); + Cairo::Matrix matrix; + matrix.xx = prev_transform[0]; + matrix.yx = prev_transform[1]; + matrix.xy = prev_transform[2]; + matrix.yy = prev_transform[3]; + matrix.x0 = prev_transform[4]; + matrix.y0 = prev_transform[5]; + cr->scale(2,2); + //cr->set_matrix(matrix); + cr->rectangle(dx, dy, _allocation.get_width(), _allocation.get_height()); + cr->clip(); + cr->paint(); + cr->restore(); */ + _backing_store = new_store; + /* std::filesystem::copy("./debug.png", "./debug2.png", std::filesystem::copy_options::update_existing); + cairo_surface_write_to_png (_backing_store->cobj(), "./debug.png"); */ + } + + + /* auto cr = Cairo::Context::create(_backing_store); + + + + + // Paint background + cr->save(); + Cairo::Matrix matrix; + matrix.xx = prev_transform[0]; + matrix.yx = prev_transform[1]; + matrix.xy = prev_transform[2]; + matrix.yy = prev_transform[3]; + matrix.x0 = prev_transform[4]; + matrix.y0 = prev_transform[5]; + cr->set_matrix(matrix); + cr->rectangle(_x0, _y0, _allocation.get_width(), _allocation.get_height()); cr->clip(); + cr->paint(); + cr->restore(); */ + queue_draw_area(_x0, _y0, _allocation.get_width(), _allocation.get_height()); + } redraw_all(); return; // Check if this is OK } diff --git a/src/ui/widget/canvas.h b/src/ui/widget/canvas.h index b484694b72..97daf725e4 100644 --- a/src/ui/widget/canvas.h +++ b/src/ui/widget/canvas.h @@ -68,7 +68,7 @@ public: void redraw_area(Geom::Rect& area); // Draw specified area during idle. void redraw_now(); // Draw areas needing update immediately. void request_update(); // Draw after updating canvas items. - void scroll_to(Geom::Point const &c, bool clear); + void scroll_to(Geom::Point const &c, bool clear, Geom::Affine advert_transform = Geom::identity()); void set_background_color(guint32 rgba); void set_background_checkerboard(guint32 rgba = 0xC4C4C4FF); @@ -183,6 +183,8 @@ private: // Geometry int _x0 = 0; ///< World coordinate of the leftmost pixels of window. int _y0 = 0; ///< World coordinate of the topmost pixels of window. + int _prev_x0 = 0; ///< Previous world coordinate of the leftmost pixels of window. + int _prev_y0 = 0; ///< Previos world coordinate of the topmost pixels of window. Geom::Point _window_origin; ///< World coordinate of the upper-leftmost pixel of window. Geom::Affine _affine; // Only used for canvas items at moment. bool _in_full_redraw = false; -- GitLab From 8a3efeec7413b3fd8654581a071978435d9890a1 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 30 Oct 2020 22:15:27 +0000 Subject: [PATCH 2/2] fix compiling issue --- src/ui/widget/canvas.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/canvas.cpp b/src/ui/widget/canvas.cpp index ed37ed450a..f99fe4f4bb 100644 --- a/src/ui/widget/canvas.cpp +++ b/src/ui/widget/canvas.cpp @@ -341,8 +341,8 @@ Canvas::scroll_to(Geom::Point const &c, bool clear, Geom::Affine advert_transfor // Copy the old store contents to new backing store. auto cr = Cairo::Context::create(new_store); - /* Geom::Rect w(Geom::Point(), get_area_world().dimensions()); - Geom::Rect w1(Geom::Point(old_x0,old_y0), get_area_world().dimensions()); + Geom::Rect w(Geom::Point(), get_area_world().dimensions()); + /*Geom::Rect w1(Geom::Point(old_x0,old_y0), get_area_world().dimensions()); Geom::Rect w2(Geom::Point(_x0,_y0), get_area_world().dimensions()); Geom::Point res = _desktop->prev_w2d(Geom::Point(_x0,_y0) + w.midpoint()) - _desktop->prev_w2d(Geom::Point(old_x0,old_y0) + w.midpoint());; */ -- GitLab