Update of /cvsroot/freevo/kaa/canvas/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19952/src
Added Files:
.cvsignore __init__.py canvasobject.py
Log Message:
Initial import of new canvas system. Highly WIP.
--- NEW FILE: .cvsignore ---
*.pyc *.pyo version.py
--- NEW FILE: canvasobject.py ---
#__all__ = [ 'CanvasError', 'CanvasObject' ]
# XXX: all this stuff is in a single file right now since it's easier for
# initial development. I'll split it up later.
__all__ = [ 'CanvasObject', 'CanvasError', 'CanvasContainer', 'CanvasImage',
'Canvas', 'X11Canvas' ]
import types
import kaa
from kaa import evas, display, notifier
from kaa.base import weakref
from kaa.notifier import Signal
try:
from kaa import imlib2
except ImportError:
imlib2 = None
class CanvasError(Exception):
pass
class CanvasObject(object):
def __init__(self):
self._properties = {}
self._properties_serial = 0
self._relative_values_cache = { "serial": -1 }
self._o = self._canvas = self._parent = None
self["pos"] = (0, 0)
self["size"] = (-1, -1)
self["color"] = (255, 255, 255, 255)
self["visible"] = True
self["layer"] = 0
def __contains__(self, key):
return key in self._properties
def __getitem__(self, key):
if hasattr(self, "_get_property_" + key):
return getattr(self, "_get_property_" + key)()
if key in self._properties:
return self._properties[key]
return None
def __setitem__(self, key, value):
#print "Set property '%s', oldval=%s newval=%s" % (key,
repr(self[key]), repr(value))
if self[key] == value:
return False
if hasattr(self, "_set_property_" + key):
getattr(self, "_set_property_" + key)(value)
else:
self._set_property_generic(key, value)
self._properties_serial += 1
def _set_property_generic(self, key, value):
self._properties[key] = value
self._queue_render()
def __delitem__(self, key):
if key in self._properties:
del self._properties[key]
def _wrap(self, evas_object):
self._o = evas_object
if not self._o:
return
self._o._canvas_object = weakref(self)
self._queue_render()
def _queue_render(self):
if self._canvas:
self._canvas._queue_render(self)
def _adopted(self, parent):
self._parent = weakref(parent)
def _orphaned(self):
self._parent = None
def _canvased(self, canvas):
self._canvas = weakref(canvas)
if self["name"]:
self._canvas._register_object_name(self["name"], self)
def _uncanvased(self):
if self["name"] and self._canvas:
self._canvas._unregister_object_name(self["name"])
self._wrap(None)
self._canvas = None
def _get_relative_values(self, container = None, pos = None, layer = None,
color = None, visible = None):
if self._properties_serial <= self._relative_values_cache["serial"]:
return self._relative_values_cache
pos = (pos, self["pos"])[pos == None]
layer = (layer, self["layer"])[layer == None]
color = (color, self["color"])[color == None]
visible = (visible, self["visible"])[visible == None]
def _blend_pixel(a, b):
tmp = (a * b) + 0x80
return (tmp + (tmp >> 8)) >> 8
parent = self._parent
while parent:
pos = map(lambda x,y: x+y, pos, parent["pos"])
layer += parent["layer"]
visible = visible and parent["visible"]
color = map(_blend_pixel, color, parent["color"])
if container and parent == container:
break
parent = parent._parent
r = { "pos": pos, "layer": layer, "color": color, "visible": visible,
"serial": self._properties_serial }
self._relative_values_cache = r
#print "Relative", self, r
return r
def _set_property_color(self, color):
# If color element is None, use the existing value.
if None in color:
color = tuple(map(lambda x, y: (x,y)[x==None], color,
self["color"]))
r,g,b,a = color
assert(type(r) == type(g) == type(b) == type(a) == int)
if color != self["color"]:
self._set_property_generic("color", color)
return True
def _sync_properties(self):
if not isinstance(self._o, evas.Object):
return
props = self._get_relative_values()
cur_pos, cur_size = self._o.geometry_get()
if props["pos"] != cur_pos:
self._o.move(props["pos"])
if props["visible"] != self._o.visible_get():
self._o.visible_set(props["visible"])
if props["layer"] != self._o.layer_get():
self._o.layer_set(props["layer"])
if props["color"] != self._o.color_get():
self._o.color_set(*props["color"])
if self["size"] != (-1, -1) and self["size"] != cur_size:
self._o.resize(self._get_computed_size(self["size"]))
def _get_computed_size(self, (w, h)):
orig_w, orig_h = self.get_size()
aspect = orig_w / float(orig_h)
if w == -1:
w = h * aspect
elif h == -1:
h = w / aspect
return int(w), int(h)
# Public API
def get_parent(self):
return self._parent
def move(self, (x, y)):
assert(type(x) == int and type(y) == int)
self["pos"] = (x, y)
def set_color(self, r = None, g = None, b = None, a = None):
self["color"] = (r, g, b, a)
def show(self):
self.set_visible(True)
def hide(self):
self.set_visible(False)
def set_visible(self, visible):
self["visible"] = visible
def set_layer(self, layer):
self["layer"] = layer
def resize(self, size):
self["size"] = size
def get_size(self):
if isinstance(self._o, evas.Object):
return self._o.geometry_get()[1]
return self["size"]
def get_name(self):
return self["name"]
def set_name(self, name):
self["name"] = name
if self._canvas:
self._canvas._register_object_name(name, self)
class CanvasContainer(CanvasObject):
def __init__(self):
self._children = []
super(CanvasContainer, self).__init__()
def _canvased(self, canvas):
super(CanvasContainer, self)._canvased(canvas)
for child in self._children:
child._canvased(canvas)
def _uncanvased(self):
for child in self._children:
child._uncanvased()
def __setitem__(self, key, value):
super(CanvasContainer, self).__setitem__(key, value)
for child in self._children:
child._properties_serial += 1
def _sync_properties(self):
for child in self._children:
child._sync_properties()
def add_child(self, child):
if child._parent:
raise CanvasError, "Attempt to parent an adopted child."
self._children.append(child)
child._adopted(self)
if isinstance(self, Canvas):
child._canvased(self)
elif self._canvas:
child._canvased(self._canvas)
return child
def remove_child(self, child):
if child not in self._children:
return False
self._children.remove(child)
if child._o:
child._o.hide()
# FIXME: shouldn't access _queued_children directly
if child._canvas and child in child._canvas._queued_children:
del child._canvas._queued_children[child]
child._orphaned()
return True
# Convenience functions for object creation.
def add_container(self, pos = (0, 0), visible = True, color = (255, 255,
255, 255), layer = 0, name = None):
c = CanvasContainer()
c.move(pos)
c.set_layer(layer)
c.set_color(*color)
c.set_visible(visible)
c.set_name(name)
self.add_child(c)
return c
def add_image(self, image, dst_pos = (0, 0), dst_size = (-1, -1),
src_pos = (0, 0), src_size = (-1, -1), visible = True,
color = (255, 255, 255, 255), layer = 0, name = None):
img = CanvasImage(image)
img.move(dst_pos)
img.resize(dst_size)
# Do src_pos/size via crop
img.set_layer(layer)
img.set_color(*color)
img.set_visible(visible)
img.set_name(name)
self.add_child(img)
return img
class CanvasImage(CanvasObject):
def __init__(self, image_or_file = None):
super(CanvasImage, self).__init__()
self["loaded"] = False
self["has_alpha"] = True
if image_or_file:
self.set_image(image_or_file)
def set_image(self, image_or_file):
del self["filename"], self["image"]
if type(image_or_file) in types.StringTypes:
self["filename"] = image_or_file
elif imlib2 and type(image_or_file) == imlib2.Image:
self["image"] = image_or_file
self["image"].signals["changed"].connect_weak(self.set_dirty)
else:
raise ValueError, "Unsupported argument to set_image: " +
repr(type(image_or_file))
self["loaded"] = False
def _canvased(self, canvas):
super(CanvasImage, self)._canvased(canvas)
if self._o:
o = self._o
else:
o = canvas.get_evas().object_image_add()
o.alpha_set(True)
self._wrap(o)
def _set_property_filename(self, filename):
if self._o:
self._o.load(filename)
self._set_property_generic("filename", filename)
def _set_property_image(self, image):
assert(imlib2 and type(image) == imlib2.Image)
self._set_property_generic("image", image)
def _sync_properties(self):
super(CanvasImage, self)._sync_properties()
if not self["loaded"]:
if "image" in self:
size = self["image"].size
print "Importing imlib2 image"
self._o.size_set(size)
self._o.resize(size)
self._o.fill_set((0, 0), size)
self._o.data_set(self["image"].get_raw_data(), copy = False)
elif "filename" in self:
self._o.load(self["filename"])
self["loaded"] = True
if self["size"] != (-1, -1) and ((0,0), self.get_size()) !=
self._o.fill_get():
print "SET FILL"
self._o.fill_set((0, 0), self.get_size())
if self["has_alpha"] and self._o.alpha_get() != self["has_alpha"]:
self._o.alpha_set(self["has_alpha"])
if self["dirty"]:
self._o.pixels_dirty_set()
if self["image"]:
# Even though we're sharing the memory between the evas image
buffer
# and the Imlib2 image's buffer, we need to call this function
# for canvas backends where this data gets copied again (like GL
# textures).
self._o.data_set(self["image"].get_raw_data(), copy = False)
self["dirty"] = False
def set_dirty(self, dirty = True):
self["dirty"] = dirty
def as_image(self):
if not imlib2:
assert CanvasError, "kaa.imlib2 not available."
if not self["image"]:
# No existing Imlib2 image, so we need to make one.
if self["loaded"]:
# The evas object already exists, so create an Imlib2 image
# from evas data and use the Imlib2 image as the buffer for
# thee evas object.
size = self._o.size_get()
self["image"] = imlib2.new(size, self._o.data_get())
self._o.data_set(self["image"].get_raw_data(), copy = False)
print "MAKING IMAGE FROM EVAS OBJECT"
elif self["filename"]:
# Evas object not created yet,
self["image"] = imlib2.open(self["filename"])
self["image"].signals["changed"].connect_weak(self.set_dirty)
return self["image"]
def get_image_size(self):
return self._o.size_get()
def set_has_alpha(self, has_alpha = True):
self["has_alpha"] = has_alpha
class Canvas(CanvasContainer):
def __init__(self, size):
self.signals = {
"key_press_event": Signal()
}
self._queued_children = {}
self._names = {}
kaa.signals["idle"].connect_weak(self._check_render_queued)
super(Canvas, self).__init__()
def _register_object_name(self, name, object):
self._names[name] = weakref(object)
def _unregister_object_name(self, name):
if name in self._names:
del self._names[name]
def find_object_by_name(self, name):
if name in self._names:
object = self._names[name]
if object:
return object._ref()
# Dead weakref, remove it.
del self._names[name]
def _get_property_pos(self):
return 0, 0
def _queue_render(self, child = None):
if not child:
child = self
self._queued_children[child] = 1
def _check_render_queued(self):
if len(self._queued_children) == 0:
return
print "Render requested"
for child in self._queued_children.keys():
child._sync_properties()
self._queued_children = {}
self.render()
def render(self):
self._check_render_queued()
self._o.render()
def get_evas(self):
return self._o
class X11Canvas(Canvas):
def __init__(self, size, use_gl = False, title = "Canvas"):
self._window = display.EvasX11Window(use_gl, size = size, title = "Kaa
Display Test")
super(X11Canvas, self).__init__(size)
self._wrap(self._window.get_evas())
self._window.signals["key_press_event"].connect_weak(self.signals["key_press_event"].emit)
self._window.set_cursor_hide_timeout(1)
def _sync_properties(self):
self._visibility_on_next_render = self["visible"]
def _set_property_visible(self, vis):
# Delay window hide/show until next render, because we want the
# the render to happen before the window gets shown.
self._visibility_on_next_render = vis
self._queue_render()
self._set_property_generic("visible", vis)
def _set_property_pos(self, pos):
self._window.move(pos)
self._set_property_generic("pos", pos)
def _set_property_size(self, size):
self._window.resize(size)
self._set_property_generic("size", size)
def render(self):
self._check_render_queued()
vis = self._visibility_on_next_render
if vis == False:
self._window.hide()
self._o.render()
if vis == True:
self._window.show()
self._visibility_on_next_render = None
--- NEW FILE: __init__.py ---
from canvasobject import *
-------------------------------------------------------
This SF.Net email is sponsored by the 'Do More With Dual!' webinar happening
July 14 at 8am PDT/11am EDT. We invite you to explore the latest in dual
core and dual graphics technology at this free one hour event hosted by HP,
AMD, and NVIDIA. To register visit http://www.hp.com/go/dualwebinar
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog