diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2016-04-13 11:38:28 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2016-04-13 11:38:28 +0000 |
| commit | d2a3bc0b327557fba34f09a110a0ac5b6d18f85e (patch) | |
| tree | a852962eb33ecbb72e1ef832bd5f74075dfb1874 /src | |
| parent | gimpcolorwheel: Fix deprecated gtk_widget_style_attach #Hackfest2016 (diff) | |
| download | inkscape-d2a3bc0b327557fba34f09a110a0ac5b6d18f85e.tar.gz inkscape-d2a3bc0b327557fba34f09a110a0ac5b6d18f85e.zip | |
Move background drawing to SPCanvas to avoid temporarily drawing an incorrect
background. #Hackfest2016
(bzr r14821)
Diffstat (limited to 'src')
| -rw-r--r-- | src/desktop.cpp | 17 | ||||
| -rw-r--r-- | src/desktop.h | 1 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 85 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 18 |
4 files changed, 79 insertions, 42 deletions
diff --git a/src/desktop.cpp b/src/desktop.cpp index 331ab3351..5cd9ef32f 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -111,7 +111,6 @@ SPDesktop::SPDesktop() : sketch( NULL ), controls( NULL ), tempgroup ( NULL ), - table( NULL ), page( NULL ), page_border( NULL ), current( NULL ), @@ -211,11 +210,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid g_signal_connect (G_OBJECT (main), "event", G_CALLBACK (sp_desktop_root_handler), this); /* This is the background the page sits on. */ - table = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL); - SP_CTRLRECT(table)->setRectangle(Geom::Rect(Geom::Point(-80000, -80000), Geom::Point(80000, 80000))); - SP_CTRLRECT(table)->setColor(0x00000000, true, 0x00000000); - SP_CTRLRECT(table)->setCheckerboard( false ); - sp_canvas_item_move_to_z (table, 0); + canvas->setBackgroundColor(0xffffff00); page = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL); ((CtrlRect *) page)->setColor(0x00000000, FALSE, 0x00000000); @@ -1733,17 +1728,11 @@ static void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) SPNamedView *nv=SP_NAMEDVIEW(obj); if (flags & SP_OBJECT_MODIFIED_FLAG) { - - /* Set page background */ - sp_canvas_item_show (desktop->table); if (nv->pagecheckerboard) { - ((CtrlRect *) desktop->table)->setCheckerboard( true ); - ((CtrlRect *) desktop->table)->setColor(0x00000000, true, nv->pagecolor ); // | 0xff); + desktop->canvas->setBackgroundCheckerboard(); } else { - ((CtrlRect *) desktop->table)->setCheckerboard( false ); - ((CtrlRect *) desktop->table)->setColor(0x00000000, true, nv->pagecolor | 0xff); + desktop->canvas->setBackgroundColor(nv->pagecolor); } - sp_canvas_item_move_to_z (desktop->table, 0); /* Show/hide page border */ if (nv->showborder) { diff --git a/src/desktop.h b/src/desktop.h index f1444ba7b..3652d4a97 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -174,7 +174,6 @@ public: SPCanvasGroup *sketch; SPCanvasGroup *controls; SPCanvasGroup *tempgroup; ///< contains temporary canvas items - SPCanvasItem *table; ///< outside-of-page background SPCanvasItem *page; ///< page background SPCanvasItem *page_border; ///< page border SPCSSAttr *current; ///< current style diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 644da8d5a..6b7836d2e 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -27,6 +27,7 @@ #include "helper/sp-marshal.h" #include <2geom/rect.h> #include <2geom/affine.h> +#include "display/cairo-utils.h" #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" #include "preferences.h" @@ -37,6 +38,7 @@ #include "display/cairo-utils.h" #include "debug/gdk-event-latency-tracker.h" #include "desktop.h" +#include "color.h" using Inkscape::Debug::GdkEventLatencyTracker; @@ -959,6 +961,8 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_backing_store = NULL; canvas->_clean_region = cairo_region_create(); + canvas->_background = cairo_pattern_create_rgb(1, 1, 1); + canvas->_background_is_checkerboard = false; canvas->_forced_redraw_count = 0; canvas->_forced_redraw_limit = -1; @@ -972,10 +976,7 @@ static void sp_canvas_init(SPCanvas *canvas) void SPCanvas::shutdownTransients() { // Reset the clean region - if (_clean_region && !cairo_region_is_empty(_clean_region)) { - cairo_region_destroy(_clean_region); - _clean_region = cairo_region_create(); - } + dirtyAll(); if (_grabbed_item) { _grabbed_item = NULL; @@ -1006,6 +1007,10 @@ void SPCanvas::dispose(GObject *object) cairo_region_destroy(canvas->_clean_region); canvas->_clean_region = NULL; } + if (canvas->_background) { + cairo_pattern_destroy(canvas->_background); + canvas->_background = NULL; + } canvas->shutdownTransients(); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) @@ -1529,9 +1534,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect { GtkWidget *widget = GTK_WIDGET (this); - // Mark the region clean - markRect(paint_rect, 0); - SPCanvasBuf buf; buf.buf = NULL; buf.buf_rowstride = 0; @@ -1543,7 +1545,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect // create temporary surface cairo_surface_t *imgs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, paint_rect.width(), paint_rect.height()); buf.ct = cairo_create(imgs); - //cairo_translate(buf.ct, -x0, -y0); // fix coordinates, clip all drawing to the tile and clear the background //cairo_translate(buf.ct, paint_rect.left() - canvas->x0, paint_rect.top() - canvas->y0); @@ -1553,18 +1554,12 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect //cairo_stroke_preserve(buf.ct); //cairo_clip(buf.ct); -#if GTK_CHECK_VERSION(3,0,0) - GtkStyleContext *context = gtk_widget_get_style_context(widget); - gtk_render_background(context, buf.ct, 0, 0, paint_rect.width(), paint_rect.height()); -#else - GtkStyle *style = gtk_widget_get_style (widget); - gdk_cairo_set_source_color(buf.ct, &style->bg[GTK_STATE_NORMAL]); -#endif - + cairo_save(buf.ct); + cairo_translate(buf.ct, -paint_rect.left(), -paint_rect.top()); + cairo_set_source(buf.ct, _background); cairo_set_operator(buf.ct, CAIRO_OPERATOR_SOURCE); - //cairo_rectangle(buf.ct, 0, 0, paint_rect.width(), paint_rec.height()); cairo_paint(buf.ct); - cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); + cairo_restore(buf.ct); if (_root->visible) { SP_CANVAS_ITEM_GET_CLASS(_root)->render(_root, &buf); @@ -1608,8 +1603,8 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_destroy(xct); cairo_surface_destroy(imgs); - cairo_rectangle_int_t crect = { paint_rect.left(), paint_rect.right(), paint_rect.width(), paint_rect.height() }; - cairo_region_union_rectangle(_clean_region, &crect); + // Mark the painted rectangle clean + markRect(paint_rect, 0); gtk_widget_queue_draw_area(GTK_WIDGET(this), paint_rect.left() -_x0, paint_rect.top() - _y0, paint_rect.width(), paint_rect.height()); @@ -1816,6 +1811,16 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) { cairo_region_subtract(draw_dirty, canvas->_clean_region); cairo_region_intersect(draw_region, canvas->_clean_region); + // Draw the background + cairo_save(cr); + cairo_translate(cr, -canvas->_x0, -canvas->_y0); + cairo_set_source(cr, canvas->_background); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_restore(cr); + /*cairo_set_source(cr, canvas->_background); + cairo_paint(cr);*/ + // Draw the clean portion if (!cairo_region_is_empty(draw_region)) { cairo_region_translate(draw_region, -canvas->_x0, -canvas->_y0); @@ -2007,6 +2012,7 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll gtk_widget_get_allocation(&_widget, &allocation); + // adjust backing store contents assert(_backing_store); cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height); @@ -2021,8 +2027,7 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll _backing_store = new_backing_store; if (clear) { - cairo_region_destroy(_clean_region); - _clean_region = cairo_region_create(); + dirtyAll(); } else { cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; cairo_region_intersect_rectangle(_clean_region, &crect); @@ -2070,6 +2075,35 @@ void SPCanvas::requestRedraw(int x0, int y0, int x1, int y1) addIdle(); } +void SPCanvas::setBackgroundColor(guint32 rgba) { + double new_r = SP_RGBA32_R_F(rgba); + double new_g = SP_RGBA32_G_F(rgba); + double new_b = SP_RGBA32_B_F(rgba); + if (!_background_is_checkerboard) { + double old_r, old_g, old_b; + cairo_pattern_get_rgba(_background, &old_r, &old_g, &old_b, NULL); + if (new_r == old_r && new_g == old_g && new_b == old_b) return; + } + if (_background) { + cairo_pattern_destroy(_background); + } + _background = cairo_pattern_create_rgb(new_r, new_g, new_b); + _background_is_checkerboard = false; + dirtyAll(); + addIdle(); +} + +void SPCanvas::setBackgroundCheckerboard() { + if (_background_is_checkerboard) return; + if (_background) { + cairo_pattern_destroy(_background); + } + _background = ink_cairo_pattern_create_checkerboard(); + _background_is_checkerboard = true; + dirtyAll(); + addIdle(); +} + /** * Sets world coordinates from win and canvas. */ @@ -2175,6 +2209,13 @@ void SPCanvas::dirtyRect(Geom::IntRect const &area) { markRect(area, 1); } +void SPCanvas::dirtyAll() { + if (_clean_region && !cairo_region_is_empty(_clean_region)) { + cairo_region_destroy(_clean_region); + _clean_region = cairo_region_create(); + } +} + void SPCanvas::markRect(Geom::IntRect const &area, uint8_t val) { cairo_rectangle_int_t crect = { area.left(), area.top(), area.width(), area.height() }; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index a1f8d0a1a..171fdaf67 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -87,6 +87,9 @@ struct SPCanvas { Geom::IntRect getViewboxIntegers() const; SPCanvasGroup *getRoot(); + void setBackgroundColor(guint32 rgba); + void setBackgroundCheckerboard(); + /// Returns new canvas as widget. static GtkWidget *createAA(); @@ -105,7 +108,8 @@ private: /// Marks the specified area as dirty (requiring redraw) void dirtyRect(Geom::IntRect const &area); - /// Marks specific canvas rectangle as clean (val == 0) or dirty (otherwise) + /// Marks the whole widget for redraw + void dirtyAll(); void markRect(Geom::IntRect const &area, uint8_t val); /// Invokes update, paint, and repick on canvas. @@ -177,14 +181,18 @@ public: bool _is_dragging; double _dx0; double _dy0; - int _x0; - int _y0; + int _x0; ///< World coordinate of the leftmost pixels + int _y0; ///< World coordinate of the topmost pixels - /* Area that needs redrawing, stored as a microtile array */ + /// Image surface storing the contents of the widget cairo_surface_t *_backing_store; + /// Area of the widget that has up-to-date content cairo_region_t *_clean_region; + /// Widget background, defaults to white + cairo_pattern_t *_background; + bool _background_is_checkerboard; - /** Last known modifier state, for deferred repick when a button is down. */ + /// Last known modifier state, for deferred repick when a button is down. int _state; /** The item containing the mouse pointer, or NULL if none. */ |
