Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Area.py
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2012-03-27 21:39:46 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2012-03-27 21:39:46 (GMT)
commit35da02ebed5442024198660b93177a6d16ffdfb8 (patch)
tree9abef7ab7165e90369cb6c4544c51f2c31e468ff /Area.py
parentd6026d204a9586fad31f2952af8d53a4037b4371 (diff)
Implement a fallback fill_flood bucket method in python
The code is slower than the c implementation, but the activity can run if we do not have code compiled for the architecture/gcc/python version in use Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
Diffstat (limited to 'Area.py')
-rw-r--r--Area.py70
1 files changed, 65 insertions, 5 deletions
diff --git a/Area.py b/Area.py
index d953005..c7b6cce 100644
--- a/Area.py
+++ b/Area.py
@@ -69,11 +69,19 @@ import os
import tempfile
import math
import pango
-from fill import fill
+
from Desenho import Desenho
from urlparse import urlparse
from sugar.graphics.style import zoom
+FALLBACK_FILL = True
+try:
+ from fill import fill
+ FALLBACK_FILL = False
+except:
+ logging.debug('No valid fill binaries. Using slower python code')
+ pass
+
##Tools and events manipulation are handle with this class.
@@ -603,10 +611,25 @@ class Area(gtk.DrawingArea):
private_undo = True
elif self.tool['name'] == 'bucket':
- width, height = self.window.get_size()
- fill(self.pixmap, self.gc, coords[0], coords[1],
- width, height, self.gc_line.foreground.pixel)
- widget.queue_draw()
+ if FALLBACK_FILL:
+ if self.tool['stroke color'] is not None:
+ stroke_color = self.tool['stroke color']
+ color_r = int(stroke_color.red_float * 65535)
+ color_g = int(stroke_color.green_float * 65535)
+ color_b = int(stroke_color.blue_float * 65535)
+ else:
+ color_r, color_g, color_b = 0, 0, 0
+ cmap = self.pixmap.get_colormap()
+ fill_color = \
+ cmap.alloc_color(color_r, color_g, color_b).pixel
+ self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
+ gobject.idle_add(self.flood_fill, coords[0], coords[1],
+ fill_color)
+ else:
+ width, height = self.window.get_size()
+ fill(self.pixmap, self.gc, coords[0], coords[1], width,
+ height, self.gc_line.foreground.pixel)
+ widget.queue_draw()
elif self.tool['name'] == 'triangle':
self.d.triangle(widget, coords, False, self.tool['fill'])
@@ -640,6 +663,43 @@ class Area(gtk.DrawingArea):
if not private_undo:
self.enableUndo(widget)
+ def flood_fill(self, x, y, fill_color):
+ width, height = self.window.get_size()
+
+ gdk_image = self.pixmap.get_image(0, 0, width, height)
+
+ def within(x, y):
+ if x < 0 or x >= width:
+ return False
+ if y < 0 or y >= height:
+ return False
+ return True
+
+ if not within(x, y):
+ return
+ edge = [(x, y)]
+
+ old_color = gdk_image.get_pixel(x, y)
+ if old_color == fill_color:
+ logging.debug('Already filled')
+ return
+
+ gdk_image.put_pixel(x, y, fill_color)
+
+ while len(edge) > 0:
+ newedge = []
+ for (x, y) in edge:
+ for (s, t) in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
+ if within(s, t) and \
+ gdk_image.get_pixel(s, t) == old_color:
+ gdk_image.put_pixel(s, t, fill_color)
+ newedge.append((s, t))
+ edge = newedge
+
+ self.pixmap.draw_image(self.gc, gdk_image, 0, 0, 0, 0, width, height)
+ self.queue_draw()
+ self.window.set_cursor(None)
+
def mouseleave(self, widget, event):
if self.tool['name'] in ['pencil', 'eraser', 'brush', 'rainbow',
'stamp']: