Source

PyCessing / drawing_cairo.py

Full commit
Brendan Howell a5a2b46 

Brendan Howell a20f351 
Brendan Howell a5a2b46 



















Brendan Howell a20f351 

Brendan Howell a5a2b46 

Brendan Howell 6441194 
Brendan Howell a5a2b46 












Brendan Howell 26ca2e9 
Brendan Howell a5a2b46 



Brendan Howell 10d3dc7 
Brendan Howell a5a2b46 
Brendan Howell 10d3dc7 





Brendan Howell 27cb564 

Brendan Howell 10d3dc7 
Brendan Howell 27cb564 
Brendan Howell 10d3dc7 

Brendan Howell 27cb564 
Brendan Howell 10d3dc7 
Brendan Howell a5a2b46 
Brendan Howell a20f351 


Brendan Howell a5a2b46 
Brendan Howell cce2f72 




Brendan Howell a5a2b46 

Brendan Howell cce2f72 
Brendan Howell a5a2b46 


Brendan Howell cce2f72 





Brendan Howell a5a2b46 



Brendan Howell cce2f72 






Brendan Howell a5a2b46 











































Brendan Howell a20f351 
















Brendan Howell a5a2b46 










Brendan Howell 26ca2e9 
Brendan Howell cce2f72 
Brendan Howell a5a2b46 


Brendan Howell 26ca2e9 

Brendan Howell 10d3dc7 

Brendan Howell 27cb564 










Brendan Howell a5a2b46 
"""
    drawing.py
    Copyright 2012 Brendan Howell (brendan@howell-ersatz.com)

    This file is part of PyCessing.

    PyCessing is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PyCessing is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PyCessing.  If not, see <http://www.gnu.org/licenses/>.
"""


import pygame
import cairo
import pangocairo
import pango
import numpy
import math
import array


