<bullet> xml tag added
authorrgbecker
Wed, 31 May 2000 10:12:45 +0000
changeset 250 a1bcf9c6c21e
parent 249 1d9ea4f00348
child 251 6f6cd14069f6
<bullet> xml tag added
reportlab/demos/odyssey/odyssey.txt
reportlab/platypus/paragraph.py
reportlab/platypus/paraparser.py
--- a/reportlab/demos/odyssey/odyssey.txt	Fri May 26 10:27:37 2000 +0000
+++ b/reportlab/demos/odyssey/odyssey.txt	Wed May 31 10:12:45 2000 +0000
@@ -11,9 +11,7 @@
 ----------------------------------------------------------------------
 
 BOOK I
-<para align=center font="times-bold" size=24 leading=28.8 spaceAfter=72>ReportLab -- Reporting for the Internet Age</para>
-
-<font color=green><b><i>Tell</i></b></font> me, O muse, of that ingenious hero who travelled far and wide
+<bullet indent=-18><font name=courier size=13 color=blue>I</fontt></bullet><font color=green><b><i>Tell</i></b></font> me, O muse, of that ingenious hero who travelled far and wide
 after he had sacked the famous town of <font color=red size=12><b>Troy</b></font>. Many cities did he visit,
 and many were the nations with whose manners and customs he was acquainted;
 moreover he suffered much by sea while trying to save his own life
--- a/reportlab/platypus/paragraph.py	Fri May 26 10:27:37 2000 +0000
+++ b/reportlab/platypus/paragraph.py	Wed May 31 10:12:45 2000 +0000
@@ -31,9 +31,12 @@
 #
 ###############################################################################
 #	$Log: paragraph.py,v $
+#	Revision 1.10  2000/05/31 10:12:20  rgbecker
+#	<bullet> xml tag added
+#
 #	Revision 1.9  2000/05/16 16:15:16  rgbecker
 #	Changes related to removal of SimpleFlowDocument
-#
+#	
 #	Revision 1.8  2000/05/16 15:58:27  rgbecker
 #	Fixed font setting bug
 #	
@@ -58,7 +61,7 @@
 #	Revision 1.1  2000/04/14 13:21:52  rgbecker
 #	Removed from layout.py
 #	
-__version__=''' $Id: paragraph.py,v 1.9 2000/05/16 16:15:16 rgbecker Exp $ '''
+__version__=''' $Id: paragraph.py,v 1.10 2000/05/31 10:12:20 rgbecker Exp $ '''
 import string
 import types
 from reportlab.pdfbase.pdfmetrics import stringWidth
@@ -220,14 +223,33 @@
 			f.append(w)
 	return f
 
+def _drawBullet(canvas, offset, cur_y, bulletText, style):
+	'''draw a bullet text could be a simple string or a frag list'''
+	tx2 = canvas.beginText(style.bulletIndent, cur_y)
+	tx2.setFont(style.bulletFontName, style.bulletFontSize)
+	tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
+	if type(bulletText) is types.StringType:
+		tx2.textOut(bulletText)
+	else:
+		for f in bulletText:
+			tx2.setFont(f.fontName, f.fontSize)
+			tx2.setFillColor(f.textColor)
+			tx2.textOut(f.text)
+
+	bulletEnd = tx2.getX()
+	offset = max(offset, bulletEnd - style.leftIndent)
+	canvas.drawText(tx2)
+	return offset
+
 class Paragraph(Flowable):
 	def __init__(self, text, style, bulletText = None, frags=None):
 		if frags is None:
 			text = cleanBlockQuotedText(text)
-			style, frags = _parser.parse(text,style)
+			style, frags, bFrags = _parser.parse(text,style)
 			if frags is None:
 				raise "xml parser error (%s) in paragraph beginning\n'%s'"\
 					% (_parser.errors[0],text[:min(30,len(text))])
+			if bFrags: bulletText = bFrags
 		self.frags = frags
 		self.style = style
 		self.bulletText = bulletText
@@ -312,10 +334,17 @@
 		fFontSize = float(style.fontSize)
 
 		#for bullets, work out width and ensure we wrap the right amount onto line one
-		if self.bulletText <> None:
-			bulletWidth = stringWidth(
-				self.bulletText,
-				style.bulletFontName, style.bulletFontSize)
+		bulletText = self.bulletText
+		if bulletText <> None:
+			if type(bulletText) is types.StringType:
+				bulletWidth = stringWidth(
+					bulletText,
+					style.bulletFontName, style.bulletFontSize)
+			else:
+				#it's a list of fragments
+				bulletWidth = 0
+				for f in bulletText:
+					bulletWidth = bulletWidth + stringWidth(f.text, f.fontName, f.fontSize)
 			bulletRight = style.bulletIndent + bulletWidth
 			if bulletRight > style.firstLineIndent:
 				#..then it overruns, and we have less space available on line 1
