<menuitem action='Undo'/>
<menuitem action='Redo'/>
<separator/>
+ <menuitem action='CopyLayer'/>
+ <menuitem action='PasteLayer'/>
+ <separator/>
<menuitem action='ModifyLastStroke'/>
<menuitem action='ModifyEnd'/>
</menu>
('EditMenu', None, 'Edit'),
('Undo', None, 'Undo', '<control>Z', None, self.undo_cb),
('Redo', None, 'Redo', '<control>Y', None, self.redo_cb),
+ ('CopyLayer', None, 'Copy Layer to Clipboard', '<control>C', None, self.copy_cb),
+ ('PasteLayer', None, 'Paste Layer from Clipboard', '<control>V', None, self.paste_cb),
('ModifyLastStroke', None, 'Modify Last Stroke', 'm', None, self.modify_last_stroke_cb),
('ModifyEnd', None, 'Stop Modifying', 'n', None, self.modify_end_cb),
def redo_cb(self, action):
self.doc.redo()
+ def copy_cb(self, action):
+ pixbuf = self.doc.render_current_layer_as_pixbuf()
+ cb = gtk.Clipboard()
+ cb.set_image(pixbuf)
+
+ def paste_cb(self, action):
+ cb = gtk.Clipboard()
+ def callback(clipboard, pixbuf, trash):
+ if not pixbuf:
+ print 'The clipboard doeas not contain any image to paste!'
+ return
+ self.doc.load_layer_from_pixbuf(pixbuf)
+ cb.request_image(callback)
+
def get_recent_strokes(self, max_count):
assert max_count > 0
result = self.layer.strokes[:] # copy
t += cmd.stroke.total_painting_time
return t
- def render_as_pixbuf(self, x, y, w, h):
+ def render_as_pixbuf(self, x, y, w, h, layers=None):
from gtk import gdk
pixbuf = gdk.Pixbuf(gdk.COLORSPACE_RGB, False, 8, w, h)
pixbuf.fill(0xffffffff)
arr = pixbuf.get_pixels_array()
arr = mypaintlib.gdkpixbuf2numpy(arr)
- self.render(arr, -x, -y)
+ self.render(arr, -x, -y, layers)
return pixbuf
+ def render_current_layer_as_pixbuf(self):
+ l = self.layers[self.layer_idx]
+ bbox = list(l.surface.get_bbox())
+ return self.render_as_pixbuf(*bbox + [[l]])
+
def add_layer(self, insert_idx=None):
if insert_idx is None:
insert_idx = self.layer_idx+1
def load_layer_from_data(self, data):
self.do(command.LoadLayer(self, data))
- def load_from_pixbuf(self, pixbuf):
- self.clear()
+ def load_layer_from_pixbuf(self, pixbuf):
arr = pixbuf.get_pixels_array()
arr = mypaintlib.gdkpixbuf2numpy(arr)
self.load_layer_from_data(arr)
+ def load_from_pixbuf(self, pixbuf):
+ self.clear()
+ self.load_layer_from_pixbuf(pixbuf)
+
def save(self, filename):
trash, ext = os.path.splitext(filename)
ext = ext.lower().replace('.', '')
def render_from_empty():
#print 'full rerender'
- if self.background is not None:
- surface.load_from_data(self.background)
- else:
- surface.clear()
+ try:
+ if self.background is not None:
+ surface.load_from_data(self.background)
+ else:
+ surface.clear()
+ finally:
+ self.rendered.background = self.background
self.rendered.strokes = []
- self.rendered.background = self.background
render_new_strokes()
cost = len(self.strokes)
im.save(filename)
def load_from_data(self, data):
- self.clear()
+ dirty_tiles = set(self.tiledict.keys())
+ self.tiledict = {}
+
+ if data.shape[0] % N or data.shape[1] % N:
+ s = list(data.shape)
+ print 'reshaping', s
+ s[0] = ((s[0]+N-1) / N) * N
+ s[1] = ((s[1]+N-1) / N) * N
+ data_new = zeros(s, data.dtype)
+ data_new[:data.shape[0],:data.shape[1],:] = data
+ data = data_new
+
for x, y, rgba in self.iter_tiles_memory(0, 0, data.shape[1], data.shape[0], readonly=False):
# FIXME: will be buggy at border?
tmp = data[y:y+N,x:x+N,:].astype('float32') / 255.0
rgba[:,:,0:3] = tmp
rgba[:,:,3] = 1<<15
+ dirty_tiles.update(self.tiledict.keys())
+ bbox = get_tiles_bbox(dirty_tiles)
+ self.notify_observers(*bbox)
+
+
+
def get_bbox(self):
+ # FIXME: should get precise bbox instead of tile bbox
return get_tiles_bbox(self.tiledict)