summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2016-04-13 11:38:28 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2016-04-13 11:38:28 +0000
commitd2a3bc0b327557fba34f09a110a0ac5b6d18f85e (patch)
treea852962eb33ecbb72e1ef832bd5f74075dfb1874 /src
parentgimpcolorwheel: Fix deprecated gtk_widget_style_attach #Hackfest2016 (diff)
downloadinkscape-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.cpp17
-rw-r--r--src/desktop.h1
-rw-r--r--src/display/sp-canvas.cpp85
-rw-r--r--src/display/sp-canvas.h18
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. */