Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Desenho.py
diff options
context:
space:
mode:
Diffstat (limited to 'Desenho.py')
-rw-r--r--Desenho.py844
1 files changed, 361 insertions, 483 deletions
diff --git a/Desenho.py b/Desenho.py
index d4572c9..e110aa2 100644
--- a/Desenho.py
+++ b/Desenho.py
@@ -61,14 +61,12 @@ Walter Bender (walter@laptop.org)
"""
-
-import pygtk
-pygtk.require('2.0')
-import gtk
+from gi.repository import Gdk
+from gi.repository import GObject
+from gi.repository import PangoCairo
import logging
import math
-import gc
-import gobject
+import cairo
RESIZE_DELAY = 500 # The time to wait for the resize operation to be
# executed, after the resize controls are pressed.
@@ -85,9 +83,27 @@ class Desenho:
"""
self._resize_timer = None
- #self.d = widget
-
- def line(self, widget, coords):
+ self._rainbow_color_list = ['#ff0000', # red
+ '#ff8000', # orange
+ '#ffff00', # yellow
+ '#80ff00', # lime
+ '#00ff00', # green
+ '#00ff80', # green water
+ '#00ffff', # light blue
+ '#007fff', # almost blue
+ '#0000ff', # blue
+ '#8000ff', # indigo
+ '#ff00ff', # pink violet
+ '#ff0080'] # violet
+ 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.
@param self -- Desenho.Desenho instance
@@ -95,16 +111,21 @@ class Desenho:
@param coords -- Two value tuple
"""
- width, height = widget.window.get_size()
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- widget.pixmap_temp.draw_line(widget.gc_line, widget.oldx, widget.oldy,
- coords[0], coords[1])
- #widget.newx = coords[0]
- #widget.newy = coords[1]
+ if temp == True:
+ ctx = widget.temp_ctx
+ else:
+ ctx = widget.drawing_ctx
+
+ ctx.set_line_width(widget.tool['line size'])
+ ctx.set_line_cap(cairo.LINE_CAP_ROUND)
+ ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
+ 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, size=30, shape='circle'):
+ def eraser(self, widget, coords, last):
"""Erase part of the drawing.
@param self -- Desenho.Desenho instance
@@ -115,11 +136,9 @@ class Desenho:
@param shape -- string (default 'circle')
"""
- widget.desenha = False
- self._trace(widget, widget.gc_eraser, coords, last, size, shape)
- #widget.queue_draw()
+ self._trace(widget, coords, last)
- def brush(self, widget, coords, last, size=5, shape='circle'):
+ def brush(self, widget, coords, last):
"""Paint with brush.
@param self -- Desenho.Desenho instance
@@ -130,8 +149,7 @@ class Desenho:
@param shape -- string (default 'circle')
"""
- widget.desenha = False
- self._trace(widget, widget.gc_brush, coords, last, size, shape)
+ self._trace(widget, coords, last)
def stamp(self, widget, coords, last, stamp_size=20):
"""Paint with stamp.
@@ -143,19 +161,25 @@ class Desenho:
@param stamp_size -- integer (default 20)
"""
+
widget.desenha = False
- gc = widget.gc_brush
width = widget.resized_stamp.get_width()
height = widget.resized_stamp.get_height()
dx = coords[0] - width / 2
dy = coords[1] - height / 2
- widget.pixmap.draw_pixbuf(gc, widget.resized_stamp,
- 0, 0, dx, dy, width, height)
- widget.queue_draw()
+ widget.drawing_ctx.save()
+ widget.drawing_ctx.translate(dx, dy)
+ widget.drawing_ctx.rectangle(dx, dy, width, height)
+ Gdk.cairo_set_source_pixbuf(widget.drawing_ctx, widget.resized_stamp,
+ 0, 0)
+ widget.drawing_ctx.paint()
+ widget.drawing_ctx.restore()
+
+ widget.queue_draw_area(dx, dy, width, height)
- def rainbow(self, widget, coords, last, color, size=5, shape='circle'):
+ def rainbow(self, widget, coords, last):
"""Paint with rainbow.
@param self -- Desenho.Desenho instance
@@ -167,52 +191,62 @@ class Desenho:
@param shape -- string (default 'circle')
"""
- colormap = widget.get_colormap()
- rainbow_colors = [
- colormap.alloc_color('#ff0000', True, True), # vermelho
- colormap.alloc_color('#ff8000', True, True), # laranja
- colormap.alloc_color('#ffff00', True, True), # amarelo
- colormap.alloc_color('#80ff00', True, True), # verde lima
- colormap.alloc_color('#00ff00', True, True), # verde
- colormap.alloc_color('#00ff80', True, True), # verde agua
- colormap.alloc_color('#00ffff', True, True), # azul claro
- colormap.alloc_color('#007fff', True, True), # quase azul
- colormap.alloc_color('#0000ff', True, True), # azul
- colormap.alloc_color('#8000ff', True, True), # anil
- colormap.alloc_color('#ff00ff', True, True), # rosa violeta
- colormap.alloc_color('#ff0080', True, True), # violeta
- ]
-
- widget.gc_rainbow.set_foreground(rainbow_colors[color])
- widget.desenha = False
- self._trace(widget, widget.gc_rainbow, coords, last, size, shape)
+ _color_str = self._rainbow_color_list[self._rainbow_counter]
+ _color = Gdk.color_parse(_color_str)
+ self._rainbow_counter += 1
+ if self._rainbow_counter > 11:
+ self._rainbow_counter = 0
+
+ widget.drawing_ctx.set_source_rgba(_color.red, _color.green,
+ _color.blue, 0.3)
+ self._old_trace(widget, coords, last)
- def _trace(self, widget, gc, coords, last, size, shape):
+ def _old_trace(self, widget, coords, last):
+ """
+ _old_trace is used only by rainbow
+ """
+ widget.desenha = False
+ size = widget.tool['line size']
+ shape = widget.tool['line shape']
if shape == 'circle':
- widget.pixmap.draw_arc(gc, True,
- coords[0] - size / 2, coords[1] - size / 2,
- size, size, 0, 360 * 64)
if last:
- gc.set_line_attributes(size, gtk.gdk.LINE_SOLID,
- gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_ROUND)
- widget.pixmap.draw_line(gc,
- last[0], last[1], coords[0], coords[1])
- gc.set_line_attributes(0, gtk.gdk.LINE_SOLID,
- gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_ROUND)
+ widget.drawing_ctx.set_line_width(size)
+
+ widget.drawing_ctx.set_line_cap(cairo.LINE_CAP_ROUND)
+ widget.drawing_ctx.set_line_join(cairo.LINE_JOIN_ROUND)
+ widget.drawing_ctx.move_to(last[0], last[1])
+ widget.drawing_ctx.line_to(coords[0], coords[1])
+ widget.drawing_ctx.stroke()
+ else:
+ widget.drawing_ctx.move_to(coords[0],
+ coords[1])
+ widget.drawing_ctx.arc(coords[0], coords[1],
+ size / 2, 0., 2 * math.pi)
+ widget.drawing_ctx.fill()
+
elif shape == 'square':
- widget.pixmap.draw_rectangle(gc, True,
- coords[0] - size / 2, coords[1] - size / 2, size, size)
if last:
points = [(last[0] - size / 2, last[1] - size / 2),
(coords[0] - size / 2, coords[1] - size / 2),
(coords[0] + size / 2, coords[1] + size / 2),
(last[0] + size / 2, last[1] + size / 2)]
- widget.pixmap.draw_polygon(gc, True, points)
+ for point in points:
+ widget.drawing_ctx.line_to(*point)
+ widget.drawing_ctx.fill()
points = [(last[0] + size / 2, last[1] - size / 2),
(coords[0] + size / 2, coords[1] - size / 2),
(coords[0] - size / 2, coords[1] + size / 2),
(last[0] - size / 2, last[1] + size / 2)]
- widget.pixmap.draw_polygon(gc, True, points)
+ for point in points:
+ widget.drawing_ctx.line_to(*point)
+ widget.drawing_ctx.fill()
+ else:
+ widget.drawing_ctx.move_to(coords[0] - size / 2,
+ coords[1] - size / 2)
+ widget.drawing_ctx.rectangle(coords[0] - size / 2,
+ coords[1] - size / 2, size, size)
+ widget.drawing_ctx.fill()
+
if last:
x = min(coords[0], last[0])
width = max(coords[0], last[0]) - x
@@ -224,171 +258,184 @@ class Desenho:
else:
widget.queue_draw()
+ def finish_trace(self, widget):
+ widget.desenha = False
+ shape = widget.tool['line shape']
+ rounded = (shape == 'circle')
+ self._draw_polygon(widget, False, False, self.points, False, rounded)
+ if not rounded and len(self.points) == 1:
+ # draw a square if the mouse was not moved
+ size = widget.tool['line size']
+ coords = self.points[0]
+ widget.drawing_ctx.save()
+ if widget.tool['name'] == 'eraser':
+ color = (1.0, 1.0, 1.0, 1.0)
+ else:
+ color = widget.tool['cairo_stroke_color']
+ widget.drawing_ctx.set_source_rgba(*color)
+ widget.drawing_ctx.move_to(coords[0] - size / 2,
+ coords[1] - size / 2)
+ widget.drawing_ctx.rectangle(coords[0] - size / 2,
+ coords[1] - size / 2, size, size)
+ widget.drawing_ctx.fill()
+ widget.drawing_ctx.restore()
+
+ self.points = []
+
+ def _trace(self, widget, coords, last):
+ widget.desenha = True
+ size = widget.tool['line size']
+ shape = widget.tool['line shape']
+
+ rounded = (shape == 'circle')
+
+ self.points.append((coords[0], coords[1]))
+ 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
+ y = min(coords[1], last[1])
+ height = max(coords[1], last[1]) - y
+ # We add size to avoid drawing dotted lines
+ widget.queue_draw_area(x - size, y - size,
+ width + size * 2, height + size * 2)
+
def square(self, widget, event, coords, temp, fill):
"""Draw a square.
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between drawing context and temp context
@param fill -- Fill object
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
x, y, dx, dy, = self.adjust(widget, coords)
+ points = [(x, y), (x + dx, y), (x + dx, y + dy), (x, y + dy)]
+ self._draw_polygon(widget, temp, fill, points)
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_rectangle(widget.gc, True, x, y, dx, dy)
- pixmap.draw_rectangle(widget.gc_line, False, x, y, dx, dy)
- widget.queue_draw()
+ def _draw_polygon(self, widget, temp, fill, points, closed=True,
+ rounded=False):
+ if not points:
+ return
+ if temp == True:
+ ctx = widget.temp_ctx
+ else:
+ ctx = widget.drawing_ctx
+
+ ctx.save()
+ ctx.new_path()
+ ctx.move_to(*points[0])
+ for point in points:
+ ctx.line_to(*point)
+ if closed:
+ ctx.close_path()
+ if rounded:
+ ctx.set_line_cap(cairo.LINE_CAP_ROUND)
+ ctx.set_line_join(cairo.LINE_JOIN_ROUND)
+ else:
+ ctx.set_line_cap(cairo.LINE_CAP_SQUARE)
+ ctx.set_line_join(cairo.LINE_JOIN_MITER)
+ if fill:
+ ctx.set_source_rgba(*widget.tool['cairo_fill_color'])
+ ctx.set_line_width(0)
+ ctx.fill_preserve()
+
+ if widget.tool['name'] == 'eraser':
+ ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0)
+ else:
+ ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
+ ctx.set_line_width(widget.tool['line size'])
+ ctx.stroke()
+ ctx.restore()
+ 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.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between drawing context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
points = [(widget.oldx, widget.oldy),
(widget.oldx + int((coords[0] - widget.oldx) / 2), coords[1]),
(coords[0], widget.oldy)]
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, points)
- pixmap.draw_polygon(widget.gc_line, False, points)
- widget.queue_draw()
+ self._draw_polygon(widget, temp, fill, points)
def trapezoid(self, widget, coords, temp, fill):
"""Draw a trapezoid.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
dif = int((coords[0] - widget.oldx) / 4)
points = [(widget.oldx, widget.oldy), (widget.oldx + dif, coords[1]),
(coords[0] - dif, coords[1]), (coords[0], widget.oldy)]
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, points)
- pixmap.draw_polygon(widget.gc_line, False, points)
- widget.queue_draw()
+ self._draw_polygon(widget, temp, fill, points)
def arrow(self, widget, coords, temp, fill):
"""Draw a arrow.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
x = coords[0] - widget.oldx
y = coords[1] - widget.oldy
A = math.atan2(y, x)
dA = 2 * math.pi / 2
r = math.hypot(y, x)
- m = math.sin(A)
p = [(widget.oldx, widget.oldy)]
- p.append((widget.oldx + int(r * math.cos(A)),\
+ p.append((widget.oldx + int(r * math.cos(A)),
widget.oldy + int(r * math.sin(A))))
- p.append((widget.oldx + int(0.74 * r * math.cos(A + dA / 6)),\
+ p.append((widget.oldx + int(0.74 * r * math.cos(A + dA / 6)),
widget.oldy + int(0.74 * r * math.sin(A + dA / 6))))
- p.append((widget.oldx + int(2 * r * math.cos(A + dA / 6 + dA / 20)),\
+ p.append((widget.oldx + int(2 * r * math.cos(A + dA / 6 + dA / 20)),
widget.oldy + int(2 * r * math.sin(A + dA / 6 + dA / 20))))
p.append((widget.oldx +\
- int(2 * r * math.cos(A + dA / 6 - dA / 20 + dA / 6)),\
+ int(2 * r * math.cos(A + dA / 6 - dA / 20 + dA / 6)), \
widget.oldy +\
int(2 * r * math.sin(A + dA / 6 - dA / 20 + dA / 6))))
- p.append((widget.oldx + int(0.74 * r * math.cos(A + dA / 6 + dA / 6)),\
+ p.append((widget.oldx + int(0.74 * r * math.cos(A + dA / 6 + dA / 6)),
widget.oldy + int(0.74 * r * math.sin(A + dA / 6 + dA / 6))))
- p.append((widget.oldx + int(r * math.cos(A + dA / 2)),\
+ p.append((widget.oldx + int(r * math.cos(A + dA / 2)),
widget.oldy + int(r * math.sin(A + dA / 2))))
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- tp = tuple(p)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, tp)
- pixmap.draw_polygon(widget.gc_line, False, tp)
- widget.queue_draw()
+
+ self._draw_polygon(widget, temp, fill, p)
def parallelogram(self, widget, coords, temp, fill):
"""Draw a parallelogram.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
x = int((coords[0] - widget.oldx) / 4)
points = [(widget.oldx, widget.oldy), (coords[0] - x, widget.oldy),
(coords[0], coords[1]), (widget.oldx + x, coords[1])]
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, points)
- pixmap.draw_polygon(widget.gc_line, False, points)
- widget.queue_draw()
+ self._draw_polygon(widget, temp, fill, points)
def star(self, widget, coords, n, temp, fill):
"""Draw polygon with n sides.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
@param n -- number of sides
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
x = coords[0] - widget.oldx
y = coords[1] - widget.oldy
A = math.atan2(y, x)
@@ -398,38 +445,23 @@ class Desenho:
widget.oldy + int(r * math.sin(A))), \
(widget.oldx + int(0.4 * r * math.cos(A + dA / 2)),
widget.oldy + int(0.4 * r * math.sin(A + dA / 2)))]
- for i in range(int(n) - 1):
+ for _i in range(int(n) - 1):
A = A + dA
p.append((widget.oldx + int(r * math.cos(A)), \
widget.oldy + int(r * math.sin(A))))
p.append((widget.oldx + int(0.4 * r * math.cos(A + dA / 2)), \
widget.oldy + int(0.4 * r * math.sin(A + dA / 2))))
- tp = tuple(p)
-
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, tp)
- pixmap.draw_polygon(widget.gc_line, False, tp)
- widget.queue_draw()
+ self._draw_polygon(widget, temp, fill, p)
def polygon_regular(self, widget, coords, n, temp, fill):
"""Draw polygon with n sides.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
@param n -- number of sides
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
x = coords[0] - widget.oldx
y = coords[1] - widget.oldy
A = math.atan2(y, x)
@@ -437,158 +469,117 @@ class Desenho:
r = math.hypot(y, x)
p = [(widget.oldx + int(r * math.cos(A)), \
widget.oldy + int(r * math.sin(A)))]
- for i in range(int(n) - 1):
+ for _i in range(int(n) - 1):
A = A + dA
p.append((widget.oldx + int(r * math.cos(A)), \
widget.oldy + int(r * math.sin(A))))
- tp = tuple(p)
-
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, tp)
- pixmap.draw_polygon(widget.gc_line, False, tp)
- widget.queue_draw()
+ self._draw_polygon(widget, temp, fill, p)
def heart(self, widget, coords, temp, fill):
"""Draw polygon with n sides.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
if temp == True:
- pixmap = widget.pixmap_temp
+ ctx = widget.temp_ctx
else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
+ ctx = widget.drawing_ctx
- if coords[0] < widget.oldx:
- x = coords[0]
- else:
- x = widget.oldx
- if coords[1] < widget.oldy:
- y = coords[1]
- else:
- y = widget.oldy
-
- dx = math.fabs(coords[0] - widget.oldx)
dy = math.fabs(coords[1] - widget.oldy)
-
- w = int(4 * dx)
- e = int(4 * dx / math.sqrt(3))
-
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_arc(widget.gc, True,
- int(widget.oldx - dx),
- int(widget.oldy - e / 2), w, e, 180 * 64, 60 * 64)
- pixmap.draw_arc(widget.gc, True,
- int(widget.oldx - 3 * dx),
- int(widget.oldy - e / 2), w, e, 300 * 64, 60 * 64)
- pixmap.draw_arc(widget.gc, True,
- int(widget.oldx - dx * 0.2),
- int(widget.oldy - 0.6 * dx + 2),
- int(1.2 * dx), int(1.2 * dx), 0, 180 * 64)
- pixmap.draw_arc(widget.gc, True,
- int(widget.oldx - dx),
- int(widget.oldy - 0.6 * dx + 2),
- int(1.2 * dx), int(1.2 * dx), 0, 180 * 64)
- pixmap.draw_arc(widget.gc_line, False,
- int(widget.oldx - dx),
- int(widget.oldy - e / 2), w, e, 180 * 64, 60 * 64)
- pixmap.draw_arc(widget.gc_line, False,
- int(widget.oldx - dx - w / 2),
- int(widget.oldy - e / 2), w, e, 300 * 64, 60 * 64)
- pixmap.draw_arc(widget.gc_line, False,
- int(widget.oldx - dx * 0.2),
- int(widget.oldy - 0.6 * dx + 2),
- int(1.2 * dx), int(1.2 * dx), 0, 132 * 64)
- pixmap.draw_arc(widget.gc_line, False,
- int(widget.oldx - dx),
- int(widget.oldy - 0.6 * dx + 2),
- int(1.2 * dx), int(1.2 * dx), 48 * 64, 132 * 64)
-
+ r = math.hypot(dy, dy)
+ w = r / 10.0
+
+ if w == 0:
+ # non invertible cairo matrix
+ return
+
+ ctx.set_line_width(widget.tool['line size'])
+ line_width = ctx.get_line_width()
+
+ ctx.save()
+ ctx.new_path()
+ ctx.translate(widget.oldx, widget.oldy)
+ ctx.scale(w, w)
+ ctx.move_to(0, 0)
+ ctx.curve_to(0, -30, -50, -30, -50, 0)
+ ctx.curve_to(-50, 30, 0, 35, 0, 60)
+ ctx.curve_to(0, 35, 50, 30, 50, 0)
+ ctx.curve_to(50, -30, 0, -30, 0, 0)
+
+ ctx.set_line_width(line_width / w)
+ if fill:
+ ctx.set_source_rgba(*widget.tool['cairo_fill_color'])
+ ctx.fill_preserve()
+ ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
+ ctx.stroke()
+ ctx.restore()
+
+ # TODO: clip
widget.queue_draw()
def circle(self, widget, coords, temp, fill):
"""Draw a circle.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between context and temp context
@param fill -- Fill object
-
"""
-
if temp == True:
- pixmap = widget.pixmap_temp
+ ctx = widget.temp_ctx
else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
+ ctx = widget.drawing_ctx
x, y, dx, dy = self.adjust(widget, coords)
-
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
- if fill == True:
- pixmap.draw_arc(widget.gc, True, x, y, dx, dy, 0, 360 * 64)
- pixmap.draw_arc(widget.gc_line, False, x, y, dx, dy, 0, 360 * 64)
+ if dx == 0 or dy == 0:
+ # scale by 0 gives error
+ return
+ ctx.set_line_width(widget.tool['line size'])
+ line_width = ctx.get_line_width()
+ ctx.save()
+ ctx.new_path()
+ ctx.translate(x, y)
+ ctx.scale(dx, dy)
+ ctx.arc(0., 0., 1., 0., 2 * math.pi)
+ ctx.set_line_width(line_width / float(min(dx, dy)))
+ if fill:
+ ctx.set_source_rgba(*widget.tool['cairo_fill_color'])
+ ctx.fill_preserve()
+ ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
+ ctx.stroke()
+ ctx.restore()
+ # TODO: clip
widget.queue_draw()
def clear(self, widget):
"""Clear the drawing.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
"""
logging.debug('Desenho.clear')
+ widget.desenha = False
- widget.desenho = []
widget.textos = []
-
+ x, y = 0, 0
+ width, height = widget.get_size()
# try to clear a selected area first
if widget.is_selected():
- try:
- width, height = widget.pixmap_sel.get_size()
-
- # Clear the selected area
- widget.pixmap_sel.draw_rectangle(widget.get_style().white_gc,
- True, 0, 0, width, height)
- # Draw the selected area in the displayed pixmap
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap_sel,
- 0, 0, widget.orig_x, widget.orig_y, width, height)
- # Draw the selection rectangle
- widget.pixmap_temp.draw_rectangle(widget.gc_selection, False,
- widget.orig_x, widget.orig_y, width, height)
- widget.pixmap_temp.draw_rectangle(widget.gc_selection1, False,
- widget.orig_x - 1, widget.orig_y - 1,
- width + 2, height + 2)
-
- except NameError, message:
- logging.debug(message)
- except Exception, message:
- logging.debug('Unexpected error: %s', message)
- else:
- width, height = widget.window.get_size()
- widget.pixmap.draw_rectangle(widget.get_style().white_gc, True,
- 0, 0, width, height)
- widget.pixmap_temp.draw_rectangle(widget.get_style().white_gc,
- True, 0, 0, width, height)
+ x, y, width, height = widget.get_selection_bounds()
+
+ widget.drawing_ctx.rectangle(x, y, width, height)
+ widget.drawing_ctx.set_source_rgb(1.0, 1.0, 1.0)
+ widget.drawing_ctx.fill()
+
widget.queue_draw()
def text(self, widget, event):
"""Display and draw text in the drawing area.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param event -- GdkEvent
-
"""
if not widget.text_in_progress:
@@ -602,76 +593,54 @@ class Desenho:
else:
widget.text_in_progress = False
- try:
- # This works for a gtk.Entry
- text = widget.activity.textview.get_text()
- except AttributeError:
- # This works for a gtk.TextView
- buf = widget.activity.textview.get_buffer()
- start, end = buf.get_bounds()
- text = buf.get_text(start, end)
+ buf = widget.activity.textview.get_buffer()
+ start, end = buf.get_bounds()
+ text = buf.get_text(start, end, True)
+
+ textview = widget.activity.textview
+ tv_layout = textview.create_pango_layout(text)
- layout = widget.activity.textview.create_pango_layout(text)
+ ctx = widget.drawing_ctx
+
+ ctx.save()
+ ctx.new_path()
+ ctx.set_source_rgba(*widget.tool['cairo_stroke_color'])
+
+ pango_layout = PangoCairo.create_layout(ctx)
+ pango_layout.set_font_description(widget.get_font_description())
+ pango_layout.set_text(unicode(text), len(unicode(text)))
+
+ tv_alloc = textview.get_allocation()
+ ctx.move_to(tv_alloc.x, tv_alloc.y)
+ PangoCairo.show_layout(ctx, pango_layout)
+ ctx.stroke()
+ ctx.restore()
- widget.pixmap.draw_layout(widget.gc_brush,
- widget.oldx, widget.oldy, layout)
- widget.pixmap_temp.draw_layout(widget.gc,
- widget.oldx, widget.oldy, layout)
widget.activity.textview.hide()
+ widget.drawing_canvas.flush()
try:
widget.activity.textview.set_text('')
except AttributeError:
buf.set_text('')
- widget.enableUndo(widget)
-
+ widget.enable_undo()
+ # TODO: clip
widget.queue_draw()
- def selection(self, widget, coords, temp=True):
+ def selection(self, widget, coords):
"""Make a selection.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
- @param fill -- Fill object
-
- @return (x0,y0,x1,y1) -- coords of corners
"""
- width, height = widget.window.get_size()
-
x, y, dx, dy = self.adjust(widget, coords, True)
-
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap,
- 0, 0, 0, 0, width, height)
- if temp:
- widget.pixmap_temp.draw_rectangle(widget.gc_selection, False,
- x, y, dx, dy)
- widget.pixmap_temp.draw_rectangle(widget.gc_selection1, False,
- x - 1, y - 1, dx + 2, dy + 2)
- else:
- try:
- del (widget.pixmap_sel)
- except:
- pass
-
- widget.pixmap_sel = gtk.gdk.Pixmap(widget.window, dx, dy, -1)
- widget.pixmap_sel.draw_drawable(widget.gc, widget.pixmap,
- x, y, 0, 0, dx, dy)
- widget.pixmap.draw_rectangle(widget.get_style().white_gc, True,
- x, y, dx, dy)
- widget.orig_x = x
- widget.orig_y = y
- widget.pixmap_temp.draw_rectangle(widget.gc_selection, False,
- x, y, dx, dy)
- widget.pixmap_temp.draw_rectangle(widget.gc_selection1, False,
- x - 1, y - 1, dx + 2, dy + 2)
-
+ widget.set_selection_bounds(x, y, dx, dy)
+ # TODO: clip
widget.queue_draw()
- def moveSelection(self, widget, coords):
+ def move_selection(self, widget, coords):
"""Move the selection.
@param self -- Desenho.Desenho instance
@@ -681,25 +650,34 @@ class Desenho:
@param pixbuf_copy -- For import image
"""
-
- width, height = widget.window.get_size()
-
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap,
- 0, 0, 0, 0, width, height)
+ widget.desenha = True
dx = int(coords[0] - widget.oldx)
dy = int(coords[1] - widget.oldy)
- size = widget.pixmap_sel.get_size()
-
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap_sel,
- 0, 0, widget.orig_x + dx, widget.orig_y + dy, size[0], size[1])
-
- widget.pixmap_temp.draw_rectangle(widget.gc_selection, False,
- widget.orig_x + dx, widget.orig_y + dy, size[0], size[1])
- widget.pixmap_temp.draw_rectangle(widget.gc_selection1, False,
- widget.orig_x + dx - 1, widget.orig_y + dy - 1,
- size[0] + 2, size[1] + 2)
+ x, y, width, height = widget.get_selection_bounds()
+
+ if widget.pending_clean_selection_background:
+ # clear the selection background
+ widget.drawing_ctx.save()
+ widget.drawing_ctx.new_path()
+ widget.drawing_ctx.rectangle(x, y, width, height)
+ widget.drawing_ctx.set_source_rgb(1.0, 1.0, 1.0)
+ widget.drawing_ctx.fill()
+ widget.drawing_ctx.restore()
+ widget.pending_clean_selection_background = False
+
+ selection_surface = widget.get_selection()
+ widget.oldx = coords[0]
+ widget.oldy = coords[1]
+
+ new_x, new_y = x + dx, y + dy
+ widget.temp_ctx.save()
+ widget.temp_ctx.translate(new_x, new_y)
+ widget.temp_ctx.set_source_surface(selection_surface)
+ widget.temp_ctx.paint()
+ widget.temp_ctx.restore()
+ widget.set_selection_start(new_x, new_y)
widget.queue_draw()
@@ -711,173 +689,73 @@ class Desenho:
@param height_percent -- Percent of y scale
"""
- width, height = widget.window.get_size()
- widget.desenha = True
- widget.selmove = True
-
- #Create the pixbuf for future resizes
- try:
- self.pixbuf_resize
- except:
- size = widget.pixmap_sel.get_size()
- self.pixbuf_resize = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False,
- 8, size[0], size[1])
- self.pixbuf_resize.get_from_drawable(widget.pixmap_sel,
- gtk.gdk.colormap_get_system(), 0, 0, 0, 0, size[0], size[1])
-
- w = self.pixbuf_resize.get_width()
- h = self.pixbuf_resize.get_height()
- wr = int(w * width_percent)
- hr = int(h * height_percent)
-
- self._draw_selection(widget, wr, hr, is_preview=True)
-
# Add a timer for resize or update it if there is one already:
if self._resize_timer is not None:
- gobject.source_remove(self._resize_timer)
- self._resize_timer = gobject.timeout_add(RESIZE_DELAY,
- self._do_resize, widget, wr, hr)
+ GObject.source_remove(self._resize_timer)
+ self._resize_timer = GObject.timeout_add(RESIZE_DELAY,
+ self._do_resize, widget, width_percent, height_percent)
- def _do_resize(self, widget, wr, hr):
+ def _do_resize(self, widget, width_percent, height_percent):
"""Do the resize calculation.
-
"""
- resized = self.pixbuf_resize.scale_simple(wr, hr, gtk.gdk.INTERP_HYPER)
-
- #Copy the resized picture to pixmap_sel
- try:
- del (widget.pixmap_sel)
- except:
- pass
- widget.pixmap_sel = gtk.gdk.Pixmap(widget.window, wr, hr, -1)
- widget.pixmap_sel.draw_pixbuf(widget.get_style().white_gc, resized,
- 0, 0, 0, 0, wr, hr)
-
- #Draw the new pixmap_sel
- self._draw_selection(widget, wr, hr)
-
- # Clean the timer:
- self.resize_timer = None
- return False
-
- def _draw_selection(self, widget, wr, hr, is_preview=False):
- gc.collect()
- width, height = widget.window.get_size()
-
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap,
- 0, 0, 0, 0, width, height)
- if is_preview:
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap_sel,
- 0, 0, widget.orig_x, widget.orig_y, -1, -1)
- else:
- widget.pixmap_temp.draw_drawable(widget.gc, widget.pixmap_sel,
- 0, 0, widget.orig_x, widget.orig_y, wr, hr)
- widget.pixmap_temp.draw_rectangle(widget.gc_selection, False,
- widget.orig_x, widget.orig_y, wr, hr)
- widget.pixmap_temp.draw_rectangle(widget.gc_selection1, False,
- widget.orig_x - 1, widget.orig_y - 1, wr + 2, hr + 2)
-
+ widget.desenha = True
+ widget.resize_selection_surface(float(width_percent),
+ float(height_percent))
widget.queue_draw()
- gc.collect()
- def polygon(self, widget, coords, temp, fill, param=None):
+ def freeform(self, widget, coords, temp, fill, param=None):
"""Draw polygon.
-
@param self -- Desenho.Desenho instance
@param widget -- Area object (GtkDrawingArea)
@param coords -- Two value tuple
- @param temp -- switch between pixmap and pixmap_temp
+ @param temp -- switch between drawing context and temp context
@param fill -- Fill object
-
"""
- if temp == True:
- pixmap = widget.pixmap_temp
- else:
- pixmap = widget.pixmap
- width, height = widget.window.get_size()
-
- pixmap.draw_drawable(widget.gc, widget.pixmap, 0, 0, 0, 0,
- width, height)
-
if param == "moving":
# mouse not pressed moving
- if not widget.polygon_start:
- pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- elif widget.polygon_start == True: # Starting a new polygon ?
- if param == "motion":
- # first press
- try:
- pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- widget.pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- widget.points.append(coords)
- except:
- pixmap.draw_line(widget.gc_line, widget.oldx, widget.oldy,
- coords[0], coords[1])
- widget.pixmap.draw_line(widget.gc_line,
- widget.oldx, widget.oldy, coords[0], coords[1])
- widget.first = widget.oldx, widget.oldy
- widget.points = [widget.first, coords]
- widget.enableUndo(widget, overrite=True)
- widget.last = coords
- else: # param == "release"
- # first release
- try:
- widget.first
- widget.points.append(coords)
- widget.pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- except:
- widget.first = widget.oldx, widget.oldy
- widget.points = [widget.first, coords]
- widget.pixmap.draw_line(widget.gc_line,
- widget.oldx, widget.oldy, coords[0], coords[1])
- widget.enableUndo(widget, overrite=True)
- widget.last = coords
- widget.polygon_start = False
- else:
- if param == "motion":
- # print "press"
- pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- widget.pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
- widget.enableUndo(widget, overrite=True)
- widget.last = coords
- widget.points.append(coords)
- elif param == "release":
- # print "release"
- x = coords[0] - widget.first[0]
- y = coords[1] - widget.first[1]
- d = math.hypot(x, y)
- if d > 20: # close the polygon ?
- pixmap.draw_line(widget.gc_line,
- widget.last[0], widget.last[1], coords[0], coords[1])
+ if self.points:
+ if widget.last:
+ self.points.append((coords[0], coords[1]))
+ widget.last = []
+ else:
+ self.points[-1] = (coords[0], coords[1])
+ elif param == "motion":
+ # when mousepress or mousemove
+ if widget.last:
+ self.points.append((widget.last[0], widget.last[1]))
+ self.points.append((coords[0], coords[1]))
+ else:
+ self.points.append((widget.oldx, widget.oldy))
+ self.points.append((coords[0], coords[1]))
+ widget.enable_undo(overrite=True)
+ widget.last = coords
+ elif param == "release":
+ if len(self.points) > 2:
+ first = self.points[0]
+ dx = coords[0] - first[0]
+ dy = coords[1] - first[1]
+ d = math.hypot(dx, dy)
+ if d > 20:
widget.last = coords
- widget.points.append(coords)
+ self.points.append(coords)
else:
- tp = tuple(widget.points)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, tp)
- pixmap.draw_polygon(widget.gc_line, False, tp)
+ # close the polygon
+ self.points.append((first[0], first[1]))
+ self._draw_polygon(widget, False, fill, self.points)
widget.last = []
- widget.polygon_start = True
- widget.enableUndo(widget, overrite=True)
- elif param == "bug":
- tp = tuple(widget.points)
- if fill == True:
- pixmap.draw_polygon(widget.gc, True, tp)
- pixmap.draw_polygon(widget.gc_line, False, tp)
- widget.last = []
- widget.polygon_start = True
- widget.enableUndo(widget, overrite=True)
- widget.queue_draw()
+ self.points = []
+ widget.enable_undo(overrite=True)
+ widget.queue_draw()
+ return
+
+ widget.desenha = True
+ # Display the polygon open in the temp canvas
+ self._draw_polygon(widget, True, False, self.points, closed=False)
+ self.clear_control_points()
def adjust(self, widget, coords, locked=False):
- width, height = widget.window.get_size()
+ width, height = widget.get_size()
if widget.oldx > int(coords[0]):
xi = int(coords[0])
xf = widget.oldx