Created
December 3, 2010 18:18
-
-
Save mattharrison/727312 to your computer and use it in GitHub Desktop.
attempt to see if drawing charts caused leaks, note that this removes the drawer portion and goes straight to ctx. I'm not seeing leaks with this.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import random | |
import sys, os, gc | |
import pango | |
import cairo | |
import pangocairo | |
class _Graph(): | |
fixed_upper_bound = False | |
defaults = ( | |
("graph_color", "18BAEB", "Graph color"), | |
("fill_color", "1667EB.3", "Fill color for linefill graph"), | |
("background", "000000", "Widget background"), | |
("border_color", "215578", "Widget border color"), | |
("border_width", 2, "Widget background"), | |
("margin_x", 3, "Margin X"), | |
("margin_y", 3, "Margin Y"), | |
("samples", 100, "Count of graph samples."), | |
("frequency", 0.5, "Update frequency in seconds"), | |
("type", "linefill", "'box', 'line', 'linefill'"), | |
("line_width", 3, "Line width"), | |
) | |
def __init__(self, ctx, width = 100, **config): | |
#base._Widget.__init__(self, width, **config) | |
self.offset = 0 | |
self.ctx = ctx | |
self.width = 300 | |
self.height = 100 | |
self.samples = 100 | |
for name, value, ignore in self.defaults: | |
setattr(self, name, value) | |
self.values = [0]*self.samples | |
self.lasttick = 0 | |
self.maxvalue = 0 | |
@property | |
def graphwidth(self): | |
return self.width - self.border_width*2 - self.margin_x*2 | |
@property | |
def graphheight(self): | |
return self.height - self.margin_y*2 - self.border_width*2 | |
def draw_box(self, x, y, values): | |
step = self.graphwidth/float(self.samples) | |
for val in values: | |
self.fillrect(x, y-val, step, val, self.graph_color) | |
x += step | |
def draw_line(self, x, y, values): | |
step = self.graphwidth/float(self.samples-1) | |
self.ctx.set_line_join(cairo.LINE_JOIN_ROUND) | |
self.set_source_rgb(self.graph_color) | |
self.ctx.set_line_width(self.line_width) | |
for val in values: | |
self.ctx.line_to(x, y-val) | |
x += step | |
self.ctx.stroke() | |
def draw_linefill(self, x, y, values): | |
step = self.graphwidth/float(self.samples-1) | |
self.ctx.set_line_join(cairo.LINE_JOIN_ROUND) | |
self.set_source_rgb(self.graph_color) | |
self.ctx.set_line_width(self.line_width) | |
current = x | |
for val in values: | |
self.ctx.line_to(current, y-val) | |
current += step | |
self.ctx.stroke_preserve() | |
self.ctx.line_to(current, y + self.line_width/2.0) | |
self.ctx.line_to(x, y + self.line_width/2.0) | |
self.set_source_rgb(self.fill_color) | |
self.ctx.fill() | |
def draw(self): | |
self.clear(self.background) | |
if self.border_width: | |
self.set_source_rgb(self.border_color) | |
self.ctx.set_line_width(self.border_width) | |
self.ctx.rectangle( | |
self.margin_x + self.border_width/2.0, self.margin_y + self.border_width/2.0, | |
self.graphwidth + self.border_width, | |
self.height - self.margin_y*2 - self.border_width, | |
) | |
self.ctx.stroke() | |
x = self.margin_x + self.border_width | |
y = self.margin_y + self.graphheight + self.border_width | |
k = 1.0/(self.maxvalue or 1) | |
scaled = [self.graphheight * val * k for val in reversed(self.values)] | |
if self.type == "box": | |
self.draw_box(x, y, scaled) | |
elif self.type == "line": | |
self.draw_line(x, y, scaled) | |
elif self.type == "linefill": | |
self.draw_linefill(x, y, scaled) | |
else: | |
raise ValueError("Unknown graph type: %s."%self.type) | |
#self.draw(self.offset, self.width) | |
def push(self, value): | |
self.values.insert(0, value) | |
self.values.pop() | |
if not self.fixed_upper_bound: | |
self.maxvalue = max(self.values) | |
self.draw() | |
def _configure(self, qtile, bar): | |
base._Widget._configure(self, qtile, bar) | |
hook.subscribe.tick(self.update) | |
def update(self): | |
t = time.time() | |
if self.lasttick + self.frequency < t: | |
self.lasttick = t | |
self.update_graph() | |
def set_source_rgb(self, colour): | |
self.ctx.set_source_rgba(*rgb(colour)) | |
# hacks | |
def clear(self, colour): | |
self.set_source_rgb(colour) | |
self.ctx.rectangle(0, 0, self.width, self.height) | |
self.ctx.fill() | |
self.ctx.stroke() | |
def rgb(x): | |
""" | |
Returns a valid RGBA tuple. | |
Here are some valid specifcations: | |
#ff0000 | |
ff0000 | |
with alpha: ff0000.5 | |
(255, 0, 0) | |
(255, 0, 0, 0.5) | |
""" | |
if isinstance(x, tuple) or isinstance(x, list): | |
if len(x) == 4: | |
alpha = x[3] | |
else: | |
alpha = 1 | |
return (x[0]/255.0, x[1]/255.0, x[2]/255.0, alpha) | |
elif isinstance(x, basestring): | |
if x.startswith("#"): | |
x = x[1:] | |
if "." in x: | |
x, alpha = x.split(".") | |
alpha = float("0."+alpha) | |
else: | |
alpha = 1 | |
if len(x) != 6: | |
raise ValueError("RGB specifier must be 6 characters long.") | |
vals = [int(i, 16) for i in (x[0:2], x[2:4], x[4:6])] | |
vals.append(alpha) | |
return rgb(vals) | |
raise ValueError("Invalid RGB specifier.") | |
if __name__ == '__main__': | |
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300) | |
cr = pangocairo.CairoContext(cairo.Context(surface)) | |
g = _Graph(cr) | |
cr.set_source_rgb(1.0, 0.0, 0.0) | |
layout = cr.create_layout() | |
for i in xrange(500000): | |
g.push(random.randint(0,100)) | |
# cr.new_path() | |
# cr.move_to(100, 100) | |
# layout.set_text('text text text') | |
# cr.show_layout(layout) | |
#print len(gc.get_objects()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment