def _center_transform(self, transform): '''' Works like setupTransform of a version of java nodebox http://dev.nodebox.net/browser/nodebox-java/branches/rewrite/src/java/net/nodebox/graphics/Grob.java ''' dx, dy = self._get_center() t = cairo.Matrix() t.translate(dx, dy) t = transform * t t.translate(-dx, -dy) return t
def _render(cairo_ctx): """ At the moment this is based on cairo. TODO: Need to work out how to move the cairo specific bits somewhere else. """ # Go to initial point (CORNER or CENTER): transform = self._call_transform_mode(self._transform) if fillcolor is None and strokecolor is None: # Fixes _bug_FillStrokeNofillNostroke.bot return cairo_ctx.set_matrix(transform) # Run the path commands on the cairo context: self._traverse(cairo_ctx) # Matrix affects stroke, so we need to reset it: cairo_ctx.set_matrix(cairo.Matrix()) if fillcolor is not None and strokecolor is not None: if strokecolor[3] < 1: # Draw onto intermediate surface so that stroke # does not overlay fill cairo_ctx.push_group() cairo_ctx.set_source_rgba(*fillcolor) cairo_ctx.fill_preserve() e = cairo_ctx.stroke_extents() cairo_ctx.set_source_rgba(*strokecolor) cairo_ctx.set_operator(cairo.OPERATOR_SOURCE) cairo_ctx.set_line_width(strokewidth) cairo_ctx.stroke() cairo_ctx.pop_group_to_source() cairo_ctx.paint() else: # Fast path if no alpha in stroke cairo_ctx.set_source_rgba(*fillcolor) cairo_ctx.fill_preserve() cairo_ctx.set_source_rgba(*strokecolor) cairo_ctx.set_line_width(strokewidth) cairo_ctx.stroke() elif fillcolor is not None: cairo_ctx.set_source_rgba(*fillcolor) cairo_ctx.fill() elif strokecolor is not None: cairo_ctx.set_source_rgba(*strokecolor) cairo_ctx.set_line_width(strokewidth) cairo_ctx.stroke()
def endpath(self, draw=True): if self._path is None: raise ShoebotError(_("No current path. Use beginpath() first.")) p = self._path if self._autoclosepath is True: self._path.closepath() if draw: p.draw() else: # keep the transform so we don't lose it self._path.transform = cairo.Matrix(*self._canvas.transform) self._path = None return p
def set_matrix(self, transform=None): if transform is None: pass elif isinstance(transform, Transform): self.append(transform) elif isinstance(transform, (list, tuple)): matrix = tuple(transform) t = cairo.Matrix(*matrix) self.append(t) elif isinstance(transform, cairo.Matrix): self.append(transform) else: raise ValueError(_("Transform: Don't know how to handle transform %s.") % transform)
def _render(cairo_ctx): """ At the moment this is based on cairo. TODO: Need to work out how to move the cairo specific bits somewhere else. """ # Go to initial point (CORNER or CENTER): transform = self._call_transform_mode(self._transform) if fillcolor is None and strokecolor is None: # Fixes _bug_FillStrokeNofillNostroke.bot return cairo_ctx.set_matrix(transform) # Run the path commands on the cairo context: self._traverse(cairo_ctx) # Matrix affects stroke, so we need to reset it: cairo_ctx.set_matrix(cairo.Matrix()) if blendmode: cairo_ctx.set_operator(BLENDMODES[blendmode]) if fillcolor: cairo_ctx.set_source_rgba(*fillcolor) if fillrule: cairo_ctx.set_fill_rule(fillrule) if not strokecolor: cairo_ctx.fill() else: cairo_ctx.fill_preserve() if strokecolor: cairo_ctx.set_source_rgba(*strokecolor) cairo_ctx.set_line_width(strokewidth) if strokedash: cairo_ctx.set_dash(strokedash, dashoffset) if strokecap: # this is needed because strokecap and strokejoin have a ROUND # option which is a different value for each cairo_ctx.set_line_cap(STROKE_CAPS[strokecap]) if strokejoin: cairo_ctx.set_line_join(STROKE_JOINS[strokejoin]) cairo_ctx.stroke() if blendmode: # reset blend mode cairo_ctx.set_operator(cairo.OPERATOR_OVER)
def __init__(self, bot): # Takes bot rather than canvas for compatibility with libraries - e.g. the colors library self._canvas = canvas = bot._canvas self._bot = bot self._set_mode(canvas.mode) self._transform = cairo.Matrix(*canvas.transform)
def get_matrix_with_center(self, x, y, mode): m = cairo.Matrix() centerx = x centery = y m_archived = [] for trans in self.stack: if isinstance(trans, cairo.Matrix): # multiply matrix m *= trans elif isinstance(trans, tuple) and trans[0] in TRANSFORMS: # parse transform command cmd = trans[0] args = trans[1:] t = cairo.Matrix() if cmd == "translate": xt = args[0] yt = args[1] m.translate(xt, yt) elif cmd == "rotate": if mode == "corner": # apply existing transform to cornerpoint deltax, deltay = m.transform_point(0, 0) a = args[0] ct = cos(a) st = sin(a) m *= cairo.Matrix( ct, st, -st, ct, deltax - (ct * deltax) + (st * deltay), deltay - (st * deltax) - (ct * deltay), ) elif mode == "center": # apply existing transform to centerpoint deltax, deltay = m.transform_point(centerx, centery) a = args[0] ct = cos(a) st = sin(a) m *= cairo.Matrix( ct, st, -st, ct, deltax - (ct * deltax) + (st * deltay), deltay - (st * deltax) - (ct * deltay), ) elif cmd == "scale": if mode == "corner": t.scale(args[0], args[1]) m *= t elif mode == "center": # apply existing transform to centerpoint deltax, deltay = m.transform_point(centerx, centery) x, y = args m1 = cairo.Matrix() m2 = cairo.Matrix() m1.translate(-deltax, -deltay) m2.translate(deltax, deltay) m *= m1 m *= cairo.Matrix(x, 0, 0, y, 0, 0) m *= m2 elif cmd == "skew": if mode == "corner": x, y = args ## TODO: x and y should be the tangent of an angle t *= cairo.Matrix(1, 0, x, 1, 0, 0) t *= cairo.Matrix(1, y, 0, 1, 0, 0) m *= t elif mode == "center": # apply existing transform to centerpoint deltax, deltay = m.transform_point(centerx, centery) x, y = args m1 = cairo.Matrix() m2 = cairo.Matrix() m1.translate(-deltax, -deltay) m2.translate(deltax, deltay) t *= m t *= m1 t *= cairo.Matrix(1, 0, x, 1, 0, 0) t *= cairo.Matrix(1, y, 0, 1, 0, 0) t *= m2 m = t elif cmd == "push": m_archived.append(m) elif cmd == "pop": m = m_archived.pop() return m
def skew(self, x=1, y=0): # TODO bring back transform mixin t = self._canvas.transform t *= cairo.Matrix(1, 0, x, 1, 0, 0) t *= cairo.Matrix(1, y, 0, 1, 0, 0) self._canvas.transform = t