reportlab/graphics/renderbase.py
 changeset 1677 1450177dd19e parent 1665 c2ce87221cf7 child 1683 7fa753e4420a
```--- a/reportlab/graphics/renderbase.py	Wed Jul 17 22:12:13 2002 +0000
+++ b/reportlab/graphics/renderbase.py	Wed Jul 17 22:46:24 2002 +0000
@@ -1,7 +1,7 @@
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/graphics/renderbase.py?cvsroot=reportlab
-#\$Header: /tmp/reportlab/reportlab/graphics/renderbase.py,v 1.12 2002/07/03 10:21:07 rgbecker Exp \$
+#\$Header: /tmp/reportlab/reportlab/graphics/renderbase.py,v 1.13 2002/07/17 22:46:22 andy_robinson Exp \$
"""
Superclass for renderers to factor out common functionality and default implementations.
"""
@@ -12,274 +12,274 @@
from reportlab.graphics.shapes import *

def inverse(A):
-	"For A affine 2D represented as 6vec return 6vec version of A**(-1)"
-	# I checked this RGB
-	det = float(A[0]*A[3] - A[2]*A[1])
-	R = [A[3]/det, -A[1]/det, -A[2]/det, A[0]/det]
-	return tuple(R+[-R[0]*A[4]-R[2]*A[5],-R[1]*A[4]-R[3]*A[5]])
+    "For A affine 2D represented as 6vec return 6vec version of A**(-1)"
+    # I checked this RGB
+    det = float(A[0]*A[3] - A[2]*A[1])
+    R = [A[3]/det, -A[1]/det, -A[2]/det, A[0]/det]
+    return tuple(R+[-R[0]*A[4]-R[2]*A[5],-R[1]*A[4]-R[3]*A[5]])

def mmult(A, B):
-	"A postmultiplied by B"
-	# I checked this RGB
-	# [a0 a2 a4]	[b0 b2 b4]
-	# [a1 a3 a5] *	[b1 b3 b5]
-	# [		 1 ]	[	   1 ]
-	#
-	return (A[0]*B[0] + A[2]*B[1],
-			A[1]*B[0] + A[3]*B[1],
-			A[0]*B[2] + A[2]*B[3],
-			A[1]*B[2] + A[3]*B[3],
-			A[0]*B[4] + A[2]*B[5] + A[4],
-			A[1]*B[4] + A[3]*B[5] + A[5])
+    "A postmultiplied by B"
+    # I checked this RGB
+    # [a0 a2 a4]    [b0 b2 b4]
+    # [a1 a3 a5] *  [b1 b3 b5]
+    # [      1 ]    [      1 ]
+    #
+    return (A[0]*B[0] + A[2]*B[1],
+            A[1]*B[0] + A[3]*B[1],
+            A[0]*B[2] + A[2]*B[3],
+            A[1]*B[2] + A[3]*B[3],
+            A[0]*B[4] + A[2]*B[5] + A[4],
+            A[1]*B[4] + A[3]*B[5] + A[5])

def getStateDelta(shape):
-	"""Used to compute when we need to change the graphics state.
-	For example, if we have two adjacent red shapes we don't need
-	to set the pen color to red in between. Returns the effect
-	the given shape would have on the graphics state"""
-	delta = {}
-	for (prop, value) in shape.getProperties().items():
-		if STATE_DEFAULTS.has_key(prop):
-			delta[prop] = value
-	return delta
+    """Used to compute when we need to change the graphics state.
+    For example, if we have two adjacent red shapes we don't need
+    to set the pen color to red in between. Returns the effect
+    the given shape would have on the graphics state"""
+    delta = {}
+    for (prop, value) in shape.getProperties().items():
+        if STATE_DEFAULTS.has_key(prop):
+            delta[prop] = value
+    return delta

class StateTracker:
-	"""Keeps a stack of transforms and state
-	properties.  It can contain any properties you
-	want, but the keys 'transform' and 'ctm' have
-	special meanings.  The getCTM()
-	method returns the current transformation
-	matrix at any point, without needing to
-	invert matrixes when you pop."""
-	def __init__(self, defaults=None):
-		# one stack to keep track of what changes...
-		self.__deltas = []
+    """Keeps a stack of transforms and state
+    properties.  It can contain any properties you
+    want, but the keys 'transform' and 'ctm' have
+    special meanings.  The getCTM()
+    method returns the current transformation
+    matrix at any point, without needing to
+    invert matrixes when you pop."""
+    def __init__(self, defaults=None):
+        # one stack to keep track of what changes...
+        self.__deltas = []

-		# and another to keep track of cumulative effects.	Last one in
-		# list is the current graphics state.  We put one in to simplify
-		# loops below.
-		self.__combined = []
-		if defaults is None:
-			defaults = STATE_DEFAULTS.copy()
-		#ensure  that if we have a transform, we have a CTM
-		if defaults.has_key('transform'):
-			defaults['ctm'] = defaults['transform']
-		self.__combined.append(defaults)
+        # and another to keep track of cumulative effects.  Last one in
+        # list is the current graphics state.  We put one in to simplify
+        # loops below.
+        self.__combined = []
+        if defaults is None:
+            defaults = STATE_DEFAULTS.copy()
+        #ensure  that if we have a transform, we have a CTM
+        if defaults.has_key('transform'):
+            defaults['ctm'] = defaults['transform']
+        self.__combined.append(defaults)

-	def push(self,delta):
-		"""Take a new state dictionary of changes and push it onto
-		the stack.	After doing this, the combined state is accessible
-		through getState()"""
+    def push(self,delta):
+        """Take a new state dictionary of changes and push it onto
+        the stack.  After doing this, the combined state is accessible
+        through getState()"""

-		newstate = self.__combined[-1].copy()
-		for (key, value) in delta.items():
-			if key == 'transform':	#do cumulative matrix
-				newstate['transform'] = delta['transform']
-				newstate['ctm'] = mmult(self.__combined[-1]['ctm'], delta['transform'])
-				#print 'statetracker transform = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['transform'])
-				#print 'statetracker ctm = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['ctm'])
+        newstate = self.__combined[-1].copy()
+        for (key, value) in delta.items():
+            if key == 'transform':  #do cumulative matrix
+                newstate['transform'] = delta['transform']
+                newstate['ctm'] = mmult(self.__combined[-1]['ctm'], delta['transform'])
+                #print 'statetracker transform = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['transform'])
+                #print 'statetracker ctm = (%0.2f, %0.2f, %0.2f, %0.2f, %0.2f, %0.2f)' % tuple(newstate['ctm'])

-			else:  #just overwrite it
-				newstate[key] = value
+            else:  #just overwrite it
+                newstate[key] = value

-		self.__combined.append(newstate)
-		self.__deltas.append(delta)
+        self.__combined.append(newstate)
+        self.__deltas.append(delta)

-	def pop(self):
-		"""steps back one, and returns a state dictionary with the
-		deltas to reverse out of wherever you are.	Depending
-		on your back end, you may not need the return value,
-		since you can get the complete state afterwards with getState()"""
-		del self.__combined[-1]
-		newState = self.__combined[-1]
-		lastDelta = self.__deltas[-1]
-		del  self.__deltas[-1]
-		#need to diff this against the last one in the state
-		reverseDelta = {}
-		#print 'pop()...'
-		for key, curValue in lastDelta.items():
-			#print '   key=%s, value=%s' % (key, curValue)
-			prevValue = newState[key]
-			if prevValue <> curValue:
-				#print '	state popping "%s"="%s"' % (key, curValue)
-				if key == 'transform':
-					reverseDelta[key] = inverse(lastDelta['transform'])
-					reverseDelta[key] = prevValue
-		return reverseDelta
+    def pop(self):
+        """steps back one, and returns a state dictionary with the
+        deltas to reverse out of wherever you are.  Depending
+        on your back end, you may not need the return value,
+        since you can get the complete state afterwards with getState()"""
+        del self.__combined[-1]
+        newState = self.__combined[-1]
+        lastDelta = self.__deltas[-1]
+        del  self.__deltas[-1]
+        #need to diff this against the last one in the state
+        reverseDelta = {}
+        #print 'pop()...'
+        for key, curValue in lastDelta.items():
+            #print '   key=%s, value=%s' % (key, curValue)
+            prevValue = newState[key]
+            if prevValue <> curValue:
+                #print '    state popping "%s"="%s"' % (key, curValue)
+                if key == 'transform':
+                    reverseDelta[key] = inverse(lastDelta['transform'])
+                    reverseDelta[key] = prevValue
+        return reverseDelta

-	def getState(self):
-		"returns the complete graphics state at this point"
-		return self.__combined[-1]
+    def getState(self):
+        "returns the complete graphics state at this point"
+        return self.__combined[-1]

-	def getCTM(self):
-		"returns the current transformation matrix at this point"""
-		return self.__combined[-1]['ctm']
+    def getCTM(self):
+        "returns the current transformation matrix at this point"""
+        return self.__combined[-1]['ctm']

def testStateTracker():
-	print 'Testing state tracker'
-	defaults = {'fillColor':None, 'strokeColor':None,'fontName':None, 'transform':[1,0,0,1,0,0]}
-	deltas = [
-		{'fillColor':'red'},
-		{'fillColor':'green', 'strokeColor':'blue','fontName':'Times-Roman'},
-		{'transform':[0.5,0,0,0.5,0,0]},
-		{'transform':[0.5,0,0,0.5,2,3]},
-		{'strokeColor':'red'}
-		]
+    print 'Testing state tracker'
+    defaults = {'fillColor':None, 'strokeColor':None,'fontName':None, 'transform':[1,0,0,1,0,0]}
+    deltas = [
+        {'fillColor':'red'},
+        {'fillColor':'green', 'strokeColor':'blue','fontName':'Times-Roman'},
+        {'transform':[0.5,0,0,0.5,0,0]},
+        {'transform':[0.5,0,0,0.5,2,3]},
+        {'strokeColor':'red'}
+        ]

-	st = StateTracker(defaults)
-	print 'initial:', st.getState()
-	print
-	for delta in deltas:
-		print 'pushing:', delta
-		st.push(delta)
-		print 'state:  ',st.getState(),'\n'
+    st = StateTracker(defaults)
+    print 'initial:', st.getState()
+    print
+    for delta in deltas:
+        print 'pushing:', delta
+        st.push(delta)
+        print 'state:  ',st.getState(),'\n'

-	for delta in deltas:
-		print 'popping:',st.pop()
-		print 'state:  ',st.getState(),'\n'
+    for delta in deltas:
+        print 'popping:',st.pop()
+        print 'state:  ',st.getState(),'\n'

def _expandUserNode(node,canvas):
-	if isinstance(node, UserNode):
-		try:
-			if hasattr(node,'_canvas'):
-				ocanvas = 1
-			else:
-				node._canvas = canvas
-				ocanvas = None
-			onode = node
-			node = node.provideNode()
-		finally:
-			if not ocanvas: del onode._canvas
-	return node
+    if isinstance(node, UserNode):
+        try:
+            if hasattr(node,'_canvas'):
+                ocanvas = 1
+            else:
+                node._canvas = canvas
+                ocanvas = None
+            onode = node
+            node = node.provideNode()
+        finally:
+            if not ocanvas: del onode._canvas
+    return node

class Renderer:
-	"""Virtual superclass for graphics renderers."""
+    """Virtual superclass for graphics renderers."""

-	def __init__(self):
-		self._tracker = StateTracker()
+    def __init__(self):
+        self._tracker = StateTracker()

-	def undefined(self, operation):
-		raise ValueError, "%s operation not defined at superclass class=%s" %(operation, self.__class__)
+    def undefined(self, operation):
+        raise ValueError, "%s operation not defined at superclass class=%s" %(operation, self.__class__)

-	def draw(self, drawing, canvas, x, y):
-		"""This is the top level function, which
-		draws the drawing at the given location.
-		The recursive part is handled by drawNode."""
-		print 'enter Renderer.draw()'
-		self.undefined("draw")
-		print 'enter Renderer.draw()'
+    def draw(self, drawing, canvas, x, y):
+        """This is the top level function, which
+        draws the drawing at the given location.
+        The recursive part is handled by drawNode."""
+        print 'enter Renderer.draw()'
+        self.undefined("draw")
+        print 'enter Renderer.draw()'

-	def drawNode(self, node):
-		"""This is the recursive method called for each node
-		in the tree"""
-		# Undefined here, but with closer analysis probably can be handled in superclass
-		self.undefined("drawNode")
+    def drawNode(self, node):
+        """This is the recursive method called for each node
+        in the tree"""
+        # Undefined here, but with closer analysis probably can be handled in superclass
+        self.undefined("drawNode")

-	def drawNodeDispatcher(self, node):
-		"""dispatch on the node's (super) class: shared code"""
+    def drawNodeDispatcher(self, node):
+        """dispatch on the node's (super) class: shared code"""

-		canvas = getattr(self,'_canvas',None)
-		# replace UserNode with its contents
+        canvas = getattr(self,'_canvas',None)
+        # replace UserNode with its contents

-		try:
-			node = _expandUserNode(node,canvas)
-			if hasattr(node,'_canvas'):
-				ocanvas = 1
-			else:
-				node._canvas = canvas
-				ocanvas = None
+        try:
+            node = _expandUserNode(node,canvas)
+            if hasattr(node,'_canvas'):
+                ocanvas = 1
+            else:
+                node._canvas = canvas
+                ocanvas = None

-			#draw the object, or recurse
-			if isinstance(node, Line):
-				self.drawLine(node)
-			elif isinstance(node, Image):
-				self.drawImage(node)
-			elif isinstance(node, Rect):
-				self.drawRect(node)
-			elif isinstance(node, Circle):
-				self.drawCircle(node)
-			elif isinstance(node, Ellipse):
-				self.drawEllipse(node)
-			elif isinstance(node, PolyLine):
-				self.drawPolyLine(node)
-			elif isinstance(node, Polygon):
-				self.drawPolygon(node)
-			elif isinstance(node, Path):
-				self.drawPath(node)
-			elif isinstance(node, String):
-				self.drawString(node)
-			elif isinstance(node, Group):
-				self.drawGroup(node)
-			elif isinstance(node, Wedge):
-				self.drawWedge(node)
-			else:
-				print 'DrawingError','Unexpected element %s in drawing!' % str(node)
-		finally:
-			if not ocanvas: del node._canvas
+            #draw the object, or recurse
+            if isinstance(node, Line):
+                self.drawLine(node)
+            elif isinstance(node, Image):
+                self.drawImage(node)
+            elif isinstance(node, Rect):
+                self.drawRect(node)
+            elif isinstance(node, Circle):
+                self.drawCircle(node)
+            elif isinstance(node, Ellipse):
+                self.drawEllipse(node)
+            elif isinstance(node, PolyLine):
+                self.drawPolyLine(node)
+            elif isinstance(node, Polygon):
+                self.drawPolygon(node)
+            elif isinstance(node, Path):
+                self.drawPath(node)
+            elif isinstance(node, String):
+                self.drawString(node)
+            elif isinstance(node, Group):
+                self.drawGroup(node)
+            elif isinstance(node, Wedge):
+                self.drawWedge(node)
+            else:
+                print 'DrawingError','Unexpected element %s in drawing!' % str(node)
+        finally:
+            if not ocanvas: del node._canvas

-	_restores = {'stroke':'_stroke','stroke_width': '_lineWidth','stroke_linecap':'_lineCap',
-				'stroke_linejoin':'_lineJoin','fill':'_fill','font_family':'_font',
-				'font_size':'_fontSize'}
+    _restores = {'stroke':'_stroke','stroke_width': '_lineWidth','stroke_linecap':'_lineCap',
+                'stroke_linejoin':'_lineJoin','fill':'_fill','font_family':'_font',
+                'font_size':'_fontSize'}

-	def drawGroup(self, group):
-		# just do the contents.  Some renderers might need to override this
-		# if they need a flipped transform
-		canvas = getattr(self,'_canvas',None)
-		for node in group.getContents():
-			node = _expandUserNode(node,canvas)
-			try:
-				if hasattr(node,'_canvas'):
-					ocanvas = 1
-				else:
-					node._canvas = canvas
-					ocanvas = None
-				self.drawNode(node)
-			finally:
-				if not ocanvas: del node._canvas
+    def drawGroup(self, group):
+        # just do the contents.  Some renderers might need to override this
+        # if they need a flipped transform
+        canvas = getattr(self,'_canvas',None)
+        for node in group.getContents():
+            node = _expandUserNode(node,canvas)
+            try:
+                if hasattr(node,'_canvas'):
+                    ocanvas = 1
+                else:
+                    node._canvas = canvas
+                    ocanvas = None
+                self.drawNode(node)
+            finally:
+                if not ocanvas: del node._canvas

-	def drawWedge(self, wedge):
-		# by default ask the wedge to make a polygon of itself and draw that!
-		#print "drawWedge"
-		polygon = wedge.asPolygon()
-		self.drawPolygon(polygon)
+    def drawWedge(self, wedge):
+        # by default ask the wedge to make a polygon of itself and draw that!
+        #print "drawWedge"
+        polygon = wedge.asPolygon()
+        self.drawPolygon(polygon)

-	def drawPath(self, path):
-		polygons = path.asPolygons()
-		for polygon in polygons:
-				self.drawPolygon(polygon)
+    def drawPath(self, path):
+        polygons = path.asPolygons()
+        for polygon in polygons:
+                self.drawPolygon(polygon)

-	def drawRect(self, rect):
-		# could be implemented in terms of polygon
-		self.undefined("drawRect")
+    def drawRect(self, rect):
+        # could be implemented in terms of polygon
+        self.undefined("drawRect")

-	def drawLine(self, line):
-		self.undefined("drawLine")
+    def drawLine(self, line):
+        self.undefined("drawLine")

-	def drawCircle(self, circle):
-		self.undefined("drawCircle")
+    def drawCircle(self, circle):
+        self.undefined("drawCircle")

-	def drawPolyLine(self, p):
-		self.undefined("drawPolyLine")
+    def drawPolyLine(self, p):
+        self.undefined("drawPolyLine")

-	def drawEllipse(self, ellipse):
-		self.undefined("drawEllipse")
+    def drawEllipse(self, ellipse):
+        self.undefined("drawEllipse")

-	def drawPolygon(self, p):
-		self.undefined("drawPolygon")
+    def drawPolygon(self, p):
+        self.undefined("drawPolygon")

-	def drawString(self, stringObj):
-		self.undefined("drawString")
+    def drawString(self, stringObj):
+        self.undefined("drawString")

-	def applyStateChanges(self, delta, newState):
-		"""This takes a set of states, and outputs the operators
-		needed to set those properties"""
-		self.undefined("applyStateChanges")
+    def applyStateChanges(self, delta, newState):
+        """This takes a set of states, and outputs the operators
+        needed to set those properties"""
+        self.undefined("applyStateChanges")

if __name__=='__main__':
-	print "this file has no script interpretation"
-	print __doc__
+    print "this file has no script interpretation"
+    print __doc__```