Source

PyCessing / pycessing / drawing_cairo.py

Brendan Howell a5a2b46 

Brendan Howell a20f351 
Brendan Howell a5a2b46 



















Brendan Howell a20f351 
Brendan Howell a5a2b46 
Brendan Howell cc8dcb5 
Brendan Howell a5a2b46 











Brendan Howell cc8dcb5 



Brendan Howell 7fc7dce 
Brendan Howell d18816a 
Brendan Howell a5a2b46 



Brendan Howell cc8dcb5 









Brendan Howell 10d3dc7 
Brendan Howell a5a2b46 
Brendan Howell a20f351 


Brendan Howell 7fc7dce 
Brendan Howell cce2f72 

Brendan Howell b92f8ba 
Brendan Howell cce2f72 
Brendan Howell b92f8ba 
Brendan Howell a5a2b46 
Brendan Howell 7fc7dce 
Brendan Howell cce2f72 
Brendan Howell a5a2b46 

Brendan Howell 7fc7dce 
Brendan Howell cce2f72 

Brendan Howell b92f8ba 

Brendan Howell cce2f72 
Brendan Howell b92f8ba 
Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 

Brendan Howell 7fc7dce 
Brendan Howell cce2f72 

Brendan Howell b92f8ba 

Brendan Howell cce2f72 
Brendan Howell b92f8ba 
Brendan Howell cce2f72 
Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 

Brendan Howell 7fc7dce 

Brendan Howell a5a2b46 

Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 


Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 






Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 


Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 



Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 







Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 




Brendan Howell 603b9f8 
Brendan Howell a5a2b46 
Brendan Howell a20f351 
Brendan Howell 7fc7dce 
Brendan Howell a5a2b46 









Brendan Howell 26ca2e9 
Brendan Howell cce2f72 
Brendan Howell a5a2b46 
Brendan Howell b92f8ba 
Brendan Howell 7fc7dce 

Brendan Howell 10d3dc7 
Brendan Howell cc8dcb5 


"""
    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 math
import sys


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)
        if sys.platform == "darwin":
            self.machack = True  # check if we are on a mac
        else:
            self.machack = False

    #set up cairo and pango contexts
    def setSurface(self, sdl_surface):
        self.sdl_surface = sdl_surface
        width = sdl_surface.get_width()
        height = sdl_surface.get_height()

        #TODO: try this on the mac with surface.convert instead
        # of reversing the array - make sure to check platform here
        #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))

        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 green is None:
            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 green is None:
            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()

    #TODO: this is broken under cairo
    def screenGrab(self, fileName):
        pygame.image.save(self.sdl_surface, fileName)

    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)
        if self.machack:
            dest.data[:] = self.surface.get_data()[::-1]
        else:
            dest.data[:] = self.surface.get_data()