reportlab/graphics/renderbase.py
author rgbecker
Wed, 20 Oct 2004 19:27:07 +0000
changeset 2401 cd68d7a84d05
parent 2360 0fbaee224de1
child 2544 a6b9aa99b3c3
permissions -rw-r--r--
CanvasAdapter related changes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2004
817
8c3a399effda License text changes
rgbecker
parents: 604
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/renderbase.py
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     4
"""
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     5
Superclass for renderers to factor out common functionality and default implementations.
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     6
"""
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     7
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     8
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     9
__version__=''' $Id $ '''
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    10
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    11
from reportlab.graphics.shapes import *
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
    12
from reportlab import rl_config
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    13
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    14
def inverse(A):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    15
    "For A affine 2D represented as 6vec return 6vec version of A**(-1)"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    16
    # I checked this RGB
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    17
    det = float(A[0]*A[3] - A[2]*A[1])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    18
    R = [A[3]/det, -A[1]/det, -A[2]/det, A[0]/det]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    19
    return tuple(R+[-R[0]*A[4]-R[2]*A[5],-R[1]*A[4]-R[3]*A[5]])
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    20
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    21
def mmult(A, B):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    22
    "A postmultiplied by B"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    23
    # I checked this RGB
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    24
    # [a0 a2 a4]    [b0 b2 b4]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    25
    # [a1 a3 a5] *  [b1 b3 b5]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    26
    # [      1 ]    [      1 ]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    27
    #
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    28
    return (A[0]*B[0] + A[2]*B[1],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    29
            A[1]*B[0] + A[3]*B[1],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    30
            A[0]*B[2] + A[2]*B[3],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    31
            A[1]*B[2] + A[3]*B[3],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    32
            A[0]*B[4] + A[2]*B[5] + A[4],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    33
            A[1]*B[4] + A[3]*B[5] + A[5])
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    34
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    35
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    36
def getStateDelta(shape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    37
    """Used to compute when we need to change the graphics state.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    38
    For example, if we have two adjacent red shapes we don't need
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    39
    to set the pen color to red in between. Returns the effect
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    40
    the given shape would have on the graphics state"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    41
    delta = {}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    42
    for (prop, value) in shape.getProperties().items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    43
        if STATE_DEFAULTS.has_key(prop):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    44
            delta[prop] = value
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    45
    return delta
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    46
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    47
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    48
class StateTracker:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    49
    """Keeps a stack of transforms and state
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    50
    properties.  It can contain any properties you
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    51
    want, but the keys 'transform' and 'ctm' have
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    52
    special meanings.  The getCTM()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    53
    method returns the current transformation
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    54
    matrix at any point, without needing to
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    55
    invert matrixes when you pop."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    56
    def __init__(self, defaults=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    57
        # one stack to keep track of what changes...
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    58
        self.__deltas = []
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    59
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    60
        # and another to keep track of cumulative effects.  Last one in
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    61
        # list is the current graphics state.  We put one in to simplify
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    62
        # loops below.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    63
        self.__combined = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    64
        if defaults is None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    65
            defaults = STATE_DEFAULTS.copy()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    66
        #ensure  that if we have a transform, we have a CTM
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    67
        if defaults.has_key('transform'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    68
            defaults['ctm'] = defaults['transform']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    69
        self.__combined.append(defaults)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    70
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    71
    def push(self,delta):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    72
        """Take a new state dictionary of changes and push it onto
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    73
        the stack.  After doing this, the combined state is accessible
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    74
        through getState()"""
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
    75
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    76
        newstate = self.__combined[-1].copy()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    77
        for (key, value) in delta.items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    78
            if key == 'transform':  #do cumulative matrix
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    79
                newstate['transform'] = delta['transform']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    80
                newstate['ctm'] = mmult(self.__combined[-1]['ctm'], delta['transform'])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    81
                #print 'statetracker transform = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['transform'])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    82
                #print 'statetracker ctm = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['ctm'])
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    83
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    84
            else:  #just overwrite it
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    85
                newstate[key] = value
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    86
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    87
        self.__combined.append(newstate)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    88
        self.__deltas.append(delta)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    89
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    90
    def pop(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    91
        """steps back one, and returns a state dictionary with the
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    92
        deltas to reverse out of wherever you are.  Depending
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    93
        on your back end, you may not need the return value,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    94
        since you can get the complete state afterwards with getState()"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    95
        del self.__combined[-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    96
        newState = self.__combined[-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    97
        lastDelta = self.__deltas[-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    98
        del  self.__deltas[-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    99
        #need to diff this against the last one in the state
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   100
        reverseDelta = {}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   101
        #print 'pop()...'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   102
        for key, curValue in lastDelta.items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   103
            #print '   key=%s, value=%s' % (key, curValue)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   104
            prevValue = newState[key]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   105
            if prevValue <> curValue:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   106
                #print '    state popping "%s"="%s"' % (key, curValue)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   107
                if key == 'transform':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   108
                    reverseDelta[key] = inverse(lastDelta['transform'])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   109
                else:  #just return to previous state
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   110
                    reverseDelta[key] = prevValue
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   111
        return reverseDelta
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   112
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   113
    def getState(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   114
        "returns the complete graphics state at this point"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   115
        return self.__combined[-1]
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   116
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   117
    def getCTM(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   118
        "returns the current transformation matrix at this point"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   119
        return self.__combined[-1]['ctm']
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   120
2401
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   121
    def __getitem__(self,key):
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   122
        "returns the complete graphics state value of key at this point"
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   123
        return self.__combined[-1][key]
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   124
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   125
    def __setitem__(self,key,value):
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   126
        "sets the complete graphics state value of key to value"
cd68d7a84d05 CanvasAdapter related changes
rgbecker
parents: 2360
diff changeset
   127
        self.__combined[-1][key] = value
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   128
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   129
def testStateTracker():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   130
    print 'Testing state tracker'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   131
    defaults = {'fillColor':None, 'strokeColor':None,'fontName':None, 'transform':[1,0,0,1,0,0]}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   132
    deltas = [
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   133
        {'fillColor':'red'},
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   134
        {'fillColor':'green', 'strokeColor':'blue','fontName':'Times-Roman'},
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   135
        {'transform':[0.5,0,0,0.5,0,0]},
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   136
        {'transform':[0.5,0,0,0.5,2,3]},
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   137
        {'strokeColor':'red'}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   138
        ]
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   139
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   140
    st = StateTracker(defaults)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   141
    print 'initial:', st.getState()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   142
    print
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   143
    for delta in deltas:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   144
        print 'pushing:', delta
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   145
        st.push(delta)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   146
        print 'state:  ',st.getState(),'\n'
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   147
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   148
    for delta in deltas:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   149
        print 'popping:',st.pop()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   150
        print 'state:  ',st.getState(),'\n'
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   151
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   152
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   153
def _expandUserNode(node,canvas):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   154
    if isinstance(node, UserNode):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   155
        try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   156
            if hasattr(node,'_canvas'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   157
                ocanvas = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   158
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   159
                node._canvas = canvas
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   160
                ocanvas = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   161
            onode = node
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   162
            node = node.provideNode()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   163
        finally:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   164
            if not ocanvas: del onode._canvas
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   165
    return node
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   166
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   167
class Renderer:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   168
    """Virtual superclass for graphics renderers."""
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   169
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   170
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   171
        self._tracker = StateTracker()
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   172
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   173
    def undefined(self, operation):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   174
        raise ValueError, "%s operation not defined at superclass class=%s" %(operation, self.__class__)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   175
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   176
    def draw(self, drawing, canvas, x=0, y=0, showBoundary=rl_config._unset_):
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   177
        """This is the top level function, which draws the drawing at the given
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   178
        location. The recursive part is handled by drawNode."""
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   179
        #stash references for ease of  communication
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   180
        if showBoundary is rl_config._unset_: showBoundary=rl_config.showBoundary
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   181
        self._canvas = canvas
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   182
        canvas.__dict__['_drawing'] = self._drawing = drawing
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   183
        drawing._parent = None
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   184
        try:
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   185
            #bounding box
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   186
            if showBoundary: canvas.rect(x, y, drawing.width, drawing.height)
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   187
            canvas.saveState()
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   188
            self.initState(x,y)
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   189
            self.drawNode(drawing)
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   190
            self.pop()
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   191
            canvas.restoreState()
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   192
        finally:
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   193
            #remove any circular references
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   194
            del self._canvas, self._drawing, canvas._drawing, drawing._parent
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   195
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   196
    def initState(self,x,y):
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   197
        deltas = STATE_DEFAULTS.copy()
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   198
        deltas['transform'] = [1,0,0,1,x,y]
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   199
        self._tracker.push(deltas)
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   200
        self.applyStateChanges(deltas, {})
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   201
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   202
    def pop(self):
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   203
        self._tracker.pop()
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   204
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   205
    def drawNode(self, node):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   206
        """This is the recursive method called for each node
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   207
        in the tree"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   208
        # Undefined here, but with closer analysis probably can be handled in superclass
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   209
        self.undefined("drawNode")
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   210
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   211
    def drawNodeDispatcher(self, node):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   212
        """dispatch on the node's (super) class: shared code"""
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   213
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   214
        canvas = getattr(self,'_canvas',None)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   215
        # replace UserNode with its contents
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   216
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   217
        try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   218
            node = _expandUserNode(node,canvas)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   219
            if hasattr(node,'_canvas'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   220
                ocanvas = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   221
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   222
                node._canvas = canvas
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   223
                ocanvas = None
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   224
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   225
            #draw the object, or recurse
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   226
            if isinstance(node, Line):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   227
                self.drawLine(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   228
            elif isinstance(node, Image):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   229
                self.drawImage(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   230
            elif isinstance(node, Rect):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   231
                self.drawRect(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   232
            elif isinstance(node, Circle):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   233
                self.drawCircle(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   234
            elif isinstance(node, Ellipse):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   235
                self.drawEllipse(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   236
            elif isinstance(node, PolyLine):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   237
                self.drawPolyLine(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   238
            elif isinstance(node, Polygon):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   239
                self.drawPolygon(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   240
            elif isinstance(node, Path):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   241
                self.drawPath(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   242
            elif isinstance(node, String):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   243
                self.drawString(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   244
            elif isinstance(node, Group):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   245
                self.drawGroup(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   246
            elif isinstance(node, Wedge):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   247
                self.drawWedge(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   248
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   249
                print 'DrawingError','Unexpected element %s in drawing!' % str(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   250
        finally:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   251
            if not ocanvas: del node._canvas
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   252
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   253
    _restores = {'stroke':'_stroke','stroke_width': '_lineWidth','stroke_linecap':'_lineCap',
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   254
                'stroke_linejoin':'_lineJoin','fill':'_fill','font_family':'_font',
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   255
                'font_size':'_fontSize'}
585
e0144950b3e2 Fixes to CTM to support bitmap renderer; extra string rotation
andy_robinson
parents: 580
diff changeset
   256
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   257
    def drawGroup(self, group):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   258
        # just do the contents.  Some renderers might need to override this
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   259
        # if they need a flipped transform
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   260
        canvas = getattr(self,'_canvas',None)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   261
        for node in group.getContents():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   262
            node = _expandUserNode(node,canvas)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   263
            try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   264
                if hasattr(node,'_canvas'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   265
                    ocanvas = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   266
                else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   267
                    node._canvas = canvas
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   268
                    ocanvas = None
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   269
                node._parent = group
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   270
                self.drawNode(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   271
            finally:
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   272
                del node._parent
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   273
                if not ocanvas: del node._canvas
585
e0144950b3e2 Fixes to CTM to support bitmap renderer; extra string rotation
andy_robinson
parents: 580
diff changeset
   274
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   275
    def drawWedge(self, wedge):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   276
        # by default ask the wedge to make a polygon of itself and draw that!
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   277
        #print "drawWedge"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   278
        polygon = wedge.asPolygon()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   279
        self.drawPolygon(polygon)
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   280
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   281
    def drawPath(self, path):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   282
        polygons = path.asPolygons()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   283
        for polygon in polygons:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   284
                self.drawPolygon(polygon)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   285
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   286
    def drawRect(self, rect):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   287
        # could be implemented in terms of polygon
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   288
        self.undefined("drawRect")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   289
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   290
    def drawLine(self, line):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   291
        self.undefined("drawLine")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   292
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   293
    def drawCircle(self, circle):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   294
        self.undefined("drawCircle")
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   295
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   296
    def drawPolyLine(self, p):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   297
        self.undefined("drawPolyLine")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   298
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   299
    def drawEllipse(self, ellipse):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   300
        self.undefined("drawEllipse")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   301
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   302
    def drawPolygon(self, p):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   303
        self.undefined("drawPolygon")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   304
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   305
    def drawString(self, stringObj):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   306
        self.undefined("drawString")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   307
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   308
    def applyStateChanges(self, delta, newState):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   309
        """This takes a set of states, and outputs the operators
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   310
        needed to set those properties"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   311
        self.undefined("applyStateChanges")
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   312
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   313
if __name__=='__main__':
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   314
    print "this file has no script interpretation"
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 2332
diff changeset
   315
    print __doc__