diff options
| author | Ted Gould <ted@gould.cx> | 2016-08-12 04:11:03 +0000 |
|---|---|---|
| committer | Ted Gould <ted@gould.cx> | 2016-08-12 04:11:03 +0000 |
| commit | ff848ebc9919d158c3ec3d7420e72b6aca99a3ea (patch) | |
| tree | 030ab171865d0ed7f6bae3ef68315639cdb2622b /src/display | |
| parent | Merging 0.92.x branch (diff) | |
| parent | CloneTiler: Further C++ification (diff) | |
| download | inkscape-ff848ebc9919d158c3ec3d7420e72b6aca99a3ea.tar.gz inkscape-ff848ebc9919d158c3ec3d7420e72b6aca99a3ea.zip | |
Merge trunk
(bzr r14950.1.20)
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/Makefile_insert | 125 | ||||
| -rw-r--r-- | src/display/canvas-axonomgrid.cpp | 40 | ||||
| -rw-r--r-- | src/display/canvas-grid.cpp | 40 | ||||
| -rw-r--r-- | src/display/nr-svgfonts.cpp | 35 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 458 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 38 |
6 files changed, 220 insertions, 516 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert deleted file mode 100644 index 419852f7d..000000000 --- a/src/display/Makefile_insert +++ /dev/null @@ -1,125 +0,0 @@ -## Makefile.am fragment sourced by src/Makefile.am. - -display/canvas-arena.$(OBJEXT): helper/sp-marshal.h -display/sp-canvas.$(OBJEXT): helper/sp-marshal.h - -ink_common_sources += \ - display/cairo-templates.h \ - display/cairo-utils.cpp \ - display/cairo-utils.h \ - display/canvas-arena.cpp \ - display/canvas-arena.h \ - display/canvas-axonomgrid.cpp \ - display/canvas-axonomgrid.h \ - display/canvas-bpath.cpp \ - display/canvas-bpath.h \ - display/canvas-grid.cpp \ - display/canvas-grid.h \ - display/canvas-temporary-item.cpp \ - display/canvas-temporary-item.h \ - display/canvas-temporary-item-list.cpp \ - display/canvas-temporary-item-list.h \ - display/canvas-text.cpp \ - display/canvas-text.h \ - display/curve.cpp \ - display/curve.h \ - display/drawing.cpp \ - display/drawing.h \ - display/drawing-context.cpp \ - display/drawing-context.h \ - display/drawing-group.cpp \ - display/drawing-group.h \ - display/drawing-image.cpp \ - display/drawing-image.h \ - display/drawing-item.cpp \ - display/drawing-item.h \ - display/drawing-pattern.cpp \ - display/drawing-pattern.h \ - display/drawing-shape.cpp \ - display/drawing-shape.h \ - display/drawing-surface.cpp \ - display/drawing-surface.h \ - display/drawing-text.cpp \ - display/drawing-text.h \ - display/gnome-canvas-acetate.cpp \ - display/gnome-canvas-acetate.h \ - display/grayscale.cpp \ - display/grayscale.h \ - display/guideline.cpp \ - display/guideline.h \ - display/nr-3dutils.cpp \ - display/nr-3dutils.h \ - display/nr-filter-blend.cpp \ - display/nr-filter-blend.h \ - display/nr-filter-colormatrix.cpp \ - display/nr-filter-colormatrix.h \ - display/nr-filter-component-transfer.cpp \ - display/nr-filter-component-transfer.h \ - display/nr-filter-composite.cpp \ - display/nr-filter-composite.h \ - display/nr-filter-convolve-matrix.cpp \ - display/nr-filter-convolve-matrix.h \ - display/nr-filter.cpp \ - display/nr-filter-diffuselighting.cpp \ - display/nr-filter-diffuselighting.h \ - display/nr-filter-displacement-map.cpp \ - display/nr-filter-displacement-map.h \ - display/nr-filter-flood.cpp \ - display/nr-filter-flood.h \ - display/nr-filter-gaussian.cpp \ - display/nr-filter-gaussian.h \ - display/nr-filter.h \ - display/nr-filter-image.cpp \ - display/nr-filter-image.h \ - display/nr-filter-merge.cpp \ - display/nr-filter-merge.h \ - display/nr-filter-morphology.cpp \ - display/nr-filter-morphology.h \ - display/nr-filter-offset.cpp \ - display/nr-filter-offset.h \ - display/nr-filter-primitive.cpp \ - display/nr-filter-primitive.h \ - display/nr-filter-slot.cpp \ - display/nr-filter-slot.h \ - display/nr-filter-specularlighting.cpp \ - display/nr-filter-specularlighting.h \ - display/nr-filter-tile.cpp \ - display/nr-filter-tile.h \ - display/nr-filter-turbulence.cpp \ - display/nr-filter-turbulence.h \ - display/nr-filter-types.h \ - display/nr-filter-units.cpp \ - display/nr-filter-units.h \ - display/nr-filter-utils.h \ - display/nr-light.cpp \ - display/nr-light.h \ - display/nr-light-types.h \ - display/nr-style.cpp \ - display/nr-style.h \ - display/nr-svgfonts.cpp \ - display/nr-svgfonts.h \ - display/rendermode.h \ - display/snap-indicator.cpp \ - display/snap-indicator.h \ - display/sodipodi-ctrl.cpp \ - display/sodipodi-ctrl.h \ - display/sodipodi-ctrlrect.cpp \ - display/sodipodi-ctrlrect.h \ - display/sp-canvas.cpp \ - display/sp-canvas.h \ - display/sp-canvas-item.h \ - display/sp-canvas-group.h \ - display/sp-canvas-util.cpp \ - display/sp-canvas-util.h \ - display/sp-ctrlcurve.cpp \ - display/sp-ctrlcurve.h \ - display/sp-ctrlline.cpp \ - display/sp-ctrlline.h \ - display/sp-ctrlquadr.cpp \ - display/sp-ctrlquadr.h - -# ###################### -# ### CxxTest stuff #### -# ###################### -CXXTEST_TESTSUITES += \ - $(srcdir)/display/curve-test.h diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 14f36376f..421a39fbd 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -19,12 +19,7 @@ #include <gtkmm/box.h> #include <gtkmm/label.h> - -#if WITH_GTKMM_3_0 -# include <gtkmm/grid.h> -#else -# include <gtkmm/table.h> -#endif +#include <gtkmm/grid.h> #include <glibmm/i18n.h> @@ -94,15 +89,10 @@ namespace Inkscape { #define SPACE_SIZE_X 15 #define SPACE_SIZE_Y 10 static inline void -#if WITH_GTKMM_3_0 attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#else -attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#endif { for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2) { if (arr[i] && arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast<Gtk::Widget&>(*arr[i])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i]), 1, r, 1, 1); @@ -110,44 +100,23 @@ attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int (const_cast<Gtk::Widget&>(*arr[i+1])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i+1]), 2, r, 1, 1); -#else - table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { if (arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast<Gtk::Widget&>(*arr[i+1])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i+1]), 1, r, 2, 1); -#else - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else if (arr[i]) { Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i])); label.set_alignment (0.0); -#if WITH_GTKMM_3_0 label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); -#else - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { Gtk::HBox *space = Gtk::manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); -#if WITH_GTKMM_3_0 space->set_halign(Gtk::ALIGN_CENTER); space->set_valign(Gtk::ALIGN_CENTER); table.attach(*space, 0, r, 1, 1); -#else - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); -#endif } } ++r; @@ -342,14 +311,9 @@ CanvasAxonomGrid::onReprAttrChanged(Inkscape::XML::Node */*repr*/, gchar const * Gtk::Widget * CanvasAxonomGrid::newSpecificWidget() { -#if WITH_GTKMM_3_0 - Gtk::Grid *table = Gtk::manage(new Gtk::Grid()); + auto table = Gtk::manage(new Gtk::Grid()); table->set_row_spacing(2); table->set_column_spacing(2); -#else - Gtk::Table * table = Gtk::manage( new Gtk::Table(1,1) ); - table->set_spacings(2); -#endif _wr.setUpdating (true); diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index decf93626..fa45fe02c 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -19,12 +19,7 @@ #include <gtkmm/box.h> #include <gtkmm/label.h> - -#if WITH_GTKMM_3_0 -# include <gtkmm/grid.h> -#else -# include <gtkmm/table.h> -#endif +#include <gtkmm/grid.h> #include <glibmm/i18n.h> @@ -400,15 +395,10 @@ void CanvasGrid::setOrigin(Geom::Point const &origin_px) **/ #define SPACE_SIZE_X 15 #define SPACE_SIZE_Y 10 -#if WITH_GTKMM_3_0 static inline void attach_all(Gtk::Grid &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#else -static inline void attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) -#endif { for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2) { if (arr[i] && arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast<Gtk::Widget&>(*arr[i])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i]), 1, r, 1, 1); @@ -416,44 +406,23 @@ static inline void attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], (const_cast<Gtk::Widget&>(*arr[i+1])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i+1]), 2, r, 1, 1); -#else - table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { if (arr[i+1]) { -#if WITH_GTKMM_3_0 (const_cast<Gtk::Widget&>(*arr[i+1])).set_hexpand(); (const_cast<Gtk::Widget&>(*arr[i+1])).set_valign(Gtk::ALIGN_CENTER); table.attach(const_cast<Gtk::Widget&>(*arr[i+1]), 1, r, 2, 1); -#else - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else if (arr[i]) { Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i])); label.set_alignment (0.0); -#if WITH_GTKMM_3_0 label.set_hexpand(); label.set_valign(Gtk::ALIGN_CENTER); table.attach(label, 0, r, 3, 1); -#else - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); -#endif } else { Gtk::HBox *space = Gtk::manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); -#if WITH_GTKMM_3_0 space->set_halign(Gtk::ALIGN_CENTER); space->set_valign(Gtk::ALIGN_CENTER); table.attach(*space, 0, r, 1, 1); -#else - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); -#endif } } ++r; @@ -684,14 +653,9 @@ CanvasXYGrid::onReprAttrChanged(Inkscape::XML::Node */*repr*/, gchar const */*ke Gtk::Widget * CanvasXYGrid::newSpecificWidget() { -#if WITH_GTKMM_3_0 - Gtk::Grid * table = Gtk::manage( new Gtk::Grid() ); + auto table = Gtk::manage( new Gtk::Grid() ); table->set_row_spacing(2); table->set_column_spacing(2); -#else - Gtk::Table * table = Gtk::manage( new Gtk::Table(1,1) ); - table->set_spacings(2); -#endif Inkscape::UI::Widget::RegisteredUnitMenu *_rumg = Gtk::manage( new Inkscape::UI::Widget::RegisteredUnitMenu( _("Grid _units:"), "units", _wr, repr, doc) ); diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 011f51977..53a5cba49 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -203,14 +203,19 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/, //check whether is there a glyph declared on the SVG document // that matches with the text string in its current position if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ - for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){ + for(auto& node: font->children) { + if (!previous_unicode) { + break; + } //apply glyph kerning if appropriate - SPHkern *hkern = dynamic_cast<SPHkern *>(node); - if (hkern && is_horizontal_text && MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + SPHkern *hkern = dynamic_cast<SPHkern *>(&node); + if (hkern && is_horizontal_text && + MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name)) { x -= (hkern->k / 1000.0);//TODO: use here the height of the font } - SPVkern *vkern = dynamic_cast<SPVkern *>(node); - if (vkern && !is_horizontal_text && MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){ + SPVkern *vkern = dynamic_cast<SPVkern *>(&node); + if (vkern && !is_horizontal_text && + MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name)) { y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font } } @@ -271,10 +276,10 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){ Geom::PathVector SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){ double units_per_em = 1000; - for (SPObject *obj = spfont->children; obj; obj = obj->next){ - if (dynamic_cast<SPFontFace *>(obj)) { + for(auto& obj: spfont->children) { + if (dynamic_cast<SPFontFace *>(&obj)) { //XML Tree being directly used here while it shouldn't be. - sp_repr_get_double(obj->getRepr(), "units_per_em", &units_per_em); + sp_repr_get_double(obj.getRepr(), "units_per_em", &units_per_em); } } @@ -339,19 +344,19 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, if (node->hasChildren()){ //render the SVG described on this glyph's child nodes. - for(node = node->children; node; node=node->next){ + for(auto& child: node->children) { { - SPPath *path = dynamic_cast<SPPath *>(node); + SPPath *path = dynamic_cast<SPPath *>(&child); if (path) { pathv = path->_curve->get_pathvector(); pathv = flip_coordinate_system(spfont, pathv); render_glyph_path(cr, &pathv); } } - if (dynamic_cast<SPObjectGroup *>(node)) { + if (dynamic_cast<SPObjectGroup *>(&child)) { g_warning("TODO: svgfonts: render OBJECTGROUP"); } - SPUse *use = dynamic_cast<SPUse *>(node); + SPUse *use = dynamic_cast<SPUse *>(&child); if (use) { SPItem* item = use->ref->getObject(); SPPath *path = dynamic_cast<SPPath *>(item); @@ -374,12 +379,12 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, cairo_font_face_t* SvgFont::get_font_face(){ if (!this->userfont) { - for(SPObject* node = this->font->children;node;node=node->next){ - SPGlyph *glyph = dynamic_cast<SPGlyph *>(node); + for(auto& node: font->children) { + SPGlyph *glyph = dynamic_cast<SPGlyph *>(&node); if (glyph) { glyphs.push_back(glyph); } - SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(node); + SPMissingGlyph *missing = dynamic_cast<SPMissingGlyph *>(&node); if (missing) { missingglyph = missing; } diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index df84e379c..9201168ef 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -8,9 +8,11 @@ * fred * bbyak * Jon A. Cruz <jon@joncruz.org> + * Krzysztof Kosiński <tweenk.pl@gmail.com> * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002-2006 authors + * Copyright (C) 2016 Google Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -25,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" @@ -35,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; @@ -122,7 +126,7 @@ struct SPCanvasClass { namespace { -gint const UPDATE_PRIORITY = G_PRIORITY_HIGH_IDLE; +gint const UPDATE_PRIORITY = G_PRIORITY_DEFAULT_IDLE; GdkWindow *getWindow(SPCanvas *canvas) { @@ -318,13 +322,9 @@ void sp_canvas_item_dispose(GObject *object) if (item == item->canvas->_grabbed_item) { item->canvas->_grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, GDK_CURRENT_TIME); -#else - gdk_pointer_ungrab (GDK_CURRENT_TIME); -#endif } if (item == item->canvas->_focused_item) { @@ -613,9 +613,8 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, // fixme: Top hack (Lauris) // fixme: If we add key masks to event mask, Gdk will abort (Lauris) // fixme: But Canvas actualle does get key events, so all we need is routing these here -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_grab(device, getWindow(item->canvas), GDK_OWNERSHIP_NONE, @@ -623,11 +622,6 @@ int sp_canvas_item_grab(SPCanvasItem *item, guint event_mask, GdkCursor *cursor, (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), cursor, etime); -#else - gdk_pointer_grab( getWindow(item->canvas), FALSE, - (GdkEventMask)(event_mask & (~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK))), - NULL, cursor, etime); -#endif item->canvas->_grabbed_item = item; item->canvas->_grabbed_event_mask = event_mask; @@ -654,13 +648,9 @@ void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime) item->canvas->_grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, etime); -#else - gdk_pointer_ungrab (etime); -#endif } /** @@ -909,16 +899,9 @@ void sp_canvas_class_init(SPCanvasClass *klass) widget_class->realize = SPCanvas::handle_realize; widget_class->unrealize = SPCanvas::handle_unrealize; - -#if GTK_CHECK_VERSION(3,0,0) widget_class->get_preferred_width = SPCanvas::handle_get_preferred_width; widget_class->get_preferred_height = SPCanvas::handle_get_preferred_height; widget_class->draw = SPCanvas::handle_draw; -#else - widget_class->size_request = SPCanvas::handle_size_request; - widget_class->expose_event = SPCanvas::handle_expose; -#endif - widget_class->size_allocate = SPCanvas::handle_size_allocate; widget_class->button_press_event = SPCanvas::handle_button; widget_class->button_release_event = SPCanvas::handle_button; @@ -935,7 +918,6 @@ void sp_canvas_class_init(SPCanvasClass *klass) static void sp_canvas_init(SPCanvas *canvas) { gtk_widget_set_has_window (GTK_WIDGET (canvas), TRUE); - gtk_widget_set_double_buffered (GTK_WIDGET (canvas), FALSE); gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE); canvas->_pick_event.type = GDK_LEAVE_NOTIFY; @@ -956,9 +938,10 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_drawing_disabled = false; - canvas->_tiles=NULL; - canvas->_tLeft=canvas->_tTop=canvas->_tRight=canvas->_tBottom=0; - canvas->_tile_h=canvas->_tile_h=0; + 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; @@ -967,32 +950,18 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_enable_cms_display_adj = false; new (&canvas->_cms_key) Glib::ustring(""); #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - canvas->_is_scrolling = false; } void SPCanvas::shutdownTransients() { - // We turn off the need_redraw flag, since if the canvas is mapped again - // it will request a redraw anyways. We do not turn off the need_update - // flag, though, because updates are not queued when the canvas remaps - // itself. - // - _need_redraw = FALSE; - if (_tiles) g_free(_tiles); - _tiles = NULL; - _tLeft = _tTop = _tRight = _tBottom = 0; - _tile_h = _tile_h = 0; + // Reset the clean region + dirtyAll(); if (_grabbed_item) { _grabbed_item = NULL; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_device_ungrab(device, GDK_CURRENT_TIME); -#else - gdk_pointer_ungrab(GDK_CURRENT_TIME); -#endif } removeIdle(); } @@ -1005,6 +974,18 @@ void SPCanvas::dispose(GObject *object) g_object_unref (canvas->_root); canvas->_root = NULL; } + if (canvas->_backing_store) { + cairo_surface_destroy(canvas->_backing_store); + canvas->_backing_store = NULL; + } + if (canvas->_clean_region) { + 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) @@ -1047,10 +1028,6 @@ void SPCanvas::handle_realize(GtkWidget *widget) attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gdk_visual_get_system(); -#if !GTK_CHECK_VERSION(3,0,0) - attributes.colormap = gdk_colormap_get_system(); -#endif - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | @@ -1067,11 +1044,7 @@ void SPCanvas::handle_realize(GtkWidget *widget) GDK_SCROLL_MASK | GDK_FOCUS_CHANGE_MASK); -#if GTK_CHECK_VERSION(3,0,0) gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; -#else - gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; -#endif GdkWindow *window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gtk_widget_set_window (widget, window); @@ -1080,18 +1053,8 @@ void SPCanvas::handle_realize(GtkWidget *widget) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/useextinput/value", true)) { gtk_widget_set_events(widget, attributes.event_mask); -#if !GTK_CHECK_VERSION(3,0,0) - gtk_widget_set_extension_events(widget, GDK_EXTENSION_EVENTS_ALL); - // TODO: Extension event stuff has been deprecated in GTK+ 3 -#endif } -#if !GTK_CHECK_VERSION(3,0,0) - // This does nothing in GTK+ 3 - GtkStyle *style = gtk_widget_get_style (widget); - gtk_widget_set_style (widget, gtk_style_attach (style, window)); -#endif - gtk_widget_set_realized (widget, TRUE); } @@ -1109,8 +1072,6 @@ void SPCanvas::handle_unrealize(GtkWidget *widget) (* GTK_WIDGET_CLASS(sp_canvas_parent_class)->unrealize)(widget); } - -#if GTK_CHECK_VERSION(3,0,0) void SPCanvas::handle_get_preferred_width(GtkWidget *widget, gint *minimum_width, gint *natural_width) { static_cast<void>(SP_CANVAS (widget)); @@ -1124,55 +1085,52 @@ void SPCanvas::handle_get_preferred_height(GtkWidget *widget, gint *minimum_heig *minimum_height = 256; *natural_height = 256; } -#else -void SPCanvas::handle_size_request(GtkWidget *widget, GtkRequisition *req) -{ - static_cast<void>(SP_CANVAS (widget)); - - req->width = 256; - req->height = 256; -} -#endif - void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { SPCanvas *canvas = SP_CANVAS (widget); - GtkAllocation widg_allocation; + GtkAllocation old_allocation; - gtk_widget_get_allocation (widget, &widg_allocation); + gtk_widget_get_allocation(widget, &old_allocation); -// Geom::IntRect old_area = Geom::IntRect::from_xywh(canvas->x0, canvas->y0, -// widg_allocation.width, widg_allocation.height); +// Geom::IntRect old_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0, +// old_allocation.width, old_allocation.height); Geom::IntRect new_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0, allocation->width, allocation->height); - // Schedule redraw of new region - canvas->resizeTiles(canvas->_x0, canvas->_y0, canvas->_x0 + allocation->width, canvas->_y0 + allocation->height); - if (SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed) - SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed (canvas->_root, new_area); - - if (allocation->width > widg_allocation.width) { - canvas->requestRedraw(canvas->_x0 + widg_allocation.width, - 0, - canvas->_x0 + allocation->width, - canvas->_y0 + allocation->height); - } - if (allocation->height > widg_allocation.height) { - canvas->requestRedraw(0, - canvas->_y0 + widg_allocation.height, - canvas->_x0 + allocation->width, - canvas->_y0 + allocation->height); - } + // resize backing store + cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + allocation->width, allocation->height); + if (canvas->_backing_store) { + cairo_t *cr = cairo_create(new_backing_store); + cairo_translate(cr, -canvas->_x0, -canvas->_y0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source(cr, canvas->_background); + cairo_paint(cr); + cairo_set_source_surface(cr, canvas->_backing_store, canvas->_x0, canvas->_y0); + cairo_paint(cr); + cairo_destroy(cr); + cairo_surface_destroy(canvas->_backing_store); + } + canvas->_backing_store = new_backing_store; + + // Clip the clean region to the new allocation + cairo_rectangle_int_t crect = { canvas->_x0, canvas->_y0, allocation->width, allocation->height }; + cairo_region_intersect_rectangle(canvas->_clean_region, &crect); gtk_widget_set_allocation (widget, allocation); + if (SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed) + SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed (canvas->_root, new_area); + if (gtk_widget_get_realized (widget)) { gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height); } + // Schedule redraw of any newly exposed regions + canvas->addIdle(); } int SPCanvas::emitEvent(GdkEvent *event) @@ -1206,9 +1164,7 @@ int SPCanvas::emitEvent(GdkEvent *event) break; case GDK_SCROLL: mask = GDK_SCROLL_MASK; -#if GTK_CHECK_VERSION(3,0,0) mask |= GDK_SMOOTH_SCROLL_MASK; -#endif break; default: mask = 0; @@ -1490,13 +1446,9 @@ gint SPCanvas::handle_scroll(GtkWidget *widget, GdkEventScroll *event) } static inline void request_motions(GdkWindow *w, GdkEventMotion *event) { -#if GTK_CHECK_VERSION(3,0,0) gdk_window_get_device_position(w, gdk_event_get_device((GdkEvent *)(event)), NULL, NULL, NULL); -#else - gdk_window_get_pointer(w, NULL, NULL, NULL); -#endif gdk_event_request_motions(event); } @@ -1526,48 +1478,23 @@ int SPCanvas::handle_motion(GtkWidget *widget, GdkEventMotion *event) void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect const &canvas_rect, int /*sw*/) { - GtkWidget *widget = GTK_WIDGET (this); - - // Mark the region clean - markRect(paint_rect, 0); - SPCanvasBuf buf; buf.buf = NULL; buf.buf_rowstride = 0; buf.rect = paint_rect; buf.visible_rect = canvas_rect; buf.is_empty = true; - //buf.ct = gdk_cairo_create(widget->window); // 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); - //cairo_rectangle(buf.ct, 0, 0, paint_rect.width(), paint_rect.height()); - //cairo_set_line_width(buf.ct, 3); - //cairo_set_source_rgba(buf.ct, 1.0, 0.0, 0.0, 0.1); - //cairo_stroke_preserve(buf.ct); - //cairo_clip(buf.ct); - -#if GTK_CHECK_VERSION(3,0,0) - GtkStyleContext *context = gtk_widget_get_style_context(widget); - GdkRGBA color; - gtk_style_context_get_background_color(context, - gtk_widget_get_state_flags(widget), - &color); - gdk_cairo_set_source_rgba(buf.ct, &color); -#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); @@ -1600,7 +1527,8 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect } #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - cairo_t *xct = gdk_cairo_create(gtk_widget_get_window (widget)); + //cairo_t *xct = gdk_cairo_create(gtk_widget_get_window (widget)); + cairo_t *xct = cairo_create(_backing_store); cairo_translate(xct, paint_rect.left() - _x0, paint_rect.top() - _y0); cairo_rectangle(xct, 0, 0, paint_rect.width(), paint_rect.height()); cairo_clip(xct); @@ -1609,6 +1537,12 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_paint(xct); cairo_destroy(xct); cairo_surface_destroy(imgs); + + // 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()); } struct PaintRectSetup { @@ -1751,16 +1685,12 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) // Save the mouse location gint x, y; -#if GTK_CHECK_VERSION(3,0,0) - GdkDeviceManager *dm = gdk_display_get_device_manager(gdk_display_get_default()); - GdkDevice *device = gdk_device_manager_get_client_pointer(dm); + auto dm = gdk_display_get_device_manager(gdk_display_get_default()); + auto device = gdk_device_manager_get_client_pointer(dm); gdk_window_get_device_position(gtk_widget_get_window(GTK_WIDGET(this)), device, &x, &y, NULL); -#else - gdk_window_get_pointer(gtk_widget_get_window(GTK_WIDGET(this)), &x, &y, NULL); -#endif setup.mouse_loc = sp_canvas_window_to_world(this, Geom::Point(x,y)); @@ -1792,55 +1722,37 @@ void SPCanvas::endForcedFullRedraws() _forced_redraw_limit = -1; } -#if GTK_CHECK_VERSION(3,0,0) gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) { SPCanvas *canvas = SP_CANVAS(widget); + // Blit from the backing store, without regard for the clean region. + // This is necessary because GTK clears the widget for us, which causes + // severe flicker while drawing if we don't blit the old contents. + cairo_set_source_surface(cr, canvas->_backing_store, 0, 0); + cairo_paint(cr); + cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr); + cairo_region_t *dirty_region = cairo_region_create(); for (int i = 0; i < rects->num_rectangles; i++) { cairo_rectangle_t rectangle = rects->rectangles[i]; - - Geom::IntRect r = Geom::IntRect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0, - rectangle.width, rectangle.height); - - canvas->requestRedraw(r.left(), r.top(), r.right(), r.bottom()); + Geom::Rect dr = Geom::Rect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0, + rectangle.width, rectangle.height); + Geom::IntRect ir = dr.roundOutwards(); + cairo_rectangle_int_t irect = { ir.left(), ir.top(), ir.width(), ir.height() }; + cairo_region_union_rectangle(dirty_region, &irect); } - cairo_rectangle_list_destroy(rects); + cairo_region_subtract(dirty_region, canvas->_clean_region); - return FALSE; -} -#else -gboolean SPCanvas::handle_expose(GtkWidget *widget, GdkEventExpose *event) -{ - SPCanvas *canvas = SP_CANVAS(widget); - - if (!gtk_widget_is_drawable (widget) || - (event->window != getWindow(canvas))) { - return FALSE; + // Render the dirty portion in the background + if (!cairo_region_is_empty(dirty_region)) { + canvas->addIdle(); } + cairo_region_destroy(dirty_region); - int n_rects = 0; - GdkRectangle *rects = NULL; - gdk_region_get_rectangles(event->region, &rects, &n_rects); - - if(rects == NULL) - return FALSE; - - for (int i = 0; i < n_rects; i++) { - GdkRectangle rectangle = rects[i]; - - Geom::IntRect r = Geom::IntRect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0, - rectangle.width, rectangle.height); - - canvas->requestRedraw(r.left(), r.top(), r.right(), r.bottom()); - } - - return FALSE; + return TRUE; } -#endif - gint SPCanvas::handle_key_event(GtkWidget *widget, GdkEventKey *event) { @@ -1890,42 +1802,22 @@ int SPCanvas::paint() _need_update = FALSE; } - if (!_need_redraw) { - return TRUE; - } - - Cairo::RefPtr<Cairo::Region> to_paint = Cairo::Region::create(); - - for (int j = _tTop; j < _tBottom; ++j) { - for (int i = _tLeft; i < _tRight; ++i) { - int tile_index = (i - _tLeft) + (j - _tTop) * _tile_h; - - if (_tiles[tile_index]) { // if this tile is dirtied (nonzero) - Cairo::RectangleInt rect = {i*TILE_SIZE, j*TILE_SIZE, - TILE_SIZE, TILE_SIZE}; - to_paint->do_union(rect); - } - } - } - - int n_rect = to_paint->get_num_rectangles(); + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); + cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; + cairo_region_t *to_draw = cairo_region_create_rectangle(&crect); + cairo_region_subtract(to_draw, _clean_region); - if (n_rect > 0) { - for (int i=0; i < n_rect; i++) { - Cairo::RectangleInt rect = to_paint->get_rectangle(i); - int x0 = rect.x; - int y0 = rect.y; - int x1 = x0 + rect.width; - int y1 = y0 + rect.height; - if (!paintRect(x0, y0, x1, y1)) { - // Aborted - return FALSE; - }; - } + int n_rects = cairo_region_num_rectangles(to_draw); + for (int i = 0; i < n_rects; ++i) { + cairo_rectangle_int_t crect; + cairo_region_get_rectangle(to_draw, i, &crect); + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + // Aborted + return FALSE; + }; } - _need_redraw = FALSE; - // we've had a full unaborted redraw, reset the full redraw counter if (_forced_redraw_limit != -1) { _forced_redraw_count = 0; @@ -2004,15 +1896,41 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll Geom::IntRect old_area = getViewboxIntegers(); Geom::IntRect new_area = old_area + Geom::IntPoint(dx, dy); - + + 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); + cairo_t *cr = cairo_create(new_backing_store); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + // Paint the background + cairo_translate(cr, -ix, -iy); + cairo_set_source(cr, _background); + cairo_paint(cr); + // Copy the old backing store contents + cairo_set_source_surface(cr, _backing_store, _x0, _y0); + cairo_rectangle(cr, _x0, _y0, allocation.width, allocation.height); + cairo_clip(cr); + cairo_paint(cr); + cairo_destroy(cr); + cairo_surface_destroy(_backing_store); + _backing_store = new_backing_store; + _dx0 = cx; // here the 'd' stands for double, not delta! _dy0 = cy; _x0 = ix; _y0 = iy; - gtk_widget_get_allocation(&_widget, &allocation); + // Adjust the clean region + if (clear) { + dirtyAll(); + } else { + cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; + cairo_region_intersect_rectangle(_clean_region, &crect); + } - resizeTiles(_x0, _y0, _x0 + allocation.width, _y0 + allocation.height); if (SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed) { SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed(_root, new_area); } @@ -2020,19 +1938,17 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll if (!clear) { // scrolling without zoom; redraw only the newly exposed areas if ((dx != 0) || (dy != 0)) { - this->_is_scrolling = is_scrolling; if (gtk_widget_get_realized(GTK_WIDGET(this))) { gdk_window_scroll(getWindow(this), -dx, -dy); } } - } else { - // scrolling as part of zoom; do nothing here - the next do_update will perform full redraw } + addIdle(); } void SPCanvas::updateNow() { - if (_need_update || _need_redraw) { + if (_need_update) { doUpdate(); } } @@ -2045,26 +1961,45 @@ void SPCanvas::requestUpdate() void SPCanvas::requestRedraw(int x0, int y0, int x1, int y1) { - GtkAllocation allocation; - if (!gtk_widget_is_drawable( GTK_WIDGET(this) )) { return; } - if ((x0 >= x1) || (y0 >= y1)) { + if (x0 >= x1 || y0 >= y1) { return; } Geom::IntRect bbox(x0, y0, x1, y1); - gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); + dirtyRect(bbox); + addIdle(); +} - Geom::IntRect canvas_rect = Geom::IntRect::from_xywh(this->_x0, this->_y0, - allocation.width, allocation.height); - - Geom::OptIntRect clip = bbox & canvas_rect; - if (clip) { - dirtyRect(*clip); - 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(); } /** @@ -2168,63 +2103,24 @@ inline int sp_canvas_tile_ceil(int x) return ((x + (TILE_SIZE - 1)) & (~(TILE_SIZE - 1))) / TILE_SIZE; } -void SPCanvas::resizeTiles(int nl, int nt, int nr, int nb) -{ - if ( nl >= nr || nt >= nb ) { - if (_tiles) g_free(_tiles); - _tLeft = _tTop = _tRight = _tBottom = 0; - _tile_h = _tile_h = 0; - _tiles = NULL; - return; - } - int tl = sp_canvas_tile_floor(nl); - int tt = sp_canvas_tile_floor(nt); - int tr = sp_canvas_tile_ceil(nr); - int tb = sp_canvas_tile_ceil(nb); - - int nh = tr-tl, nv = tb-tt; - uint8_t *ntiles = (uint8_t*) g_malloc(nh * nv * sizeof(uint8_t)); - for (int i = tl; i < tr; i++) { - for (int j = tt; j < tb; j++) { - int ind = (i-tl) + (j-tt)*nh; - if ( i >= _tLeft && i < _tRight && j >= _tTop && j < _tBottom ) { - ntiles[ind] = _tiles[(i - _tLeft) + (j - _tTop) * _tile_h]; // copy from the old tile - } else { - ntiles[ind] = 0; // newly exposed areas get 0 - } - } - } - if (_tiles) g_free(_tiles); - _tiles = ntiles; - _tLeft = tl; - _tTop = tt; - _tRight = tr; - _tBottom = tb; - _tile_h = nh; - _tile_h = nv; -} - void SPCanvas::dirtyRect(Geom::IntRect const &area) { - _need_redraw = TRUE; 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) { - int tl = sp_canvas_tile_floor(area.left()); - int tt = sp_canvas_tile_floor(area.top()); - int tr = sp_canvas_tile_ceil(area.right()); - int tb = sp_canvas_tile_ceil(area.bottom()); - if ( tl >= _tRight || tr <= _tLeft || tt >= _tBottom || tb <= _tTop ) return; - if ( tl < _tLeft ) tl = _tLeft; - if ( tr > _tRight ) tr = _tRight; - if ( tt < _tTop ) tt = _tTop; - if ( tb > _tBottom ) tb = _tBottom; - - for (int i=tl; i<tr; i++) { - for (int j=tt; j<tb; j++) { - _tiles[(i - _tLeft) + (j - _tTop) * _tile_h] = val; - } + cairo_rectangle_int_t crect = { area.left(), area.top(), area.width(), area.height() }; + if (val) { + cairo_region_subtract_rectangle(_clean_region, &crect); + } else { + cairo_region_union_rectangle(_clean_region, &crect); } } diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 1a13250b3..78d96d728 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -11,9 +11,11 @@ * Raph Levien <raph@gimp.org> * Lauris Kaplinski <lauris@kaplinski.com> * Jon A. Cruz <jon@joncruz.org> + * Krzysztof Kosiński <tweenk.pl@gmail.com> * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2016 Google Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -85,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(); @@ -103,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. @@ -139,12 +145,8 @@ public: static void dispose(GObject *object); static void handle_realize(GtkWidget *widget); static void handle_unrealize(GtkWidget *widget); -#if GTK_CHECK_VERSION(3,0,0) static void handle_get_preferred_width(GtkWidget *widget, gint *min_w, gint *nat_w); static void handle_get_preferred_height(GtkWidget *widget, gint *min_h, gint *nat_h); -#else - static void handle_size_request(GtkWidget *widget, GtkRequisition *req); -#endif static void handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation); static gint handle_button(GtkWidget *widget, GdkEventButton *event); @@ -155,11 +157,7 @@ public: */ static gint handle_scroll(GtkWidget *widget, GdkEventScroll *event); static gint handle_motion(GtkWidget *widget, GdkEventMotion *event); -#if GTK_CHECK_VERSION(3,0,0) static gboolean handle_draw(GtkWidget *widget, cairo_t *cr); -#else - static gboolean handle_expose(GtkWidget *widget, GdkEventExpose *event); -#endif static gint handle_key_event(GtkWidget *widget, GdkEventKey *event); static gint handle_crossing(GtkWidget *widget, GdkEventCrossing *event); static gint handle_focus_in(GtkWidget *widget, GdkEventFocus *event); @@ -176,15 +174,18 @@ public: bool _is_dragging; double _dx0; double _dy0; - int _x0; - int _y0; - - /* Area that needs redrawing, stored as a microtile array */ - int _tLeft, _tTop, _tRight, _tBottom; - int _tile_w, _tile_h; - uint8_t *_tiles; - - /** Last known modifier state, for deferred repick when a button is down. */ + int _x0; ///< World coordinate of the leftmost pixels + int _y0; ///< World coordinate of the topmost pixels + + /// 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. int _state; /** The item containing the mouse pointer, or NULL if none. */ @@ -208,7 +209,6 @@ public: int _close_enough; unsigned int _need_update : 1; - unsigned int _need_redraw : 1; unsigned int _need_repick : 1; int _forced_redraw_count; |
