From f35bb1f74a0ffeb5c6477a25e3c4cde87a97bcf1 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 28 Jul 2016 12:06:06 +0200 Subject: Removed unused includes, decrease compilation time (bzr r15025) --- src/desktop.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index d482d0d7f..7e0953d4d 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -23,12 +23,11 @@ #ifdef HAVE_CONFIG_H -# include "config.h" +#include #endif #include "ui/dialog/dialog-manager.h" #include -#include #include <2geom/transforms.h> #include <2geom/rect.h> @@ -45,35 +44,24 @@ #include "display/canvas-temporary-item-list.h" #include "display/drawing-group.h" #include "display/gnome-canvas-acetate.h" -#include "display/drawing.h" #include "display/snap-indicator.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-group.h" -#include "display/sp-canvas.h" #include "display/sp-canvas-util.h" -#include "document.h" #include "document-undo.h" #include "event-log.h" #include "helper/action-context.h" #include "ui/interface.h" #include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" -#include "macros.h" #include "message-context.h" #include "message-stack.h" -#include "preferences.h" #include "resource-manager.h" #include "ui/tools/select-tool.h" -#include "selection.h" -#include "sp-item-group.h" -#include "sp-item-group.h" #include "sp-namedview.h" #include "sp-root.h" -#include "sp-defs.h" #include "ui/tool-factory.h" #include "widgets/desktop-widget.h" -#include "xml/repr.h" #include "helper/action.h" //sp_action_perform // TODO those includes are only for node tool quick zoom. Remove them after fixing it. -- cgit v1.2.3 From 43b49e325db73cc19b1731db6c69545664ee8fbe Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 28 Jul 2016 13:26:17 +0200 Subject: Reverted changes to r15024 after many building problems (bzr r15027) --- src/desktop.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index 7e0953d4d..d482d0d7f 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -23,11 +23,12 @@ #ifdef HAVE_CONFIG_H -#include +# include "config.h" #endif #include "ui/dialog/dialog-manager.h" #include +#include #include <2geom/transforms.h> #include <2geom/rect.h> @@ -44,24 +45,35 @@ #include "display/canvas-temporary-item-list.h" #include "display/drawing-group.h" #include "display/gnome-canvas-acetate.h" +#include "display/drawing.h" #include "display/snap-indicator.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-group.h" +#include "display/sp-canvas.h" #include "display/sp-canvas-util.h" +#include "document.h" #include "document-undo.h" #include "event-log.h" #include "helper/action-context.h" #include "ui/interface.h" #include "layer-fns.h" #include "layer-manager.h" +#include "layer-model.h" +#include "macros.h" #include "message-context.h" #include "message-stack.h" +#include "preferences.h" #include "resource-manager.h" #include "ui/tools/select-tool.h" +#include "selection.h" +#include "sp-item-group.h" +#include "sp-item-group.h" #include "sp-namedview.h" #include "sp-root.h" +#include "sp-defs.h" #include "ui/tool-factory.h" #include "widgets/desktop-widget.h" +#include "xml/repr.h" #include "helper/action.h" //sp_action_perform // TODO those includes are only for node tool quick zoom. Remove them after fixing it. -- cgit v1.2.3 From 49a7927ecf31ace696e9e5770e8d6543c356db7a Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Thu, 28 Jul 2016 19:15:34 +0100 Subject: Finish removing GTK+ 2 fallbacks (bzr r15023.2.8) --- src/desktop.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index d482d0d7f..83110f8e0 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1444,11 +1444,7 @@ void SPDesktop::setWaitingCursor() GdkDisplay *display = gdk_display_get_default(); GdkCursor *waiting = gdk_cursor_new_for_display(display, GDK_WATCH); gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(getCanvas())), waiting); -#if GTK_CHECK_VERSION(3,0,0) g_object_unref(waiting); -#else - gdk_cursor_unref(waiting); -#endif // GDK needs the flush for the cursor change to take effect gdk_flush(); waiting_cursor = true; -- cgit v1.2.3 From 35830f456cadaecf8b8e3944e3031a1a93f6cb41 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Wed, 3 Aug 2016 15:29:38 +0200 Subject: Removed unused includes, decreased compilation time. Once again (bzr r15034) --- src/desktop.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index d482d0d7f..7e0953d4d 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -23,12 +23,11 @@ #ifdef HAVE_CONFIG_H -# include "config.h" +#include #endif #include "ui/dialog/dialog-manager.h" #include -#include #include <2geom/transforms.h> #include <2geom/rect.h> @@ -45,35 +44,24 @@ #include "display/canvas-temporary-item-list.h" #include "display/drawing-group.h" #include "display/gnome-canvas-acetate.h" -#include "display/drawing.h" #include "display/snap-indicator.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-group.h" -#include "display/sp-canvas.h" #include "display/sp-canvas-util.h" -#include "document.h" #include "document-undo.h" #include "event-log.h" #include "helper/action-context.h" #include "ui/interface.h" #include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" -#include "macros.h" #include "message-context.h" #include "message-stack.h" -#include "preferences.h" #include "resource-manager.h" #include "ui/tools/select-tool.h" -#include "selection.h" -#include "sp-item-group.h" -#include "sp-item-group.h" #include "sp-namedview.h" #include "sp-root.h" -#include "sp-defs.h" #include "ui/tool-factory.h" #include "widgets/desktop-widget.h" -#include "xml/repr.h" #include "helper/action.h" //sp_action_perform // TODO those includes are only for node tool quick zoom. Remove them after fixing it. -- cgit v1.2.3 From 6fe601cdb4ddddb004eedc28ed598d9e9e771814 Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Sat, 3 Sep 2016 17:17:22 +0300 Subject: Remove == true. (bzr r15100.1.7) --- src/desktop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index 7efa3e438..89a7da9d0 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -902,7 +902,7 @@ void SPDesktop::zoom_quick(bool enable) return; } - if (enable == true) { + if (enable) { _quick_zoom_stored_area = get_display_area(); bool zoomed = false; -- cgit v1.2.3 From 532f77b14a76fc04e6bdeca3625f9a55b5f11bdf Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 25 Oct 2016 00:58:43 +0200 Subject: CPPification: almost all sp_object_set_whatever and sp_selection_whatever global functions are now methods of ObjectSet*, with these additional benefits: - They can now act on any SelectionSet, not just the current selection; - Whenever possible, they don't need a desktop anymore and can run if called from GUI. I hope I did not break too many things in the process. *: So instead of callink sp_selection_move(desktop,x,y), you call myobjectset->move(x,y) (bzr r15189) --- src/desktop.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index 89a7da9d0..2476b10bb 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1529,6 +1529,7 @@ SPDesktop::setDocument (SPDocument *doc) } layers->setDocument(doc); + selection->setDocument(doc); // remove old EventLog if it exists (see also: bug #1071082) if (event_log) { -- cgit v1.2.3 From 014489163050d8abe9e5c4949fb80f3c21b1c17b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 13 Mar 2017 15:22:22 +0100 Subject: Replace rectangle based zooming by affine based zooming. This allows a rotation to be included in the drawing to window mapping. General code cleanup. Added documentation. Any change to zooming behavior is probably a bug. (bzr r15592) --- src/desktop.cpp | 544 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 275 insertions(+), 269 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index 2476b10bb..ddd5dfe83 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -120,20 +120,16 @@ SPDesktop::SPDesktop() : _widget( NULL ), _guides_message_context( NULL ), _active( false ), - _w2d(), - _d2w(), _doc2dt( Geom::Scale(1, -1) ), _image_render_observer(this, "/options/rendering/imageinoutlinemode"), grids_visible( false ) { - _d2w.setIdentity(); - _w2d.setIdentity(); - layers = new Inkscape::LayerModel(); layers->_layer_activated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_activated), this)); layers->_layer_deactivated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_deactivated), this)); layers->_layer_changed_signal.connect(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this)); selection = Inkscape::GC::release( new Inkscape::Selection(layers, this) ); + // _current_affine.setRotate(M_PI/4); // To test zooming with rotation } void @@ -479,7 +475,7 @@ SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempi } void SPDesktop::redrawDesktop() { - sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw + sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _current_affine.d2w()); // redraw } void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) { @@ -733,307 +729,223 @@ Geom::Point SPDesktop::point() const { Geom::Point p = _widget->getPointer(); Geom::Point pw = sp_canvas_window_to_world (canvas, p); - p = w2d(pw); - Geom::Rect const r = canvas->getViewbox(); - Geom::Point r0 = w2d(r.min()); - Geom::Point r1 = w2d(r.max()); - - if (p[Geom::X] >= r0[Geom::X] && - p[Geom::X] <= r1[Geom::X] && - p[Geom::Y] >= r1[Geom::Y] && - p[Geom::Y] <= r0[Geom::Y]) - { + if (r.interiorContains(pw)) { + p = w2d(pw); return p; - } else { - return (r0 + r1) / 2; } -} - -/** - * Put current zoom data in history list. - */ -void -SPDesktop::push_current_zoom (std::list &history) -{ - Geom::Rect area = get_display_area(); - if (history.empty() || history.front() != area) { - history.push_front(area); - } + // Shouldn't happen + std::cerr << "SPDesktop::point(): point outside of canvas!" << std::endl; + Geom::Point r0 = w2d(r.min()); + Geom::Point r1 = w2d(r.max()); + return (r0 + r1) / 2.0; } + /** - * Set viewbox (x0, x1, y0 and y1 are in document pixels. Border is in screen pixels). + * Revert back to previous transform if possible. Note: current transform is + * always at front of stack. */ void -SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log) +SPDesktop::prev_transform() { - g_assert(_widget); - bool zoomChanged = false; - - // save the zoom - if (log) { - push_current_zoom(zooms_past); - // if we do a logged zoom, our zoom-forward list is invalidated, so delete it - zooms_future.clear(); - } - - double const cx = 0.5 * (x0 + x1); - double const cy = 0.5 * (y0 + y1); - - // FIXME: This 2geom idiom doesn't allow us to declare dbox const - Geom::Rect viewbox = canvas->getViewbox(); - viewbox.expandBy(-border); - - double scale = _d2w.descrim(); - double newscale; - if (((x1 - x0) * viewbox.dimensions()[Geom::Y]) > ((y1 - y0) * viewbox.dimensions()[Geom::X])) { - newscale = viewbox.dimensions()[Geom::X] / (x1 - x0); - } else { - newscale = viewbox.dimensions()[Geom::Y] / (y1 - y0); + if (transforms_past.empty()) { + std::cerr << "SPDesktop::prev_transform: current transform missing!" << std::endl; + return; } - newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels' - - int clear = FALSE; - if (!Geom::are_near(newscale, scale, Geom::EPSILON * scale)) { - // zoom changed - set new zoom factors - _d2w = Geom::Scale(newscale, -newscale); - _w2d = Geom::Scale(1/newscale, 1/-newscale); - redrawDesktop(); - clear = TRUE; - zoomChanged = true; + if (transforms_past.size() == 1) { + messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No previous transform.")); + return; } - /* Calculate top left corner (in document pixels) */ - x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale; - y1 = cy + 0.5 * viewbox.dimensions()[Geom::Y] / newscale; - - // Scroll - canvas->scrollTo(x0 * newscale - border, y1 * -newscale - border, clear); - - /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ - //sp_box3d_context_update_lines(event_context); - if (SP_IS_BOX3D_CONTEXT(event_context)) { - SP_BOX3D_CONTEXT(event_context)->_vpdrag->updateLines(); - } + // Push current transform into future transforms list. + transforms_future.push_front( _current_affine ); - _widget->updateRulers(); - _widget->updateScrollbars(_d2w.descrim()); - _widget->updateZoom(); + // Remove the current transform from the past transforms list. + transforms_past.pop_front(); - if ( zoomChanged ) { - signal_zoom_changed.emit(_d2w.descrim()); - } -} + // restore previous transform + _current_affine = transforms_past.front(); + set_display_area (false); -void SPDesktop::set_display_area(Geom::Rect const &a, Geom::Coord b, bool log) -{ - set_display_area(a.min()[Geom::X], a.min()[Geom::Y], a.max()[Geom::X], a.max()[Geom::Y], b, log); } -/** - * Return viewbox dimensions. - */ -Geom::Rect SPDesktop::get_display_area() const -{ - Geom::Rect const viewbox = canvas->getViewbox(); - - double const scale = _d2w[0]; - - /// @fixme hardcoded desktop transform - return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale), - Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale)); -} /** - * Revert back to previous zoom if possible. + * Set transform to next in list. */ -void -SPDesktop::prev_zoom() +void SPDesktop::next_transform() { - if (zooms_past.empty()) { - messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No previous zoom.")); + if (transforms_future.empty()) { + this->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No next transform.")); return; } - // push current zoom into forward zooms list - push_current_zoom (zooms_future); + // restore next transform + _current_affine = transforms_future.front(); + set_display_area (false); - // restore previous zoom - Geom::Rect past = zooms_past.front(); - set_display_area (past.left(), past.top(), past.right(), past.bottom(), 0, false); + // remove the just-used transform from the future transforms list + transforms_future.pop_front(); - // remove the just-added zoom from the past zooms list - zooms_past.pop_front(); + // push current transform into past transforms list + transforms_past.push_front( _current_affine ); } + /** - * Set zoom to next in list. + * Clear transform lists. */ -void SPDesktop::next_zoom() +void +SPDesktop::clear_transform_history() { - if (zooms_future.empty()) { - this->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No next zoom.")); - return; - } - - // push current zoom into past zooms list - push_current_zoom (zooms_past); - - // restore next zoom - Geom::Rect future = zooms_future.front(); - set_display_area (future.left(), future.top(), future.right(), future.bottom(), 0, false); - - // remove the just-used zoom from the zooms_future list - zooms_future.pop_front(); + transforms_past.clear(); + transforms_future.clear(); } + /** - * Performs a quick zoom into what the user is working on. - * - * @param enable Whether we're going in or out of quick zoom. + * Does all the dirty work in setting the display area. + * _current_affine must already be full updated (including offset). + * log: if true, save transform in transform stack for reuse. */ -void SPDesktop::zoom_quick(bool enable) +void +SPDesktop::set_display_area (bool log) { - if (enable == _quick_zoom_enabled) { - return; + // Save the transform + if (log) { + transforms_past.push_front( _current_affine ); + // if we do a logged transform, our transform-forward list is invalidated, so delete it + transforms_future.clear(); } - if (enable) { - _quick_zoom_stored_area = get_display_area(); - bool zoomed = false; - - // TODO This needs to migrate into the node tool, but currently the design - // of this method is sufficiently wrong to prevent this. - if (!zoomed && INK_IS_NODE_TOOL(event_context)) { - Inkscape::UI::Tools::NodeTool *nt = static_cast(event_context); - if (!nt->_selected_nodes->empty()) { - Geom::Rect nodes = *nt->_selected_nodes->bounds(); - double area = nodes.area(); - // do not zoom if a single cusp node is selected aand the bounds - // have zero area. - if (!Geom::are_near(area, 0) && area * 2.0 < _quick_zoom_stored_area.area()) { - set_display_area(nodes, true); - zoomed = true; - } - } - } + redrawDesktop(); - if (!zoomed) { - Geom::OptRect const d = selection->visualBounds(); - if (d && d->area() * 2.0 < _quick_zoom_stored_area.area()) { - set_display_area(*d, true); - zoomed = true; - } - } + // Scroll + Geom::Point offset = _current_affine.getOffset(); + canvas->scrollTo(offset, true); + // To do: if transform unchanged call with 'false' (redraw only newly exposed areas). - if (!zoomed) { - zoom_relative(_quick_zoom_stored_area.midpoint()[Geom::X], _quick_zoom_stored_area.midpoint()[Geom::Y], 2.0); - } - } else { - set_display_area(_quick_zoom_stored_area, false); + /* Update perspective lines if we are in the 3D box tool (so that infinite ones are shown + * correctly) */ + if (SP_IS_BOX3D_CONTEXT(event_context)) { + SP_BOX3D_CONTEXT(event_context)->_vpdrag->updateLines(); } - _quick_zoom_enabled = enable; - return; + _widget->updateRulers(); + _widget->updateScrollbars(_current_affine.getZoom()); + _widget->updateZoom(); + + signal_zoom_changed.emit(_current_affine.getZoom()); } + /** - * Zoom to point with absolute zoom factor. + * Map the drawing to the window so that 'c' lies at 'w' where where 'c' + * is a point on the canvas and 'w' is position in window in screen pixels. */ void -SPDesktop::zoom_absolute_keep_point (double cx, double cy, double px, double py, double zoom) +SPDesktop::set_display_area (Geom::Point const &c, Geom::Point const &w, bool log) { - zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); - - // maximum or minimum zoom reached, but there's no exact equality because of rounding errors; - // this check prevents "sliding" when trying to zoom in at maximum zoom; - /// \todo someone please fix calculations properly and remove this hack - if (fabs(_d2w.descrim() - zoom) < 0.0001*zoom && (fabs(SP_DESKTOP_ZOOM_MAX - zoom) < 0.01 || fabs(SP_DESKTOP_ZOOM_MIN - zoom) < 0.000001)) - return; - - Geom::Rect const viewbox = canvas->getViewbox(); - - double const width2 = viewbox.dimensions()[Geom::X] / zoom; - double const height2 = viewbox.dimensions()[Geom::Y] / zoom; - - set_display_area(cx - px * width2, - cy - py * height2, - cx + (1 - px) * width2, - cy + (1 - py) * height2, - 0.0); + // The relative offset needed to keep c at w. + Geom::Point offset = d2w(c) - w; + _current_affine.addOffset( offset ); + set_display_area( log ); } + /** - * Apply the desktop's current style or the tool style to the object. - */ -void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text) + * Map the center of rectangle 'r' (which specifies a non-rotated region of the + * drawing) to lie at the center of the window. The zoom factor is calculated such that + * the edges of 'r' closest to 'w' are 'border' length inside of the window (if + * there is no rotation). 'r' is in document pixel units, 'border' is in screen pixels. + */ +void +SPDesktop::set_display_area( Geom::Rect const &r, double border, bool log) { - SPCSSAttr *css_current = sp_desktop_get_style(this, with_text); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + // Create a rectangle the size of the window aligned with origin. + Geom::Rect w( Geom::Point(), canvas->getViewbox().dimensions() ); // Not the SVG 'viewBox'. - if (prefs->getBool(tool_path + "/usecurrent") && css_current) { - obj->setCSS(css_current,"style"); + // Shrink window to account for border padding. + w.expandBy( -border ); + + double zoom = 1.0; + // Determine which direction limits scale: + // if (r.width/w.width > r.height/w.height) then zoom using width. + // Avoiding division in test: + if ( r.width()*w.height() > r.height()*w.width() ) { + zoom = w.width() / r.width(); } else { - SPCSSAttr *css = prefs->getInheritedStyle(tool_path + "/style"); - obj->setCSS(css,"style"); - sp_repr_css_attr_unref(css); - } - if (css_current) { - sp_repr_css_attr_unref(css_current); + zoom = w.height() / r.height(); } + _current_affine.setScale( zoom ); + + // Zero offset, actual offset calculated later. + _current_affine.setOffset( Geom::Point( 0, 0 ) ); + + set_display_area( r.midpoint(), w.midpoint(), log ); } + /** - * Zoom to center with absolute zoom factor. + * Return viewbox dimensions. FixMe: Doesn't handle rotation. FixMe InvertedY */ -void -SPDesktop::zoom_absolute (double cx, double cy, double zoom) +Geom::Rect SPDesktop::get_display_area() const { - zoom_absolute_keep_point (cx, cy, 0.5, 0.5, zoom); + Geom::Rect const viewbox = canvas->getViewbox(); + double const scale = _current_affine.getZoom(); + + /// @fixme hardcoded desktop transform + return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale), + Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale)); } + /** - * Zoom to point with relative zoom factor. + * Zoom keeping the point 'c' fixed in the desktop window. */ void -SPDesktop::zoom_relative_keep_point (double cx, double cy, double zoom) +SPDesktop::zoom_absolute_keep_point (Geom::Point const &c, double zoom) { - Geom::Rect const area = get_display_area(); - - if (cx < area.min()[Geom::X]) { - cx = area.min()[Geom::X]; - } - if (cx > area.max()[Geom::X]) { - cx = area.max()[Geom::X]; - } - if (cy < area.min()[Geom::Y]) { - cy = area.min()[Geom::Y]; - } - if (cy > area.max()[Geom::Y]) { - cy = area.max()[Geom::Y]; - } + zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + Geom::Point w = d2w( c ); // Must be before zoom changed. + _current_affine.setScale( zoom ); + set_display_area( c, w ); +} - gdouble const scale = _d2w.descrim() * zoom; - double const px = (cx - area.min()[Geom::X]) / area.dimensions()[Geom::X]; - double const py = (cy - area.min()[Geom::Y]) / area.dimensions()[Geom::Y]; - zoom_absolute_keep_point(cx, cy, px, py, scale); +void +SPDesktop::zoom_relative_keep_point (Geom::Point const &c, double zoom) +{ + double new_zoom = _current_affine.getZoom() * zoom; + zoom_absolute_keep_point( c, new_zoom ); } + /** - * Zoom to center with relative zoom factor. + * Zoom aligning the point 'c' to the center of desktop window. */ -void -SPDesktop::zoom_relative (double cx, double cy, double zoom) +void +SPDesktop::zoom_absolute_center_point (Geom::Point const &c, double zoom) +{ + zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + _current_affine.setScale( zoom ); + Geom::Rect viewbox = canvas->getViewbox(); + set_display_area( c, viewbox.midpoint() ); +} + + +void +SPDesktop::zoom_relative_center_point (Geom::Point const &c, double zoom) { - gdouble scale = _d2w.descrim() * zoom; - zoom_absolute (cx, cy, scale); + double new_zoom = _current_affine.getZoom() * zoom; + zoom_absolute_center_point( c, new_zoom ); } + /** * Set display area to origin and current document dimensions. */ @@ -1068,14 +980,23 @@ SPDesktop::zoom_page_width() set_display_area(d, 10); } + /** - * Zoom to selection. + * Zoom to whole drawing. */ void -SPDesktop::zoom_selection() +SPDesktop::zoom_drawing() { - Geom::OptRect const d = selection->visualBounds(); + g_return_if_fail (doc() != NULL); + SPItem *docitem = doc()->getRoot(); + g_return_if_fail (docitem != NULL); + docitem->bbox_valid = FALSE; + Geom::OptRect d = docitem->desktopVisualBounds(); + + /* Note that the second condition here indicates that + ** there are no items in the drawing. + */ if ( !d || d->minExtent() < 0.1 ) { return; } @@ -1083,59 +1004,95 @@ SPDesktop::zoom_selection() set_display_area(*d, 10); } + /** - * Tell widget to let zoom widget grab keyboard focus. + * Zoom to selection. */ void -SPDesktop::zoom_grab_focus() +SPDesktop::zoom_selection() { - _widget->letZoomGrabFocus(); + Geom::OptRect const d = selection->visualBounds(); + + if ( !d || d->minExtent() < 0.1 ) { + return; + } + + set_display_area(*d, 10); } + /** - * Zoom to whole drawing. + * Performs a quick zoom into what the user is working on. + * + * @param enable Whether we're going in or out of quick zoom. */ -void -SPDesktop::zoom_drawing() +void SPDesktop::zoom_quick(bool enable) { - g_return_if_fail (doc() != NULL); - SPItem *docitem = doc()->getRoot(); - g_return_if_fail (docitem != NULL); + if (enable == _quick_zoom_enabled) { + return; + } - docitem->bbox_valid = FALSE; - Geom::OptRect d = docitem->desktopVisualBounds(); + if (enable) { + _quick_zoom_affine = _current_affine; + bool zoomed = false; - /* Note that the second condition here indicates that - ** there are no items in the drawing. - */ - if ( !d || d->minExtent() < 0.1 ) { - return; + // TODO This needs to migrate into the node tool, but currently the design + // of this method is sufficiently wrong to prevent this. + if (!zoomed && INK_IS_NODE_TOOL(event_context)) { + Inkscape::UI::Tools::NodeTool *nt = static_cast(event_context); + if (!nt->_selected_nodes->empty()) { + Geom::Rect nodes = *nt->_selected_nodes->bounds(); + double area = nodes.area(); + // do not zoom if a single cusp node is selected aand the bounds + // have zero area. + if (!Geom::are_near(area, 0)) { + set_display_area(nodes, true); + zoomed = true; + } + } + } + + if (!zoomed) { + Geom::OptRect const d = selection->visualBounds(); + if (d) { + set_display_area(*d, true); + zoomed = true; + } + } + + if (!zoomed) { + Geom::Rect const d_canvas = canvas->getViewbox(); // Not SVG 'viewBox' + Geom::Point midpoint = w2d(d_canvas.midpoint()); // Midpoint of drawing on canvas. + zoom_relative_center_point(midpoint, 2.0); + } + } else { + _current_affine = _quick_zoom_affine; + set_display_area( false ); } - set_display_area(*d, 10); + _quick_zoom_enabled = enable; + return; } + /** - * Scroll canvas by specific coordinate amount in svg coordinates. + * Tell widget to let zoom widget grab keyboard focus. */ void -SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling) +SPDesktop::zoom_grab_focus() { - double scale = _d2w.descrim(); - scroll_world(dx*scale, dy*scale, is_scrolling); + _widget->letZoomGrabFocus(); } + /** - * Scroll canvas by specific coordinate amount. + * Scroll canvas by to a particular point (window coordinates). */ void -SPDesktop::scroll_world (double dx, double dy, bool is_scrolling) +SPDesktop::scroll_absolute (Geom::Point const &point, bool is_scrolling) { - g_assert(_widget); - - Geom::Rect const viewbox = canvas->getViewbox(); - - canvas->scrollTo(viewbox.min()[Geom::X] - dx, viewbox.min()[Geom::Y] - dy, FALSE, is_scrolling); + canvas->scrollTo(point, FALSE, is_scrolling); + _current_affine.setOffset( point ); /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ //sp_box3d_context_update_lines(event_context); @@ -1144,9 +1101,36 @@ SPDesktop::scroll_world (double dx, double dy, bool is_scrolling) } _widget->updateRulers(); - _widget->updateScrollbars(_d2w.descrim()); + _widget->updateScrollbars(_current_affine.getZoom()); } + +/** + * Scroll canvas by specific coordinate amount (window coordinates). + */ +void +SPDesktop::scroll_relative (Geom::Point const &delta, bool is_scrolling) +{ + Geom::Rect const viewbox = canvas->getViewbox(); + scroll_absolute( viewbox.min() - delta, is_scrolling ); +} + + +/** + * Scroll canvas by specific coordinate amount in svg coordinates. + */ +void +SPDesktop::scroll_relative_in_svg_coords (double dx, double dy, bool is_scrolling) +{ + double scale = _current_affine.getZoom(); + scroll_relative(Geom::Point(dx*scale, dy*scale), is_scrolling); +} + + +/** + * Scroll screen so as to keep point 'p' visible in window. 'p' is in drawing coordinates. + * (Used, for example, when a node is being dragged.) + */ bool SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) { @@ -1157,7 +1141,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) gdouble autoscrolldistance = (gdouble) prefs->getIntLimited("/options/autoscrolldistance/value", 0, -1000, 10000); // autoscrolldistance is in screen pixels, but the display area is in document units - autoscrolldistance /= _d2w.descrim(); + autoscrolldistance /= _current_affine.getZoom(); // FIXME: This 2geom idiom doesn't allow us to declare dbox const Geom::Rect dbox = get_display_area(); dbox.expandBy(-autoscrolldistance); @@ -1165,7 +1149,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) || !(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) { - Geom::Point const s_w( p * (Geom::Affine)_d2w ); + Geom::Point const s_w( p * _current_affine.d2w() ); gdouble x_to; if (p[X] < dbox.min()[X]) @@ -1184,14 +1168,14 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) y_to = p[Y]; Geom::Point const d_dt(x_to, y_to); - Geom::Point const d_w( d_dt * _d2w ); + Geom::Point const d_w( d_dt * _current_affine.d2w() ); Geom::Point const moved_w( d_w - s_w ); if (autoscrollspeed == 0) autoscrollspeed = prefs->getDoubleLimited("/options/autoscrollspeed/value", 1, 0, 10); if (autoscrollspeed != 0) - scroll_world (autoscrollspeed * moved_w); + scroll_relative (autoscrollspeed * moved_w); return true; } @@ -1380,6 +1364,28 @@ SPDesktop::onWindowStateEvent (GdkEventWindowState* event) return false; } + +/** + * Apply the desktop's current style or the tool style to the object. + */ +void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text) +{ + SPCSSAttr *css_current = sp_desktop_get_style(this, with_text); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + if (prefs->getBool(tool_path + "/usecurrent") && css_current) { + obj->setCSS(css_current,"style"); + } else { + SPCSSAttr *css = prefs->getInheritedStyle(tool_path + "/style"); + obj->setCSS(css,"style"); + sp_repr_css_attr_unref(css); + } + if (css_current) { + sp_repr_css_attr_unref(css_current); + } +} + + void SPDesktop::setToolboxFocusTo (gchar const *label) { @@ -1623,7 +1629,7 @@ SPDesktop::_onSelectionModified (Inkscape::Selection */*selection*/, guint /*flags*/, SPDesktop *dt) { if (!dt->_widget) return; - dt->_widget->updateScrollbars (dt->_d2w.descrim()); + dt->_widget->updateScrollbars (dt->_current_affine.getZoom()); } static void @@ -1765,17 +1771,17 @@ static void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) Geom::Affine SPDesktop::w2d() const { - return _w2d; + return _current_affine.w2d(); } Geom::Point SPDesktop::w2d(Geom::Point const &p) const { - return p * _w2d; + return p * _current_affine.w2d(); } Geom::Point SPDesktop::d2w(Geom::Point const &p) const { - return p * _d2w; + return p * _current_affine.d2w(); } Geom::Affine SPDesktop::doc2dt() const -- cgit v1.2.3 From 02c5ac41e41fb335cd2946bfbb9e418a9116ba48 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 14 Mar 2017 11:17:48 +0100 Subject: Add functions to rotate drawing inside desktop. (bzr r15595) --- src/desktop.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index ddd5dfe83..f33c2bc29 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1085,6 +1085,48 @@ SPDesktop::zoom_grab_focus() } +/** + * Rotate keeping the point 'c' fixed in the desktop window. + */ +void +SPDesktop::rotate_absolute_keep_point (Geom::Point const &c, double rotate) +{ + Geom::Point w = d2w( c ); // Must be before rotate changed. + _current_affine.setRotate( rotate ); + set_display_area( c, w ); +} + + +void +SPDesktop::rotate_relative_keep_point (Geom::Point const &c, double rotate) +{ + Geom::Point w = d2w( c ); // Must be before rotate changed. + _current_affine.addRotate( rotate ); + set_display_area( c, w ); +} + + +/** + * Rotate aligning the point 'c' to the center of desktop window. + */ +void +SPDesktop::rotate_absolute_center_point (Geom::Point const &c, double rotate) +{ + _current_affine.setRotate( rotate ); + Geom::Rect viewbox = canvas->getViewbox(); + set_display_area( c, viewbox.midpoint() ); +} + + +void +SPDesktop::rotate_relative_center_point (Geom::Point const &c, double rotate) +{ + _current_affine.addRotate( rotate ); + Geom::Rect viewbox = canvas->getViewbox(); + set_display_area( c, viewbox.midpoint() ); +} + + /** * Scroll canvas by to a particular point (window coordinates). */ -- cgit v1.2.3 From d23459d4fb144af1b84113e756aeec02e415d4ca Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 14 Mar 2017 13:48:27 +0100 Subject: Modify scroll_to_point() to work with rotated desktop. Simplified code to boot. (bzr r15596) --- src/desktop.cpp | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index f33c2bc29..c46d6e2f6 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1170,54 +1170,32 @@ SPDesktop::scroll_relative_in_svg_coords (double dx, double dy, bool is_scrollin /** - * Scroll screen so as to keep point 'p' visible in window. 'p' is in drawing coordinates. + * Scroll screen so as to keep point 'p' visible in window. * (Used, for example, when a node is being dragged.) + * 'p': The point in desktop coordinates. + * 'autoscrollspeed': The scroll speed (or zero to use preferences' value). */ bool SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) { - using Geom::X; - using Geom::Y; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + // autoscrolldistance is in screen pixels. gdouble autoscrolldistance = (gdouble) prefs->getIntLimited("/options/autoscrolldistance/value", 0, -1000, 10000); - // autoscrolldistance is in screen pixels, but the display area is in document units - autoscrolldistance /= _current_affine.getZoom(); - // FIXME: This 2geom idiom doesn't allow us to declare dbox const - Geom::Rect dbox = get_display_area(); - dbox.expandBy(-autoscrolldistance); - - if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) || - !(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) { - - Geom::Point const s_w( p * _current_affine.d2w() ); - - gdouble x_to; - if (p[X] < dbox.min()[X]) - x_to = dbox.min()[X]; - else if (p[X] > dbox.max()[X]) - x_to = dbox.max()[X]; - else - x_to = p[X]; - - gdouble y_to; - if (p[Y] < dbox.min()[Y]) - y_to = dbox.min()[Y]; - else if (p[Y] > dbox.max()[Y]) - y_to = dbox.max()[Y]; - else - y_to = p[Y]; - - Geom::Point const d_dt(x_to, y_to); - Geom::Point const d_w( d_dt * _current_affine.d2w() ); - Geom::Point const moved_w( d_w - s_w ); + Geom::Rect w = canvas->getViewbox(); // Window in screen coordinates. + w.expandBy(-autoscrolldistance); // Shrink window + + Geom::Point c = d2w(p); // Point 'p' in screen coordinates. + if (!w.contains(c)) { + + Geom::Point c2 = w.clamp(c); // Constrain c to window. if (autoscrollspeed == 0) autoscrollspeed = prefs->getDoubleLimited("/options/autoscrollspeed/value", 1, 0, 10); if (autoscrollspeed != 0) - scroll_relative (autoscrollspeed * moved_w); + scroll_relative (autoscrollspeed * (c2 - c) ); return true; } -- cgit v1.2.3 From 9e2d75331ec8fa10b2fbdd7216ef2226995bea82 Mon Sep 17 00:00:00 2001 From: Minglangjun Li Date: Sun, 19 Mar 2017 13:03:55 +0800 Subject: Fix lp:1670688. Fixed bugs: - https://launchpad.net/bugs/1670688 (bzr r15577.1.1) --- src/desktop.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index 2476b10bb..a5bf99e55 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1531,12 +1531,16 @@ SPDesktop::setDocument (SPDocument *doc) layers->setDocument(doc); selection->setDocument(doc); - // remove old EventLog if it exists (see also: bug #1071082) - if (event_log) { - doc->removeUndoObserver(*event_log); - delete event_log; - event_log = 0; - } + if (event_log) { + // Remove it from the replaced document. This prevents Inkscape from + // crashing since we access it in the replaced document's destructor + // which results in an undefined behavior. (See also: bug #1670688) + if (this->doc()) { + this->doc()->removeUndoObserver(*event_log); + } + delete event_log; + event_log = 0; + } /* setup EventLog */ event_log = new Inkscape::EventLog(doc); -- cgit v1.2.3 From f47466c701b2256b2ce232f6d311d2be47136eab Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 20 Mar 2017 21:12:31 +0100 Subject: Implement rotation via desktop to window affine. Remove rotation via viewbox. Still some work to do... (bzr r15603) --- src/desktop.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index c46d6e2f6..c2fdee959 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -838,6 +838,7 @@ SPDesktop::set_display_area (bool log) _widget->updateRulers(); _widget->updateScrollbars(_current_affine.getZoom()); _widget->updateZoom(); + _widget->updateRotation(); signal_zoom_changed.emit(_current_affine.getZoom()); } -- cgit v1.2.3 From a184a53752fb8027c22e4a5d68819fd7b78a15d8 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 22 Mar 2017 20:03:41 +0100 Subject: Add canvas flip. No GUI. Can be bound to keys via preferences. (bzr r15606) --- src/desktop.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index c2fdee959..730a542e2 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1128,6 +1128,48 @@ SPDesktop::rotate_relative_center_point (Geom::Point const &c, double rotate) } +/** + * Flip keeping the point 'c' fixed in the desktop window. + */ +void +SPDesktop::flip_absolute_keep_point (Geom::Point const &c, CanvasFlip flip) +{ + Geom::Point w = d2w( c ); // Must be before flip. + _current_affine.setFlip( flip ); + set_display_area( c, w ); +} + + +void +SPDesktop::flip_relative_keep_point (Geom::Point const &c, CanvasFlip flip) +{ + Geom::Point w = d2w( c ); // Must be before flip. + _current_affine.addFlip( flip ); + set_display_area( c, w ); +} + + +/** + * Flip aligning the point 'c' to the center of desktop window. + */ +void +SPDesktop::flip_absolute_center_point (Geom::Point const &c, CanvasFlip flip) +{ + _current_affine.setFlip( flip ); + Geom::Rect viewbox = canvas->getViewbox(); + set_display_area( c, viewbox.midpoint() ); +} + + +void +SPDesktop::flip_relative_center_point (Geom::Point const &c, CanvasFlip flip) +{ + _current_affine.addFlip( flip ); + Geom::Rect viewbox = canvas->getViewbox(); + set_display_area( c, viewbox.midpoint() ); +} + + /** * Scroll canvas by to a particular point (window coordinates). */ -- cgit v1.2.3 From 3de63445fe736ca7c67cdce96426f6e5e3b8ebf4 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 30 Mar 2017 11:41:29 +0200 Subject: Add canvas-rotate for rapid previewing canvas rotation. Add canvas-debug for study of canvas tiling. (bzr r15612) --- src/desktop.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/desktop.cpp') diff --git a/src/desktop.cpp b/src/desktop.cpp index ccc3d3da4..c56c42267 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -40,7 +40,9 @@ #include "desktop-style.h" #include "device-manager.h" #include "display/canvas-arena.h" +#include "display/canvas-debug.h" #include "display/canvas-grid.h" +#include "display/canvas-rotate.h" #include "display/canvas-temporary-item-list.h" #include "display/drawing-group.h" #include "display/gnome-canvas-acetate.h" @@ -129,7 +131,6 @@ SPDesktop::SPDesktop() : layers->_layer_deactivated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_deactivated), this)); layers->_layer_changed_signal.connect(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this)); selection = Inkscape::GC::release( new Inkscape::Selection(layers, this) ); - // _current_affine.setRotate(M_PI/4); // To test zooming with rotation } void @@ -221,10 +222,10 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid // being selected? or does it intercept some of the events that should have gone to the // node handler? see bug https://bugs.launchpad.net/inkscape/+bug/414142) gridgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); - guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); - sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); tempgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); - controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); // Set the select tool as the active tool. set_event_context2("/tools/select"); @@ -252,7 +253,8 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid _doc2dt[5] = document->getHeight().value("px"); sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); - _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); + _modified_connection = + namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); Inkscape::DrawingItem *ai = document->getRoot()->invoke_show( SP_CANVAS_ARENA (drawing)->drawing, @@ -314,6 +316,10 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid temporary_item_list = new Inkscape::Display::TemporaryItemList( this ); snapindicator = new Inkscape::Display::SnapIndicator ( this ); + + canvas_rotate = sp_canvas_item_new (root, SP_TYPE_CANVAS_ROTATE, NULL); + sp_canvas_item_hide( canvas_rotate ); + // canvas_debug = sp_canvas_item_new (main, SP_TYPE_CANVAS_DEBUG, NULL); } -- cgit v1.2.3