Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames/svgsprite.py
blob: ad247dd63e6eb9c9d1426466f6dc5e692936bbe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
"""RSVG/Cairo-based rendering of SVG into Pygame Images"""
from pygame import sprite, Rect
from olpcgames import _cairoimage

class SVGSprite( sprite.Sprite ):
    """Sprite class which renders SVG source-code as a Pygame image
    
    Note:
    
        Currently this sprite class is a bit over-engineered, it gets in the way 
        if you want to, e.g. animate among a number of SVG drawings, as it 
        assumes that setSVG will always set a single SVG file for rendering.
    """
    rect = image = None
    resolution = None
    def __init__( 
        self, svg=None, size=None, *args
    ):
        """Initialise the svg sprite
        
        svg -- svg source text (i.e. content of an svg file)
        size -- optional, to constrain size, (width,height), leaving one 
            as None or 0 causes proportional scaling, leaving both 
            as None or 0 causes natural scaling (screen resolution)
        args -- if present, groups to which to automatically add
        """
        self.size = size
        super( SVGSprite, self ).__init__( *args )
        if svg:
            self.setSVG( svg )
    def setSVG( self, svg ):
        """Set our SVG source"""
        self.svg = svg
        # XXX could delay this until actually asked to display...
        if self.size:
            width,height = self.size
        else:
            width,height = None,None
        self.image = self._render( width,height ).convert_alpha()
        rect = self.image.get_rect()
        if self.rect:
            rect.move( self.rect ) # should let something higher-level do that...
        self.rect = rect 

    def _render( self, width, height ):
        """Render our SVG to a Pygame image"""
        import rsvg
        handle = rsvg.Handle( data = self.svg )
        originalSize = (width,height)
        scale = 1.0
        hw,hh = handle.get_dimension_data()[:2]
        if hw and hh:
            if not width:
                if not height:
                    width,height = hw,hh 
                else:
                    scale = float(height)/hh
                    width = hh/float(hw) * height
            elif not height:
                scale = float(width)/hw
                height = hw/float(hh) * width
            else:
                # scale only, only rendering as large as it is...
                if width/height > hw/hh:
                    # want it taller than it is...
                    width = hh/float(hw) * height
                else:
                    height = hw/float(hh) * width
                scale = float(height)/hh
            
            csrf, ctx = _cairoimage.newContext( int(width), int(height) )
            ctx.scale( scale, scale )
            handle.render_cairo( ctx )
            return _cairoimage.asImage( csrf )
        return None
    def copy( self ):
        """Create a copy of this sprite without reloading the svg image"""
        result = self.__class__(
            size = self.size
        )
        result.image = self.image 
        result.rect = Rect(self.rect)
        result.resolution = self.resolution
        return result