#-------------------------------------------------------------------- # # Python GUI - Canvas - Gtk # #-------------------------------------------------------------------- from math import sin, cos, pi, floor from cairo import OPERATOR_OVER, OPERATOR_SOURCE, FILL_RULE_EVEN_ODD, ImageSurface, SurfacePattern from GUI import export from GUI.Geometry import sect_rect from GUI.StdFonts import application_font from GUI.StdColors import black, white from GUI.GCanvases import Canvas as GCanvas from GUI.GCanvasPaths import CanvasPaths as GCanvasPaths import sys deg = pi / 180 twopi = 2 * pi #-------------------------------------------------------------------- class GState(object): pencolor = black fillcolor = black textcolor = black backcolor = white pensize = 1 font = application_font def __init__(self, clone = None): if clone: self.__dict__.update(clone.__dict__) #-------------------------------------------------------------------- class Canvas(GCanvas, GCanvasPaths): def _from_gdk_drawable(cls, gdk_drawable): return cls(gdk_drawable.cairo_create()) _from_gdk_drawable = classmethod(_from_gdk_drawable) def _from_cairo_context(cls, ctx): return cls(ctx) _from_cairo_context = classmethod(_from_cairo_context) def __init__(self, ctx): ctx.set_fill_rule(FILL_RULE_EVEN_ODD) self._gtk_ctx = ctx self._gstack = [] self._state = GState() GCanvas.__init__(self) GCanvasPaths.__init__(self) def get_pencolor(self): return self._state.pencolor def set_pencolor(self, c): self._state.pencolor = c def get_fillcolor(self): return self._state.fillcolor def set_fillcolor(self, c): self._state.fillcolor = c def get_textcolor(self): return self._state.textcolor def set_textcolor(self, c): self._state.textcolor = c def get_backcolor(self): return self._state.backcolor def set_backcolor(self, c): self._state.backcolor = c def get_pensize(self): return self._state.pensize def set_pensize(self, d): self._state.pensize = d def get_font(self): return self._state.font def set_font(self, f): self._state.font = f def get_current_point(self): return self._gtk_ctx.get_current_point() def rectclip(self, r): l, t, r, b = r ctx = self._gtk_ctx ctx.new_path() ctx.rectangle(l, t, r - l, b - t) ctx.clip() def gsave(self): old_state = self._state self._gstack.append(old_state) self._state = GState(old_state) self._gtk_ctx.save() def grestore(self): self._state = self._gstack.pop() self._gtk_ctx.restore() def newpath(self): self._gtk_ctx.new_path() self.minx = sys.maxint self.miny = sys.maxint self.maxx = -sys.maxint/2 self.maxy = -sys.maxint/2 def moveto(self, x, y): self._gtk_ctx.move_to(x, y) self.minx = min(self.minx, x) self.miny = min(self.miny, y) self.maxx = max(self.maxx, x) self.maxy = max(self.maxy, y) def rmoveto(self, x, y): self._gtk_ctx.rel_move_to(x, y) def lineto(self, x, y): self.minx = min(self.minx, x) self.miny = min(self.miny, y) self.maxx = max(self.maxx, x) self.maxy = max(self.maxy, y) self._gtk_ctx.line_to(x, y) def rlineto(self, x, y): self._gtk_ctx.rel_line_to(x, y) def curveto(self, p1, p2, p3): self.minx = min(self.minx, p1[0], p2[0], p3[0]) self.miny = min(self.miny, p1[1], p2[1], p3[1]) self.maxx = max(self.maxx, p1[0], p2[0], p3[0]) self.maxy = max(self.maxy, p1[1], p2[1], p3[1]) self._gtk_ctx.curve_to(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]) def rcurveto(self, p1, p2, p3): self._gtk_ctx.rel_curve_to(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]) def arc(self, c, r, a0, a1): self._gtk_ctx.arc(c[0], c[1], r, a0 * deg, a1 * deg) def closepath(self): ctx = self._gtk_ctx ctx.close_path() ctx.new_sub_path() def clip(self): self._gtk_ctx.clip_preserve() def stroke(self): state = self._state ctx = self._gtk_ctx #ctx.set_source_rgba(*state.pencolor._rgba) ctx.set_source_color(state.pencolor._gdk_color) ctx.set_line_width(state.pensize) ctx.stroke_preserve() def fill(self): ctx = self._gtk_ctx #ctx.set_source_rgba(*self._state.fillcolor._rgba) if self.fillcolor.image: # surface = ctx.save() ctx.scale((self.maxx-self.minx)*1.0/self.fillcolor.image.get_width(), (self.maxy-self.miny)*1.0/self.fillcolor.image.get_height()) ctx.set_source_pixbuf(self.fillcolor.image, 0, 0) ctx.fill_preserve() ctx.restore() else: ctx.set_source_color(self._state.fillcolor._gdk_color) ctx.fill_preserve() def erase(self): ctx = self._gtk_ctx #ctx.set_source_rgba(*self._state.backcolor._rgba) ctx.set_source_color(self._state.backcolor._gdk_color) ctx.set_operator(OPERATOR_SOURCE) ctx.fill_preserve() ctx.set_operator(OPERATOR_OVER) def show_text(self, text): font = self._state.font layout = font._get_pango_layout(text, True) dx = layout.get_pixel_size()[0] dy = font.ascent ctx = self._gtk_ctx #ctx.set_source_rgba(*self._state.textcolor._rgba) ctx.set_source_color(self._state.textcolor._gdk_color) ctx.rel_move_to(0, -dy) ctx.show_layout(layout) ctx.rel_move_to(dx, dy) def rect(self, rect): l, t, r, b = rect self._gtk_ctx.rectangle(l, t, r - l, b - t) def oval(self, rect): l, t, r, b = rect a = 0.5 * (r - l) b = 0.5 * (b - t) ctx = self._gtk_ctx ctx.new_sub_path() ctx.save() ctx.translate(l + a, t + b) ctx.scale(a, b) ctx.arc(0, 0, 1, 0, twopi) ctx.close_path() ctx.restore() def translate(self, dx, dy): self._gtk_ctx.translate(dx, dy) return def rotate(self, degrees): self._gtk_ctx.rotate(degrees*pi/180) return def scale(self, xscale, yscale): self._gtk_ctx.scale(xscale, yscale) return # def _coords(self, x, y): # x0, y0 = self._origin # return int(round(x0 + x)), int(round(y0 + y)) # def _coords(self, x, y): # return int(round(x)), int(round(y)) # def _rect_coords(self, (l, t, r, b)): # x0, y0 = self._origin # l = int(round(x0 + l)) # t = int(round(y0 + t)) # r = int(round(x0 + r)) # b = int(round(y0 + b)) # return l, t, r - l, b - t # def _rect_coords(self, (l, t, r, b)): # l = int(round(l)) # t = int(round(t)) # r = int(round(r)) # b = int(round(b)) # return l, t, r - l, b - t # def _frame_coords(self, r): # l, t, w, h = self._rect_coords(r) # p = self._gdk_gc.line_width # d = p // 2 # return ( # int(floor(l + d)), # int(floor(t + d)), # int(floor(w - p)), # int(floor(h - p))) #def _gdk_angles(start_angle, end_angle): # arc_angle = (end_angle - start_angle) % 360 # start = int(round(start_angle * 64)) # arc = int(round((arc_angle) * 64)) # return -start, -arc #def _arc_rect((cx, cy), r): # return (cx - r, cy - r, cx + r, cy + r) #def _arc_endpoint(center, r, a): # cx, cy = center # ar = a * deg # x = int(round(cx + r * cos(ar))) # y = int(round(cy + r * sin(ar))) # return x, y export(Canvas)