class Drawing:
    def __init__(self):
        self.sdl_surface = None
        self.surface = None
        self.ctx = None
        self.stroke = False
        self.stroke_color = (1, 0, 0, 1)
        self.stroke_width = 0
        self.fill = True
        self.fill_color = (0.5, 0, 0.5, 1)
        
    #grab the context at the beginning of the frame
    def setSurface(self, sdl_surface):
        self.sdl_surface = sdl_surface
        width = sdl_surface.get_width()
        height = sdl_surface.get_height()
        #subsurf = sdl_surface.subsurface((0,0,width,height))
        
        #r,g,b,a = subsurf.get_shifts()
        #print r,g,b,a
        #rm,gm,bm,am = subsurf.get_masks()
        #print rm,gm,bm,am
        #subsurf.set_shifts((a, r, g, b))
        #subsurf.set_masks((am, rm, gm, bm))
        
        
        #buf = sdl_surface.get_view("2")
        
        #stride = width * 4
        #self.surface = cairo.ImageSurface.create_for_data(buf, cairo.FORMAT_RGB24, width, height, stride)
        
        self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        self.ctx = cairo.Context(self.surface)
        self.pangoctx = pangocairo.CairoContext(self.ctx)
        self.font_map = pangocairo.cairo_font_map_get_default()
        self.families = self.font_map.list_families()
        
    def setBackground(self, red, green=None, blue=None):
        if not(green):
            self.ctx.set_source_rgba(red/255.0, red/255.0, red/255.0, 1)
        else:
            self.ctx.set_source_rgba(red/255.0, blue/255.0, green/255.0, 1)
        self.ctx.paint()
        
    def setStroke(self, red, green=None, blue=None, alpha=255, width=1):
        self.setStrokeWidth(width)
        self.setStrokeColor(red, green, blue, alpha)
        
    def setStrokeColor(self, red, green=None, blue=None, alpha=255):
        #assume greyscale if only 1 parameter is specified
        if not(green):
            self.stroke_color = (red/255.0, red/255.0, red/255.0, alpha/255.0)
        else:
            self.stroke_color = (red/255.0, green/255.0, blue/255.0, alpha/255.0)
    
    def setStrokeWidth(self, width):
        self.stroke_width = width
        
    def setFillColor(self, red, green=None, blue=None, alpha=255):
        #assume greyscale if only 1 parameter is specified, assume you want fill
        if not(green):
            self.fill_color = (red/255.0, red/255.0, red/255.0, alpha/255.0)
        else:
            self.fill_color = (red/255.0, green/255.0, blue/255.0, alpha/255.0)
        self.fill = True
        
    def setFillState(self, fill):
        self.fill = fill
        
    def rect(self, x, y, width, height): 
        self.ctx.rectangle(x, y, width, height)
        self._fillAndStroke()
    
    def circle(self, cx, cy, radius):
        self.ctx.arc(cx, cy, radius, 0, 2.0 * math.pi)
        self._fillAndStroke()
    
    def ellipse(self, cx, cy, width, height):
        self.ctx.save()
        self.ctx.translate(cx, cy)
        self.ctx.scale(width / 2.0, height / 2.0)
        self.ctx.arc(0.0, 0.0, 1.0, 0.0, 2.0 * math.pi)
        self.ctx.restore()
        self._fillAndStroke()
    
    def arc(self, cx, cy, radius, startAngle, endAngle):
        self.ctx.arc(cx, cy, radius, math.radians(startAngle), math.radians(endAngle))
        self._fillAndStroke()
        
    def line(self, x1, y1, x2, y2):
        self.ctx.move_to(x1, y1)
        self.ctx.line_to(x2, y2)
        self._fillAndStroke()
    
    def polygon(self, pointlist):
        x, y = pointlist[0]
        self.ctx.move_to(x, y)
        for point in pointlist[1:]:
            x, y = point
            self.ctx.line_to(x, y)
        self.ctx.close_path()
        self._fillAndStroke()
                
    def curve(self, x1, y1, cx1, cy1, cx2, cy2, x2, y2):
        self.ctx.move_to(x1, y1)
        self.ctx.curve_to(cx1, cy1, cx2, cy2, x2, y2)
        self._fillAndStroke()

    def screenGrab(self, fileName):
        pygame.image.save(self.sdl_surface, fileName)
        
    def drawText(self, x, y, txt):
        self.ctx.save()
        self.ctx.translate(x,y)
        self.ctx.set_source_rgb(0, 0, 0)
        layout = self.pangoctx.create_layout()
        #print dir(self.families[0])
        print self.families[0].get_name()
        layout.set_font_description(pango.FontDescription(self.families[0].get_name() + " 25"))
        layout.set_width(300)
        layout.set_text(txt)
        self.pangoctx.update_layout(layout)
        print('ctx.POS: %s %s'%self.ctx.get_current_point())
        self.pangoctx.show_layout(layout)
        print('F => %s %s'%layout.get_pixel_size())
        self.ctx.restore()
        
    def _fillAndStroke(self):
        if(self.fill):
            self.ctx.set_source_rgba(self.fill_color[0], self.fill_color[1], self.fill_color[2], self.fill_color[3])
            self.ctx.fill_preserve()
        if(self.stroke_width > 0):
            self.ctx.set_line_width(self.stroke_width)
            self.ctx.set_source_rgba(self.stroke_color[0], self.stroke_color[1], self.stroke_color[2], self.stroke_color[3])
            self.ctx.stroke()
        else:
            self.ctx.new_path()

    #TODO: finish and test PDF output
    def renderToPDF(self, fileName):
    	self.surface = cairo.PDFSurface(fileName, self.sdl_surface.get_width(), self.sdl_surface.get_height())
    	

    def _blitToScreen(self):  
        dest = pygame.surfarray.pixels2d(self.sdl_surface)
        dest.data[:] = self.surface.get_data()
        #dest = pygame.surfarray.pixels2d(self.sdl_surface)
        #dest.data[:] = self.surface.get_data()
        #destR = pygame.surfarray.pixels_red(self.sdl_surface)
        #destR.data[:] = self.surface.get_data()[1::4]
        #destG = pygame.surfarray.pixels_green(self.sdl_surface)
        #destG.data[:] = self.surface.get_data()[2::4]
        #destB = pygame.surfarray.pixels_blue(self.sdl_surface)
        #destB.data[:] = self.surface.get_data()[3::4]
        #destA = pygame.surfarray.pixels_alpha(self.sdl_surface)
        #destA.data[:] = self.surface.get_data()[::4]