@@ -421,6 +450,7 @@
 
 		return lines
 
+
 	def drawPara(self,debug=0):
 		"""Draws a paragraph according to the given style.
 		Returns the final y position at the bottom. Not safe for
@@ -455,6 +485,7 @@
 
 
 		nLines = len(lines)
+		bulletText = self.bulletText
 		if nLines > 0:
 			canvas.saveState()
 			canvas.addLiteral('% textcanvas.drawParagraph()')
@@ -474,15 +505,8 @@
 					dpl = _justifyDrawParaLine
 				f = bfrags
 				cur_y = self.height - f.fontSize
-
-				if self.bulletText <> None:
-					tx2 = canvas.beginText(style.bulletIndent, cur_y)
-					tx2.setFont(style.bulletFontName, style.bulletFontSize)
-					tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
-					tx2.textOut(self.bulletText)
-					bulletEnd = tx2.getX()
-					offset = max(offset, bulletEnd - style.leftIndent)
-					canvas.drawText(tx2)
+				if bulletText <> None:
+					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
 
 				#set up the font etc.
 				canvas._code.append('%s %s %s rg' % (f.textColor.red, f.textColor.green, f.textColor.blue))
@@ -499,6 +523,8 @@
 			else:
 				f = lines[0]
 				cur_y = self.height - f.fontSize
+				if bulletText <> None:
+					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
 				if alignment == TA_LEFT:
 					dpl = _leftDrawParaLineX
 				elif alignment == TA_CENTER:
@@ -508,14 +534,6 @@
 				elif self.style.alignment == TA_JUSTIFY:
 					dpl = _justifyDrawParaLineX
 
-				if self.bulletText <> None:
-					tx2 = canvas.beginText(style.bulletIndent, cur_y)
-					tx2.setFont(style.bulletFontName, style.bulletFontSize)
-					tx2.textOut(self.bulletText)
-					bulletEnd = tx2.getX()
-					offset = max(offset, bulletEnd - style.leftIndent)
-					canvas.drawText(tx2)
-
 				#set up the font etc.
 				tx = canvas.beginText(cur_x, cur_y)
 				tx.XtraState=ParaFrag()
--- a/reportlab/platypus/paraparser.py	Fri May 26 10:27:37 2000 +0000
+++ b/reportlab/platypus/paraparser.py	Wed May 31 10:12:45 2000 +0000
@@ -32,9 +32,12 @@
 #
 ###############################################################################
 #	$Log: paraparser.py,v $
+#	Revision 1.20  2000/05/31 10:12:20  rgbecker
+#	<bullet> xml tag added
+#
 #	Revision 1.19  2000/05/26 09:49:23  rgbecker
 #	Color fixes; thanks to J Alet
-#
+#	
 #	Revision 1.18  2000/05/20 15:36:42  andy_robinson
 #	Removed 1.5.2-style getattr call
 #	
@@ -53,7 +56,7 @@
 #	Revision 1.13  2000/04/25 13:07:57  rgbecker
 #	Added license
 #	
-__version__=''' $Id: paraparser.py,v 1.19 2000/05/26 09:49:23 rgbecker Exp $ '''
+__version__=''' $Id: paraparser.py,v 1.20 2000/05/31 10:12:20 rgbecker Exp $ '''
 import string
 import re
 from types import TupleType
@@ -103,6 +106,7 @@
 	else: raise ValueError
 
 _paraAttrMap = {'font': ('fontName', None),
+				'face': ('fontName', None),
 				'fontsize': ('fontSize', _num),
 				'size': ('fontSize', _num),
 				'leading': ('leading', _num),
@@ -113,14 +117,24 @@
 				'spaceb': ('spaceBefore', _num),
 				'spacea': ('spaceAfter', _num),
 				'bfont': ('bulletFontName', None),
-				'bfontsize': ('bulletFontIndent',_num),
-				'bindent': ('bulletFontIndent',_num),
+				'bfontsize': ('bulletFontSize',_num),
+				'bindent': ('bulletIndent',_num),
 				'bcolor': ('bulletColor',toColor),
 				'color':('textColor',toColor),
 				'fg': ('textColor',toColor)}
 
+_bulletAttrMap = {
+				'font': ('bulletFontName', None),
+				'face': ('bulletFontName', None),
+				'size': ('bulletFontSize',_num),
+				'fontsize': ('bulletFontSize',_num),
+				'indent': ('bulletIndent',_num),
+				'color': ('bulletColor',toColor),
+				'fg': ('bulletColor',toColor)}
+
 #things which are valid font attributes
 _fontAttrMap = {'size': ('fontSize', _num),
+				'face': ('fontName', None),
 				'name': ('fontName', None),
 				'fg': 	('textColor', toColor),
 				'color':('textColor', toColor)}
@@ -134,6 +148,7 @@
 
 _addAttributeNames(_paraAttrMap)
 _addAttributeNames(_fontAttrMap)
+_addAttributeNames(_bulletAttrMap)
 
 def _applyAttributes(obj, attr):
 	for k, v in attr.items():
@@ -305,11 +320,11 @@
 	def end_font(self):
 		self._pop()
 
-	def start_para(self,attr):
+	def _initial_frag(self,attr,attrMap,bullet=0):
 		style = self._style
 		if attr!={}:
 			style = copy.deepcopy(style)
-			_applyAttributes(style,self.getAttributes(attr,_paraAttrMap))
+			_applyAttributes(style,self.getAttributes(attr,attrMap))
 			self._style = style
 
 		# initialize semantic values
@@ -317,16 +332,35 @@
 		frag.sub = 0
 		frag.super = 0
 		frag.rise = 0
-		frag.fontName, frag.bold, frag.italic = ps2tt(style.fontName)
-		frag.fontSize = style.fontSize
 		frag.underline = 0
-		frag.textColor = style.textColor
 		frag.greek = 0
-		self._stack = [frag]
+		if bullet:
+			frag.fontName, frag.bold, frag.italic = ps2tt(style.bulletFontName)
+			frag.fontSize = style.bulletFontSize
+			frag.textColor = hasattr(style,'bulletColor') and style.bulletColor or style.textColor
+		else:
+			frag.fontName, frag.bold, frag.italic = ps2tt(style.fontName)
+			frag.fontSize = style.fontSize
+			frag.textColor = style.textColor
+		return frag
+
+	def start_para(self,attr):
+		self._stack = [self._initial_frag(attr,_paraAttrMap)]
 
 	def end_para(self):
 		self._pop()
 
+	def start_bullet(self,attr):
+		if hasattr(self,'bFragList'):
+			self._syntax_error('only one <bullet> tag allowed')
+		self.bFragList = []
+		frag = self._initial_frag(attr,_bulletAttrMap,1)
+		frag.isBullet = 1
+		self._stack.append(frag)
+
+	def end_bullet(self):
+		self._pop()
+
 	def _push(self,**attr):
 		frag = copy.copy(self._stack[-1])
 		_applyAttributes(frag,attr)
@@ -383,14 +417,18 @@
 			for item in greeks.keys():
 				self.entitydefs[item] = '<%s/>' % item
 
+	def _iReset(self):
+		self.fragList = []
+		if hasattr(self, 'bFragList'): delattr(self,'bFragList')
+
 	def _reset(self, style):
 		'''reset the parser'''
 		xmllib.XMLParser.reset(self)
 
 		# initialize list of string segments to empty
 		self.errors = []
-		self.fragList = []
 		self._style = style
+		self._iReset()
 
 	#----------------------------------------------------------------
 	def handle_data(self,data):
@@ -416,7 +454,11 @@
 		# bold, italic, and underline
 		frag.fontName = tt2ps(frag.fontName,frag.bold,frag.italic)
 
-		self.fragList.append(frag)
+		if hasattr(frag,'isBullet'):
+			delattr(frag,'isBullet')
+			self.bFragList.append(frag)
+		else:
+			self.fragList.append(frag)
 
 	def handle_cdata(self,data):
 		self.handle_data(data)
@@ -441,10 +483,11 @@
 		del self._style
 		if len(self.errors)==0:
 			fragList = self.fragList
-			self.fragList = []
-			return style, fragList
+			bFragList = hasattr(self,'bFragList') and self.bFragList or None
+			self._iReset()
 		else:
-			return style, None
+			fragList = bFragList = None
+		return style, fragList, bFragList
 
 if __name__=='__main__':
 	from reportlab.platypus.paragraph import cleanBlockQuotedText
@@ -452,7 +495,7 @@
 	def check_text(text,p=_parser):
 		print '##########'
 		text = cleanBlockQuotedText(text)
-		l,rv = p.parse(text,style)
+		l,rv,bv = p.parse(text,style)
 		if rv is None:
 			for l in _parser.errors:
 				print l
@@ -465,6 +508,9 @@
 	style.fontName='Times-Roman'
 	style.fontSize = 12
 	style.textColor = black
+	style.bulletFontName = black
+	style.bulletFontName='Times-Roman'
+	style.bulletFontSize=12
 
 	text='''
 	<b><i><greek>a</greek>D</i></b>&beta;
@@ -558,3 +604,7 @@
 Head the ship, therefore, away from the island.''')
 	check_text('''&lt; &gt; &amp; &quot; &apos;''')
 	check_text('''<![CDATA[<>&'"]]>''')
+	check_text('''<bullet face=courier size=14 color=green>+</bullet>
+There was a bard also to sing to them and play
+his lyre, while two tumblers went about performing in the midst of
+them when the man struck up with his tune.]''')