Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2012-07-31 20:43:15 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2012-07-31 20:43:15 (GMT)
commitf334ed5eb4a6cf4bf78e3ba49701d6fc8bfbca29 (patch)
treed7c4cca7f6e427621ea913c7d58bd55e87ae668b
parente95a67c3dc931392ca9abb40b3b6e8553a2b2db3 (diff)
Use clipping to improve performance in the slower operations
The port to cairo is a lot slower (in a xo) than using the old primitives. Previously we was painting all the screen in most of the operations. This patch calculate and apply clip over most of them and add comments "TODO: clip" in the remaining. Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r--Area.py67
-rw-r--r--Desenho.py37
2 files changed, 66 insertions, 38 deletions
diff --git a/Area.py b/Area.py
index d312c5a..68e5472 100644
--- a/Area.py
+++ b/Area.py
@@ -228,6 +228,9 @@ class Area(gtk.DrawingArea):
self.drawing_ctx = cairo.Context(self.drawing_canvas)
##This canvas is showed when we need show something and not draw it.
+ self.temp_canvas = cairo.ImageSurface(cairo.FORMAT_ARGB32,
+ width, height)
+ self.temp_ctx = cairo.Context(self.temp_canvas)
self._init_temp_canvas()
self.enable_undo()
@@ -237,14 +240,14 @@ class Area(gtk.DrawingArea):
return True
- def _init_temp_canvas(self):
+ def _init_temp_canvas(self, area=None):
#logging.error('init_temp_canvas.')
#self.drawing_canvas.flush()
- width, height = self.get_window().get_size()
- self.temp_canvas = cairo.ImageSurface(cairo.FORMAT_ARGB32,
- width, height)
- self.temp_ctx = cairo.Context(self.temp_canvas)
- self.temp_ctx.rectangle(0, 0, width, height)
+ if area == None:
+ width, height = self.get_window().get_size()
+ self.temp_ctx.rectangle(0, 0, width, height)
+ else:
+ self.temp_ctx.rectangle(area.x, area.y, area.width, area.height)
self.temp_ctx.set_source_surface(self.drawing_canvas)
self.temp_ctx.paint()
@@ -284,24 +287,23 @@ class Area(gtk.DrawingArea):
@param event -- GdkEvent
"""
- #area = event.area
- #logging.error('expose area %s', area)
+ area = event.area
context = self.get_window().cairo_create()
+ context.rectangle(area.x, area.y, area.width, area.height)
+ context.clip()
if self.desenha:
- #logging.error('Expose use temp canvas')
+ #logging.error('Expose use temp canvas area %s', area)
# Paint the canvas in the widget:
- # TODO: clipping
context.set_source_surface(self.temp_canvas)
context.paint()
else:
- #logging.error('Expose use drawing canvas')
- # TODO: clipping
+ #logging.error('Expose use drawing canvas area %s', area)
context.set_source_surface(self.drawing_canvas)
context.paint()
self.show_tool_shape(context)
- self._init_temp_canvas()
+ self._init_temp_canvas(area)
self.display_selection_border(context)
def show_tool_shape(self, context):
@@ -311,9 +313,9 @@ class Area(gtk.DrawingArea):
"""
if self.tool['name'] in ['pencil', 'eraser', 'brush', 'rainbow',
'stamp']:
- context.set_source_rgba(*self.tool['cairo_stroke_color'])
- context.set_line_width(1)
if not self.drawing:
+ context.set_source_rgba(*self.tool['cairo_stroke_color'])
+ context.set_line_width(1)
# draw stamp border in widget.window
if self.tool['name'] == 'stamp':
wr, hr = self.stamp_dimentions
@@ -337,6 +339,8 @@ class Area(gtk.DrawingArea):
context.rectangle(self.x_cursor - size / 2,
self.y_cursor - size / 2, size, size)
context.stroke()
+ self.last_x_cursor = self.x_cursor
+ self.last_y_cursor = self.y_cursor
def mousedown(self, widget, event):
"""Make the Area object (GtkDrawingArea) recognize
@@ -426,7 +430,28 @@ class Area(gtk.DrawingArea):
if design_mode:
self.desenha = True
- widget.queue_draw()
+
+ def calculate_damaged_area(self, points):
+ min_x = points[0][0]
+ min_y = points[0][1]
+ max_x = 0
+ max_y = 0
+ for point in points:
+ if point[0] < min_x:
+ min_x = point[0]
+ if point[0] > max_x:
+ max_x = point[0]
+ if point[1] < min_y:
+ min_y = point[1]
+ if point[1] > max_y:
+ max_y = point[1]
+ # add the tool size
+ size = self.tool['line size']
+ min_x = min_x - size
+ min_y = min_y - size
+ max_x = max_x + size
+ max_y = max_y + size
+ return (min_x, min_y, max_x - min_x, max_y - min_y)
def mousemove(self, widget, event):
"""Make the Area object (GtkDrawingArea)
@@ -522,7 +547,10 @@ class Area(gtk.DrawingArea):
else:
if self.tool['name'] in ['brush', 'eraser', 'rainbow', 'pencil',
'stamp']:
- widget.queue_draw()
+ # define area to update
+ last_coords = (self.last_x_cursor, self.last_y_cursor)
+ area = self.calculate_damaged_area([last_coords, coords])
+ widget.queue_draw_area(*area)
if self.tool['name'] == 'marquee-rectangular':
sel_x, sel_y, sel_width, sel_height = \
self.get_selection_bounds()
@@ -619,7 +647,6 @@ class Area(gtk.DrawingArea):
'stamp']:
self.last = []
self.d.finish_trace(self)
- widget.queue_draw()
self.drawing = False
self.desenha = False
if not private_undo and self.tool['name'] != 'bucket':
@@ -628,6 +655,8 @@ class Area(gtk.DrawingArea):
# gobject.idle_add (with the fill_flood function) finishes
# and an unconsistent undo state is saved
self.enable_undo()
+ widget.queue_draw()
+ self.d.clear_control_points()
def fast_flood_fill(self, widget, x, y, width, height):
fill(self.pixmap, self.gc, x, y, width,
@@ -1444,9 +1473,11 @@ class Area(gtk.DrawingArea):
size = 1
self.tool['line size'] = size
self.configure_line(size)
+ # TODO: clip
self.queue_draw()
if self.tool['name'] == 'stamp':
self.resize_stamp(self.stamp_size + delta)
+ # TODO: clip
self.queue_draw()
def _keep_selection_ratio(self, coords):
diff --git a/Desenho.py b/Desenho.py
index f575b83..d7f08fa 100644
--- a/Desenho.py
+++ b/Desenho.py
@@ -98,6 +98,10 @@ class Desenho:
self._rainbow_counter = 0
self.points = []
+ self._last_points_used = self.points
+
+ def clear_control_points(self):
+ self._last_points_used = []
def line(self, widget, coords, temp):
"""Draw line.
@@ -118,6 +122,7 @@ class Desenho:
ctx.move_to(widget.oldx, widget.oldy)
ctx.line_to(coords[0], coords[1])
ctx.stroke()
+ # TODO: clip
widget.queue_draw()
def eraser(self, widget, coords, last):
@@ -172,7 +177,7 @@ class Desenho:
widget.drawing_ctx.paint()
widget.drawing_ctx.restore()
- widget.queue_draw()
+ widget.queue_draw_area(dx, dy, width, height)
def rainbow(self, widget, coords, last):
"""Paint with rainbow.
@@ -288,7 +293,7 @@ class Desenho:
if last:
self._draw_polygon(widget, True, False, self.points, False,
rounded)
-
+ self.clear_control_points()
if last:
x = min(coords[0], last[0])
width = max(coords[0], last[0]) - x
@@ -297,8 +302,6 @@ class Desenho:
# We add size to avoid drawing dotted lines
widget.queue_draw_area(x - size, y - size,
width + size * 2, height + size * 2)
- else:
- widget.queue_draw()
def square(self, widget, event, coords, temp, fill):
"""Draw a square.
@@ -309,21 +312,10 @@ class Desenho:
@param temp -- switch between drawing context and temp context
@param fill -- Fill object
"""
- if temp == True:
- ctx = widget.temp_ctx
- else:
- ctx = widget.drawing_ctx
x, y, dx, dy, = self.adjust(widget, coords)
-
- ctx.rectangle(x, y, dx, dy)
- if fill == True:
- ctx.set_source_rgba(*widget.tool['cairo_fill_color'])
- ctx.fill_preserve()
- ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
- ctx.set_line_width(widget.tool['line size'])
- ctx.stroke()
- widget.queue_draw_area(x, y, dx, dy)
+ points = [(x, y), (x + dx, y), (x + dx, y + dy), (x, y + dy)]
+ self._draw_polygon(widget, temp, fill, points)
def _draw_polygon(self, widget, temp, fill, points, closed=True,
rounded=False):
@@ -359,7 +351,9 @@ class Desenho:
ctx.set_line_width(widget.tool['line size'])
ctx.stroke()
ctx.restore()
- widget.queue_draw()
+ self._last_points_used.extend(points)
+ area = widget.calculate_damaged_area(self._last_points_used)
+ widget.queue_draw_area(*area)
def triangle(self, widget, coords, temp, fill):
"""Draw a triangle.
@@ -522,6 +516,7 @@ class Desenho:
ctx.stroke()
ctx.restore()
+ # TODO: clip
widget.queue_draw()
def circle(self, widget, coords, temp, fill):
@@ -554,6 +549,7 @@ class Desenho:
ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
ctx.stroke()
ctx.restore()
+ # TODO: clip
widget.queue_draw()
def clear(self, widget):
@@ -628,7 +624,7 @@ class Desenho:
buf.set_text('')
widget.enable_undo()
-
+ # TODO: clip
widget.queue_draw()
def selection(self, widget, coords):
@@ -640,6 +636,7 @@ class Desenho:
x, y, dx, dy = self.adjust(widget, coords, True)
widget.set_selection_bounds(x, y, dx, dy)
+ # TODO: clip
widget.queue_draw()
def move_selection(self, widget, coords):
@@ -754,7 +751,7 @@ class Desenho:
widget.desenha = True
# Display the polygon open in the temp canvas
self._draw_polygon(widget, True, False, self.points, closed=False)
- widget.queue_draw()
+ self.clear_control_points()
def adjust(self, widget, coords, locked=False):
width, height = widget.window.get_size()