X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdisplay%2Fsp-canvas.cpp;h=9cc37a1a0c5b6b1c5a885b3a33d737a1b828164b;hb=8f2afbd99dcbbe962be70bc574e356b33c8b9537;hp=1714bd454e246abcff32c90af93be9f9536588a0;hpb=1dec520cc2d39cea31661d4a8fa1cad67facb255;p=inkscape.git diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 1714bd454..9cc37a1a0 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -34,28 +34,22 @@ #include #include #include "prefs-utils.h" -#include "box3d-context.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" #if ENABLE_LCMS #include "color-profile-fns.h" #endif // ENABLE_LCMS +#include "display/rendermode.h" // Define this to visualize the regions to be redrawn //#define DEBUG_REDRAW 1; -// Tiles are a way to minimize the number of redraws, eliminating too small redraws. +// Tiles are a way to minimize the number of redraws, eliminating too small redraws. // The canvas stores a 2D array of ints, each representing a TILE_SIZExTILE_SIZE pixels tile. // If any part of it is dirtied, the entire tile is dirtied (its int is nonzero) and repainted. #define TILE_SIZE 16 -enum { - RENDERMODE_NORMAL, - RENDERMODE_NOAA, - RENDERMODE_OUTLINE -}; - -const gint sp_canvas_update_priority = G_PRIORITY_HIGH_IDLE; +static gint const sp_canvas_update_priority = G_PRIORITY_HIGH_IDLE; #define SP_CANVAS_WINDOW(c) (((GtkWidget *) (c))->window) @@ -101,7 +95,7 @@ static void sp_canvas_request_update (SPCanvas *canvas); static void sp_canvas_item_class_init (SPCanvasItemClass *klass); static void sp_canvas_item_init (SPCanvasItem *item); static void sp_canvas_item_dispose (GObject *object); -static void sp_canvas_item_construct (SPCanvasItem *item, SPCanvasGroup *parent, const gchar *first_arg_name, va_list args); +static void sp_canvas_item_construct (SPCanvasItem *item, SPCanvasGroup *parent, gchar const *first_arg_name, va_list args); static int emit_event (SPCanvas *canvas, GdkEvent *event); @@ -117,7 +111,7 @@ sp_canvas_item_get_type (void) { static GType type = 0; if (!type) { - static const GTypeInfo info = { + static GTypeInfo const info = { sizeof (SPCanvasItemClass), NULL, NULL, (GClassInitFunc) sp_canvas_item_class_init, @@ -147,7 +141,7 @@ sp_canvas_item_class_init (SPCanvasItemClass *klass) item_signals[ITEM_EVENT] = g_signal_new ("event", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SPCanvasItemClass, event), + ((glong)((guint8*)&(klass->event) - (guint8*)klass)), NULL, NULL, sp_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, @@ -170,7 +164,7 @@ sp_canvas_item_init (SPCanvasItem *item) * Constructs new SPCanvasItem on SPCanvasGroup. */ SPCanvasItem * -sp_canvas_item_new (SPCanvasGroup *parent, GtkType type, const gchar *first_arg_name, ...) +sp_canvas_item_new (SPCanvasGroup *parent, GtkType type, gchar const *first_arg_name, ...) { va_list args; @@ -193,7 +187,7 @@ sp_canvas_item_new (SPCanvasGroup *parent, GtkType type, const gchar *first_arg_ * We make it static for encapsulation reasons since it was nowhere used. */ static void -sp_canvas_item_construct (SPCanvasItem *item, SPCanvasGroup *parent, const gchar *first_arg_name, va_list args) +sp_canvas_item_construct (SPCanvasItem *item, SPCanvasGroup *parent, gchar const *first_arg_name, va_list args) { g_return_if_fail (SP_IS_CANVAS_GROUP (parent)); g_return_if_fail (SP_IS_CANVAS_ITEM (item)); @@ -299,11 +293,11 @@ sp_canvas_item_invoke_update (SPCanvasItem *item, NR::Matrix const &affine, unsi GTK_OBJECT_UNSET_FLAGS (item, SP_CANVAS_ITEM_NEED_AFFINE); } -/** - * Helper function to invoke the point method of the item. +/** + * Helper function to invoke the point method of the item. * - * The argument x, y should be in the parent's item-relative coordinate - * system. This routine applies the inverse of the item's transform, + * The argument x, y should be in the parent's item-relative coordinate + * system. This routine applies the inverse of the item's transform, * maintaining the affine invariant. */ static double @@ -318,12 +312,12 @@ sp_canvas_item_invoke_point (SPCanvasItem *item, NR::Point p, SPCanvasItem **act /** * Makes the item's affine transformation matrix be equal to the specified * matrix. - * + * * @item: A canvas item. * @affine: An affine transformation matrix. */ void -sp_canvas_item_affine_absolute (SPCanvasItem *item, NR::Matrix const& affine) +sp_canvas_item_affine_absolute (SPCanvasItem *item, NR::Matrix const &affine) { item->xform = affine; @@ -340,7 +334,7 @@ sp_canvas_item_affine_absolute (SPCanvasItem *item, NR::Matrix const& affine) } /** - * Convenience function to reorder items in a group's child list. + * Convenience function to reorder items in a group's child list. * * This puts the specified link after the "before" link. */ @@ -396,7 +390,7 @@ put_item_after (GList *link, GList *before) /** * Raises the item in its parent's stack by the specified number of positions. - * + * * \param item A canvas item. * \param positions Number of steps to raise the item. * @@ -519,7 +513,7 @@ sp_canvas_item_hide (SPCanvasItem *item) /** * Grab item under cursor. - * + * * \pre !canvas->grabbed_item && item->flags & SP_CANVAS_ITEM_VISIBLE */ int @@ -552,7 +546,7 @@ sp_canvas_item_grab (SPCanvasItem *item, guint event_mask, GdkCursor *cursor, gu /** * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the * mouse. - * + * * \param item A canvas item that holds a grab. * \param etime The timestamp for ungrabbing the mouse. */ @@ -639,7 +633,7 @@ sp_canvas_item_grab_focus (SPCanvasItem *item) /** * Requests that the canvas queue an update for the specified item. - * + * * To be used only by item implementations. */ void @@ -682,25 +676,25 @@ static SPCanvasItemClass *group_parent_class; /** * Registers SPCanvasGroup class with Gtk and returns its type number. */ -GtkType -sp_canvas_group_get_type (void) +GType sp_canvas_group_get_type(void) { - static GtkType group_type = 0; - - if (!group_type) { - static const GtkTypeInfo group_info = { - "SPCanvasGroup", - sizeof (SPCanvasGroup), - sizeof (SPCanvasGroupClass), - (GtkClassInitFunc) sp_canvas_group_class_init, - (GtkObjectInitFunc) sp_canvas_group_init, - NULL, NULL, NULL + static GType type = 0; + if (!type) { + GTypeInfo info = { + sizeof(SPCanvasGroupClass), + 0, // base_init + 0, // base_finalize + (GClassInitFunc)sp_canvas_group_class_init, + 0, // class_finalize + 0, // class_data + sizeof(SPCanvasGroup), + 0, // n_preallocs + (GInstanceInitFunc)sp_canvas_group_init, + 0 // value_table }; - - group_type = gtk_type_unique (sp_canvas_item_get_type (), &group_info); + type = g_type_register_static(sp_canvas_item_get_type(), "SPCanvasGroup", &info, static_cast(0)); } - - return group_type; + return type; } /** @@ -731,7 +725,7 @@ sp_canvas_group_init (SPCanvasGroup */*group*/) } /** - * Callback that destroys all items in group and calls group's virtual + * Callback that destroys all items in group and calls group's virtual * destroy() function. */ static void @@ -740,7 +734,7 @@ sp_canvas_group_destroy (GtkObject *object) g_return_if_fail (object != NULL); g_return_if_fail (SP_IS_CANVAS_GROUP (object)); - const SPCanvasGroup *group = SP_CANVAS_GROUP (object); + SPCanvasGroup const *group = SP_CANVAS_GROUP (object); GList *list = group->items; while (list) { @@ -760,7 +754,7 @@ sp_canvas_group_destroy (GtkObject *object) static void sp_canvas_group_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags) { - const SPCanvasGroup *group = SP_CANVAS_GROUP (item); + SPCanvasGroup const *group = SP_CANVAS_GROUP (item); NR::ConvexHull corners(NR::Point(0, 0)); bool empty=true; @@ -798,9 +792,9 @@ sp_canvas_group_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned i static double sp_canvas_group_point (SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_item) { - const SPCanvasGroup *group = SP_CANVAS_GROUP (item); - const double x = p[NR::X]; - const double y = p[NR::Y]; + SPCanvasGroup const *group = SP_CANVAS_GROUP (item); + double const x = p[NR::X]; + double const y = p[NR::Y]; int x1 = (int)(x - item->canvas->close_enough); int y1 = (int)(y - item->canvas->close_enough); int x2 = (int)(x + item->canvas->close_enough); @@ -840,7 +834,7 @@ sp_canvas_group_point (SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_it static void sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf) { - const SPCanvasGroup *group = SP_CANVAS_GROUP (item); + SPCanvasGroup const *group = SP_CANVAS_GROUP (item); for (GList *list = group->items; list; list = list->next) { SPCanvasItem *child = (SPCanvasItem *)list->data; @@ -875,7 +869,7 @@ group_add (SPCanvasGroup *group, SPCanvasItem *item) sp_canvas_item_request_update (item); } -/** +/** * Removes an item from a canvas group */ static void @@ -938,25 +932,25 @@ static int do_update (SPCanvas *canvas); * * \return The type ID of the SPCanvas class. **/ -GtkType -sp_canvas_get_type (void) -{ - static GtkType canvas_type = 0; - - if (!canvas_type) { - static const GtkTypeInfo canvas_info = { - "SPCanvas", - sizeof (SPCanvas), - sizeof (SPCanvasClass), - (GtkClassInitFunc) sp_canvas_class_init, - (GtkObjectInitFunc) sp_canvas_init, - NULL, NULL, NULL +GType sp_canvas_get_type(void) +{ + static GType type = 0; + if (!type) { + GTypeInfo info = { + sizeof(SPCanvasClass), + 0, // base_init + 0, // base_finalize + (GClassInitFunc)sp_canvas_class_init, + 0, // class_finalize + 0, // class_data + sizeof(SPCanvas), + 0, // n_preallocs + (GInstanceInitFunc)sp_canvas_init, + 0 // value_table }; - - canvas_type = gtk_type_unique (GTK_TYPE_WIDGET, &canvas_info); + type = g_type_register_static(GTK_TYPE_WIDGET, "SPCanvas", &info, static_cast(0)); } - - return canvas_type; + return type; } /** @@ -989,7 +983,7 @@ sp_canvas_class_init (SPCanvasClass *klass) widget_class->focus_out_event = sp_canvas_focus_out; } -/** +/** * Callback: object initialization for SPCanvas. */ static void @@ -1022,6 +1016,11 @@ sp_canvas_init (SPCanvas *canvas) canvas->forced_redraw_count = 0; canvas->forced_redraw_limit = -1; +#if ENABLE_LCMS + canvas->enable_cms_display_adj = false; + canvas->cms_key = new Glib::ustring(""); +#endif // ENABLE_LCMS + canvas->is_scrolling = false; } @@ -1147,6 +1146,10 @@ sp_canvas_unrealize (GtkWidget *widget) { SPCanvas *canvas = SP_CANVAS (widget); + canvas->current_item = NULL; + canvas->grabbed_item = NULL; + canvas->focused_item = NULL; + shutdown_transients (canvas); gdk_gc_destroy (canvas->pixmap_gc); @@ -1194,7 +1197,7 @@ sp_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation) } widget->allocation = *allocation; - + if (GTK_WIDGET_REALIZED (widget)) { gdk_window_move_resize (widget->window, widget->allocation.x, widget->allocation.y, @@ -1203,7 +1206,7 @@ sp_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation) } /** - * Helper that emits an event for an item in the canvas, be it the current + * Helper that emits an event for an item in the canvas, be it the current * item, grabbed item, or focused item, as appropriate. */ static int @@ -1310,7 +1313,7 @@ emit_event (SPCanvas *canvas, GdkEvent *event) } /** - * Helper that re-picks the current item in the canvas, based on the event's + * Helper that re-picks the current item in the canvas, based on the event's * coordinates and emits enter/leave events for items as appropriate. */ static int @@ -1461,7 +1464,7 @@ sp_canvas_button (GtkWidget *widget, GdkEventButton *event) /* dispatch normally regardless of the event's window if an item has has a pointer grab in effect */ - if (!canvas->grabbed_item && + if (!canvas->grabbed_item && event->window != SP_CANVAS_WINDOW (canvas)) return retval; @@ -1540,6 +1543,9 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event) if (event->window != SP_CANVAS_WINDOW (canvas)) return FALSE; + if (canvas->pixmap_gc == NULL) // canvas being deleted + return FALSE; + if (canvas->grabbed_event_mask & GDK_POINTER_MOTION_HINT_MASK) { gint x, y; gdk_window_get_pointer (widget->window, &x, &y, NULL); @@ -1559,7 +1565,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, GtkWidget *widget = GTK_WIDGET (canvas); SPCanvasBuf buf; - if (canvas->rendermode != RENDERMODE_OUTLINE) { + if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) { buf.buf = nr_pixelstore_256K_new (FALSE, 0); } else { buf.buf = nr_pixelstore_1M_new (FALSE, 0); @@ -1588,14 +1594,18 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, } #if ENABLE_LCMS - cmsHPROFILE hprof = Inkscape::colorprofile_get_system_profile_handle(); - cmsHPROFILE srcprof = hprof ? cmsCreate_sRGBProfile() : 0; - cmsHTRANSFORM transf = hprof ? cmsCreateTransform( srcprof, TYPE_RGB_8, hprof, TYPE_RGB_8, INTENT_PERCEPTUAL, 0 ) : 0; + cmsHTRANSFORM transf = 0; + long long int fromDisplay = prefs_get_int_attribute_limited( "options.displayprofile", "from_display", 0, 0, 1 ); + if ( fromDisplay ) { + transf = Inkscape::colorprofile_get_display_per( canvas->cms_key ? *(canvas->cms_key) : "" ); + } else { + transf = Inkscape::colorprofile_get_display_transform(); + } #endif // ENABLE_LCMS if (buf.is_empty) { #if ENABLE_LCMS - if ( transf ) { + if ( transf && canvas->enable_cms_display_adj ) { cmsDoTransform( transf, &buf.bg_color, &buf.bg_color, 1 ); } #endif // ENABLE_LCMS @@ -1610,8 +1620,8 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, // CAIRO FIXME: after SPCanvasBuf is made 32bpp throughout, this rgb_draw below can be replaced with the below. // Why this must not be done currently: // - all canvas items (handles, nodes etc) paint themselves assuming 24bpp -// - cairo assumes bgra, but we have rgba, so r and b get swapped (until we paint all with cairo too) -// - it does not seem to be any faster; in fact since with 32bpp, buf contains less pixels, +// - cairo assumes bgra, but we have rgba, so r and b get swapped (until we paint all with cairo too) +// - it does not seem to be any faster; in fact since with 32bpp, buf contains less pixels, // we need more bufs to paint a given area and as a result it's even a bit slower cairo_surface_t* cst = cairo_image_surface_create_for_data ( @@ -1629,7 +1639,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, */ #if ENABLE_LCMS - if ( transf ) { + if ( transf && canvas->enable_cms_display_adj ) { for ( gint yy = 0; yy < (y1 - y0); yy++ ) { guchar* p = buf.buf + (sw * 3) * yy; cmsDoTransform( transf, p, p, (x1 - x0) ); @@ -1647,15 +1657,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1, x0 - canvas->x0, y0 - canvas->y0); } -#if ENABLE_LCMS - if ( transf ) { - cmsDeleteTransform( transf ); - transf = 0; - } -#endif // ENABLE_LCMS - - - if (canvas->rendermode != RENDERMODE_OUTLINE) { + if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) { nr_pixelstore_256K_free (buf.buf); } else { nr_pixelstore_1M_free (buf.buf); @@ -1695,12 +1697,12 @@ sp_canvas_paint_rect_internal (PaintRectSetup const *setup, NRRectL this_rect) // Interrupting redraw isn't always good. // For example, when you drag one node of a big path, only the buffer containing // the mouse cursor will be redrawn again and again, and the rest of the path - // will remain stale because Inkscape never has enough idle time to redraw all - // of the screen. To work around this, such operations set a forced_redraw_limit > 0. + // will remain stale because Inkscape never has enough idle time to redraw all + // of the screen. To work around this, such operations set a forced_redraw_limit > 0. // If this limit is set, and if we have aborted redraw more times than is allowed, - // interrupting is blocked and we're forced to redraw full screen once + // interrupting is blocked and we're forced to redraw full screen once // (after which we can again interrupt forced_redraw_limit times). - if (setup->canvas->forced_redraw_limit < 0 || + if (setup->canvas->forced_redraw_limit < 0 || setup->canvas->forced_redraw_count < setup->canvas->forced_redraw_limit) { if (setup->canvas->forced_redraw_limit != -1) { @@ -1730,8 +1732,8 @@ sp_canvas_paint_rect_internal (PaintRectSetup const *setup, NRRectL this_rect) NRRectL lo = this_rect; NRRectL hi = this_rect; -/* -This test determines the redraw strategy: +/* +This test determines the redraw strategy: bw < bh (strips mode) splits across the smaller dimension of the rect and therefore (on horizontally-stretched windows) results in redrawing in horizontal strips (from cursor point, in @@ -1745,8 +1747,9 @@ faster. The default for now is the strips mode. */ - if (bw < bh || bh < 2 * TILE_SIZE) { - int mid = (this_rect.x0 + this_rect.x1) / 2; + if (bw < bh || bh < 2 * TILE_SIZE) { + // to correctly calculate the mean of two ints, we need to sum them into a larger int type + int mid = ((long long) this_rect.x0 + (long long) this_rect.x1) / 2; // Make sure that mid lies on a tile boundary mid = (mid / TILE_SIZE) * TILE_SIZE; @@ -1762,7 +1765,8 @@ The default for now is the strips mode. && sp_canvas_paint_rect_internal(setup, lo); } } else { - int mid = (this_rect.y0 + this_rect.y1) / 2; + // to correctly calculate the mean of two ints, we need to sum them into a larger int type + int mid = ((long long) this_rect.y0 + (long long) this_rect.y1) / 2; // Make sure that mid lies on a tile boundary mid = (mid / TILE_SIZE) * TILE_SIZE; @@ -1790,7 +1794,7 @@ static bool sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1) { g_return_val_if_fail (!canvas->need_update, false); - + NRRectL rect; rect.x0 = xx0; rect.x1 = xx1; @@ -1807,11 +1811,11 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1) // paint the area to redraw yellow gdk_rgb_gc_set_foreground (canvas->pixmap_gc, 0xFFFF00); gdk_draw_rectangle (SP_CANVAS_WINDOW (canvas), - canvas->pixmap_gc, - TRUE, - rect.x0 - canvas->x0, rect.y0 - canvas->y0, - rect.x1 - rect.x0, rect.y1 - rect.y0); -#endif + canvas->pixmap_gc, + TRUE, + rect.x0 - canvas->x0, rect.y0 - canvas->y0, + rect.x1 - rect.x0, rect.y1 - rect.y0); +#endif PaintRectSetup setup; @@ -1824,7 +1828,7 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1) setup.mouse_loc = sp_canvas_window_to_world (canvas, NR::Point(x,y)); // CAIRO FIXME: the sw/sh calculations below all assume 24bpp, need fixing for 32bpp - if (canvas->rendermode != RENDERMODE_OUTLINE) { + if (canvas->rendermode != Inkscape::RENDERMODE_OUTLINE) { // use 256K as a compromise to not slow down gradients // 256K is the cached buffer and we need 3 channels setup.max_pixels = 87381; // 256K/3 @@ -1847,7 +1851,7 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1) void sp_canvas_force_full_redraw_after_interruptions(SPCanvas *canvas, unsigned int count) { g_return_if_fail(canvas != NULL); - + canvas->forced_redraw_limit = count; canvas->forced_redraw_count = 0; } @@ -1870,7 +1874,7 @@ sp_canvas_expose (GtkWidget *widget, GdkEventExpose *event) { SPCanvas *canvas = SP_CANVAS (widget); - if (!GTK_WIDGET_DRAWABLE (widget) || + if (!GTK_WIDGET_DRAWABLE (widget) || (event->window != SP_CANVAS_WINDOW (canvas))) return FALSE; @@ -1880,7 +1884,7 @@ sp_canvas_expose (GtkWidget *widget, GdkEventExpose *event) for (int i = 0; i < n_rects; i++) { NRRectL rect; - + rect.x0 = rects[i].x + canvas->x0; rect.y0 = rects[i].y + canvas->y0; rect.x1 = rect.x0 + rects[i].width; @@ -1970,8 +1974,8 @@ paint (SPCanvas *canvas) Gdk::Region to_paint; - for (int j=canvas->tTop; jtBottom; j++) { - for (int i=canvas->tLeft; itRight; i++) { + for (int j=canvas->tTop; jtBottom; j++) { + for (int i=canvas->tLeft; itRight; i++) { int tile_index = (i - canvas->tLeft) + (j - canvas->tTop)*canvas->tileH; if ( canvas->tiles[tile_index] ) { // if this tile is dirtied (nonzero) @@ -2013,7 +2017,7 @@ paint (SPCanvas *canvas) static int do_update (SPCanvas *canvas) { - if (!canvas->root) // canvas may have already be destroyed by closing desktop durring interrupted display! + if (!canvas->root || !canvas->pixmap_gc) // canvas may have already be destroyed by closing desktop durring interrupted display! return TRUE; /* Cause the update if necessary */ @@ -2046,7 +2050,7 @@ idle_handler (gpointer data) SPCanvas *canvas = SP_CANVAS (data); - const int ret = do_update (canvas); + int const ret = do_update (canvas); if (ret) { /* Reset idle id */ @@ -2083,7 +2087,7 @@ sp_canvas_root (SPCanvas *canvas) } /** - * Scrolls canvas to specific position. + * Scrolls canvas to specific position (cx and cy are measured in screen pixels) */ void sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear, bool is_scrolling) @@ -2091,12 +2095,12 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear, g_return_if_fail (canvas != NULL); g_return_if_fail (SP_IS_CANVAS (canvas)); - int ix = (int) (cx + 0.5); - int iy = (int) (cy + 0.5); - int dx = ix - canvas->x0; - int dy = iy - canvas->y0; + int ix = (int) round(cx); // ix and iy are the new canvas coordinates (integer screen pixels) + int iy = (int) round(cy); // cx might be negative, so (int)(cx + 0.5) will not do! + int dx = ix - canvas->x0; // dx and dy specify the displacement (scroll) of the + int dy = iy - canvas->y0; // canvas w.r.t its previous position - canvas->dx0 = cx; + canvas->dx0 = cx; // here the 'd' stands for double, not delta! canvas->dy0 = cy; canvas->x0 = ix; canvas->y0 = iy; @@ -2114,18 +2118,9 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear, } else { // scrolling as part of zoom; do nothing here - the next do_update will perform full redraw } - - /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ - SPEventContext *ec = inkscape_active_event_context(); - if (SP_IS_3DBOX_CONTEXT (ec)) { - // We could avoid redraw during panning by checking the status of is_scrolling, but this is - // neither faster nor does it get rid of artefacts, so we update PLs unconditionally - SP3DBoxContext *bc = SP_3DBOX_CONTEXT (ec); - bc->_vpdrag->updateLines(); - } } -/** +/** * Updates canvas if necessary. */ void @@ -2252,11 +2247,20 @@ bool sp_canvas_world_pt_inside_window(SPCanvas const *canvas, NR::Point const &w NR::Rect SPCanvas::getViewbox() const { GtkWidget const *w = GTK_WIDGET(this); - return NR::Rect(NR::Point(dx0, dy0), NR::Point(dx0 + w->allocation.width, dy0 + w->allocation.height)); } +/** + * Return canvas window coordinates as IRect (a rectangle defined by integers). + */ +NR::IRect SPCanvas::getViewboxIntegers() const +{ + GtkWidget const *w = GTK_WIDGET(this); + return NR::IRect(NR::IPoint(x0, y0), + NR::IPoint(x0 + w->allocation.width, y0 + w->allocation.height)); +} + inline int sp_canvas_tile_floor(int x) { return (x & (~(TILE_SIZE - 1))) / TILE_SIZE; @@ -2350,4 +2354,4 @@ void sp_canvas_mark_rect(SPCanvas* canvas, int nl, int nt, int nr, int nb, uint8 fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :