Exemple #1
0
class PILCanvas:
    def __init__(self, width=None, height=None):
        self.canvas      = Image.new("RGB", (width, height), "white")
        self.AGG_canvas  = Draw(self.canvas)
        self.helper      = PILHelper()
        self.context     = PILContext()
        
        self.AGG_canvas.setantialias(True)

    def show(self, *arguments):
        self.AGG_canvas.flush()
        self.canvas.show()
        
    def output(self, filename, file_ext):
        self.AGG_canvas.flush()
        self.canvas.save(filename, file_ext)
        
    def draw(self, ctx=None):
        if not ctx:
            ctx = self.context

        ## Draws things
        while not self.grobStack.empty():
            (priority, item) = self.grobStack.get()
            if isinstance(item, RestoreCtx):
                ctx.restore()
            else:
                if isinstance(item, BezierPath):
                    deltax, deltay = item.center
                    m = item._transform.getMatrixWCenter(deltax, deltay, item._transformmode)
                    self.AGG_canvas.settransform(tuple(m))
                    self.drawpath(item, ctx)

                elif isinstance(item, Text):
                    x, y = item.bounds
                    deltax, deltay = item.center
                    m = item._transform.getMatrixWCenter(deltax, deltay-item.line_height, item._transformmode)
                    #ctx.transform(m)
                    #ctx.translate(item.x, item.y - item.baseline)
                    self.AGG_canvas.settransform(tuple(m))

                    self.draw_text(item, ctx)

                elif isinstance(item, Image):
                    deltax, deltay = item.center
                    m = item._transform.getMatrixWCenter(deltax, deltay, item._transformmode)
                    ctx.transform(m)
                    self.drawimage(item, ctx)

            self.grobStack.task_done()

    def draw_text(self, text, ctx=None):
        #print text.draw_glyph._sentence
        R, G, B, A = text._fillcolor
        R=int(R/1.0*255)
        G=int(G/1.0*255)
        B=int(B/1.0*255)
        font = Font((R, G, B), text._fontfile, size=text._fontsize)
        self.AGG_canvas.text((text.x, text.y), text.text, font)

    def drawclip(self, path, ctx=None):
        '''Passes the path to a Cairo context.'''
        if not isinstance(path, ClippingPath):
            raise Exception("drawpath(): Expecting a ClippingPath, got %s" % path)

        if not ctx:
            ctx = self._context

        for element in path.data:
            cmd = element[0]
            values = element[1:]

            ## apply cairo context commands
            if cmd == MOVETO:
                ctx.move_to(*values)
            elif cmd == LINETO:
                ctx.line_to(*values)
            elif cmd == CURVETO:
                ctx.curve_to(*values)
            elif cmd == RLINETO:
                ctx.rel_line_to(*values)
            elif cmd == RCURVETO:
                ctx.rel_curve_to(*values)
            elif cmd == CLOSE:
                ctx.close_path()
            elif cmd == ELLIPSE:
                x, y, w, h = values
                ctx.save()
                ctx.translate (x + w / 2., y + h / 2.)
                ctx.scale (w / 2., h / 2.)
                ctx.arc (0., 0., 1., 0., 2 * pi)
                ctx.restore()

            else:
                raise Exception("PathElement(): error parsing path element command (got '%s')" % cmd)

        ctx.restore()
        ctx.clip()
    
    def drawpath(self, path, ctx=None):
        strokeWidth = None
        strokeColor = None
        ellipse     = False

        if not isinstance(path, BezierPath):
            raise Exception("drawpath(): Expecting a BezierPath, got %s" % (path))

        
        if isinstance(path.path, PathWrap):
            path.path.initPath()
            nPath = path.path.path
        else:
            return
        
        for element in path.data:
            cmd    = element[0]
            values = element[1:]

            if cmd == MOVETO:
                nPath.moveto(*values)

            elif cmd == LINETO:
                nPath.lineto(*values)

            elif cmd == CURVETO:
                nPath.curveto(*values)

            elif cmd == CURVE3TO:
                nPath.curve3to(*values)

            elif cmd == CURVE4TO:
                nPath.curve4to(*values)

            elif cmd == RLINETO:
                nPath.rlineto(*values)

            elif cmd == RCURVETO:
                nPath.rcurveto(*values)

            elif cmd == ARC:
                nPath.curveto(*values)

            elif cmd == CLOSE:
                nPath.close()

            elif cmd == ELLIPSE:
                x, y, w, h = values

                k = 0.5522847498    
                nPath.moveto(x, y+h/2)
                nPath.curveto(x, y+(1-k)*h/2, x+(1-k)*w/2, y, x+w/2, y)
                nPath.curveto(x+(1+k)*w/2, y, x+w, y+(1-k)*h/2, x+w, y+h/2)
                nPath.curveto(x+w, y+(1+k)*h/2, x+(1+k)*w/2, y+h,x+w/2, y+h)
                nPath.curveto(x+(1-k)*w/2, y+h, x, y+(1+k)*h/2, x, y+h/2)
                nPath.close()

            else:
                raise Exception("PathElement(): error parsing path element command (got '%s')" % cmd)

        arguments = self.buildPenBrush(path, templateArgs=nPath)
        self.AGG_canvas.path(*arguments)
        self.AGG_canvas.flush()

    def buildPenBrush(self, path, templateArgs=None):
        if templateArgs:
            PathArgs      = [templateArgs]
        else:
            PathArgs      = []

        PenArguments  = []
        PenDict       = {}
        brush         = None

        if path._fillcolor:
            (R, G, B, A) = self.helper.decToRgba(path._fillcolor)
            color = (R, G, B)
            brush = Brush(color, opacity=A)

        if path._strokecolor:
            (R, G, B, A) = self.helper.decToRgba(path._strokecolor)
            PenDict["color"]   = (R, G, B)
            PenDict["opacity"] = A
            
        if path._strokewidth:
            PenDict["width"] = path._strokewidth

        if PenDict.has_key("color"):
            PathArgs.append(Pen(**PenDict))
        if brush:
            PathArgs.append(brush)
        
        
        arguments = tuple(PathArgs)
        return arguments