Reply
Thread Tools
Posts: 133 | Thanked: 172 times | Joined on Jul 2009 @ Travel bag
#1
I released SVGClock based on Cairo clock, recently. This clock displays various themes in SVG format so you can have a clock widget similar to Screenlets on Maemo. Essentially, the clock consists of various components, Clock face, frame, glass, Hour/minute/second hands with their respective SVG components. This allows you to change the clock face according to your theme/mood by changing the SVG files to be displayed. For more details on SVGClock, pls look here

The present issue with the SVGClock is that, it makes the device slow, when on the foreground. It consumes CPU cycles while on the foreground, as I am painting all the SVG components mentioned above through the expose event every time seconds hand ticks, called by the self.queue_draw().

I think if we can buffer the clock's stationary background and foreground SVG files and display from the buffer, whenever the clock's Hour/Minute/Seconds hand moves (only dynamic components of the clock), then a good amount of CPU cycles can be reduced. I guess this can be done using pixbuffs/pixmaps.

I would really appreciate if someone could help show some direction on how I can achieve this buffering of the stationary SVG components and paint only the dynamic components when the clock ticks..

Though a bit lengthy I am pasting the code below for easy reference:

Code:
#All imports we need
import sys, os
import gobject
import pango
import pygtk
pygtk.require('2.0')
import gtk
from gtk import gdk
import hildondesktop
import cairo
from datetime import datetime
import time
import rsvg
import math

# set this to False to disable display of seconds and update 
# only once per minute (saves CPU cycles on the tablet)
enable_seconds = True

supports_alpha = False
svgclock_themes_dir = "/home/user/MyDocs/Themes/default"

class SVGClock(hildondesktop.HomeItem):
    def __init__(self):
        hildondesktop.HomeItem.__init__(self)

        self.set_resize_type(hildondesktop.HOME_ITEM_RESIZE_BOTH)
        self.set_size_request(200, 200)
        self.connect("expose-event", self.expose)
        self.connect("screen-changed", self.screen_changed)
        self.connect ("background", self.set_timer, False)
        self.connect ("foreground", self.set_timer, True)
        self.connect ("unrealize", self.unrealize)

        # set a timeout to update the clock, depending
        # on whether we are in the foreground or background
        self.timer = None
        self.set_timer(self, True)

        self.show_all()
    def expose(self, widget, event):

        global supports_alpha

        #Get a cairo context
        cr = widget.window.cairo_create()
        if supports_alpha == True:
            cr.set_source_rgba(0.0, 0.0, 0.0, 0.0) # Transparent
        else:
            cr.set_source_rgb(1.0, 1.0, 1.0) # Opaque white

        # Draw the background
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()

        self.DrawClockTheme(cr)
        return False

    def DrawClockTheme(self, cr):

        SVGH_Drop_Shadow = self.load_svg("clock-drop-shadow.svg")
        SVGH_Face = self.load_svg("clock-face.svg")
        SVGH_Face_Shadow = self.load_svg("clock-face-shadow.svg")
        SVGH_Marks = self.load_svg("clock-marks.svg")
        SVGH_Frame = self.load_svg("clock-frame.svg")
        SVGH_Glass = self.load_svg("clock-glass.svg")
        SVGH_Hour_Hand = self.load_svg("clock-hour-hand.svg")
        SVGH_Minute_Hand = self.load_svg("clock-minute-hand.svg")
        SVGH_Second_Hand = self.load_svg("clock-second-hand.svg")    

        cr.scale(2.0,2.0)
        cr.save()
        # Draw foreground
        SVGH_Face_Shadow.render_cairo(cr)
        SVGH_Glass.render_cairo(cr)
        SVGH_Frame.render_cairo(cr)

        # Draw Background
        cr.set_operator(cairo.OPERATOR_OVER)
        SVGH_Drop_Shadow.render_cairo(cr)
        SVGH_Face.render_cairo(cr)
        SVGH_Marks.render_cairo(cr)
        
        #Draw the clock glass face with shadow
        cr.set_operator(cairo.OPERATOR_OVER)
        SVGH_Glass.render_cairo(cr)    

        cr.translate(50,50)
        cr.save()

        #Draw the hours/minutes and seconds hands        
        time = datetime.now()
        hour = time.hour
        minutes = time.minute
        seconds = time.second

        cr.set_operator(cairo.OPERATOR_OVER)
        #cr.rotate((360/12) * (hour+9) * (3.141593/180))
        cr.rotate(((360/12) * (hour+9) * (3.141593/180)) + (((360/60) * minutes * (3.141593/180)) / 12))
        SVGH_Hour_Hand.render_cairo(cr)
        cr.restore()
        cr.save()

        cr.rotate((360/60) * (minutes+45) * (3.141593/180))
        SVGH_Minute_Hand.render_cairo(cr)
        cr.restore()
        cr.save()

        # only draw seconds when in foreground
        if enable_seconds: # disable seconds, to much work for little tablets
           cr.rotate((360/60) * (seconds+45) * (3.141593/180))
           cr.set_operator(cairo.OPERATOR_OVER)
           SVGH_Second_Hand.render_cairo(cr)
           cr.restore()
          
        return True
           

    def load_svg(self, filed):

        get_svg = lambda name: rsvg.Handle(os.path.join(svgclock_themes_dir, name))
#        get_svg = lambda name: rsvg.Handle(os.path.join("/home/user/MyDocs/Themes/default", name))
        loadval = get_svg(filed)
        return loadval
  
    def screen_changed(self, widget, old_screen=None):
        global supports_alpha
        # print "screen changed"

        # To check if the display supports alpha channels, get the colormap
        screen = self.get_screen()
        colormap = screen.get_rgba_colormap()
        if colormap == None:
            # print 'Your screen does not support alpha channels!'
            colormap = screen.get_rgb_colormap()
            supports_alpha = False
        else:
            # print 'Your screen supports alpha channels!'
            supports_alpha = True

        # Now we have a colormap appropriate for the screen, use it
        self.set_colormap(colormap)

        return False
#        return True


    def unrealize(self, widget, date=None):
        # cancel timeout
        if self.timer:
            v = gobject.source_remove(self.timer)
            print "canceled svgclock timeout:", v
            self.timer = None

    def set_timer(self, widget, on):
        # when called first time from __init__ widget is None
        if self.timer != None:
            # print "removing old timer"
            gobject.source_remove(self.timer)
        if on:
            # print "creating new timer"
            delay = 1000 if enable_seconds else 60000
            self.timer = gobject.timeout_add(delay, self.update)
            # repaint immediately when coming to the foreground
            self.update()

    def update(self):
        # print "updating svgclock"
        self.queue_draw()
        return True

def hd_plugin_get_objects():
    plugin = SVGClock()
    return [plugin]

if __name__ == "__main__":
  print SVGClock()

Last edited by shin; 2010-02-15 at 14:03.
 

The Following 2 Users Say Thank You to shin For This Useful Post:
Addison's Avatar
Posts: 3,811 | Thanked: 1,151 times | Joined on Oct 2007 @ East Lansing, MI
#2
If you don't get a response from anyone here after a week or so, maybe you could PM Matan on this.

He's a great guy and really knows his Python.

I'm sure he would be willing to help out provided he has the free time available.
 
Reply


 
Forum Jump


All times are GMT. The time now is 09:08.