Fix #338: re.sub() flag argument at wrong position.
[docutils.git] / sandbox / dreamcatcher / reportlabs.diff
blobba2c07e8a152b45a179f93cde11e1c902804a70b
1 Index: lib/rparsexml.py
2 ===================================================================
3 RCS file: /cvsroot/reportlab/reportlab/lib/rparsexml.py,v
4 retrieving revision 1.2
5 diff -u -r1.2 rparsexml.py
6 --- lib/rparsexml.py 4 Nov 2002 00:11:48 -0000 1.2
7 +++ lib/rparsexml.py 28 May 2003 19:45:52 -0000
8 @@ -168,15 +168,15 @@
9 # raise ValueError, "I don't handle ampersands yet!!!"
10 docontents = 1
11 if firstbracket<0:
12 - # no tags
13 - #if verbose: print "no tags"
14 - if toplevel is not None:
15 - #D = {NAMEKEY: NONAME, CONTENTSKEY: [xmltext[cursor:]]}
16 - ContentList = [xmltext[cursor:]]
17 - ContentList = unEscapeContentList(ContentList)
18 - return (NameString, AttDict, ContentList, ExtraStuff)
19 - else:
20 - raise ValueError, "no tags at non-toplevel %s" % `xmltext[cursor:cursor+20]`
21 + # no tags
22 + #if verbose: print "no tags"
23 + if toplevel is not None:
24 + #D = {NAMEKEY: NONAME, CONTENTSKEY: [xmltext[cursor:]]}
25 + ContentList = [xmltext[cursor:]]
26 + ContentList = unEscapeContentList(ContentList)
27 + return ((NameString, AttDict, ContentList, ExtraStuff), cursor)
28 + else:
29 + raise ValueError, "no tags at non-toplevel %s" % `xmltext[cursor:cursor+20]`
30 #D = {}
31 L = []
32 # look for start tag
33 Index: pdfgen/canvas.py
34 ===================================================================
35 RCS file: /cvsroot/reportlab/reportlab/pdfgen/canvas.py,v
36 retrieving revision 1.111
37 diff -u -r1.111 canvas.py
38 --- pdfgen/canvas.py 10 Apr 2003 00:01:17 -0000 1.111
39 +++ pdfgen/canvas.py 28 May 2003 19:45:54 -0000
40 @@ -429,13 +429,13 @@
41 is to keep the user's current zoom settings. the last
42 arguments may or may not be needed depending on the
43 choice of 'fitType'.
46 Fit types and the other arguments they use are:
47 /XYZ left top zoom - fine grained control. null
48 or zero for any of the parameters means 'leave
49 as is', so "0,0,0" will keep the reader's settings.
50 NB. Adobe Reader appears to prefer "null" to 0's.
53 /Fit - entire page fits in window
55 /FitH top - top coord at top of window, width scaled
56 @@ -443,7 +443,7 @@
58 /FitV left - left coord at left of window, height
59 scaled to fit
62 /FitR left bottom right top - scale window to fit
63 the specified rectangle
65 @@ -464,7 +464,7 @@
66 right = "null"
67 if zoom is None:
68 zoom = "null"
71 if fitType == "XYZ":
72 dest.xyz(left,top,zoom)
73 elif fitType == "Fit":
74 @@ -483,7 +483,7 @@
75 elif fitType == "FitBV":
76 dest.fitbv(left)
77 else:
78 - raise "Unknown Fit type %s" % (fitType,)
79 + raise "Unknown Fit type %s" % (fitType,)
81 dest.setPage(pageref)
82 return dest
83 @@ -498,7 +498,7 @@
84 the page."""
85 #This method should probably be deprecated since it is just a sub-set of bookmarkPage
86 return self.bookmarkPage(key,fitType="FitH",top=yhorizontal)
89 def bookmarkHorizontal(self, key, relativeX, relativeY):
90 """w.r.t. the current transformation, bookmark this horizontal."""
91 (xt, yt) = self.absolutePosition(relativeX,relativeY)
92 @@ -829,7 +829,7 @@
93 assert rot % 90.0 == 0.0, "Rotation must be a multiple of 90 degrees"
94 self._pageRotation = rot
98 def addLiteral(self, s, escaped=1):
99 """introduce the literal text of PDF operations s into the current stream.
100 Only use this if you are an expert in the PDF file format."""
101 Index: platypus/para.py
102 ===================================================================
103 RCS file: /cvsroot/reportlab/reportlab/platypus/para.py,v
104 retrieving revision 1.6
105 diff -u -r1.6 para.py
106 --- platypus/para.py 9 Apr 2003 22:58:37 -0000 1.6
107 +++ platypus/para.py 28 May 2003 19:45:55 -0000
108 @@ -63,7 +63,8 @@
109 from reportlab.platypus.flowables import Flowable
110 from reportlab.lib import colors
112 -import string
113 +from types import StringType, UnicodeType, InstanceType, TupleType, ListType, FloatType
114 +from string import letters as LETTERS, whitespace as WHITESPACE
116 # SET THIS TO CAUSE A VIEWING BUG WITH ACROREAD 3 (for at least one input)
117 # CAUSEERROR = 0
118 @@ -91,7 +92,6 @@
119 program = []
120 self.lineOpHandlers = [] # for handling underlining and hyperlinking, etc
121 self.program = program
122 - #self.
123 self.indent = self.rightIndent = 0.0
124 self.baseindent = 0.0 # adjust this to add more indentation for bullets, eg
125 self.fontName = "Helvetica"
126 @@ -102,10 +102,12 @@
127 from reportlab.lib.enums import TA_LEFT
128 self.alignment = TA_LEFT
129 self.textStateStack = []
131 TEXT_STATE_VARIABLES = ("indent", "rightIndent", "fontName", "fontSize",
132 "leading", "fontColor", "lineOpHandlers", "rise",
133 "alignment")
134 #"textStateStack")
136 def pushTextState(self):
137 state = []
138 for var in self.TEXT_STATE_VARIABLES:
139 @@ -116,6 +118,7 @@
140 #print "push", self.textStateStack
141 #print "push", len(self.textStateStack), state
142 return state
144 def popTextState(self):
145 state = self.textStateStack[-1]
146 self.textStateStack = self.textStateStack[:-1]
147 @@ -136,7 +139,6 @@
148 remainder = program[:]
149 #program1 = remainder[:] # debug only
150 lineprogram = []
151 - from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
152 #if maxheight<TOOSMALLSPACE:
153 # raise ValueError, "attempt to format inside too small a height! "+repr(maxheight)
154 heightremaining = maxheight-leading
155 @@ -150,9 +152,11 @@
156 linewidth = maxwidth - indent - rightIndent
157 beforelinestate = self.__dict__.copy()
158 if linewidth<TOOSMALLSPACE:
159 - raise ValueError, "indents %s %s too wide for space %s" % (self.indent, self.rightIndent, maxwidth)
160 + raise ValueError, "indents %s %s too wide for space %s" % (self.indent, self.rightIndent, \
161 + maxwidth)
162 try:
163 - (lineIsFull, line, cursor, currentLength, usedIndent, maxLength, justStrings) = self.fitLine(remainder, maxwidth)
164 + (lineIsFull, line, cursor, currentLength, \
165 + usedIndent, maxLength, justStrings) = self.fitLine(remainder, maxwidth)
166 except:
167 ## print "failed to fit line near", cursorcount # debug
168 ## for i in program1[max(0,cursorcount-10): cursorcount]:
169 @@ -235,20 +239,23 @@
170 self.__dict__.update(startstate)
171 heightused = maxheight - heightremaining
172 return (lineprogram, remainder, laststate, heightused)
174 def getState(self):
175 # inlined
176 return self.__dict__.copy()
178 def resetState(self, state):
179 # primarily inlined
180 self.__dict__.update(state)
182 ## def sizeOfWord(self, word):
183 ## inlineThisFunctionForEfficiency
184 ## return float(stringWidth(word, self.fontName, self.fontSize))
186 def fitLine(self, program, totalLength):
187 "fit words (and other things) onto a line"
188 # assuming word lengths and spaces have not been yet added
189 # fit words onto a line up to maxlength, adding spaces and respecting extra space
190 - from types import StringType, TupleType, InstanceType, FloatType
191 from reportlab.pdfbase.pdfmetrics import stringWidth
192 usedIndent = self.indent
193 maxLength = totalLength - usedIndent - self.rightIndent
194 @@ -269,7 +276,7 @@
195 opcode = program[cursor]
196 #if debug: print "opcode", cursor, opcode
197 topcode = type(opcode)
198 - if topcode is StringType or topcode is InstanceType:
199 + if topcode in (StringType, UnicodeType, InstanceType):
200 lastneedspace = needspace
201 needspace = 0
202 if topcode is InstanceType:
203 @@ -278,7 +285,7 @@
204 needspace = 0
205 else:
206 saveopcode = opcode
207 - opcode = opcode.strip() #string.strip(opcode)
208 + opcode = opcode.strip()
209 if opcode:
210 width = stringWidth(opcode, fontName, fontSize)
211 else:
212 @@ -342,7 +349,7 @@
213 oldcolor = self.fontColor
214 (i, colorname) = opcode
215 #print "opcode", opcode
216 - if type(colorname) is StringType:
217 + if type(colorname) in (StringType, UnicodeType):
218 color = self.fontColor = getattr(colors, colorname)
219 else:
220 color = self.fontColor = colorname # assume its something sensible :)
221 @@ -357,7 +364,7 @@
222 # change font size
223 (i, fontsize) = opcode
224 size = abs(float(fontsize))
225 - if type(fontsize) is StringType:
226 + if type(fontsize) in (StringType, UnicodeType):
227 if fontsize[:1]=="+":
228 fontSize = self.fontSize = self.fontSize + size
229 elif fontsize[:1]=="-":
230 @@ -457,41 +464,43 @@
231 line.append( ("nextLine", 0) )
232 #print "fitline", line
233 return (lineIsFull, line, cursor, currentLength, usedIndent, maxLength, justStrings)
235 def centerAlign(self, line, lineLength, maxLength):
236 diff = maxLength-lineLength
237 shift = diff/2.0
238 if shift>TOOSMALLSPACE:
239 return self.insertShift(line, shift)
240 return line
242 def rightAlign(self, line, lineLength, maxLength):
243 shift = maxLength-lineLength
244 #die
245 if shift>TOOSMALLSPACE:
246 return self.insertShift(line, shift)
247 return line
249 def insertShift(self, line, shift):
250 # insert shift just before first visible element in line
251 - from types import StringType, InstanceType
252 result = []
253 first = 1
254 for e in line:
255 te = type(e)
256 - if first and (te is StringType or te is InstanceType):
257 + if first and (te in (StringType, UnicodeType, InstanceType)):
258 result.append(shift)
259 first = 0
260 result.append(e)
261 return result
263 def justifyAlign(self, line, lineLength, maxLength):
264 diff = maxLength-lineLength
265 # count EXPANDABLE SPACES AFTER THE FIRST VISIBLE
266 - from types import InstanceType, StringType, TupleType, FloatType
267 spacecount = 0
268 visible = 0
269 for e in line:
270 te = type(e)
271 if te is FloatType and e>TOOSMALLSPACE and visible:
272 spacecount = spacecount+1
273 - elif te is StringType or te is InstanceType:
274 + elif te in (StringType, UnicodeType, InstanceType):
275 visible = 1
276 #if debug: print "diff is", diff, "wordcount", wordcount #; die
277 if spacecount<1:
278 @@ -509,7 +518,7 @@
279 e = line[cursor]
280 te = type(e)
281 result.append(e)
282 - if (te is InstanceType or te is StringType):
283 + if (te in (StringType, UnicodeType, InstanceType)):
284 visible = 1
285 elif te is FloatType and e>TOOSMALLSPACE and visible:
286 expanded = e+shift
287 @@ -545,25 +554,23 @@
288 ## first = 0
289 ## cursor = cursor+1
290 ## return result
292 def shrinkWrap(self, line):
293 # for non justified text, collapse adjacent text/shift's into single operations
294 - #return line # for testing
295 result = []
296 index = 0
297 maxindex = len(line)
298 - from types import FloatType, StringType, InstanceType
299 - from string import join
300 while index<maxindex:
301 e = line[index]
302 te = type(e)
303 - if te is StringType and index<maxindex-1:
304 + if te in (StringType, UnicodeType) and index<maxindex-1:
305 # collect strings and floats
306 thestrings = [e]
307 thefloats = 0.0
308 index = index+1
309 nexte = line[index]
310 tnexte = type(nexte)
311 - while index<maxindex and (tnexte is FloatType or tnexte is StringType):
312 + while index<maxindex and (tnexte in (FloatType, StringType, UnicodeType)):
313 # switch to expandable space if appropriate
314 if tnexte is FloatType:
315 if thefloats<0 and nexte>0:
316 @@ -571,14 +578,14 @@
317 if nexte<0 and thefloats>0:
318 nexte = -nexte
319 thefloats = thefloats + nexte
320 - elif tnexte is StringType:
321 + elif tnexte in (StringType, UnicodeType):
322 thestrings.append(nexte)
323 index = index+1
324 if index<maxindex:
325 nexte = line[index]
326 tnexte = type(nexte)
327 # wrap up the result
328 - s = string.join(thestrings)
329 + s = ' '.join(thestrings)
330 result.append(s)
331 result.append(float(thefloats))
332 # back up for unhandled element
333 @@ -588,12 +595,12 @@
334 index = index+1
336 return result
338 def cleanProgram(self, line):
339 "collapse adjacent spacings"
340 #return line # for debugging
341 result = []
342 last = 0
343 - from types import FloatType, TupleType, StringType, InstanceType
344 for e in line:
345 if type(e) is FloatType:
346 # switch to expandable space if appropriate
347 @@ -634,7 +641,9 @@
348 tthis = type(this)
349 tnext = type(next)
350 # don't swap visibles
351 - if tthis is StringType or tnext is StringType or this is InstanceType or tnext is InstanceType:
352 + if tthis in (StringType, UnicodeType) or \
353 + tnext in (StringType, UnicodeType) or \
354 + this is InstanceType or tnext is InstanceType:
355 doswap = 0
356 # only swap two tuples if the second one is an end operation and the first is something else
357 elif tthis is TupleType:
358 @@ -654,10 +663,10 @@
359 result[nextindex] = this
360 change = 1
361 return result
363 def runOpCodes(self, program, canvas, textobject):
364 "render the line(s)"
365 - #import types
366 - from types import StringType, TupleType, InstanceType, FloatType
368 escape = canvas._escape
369 code = textobject._code
370 startstate = self.__dict__.copy()
371 @@ -672,7 +681,7 @@
372 indented = 0
373 for opcode in program:
374 topcode = type(opcode)
375 - if topcode is StringType or topcode is InstanceType:
376 + if topcode in (StringType, UnicodeType, InstanceType):
377 if not indented:
378 if abs(thislineindent)>TOOSMALLSPACE:
379 #if debug: print "INDENTING", thislineindent
380 @@ -688,7 +697,7 @@
381 font = self.fontName
382 size = self.fontSize
383 textobject.setFont(font, size)
384 - if topcode is StringType:
385 + if topcode in (StringType, UnicodeType):
386 #textobject.textOut(opcode)
387 text = escape(opcode)
388 code.append('(%s) Tj' % text)
389 @@ -723,7 +732,7 @@
390 oldcolor = self.fontColor
391 (i, colorname) = opcode
392 #print "opcode", opcode
393 - if type(colorname) is StringType:
394 + if type(colorname) in (StringType, UnicodeType):
395 color = self.fontColor = getattr(colors, colorname)
396 else:
397 color = self.fontColor = colorname # assume its something sensible :)
398 @@ -744,7 +753,7 @@
399 # change font size
400 (i, fontsize) = opcode
401 size = abs(float(fontsize))
402 - if type(fontsize) is StringType:
403 + if type(fontsize) in (StringType, UnicodeType):
404 if fontsize[:1]=="+":
405 fontSize = self.fontSize = self.fontSize + size
406 elif fontsize[:1]=="-":
407 @@ -834,12 +843,12 @@
409 def stringLine(line, length):
410 "simple case: line with just strings and spacings which can be ignored"
412 strings = []
413 - from types import StringType
414 for x in line:
415 - if type(x) is StringType:
416 + if type(x) in (StringType, UnicodeType):
417 strings.append(x)
418 - text = string.join(strings)
419 + text = ' '.join(strings)
420 result = [text, float(length)]
421 nextlinemark = ("nextLine", 0)
422 if line and line[-1]==nextlinemark:
423 @@ -848,14 +857,14 @@
425 def simpleJustifyAlign(line, currentLength, maxLength):
426 "simple justification with only strings"
428 strings = []
429 - from types import StringType
430 for x in line[:-1]:
431 - if type(x) is StringType:
432 + if type(x) in (StringType, UnicodeType):
433 strings.append(x)
434 nspaces = len(strings)-1
435 slack = maxLength-currentLength
436 - text = string.join(strings)
437 + text = ' '.join(strings)
438 if nspaces>0 and slack>0:
439 wordspacing = slack/float(nspaces)
440 result = [("wordSpacing", wordspacing), text, maxLength, ("wordSpacing", 0)]
441 @@ -869,16 +878,15 @@
442 from reportlab.lib.colors import black
444 def readBool(text):
445 - if string.upper(text) in ("Y", "YES", "TRUE", "1"):
446 + if text.upper() in ("Y", "YES", "TRUE", "1"):
447 return 1
448 - elif string.upper(text) in ("N", "NO", "FALSE", "0"):
449 + elif text.upper() in ("N", "NO", "FALSE", "0"):
450 return 0
451 else:
452 raise RMLError, "true/false attribute has illegal value '%s'" % text
454 def readAlignment(text):
455 - from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
456 - up = string.upper(text)
457 + up = text.upper()
458 if up == 'LEFT':
459 return TA_LEFT
460 elif up == 'RIGHT':
461 @@ -891,13 +899,13 @@
462 def readLength(text):
463 """Read a dimension measurement: accept "3in", "5cm",
464 "72 pt" and so on."""
465 - text = string.strip(text)
466 + text = text.strip()
467 try:
468 return float(text)
469 except ValueError:
470 - text = string.lower(text)
471 + text = text.lower()
472 numberText, units = text[:-2],text[-2:]
473 - numberText = string.strip(numberText)
474 + numberText = numberText.strip()
475 try:
476 number = float(numberText)
477 except ValueError:
478 @@ -916,13 +924,12 @@
480 def lengthSequence(s, converter=readLength):
481 """from "(2, 1)" or "2,1" return [2,1], for example"""
482 - from string import split, strip
483 - s = strip(s)
484 + s = s.strip()
485 if s[:1]=="(" and s[-1:]==")":
486 s = s[1:-1]
487 - sl = split(s, ",")
488 - sl = map(strip, sl)
489 - sl = map(converter, sl)
490 + sl = s.split(',')
491 + sl = [s.strip() for s in sl]
492 + sl = [converter(s) for s in sl]
493 return sl
496 @@ -931,7 +938,7 @@
497 if not text:
498 return None
499 from reportlab.lib import colors
500 - if text[0] in string.letters:
501 + if text[0] in LETTERS:
502 return colors.__dict__[text]
503 tup = lengthSequence(text)
505 @@ -978,6 +985,7 @@
506 bulletIndent=0
507 textColor=black
508 backColor=None
510 def __init__(self, name, parent=None, **kw):
511 mydict = self.__dict__
512 if parent:
513 @@ -985,6 +993,7 @@
514 mydict[a]=b
515 for (a,b) in kw.items():
516 mydict[a] = b
518 def addAttributes(self, dictionary):
519 for key in dictionary.keys():
520 value = dictionary[key]
521 @@ -999,14 +1008,21 @@
522 "h1.defaultStyle": "Heading1",
523 "h2.defaultStyle": "Heading2",
524 "h3.defaultStyle": "Heading3",
525 + "h4.defaultStyle": "Heading4",
526 + "h5.defaultStyle": "Heading5",
527 + "h6.defaultStyle": "Heading6",
528 "title.defaultStyle": "Title",
529 + "subtitle.defaultStyle": "SubTitle",
530 "para.defaultStyle": "Normal",
531 "pre.defaultStyle": "Code",
532 - "li.defaultStyle": "Definition"
533 + "ul.defaultStyle": "Definition",
534 + "ol.defaultStyle": "Definition",
535 + "li.defaultStyle": "Definition",
538 class FastPara(Flowable):
539 "paragraph with no special features (not even a single ampersand!)"
541 def __init__(self, style, simpletext):
542 #if debug:
543 # print "FAST", id(self)
544 @@ -1015,6 +1031,7 @@
545 self.style = style
546 self.simpletext = simpletext
547 self.lines = None
549 def wrap(self, availableWidth, availableHeight):
550 simpletext = self.simpletext
551 self.availableWidth = availableWidth
552 @@ -1027,7 +1044,7 @@
553 size = style.fontSize
554 firstindent = style.firstLineIndent
555 #textcolor = style.textColor
556 - words = string.split(simpletext)
557 + words = simpletext.split()
558 lines = []
559 from reportlab.pdfbase.pdfmetrics import stringWidth
560 spacewidth = stringWidth(" ", font, size)
561 @@ -1062,18 +1079,18 @@
562 #print "currentline", currentline
563 else:
564 # emit the line
565 - lines.append( (string.join(currentline), currentlength, len(currentline)) )
566 + lines.append( (' '.join(currentline), currentlength, len(currentline)) )
567 currentline = []
568 currentlength = 0
569 heightused = heightused+leading
570 if heightused+leading>availableHeight:
571 done = 1
572 if currentlength and not done:
573 - lines.append( (string.join(currentline), currentlength, len(currentline) ))
574 + lines.append( (' '.join(currentline), currentlength, len(currentline) ))
575 heightused = heightused+leading
576 self.lines = lines
577 self.height = heightused
578 - remainder = self.remainder = string.join(words[cursor:])
579 + remainder = self.remainder = ' '.join(words[cursor:])
580 #print "lines", lines
581 #print "remainder is", remainder
582 else:
583 @@ -1086,6 +1103,7 @@
584 result = (availableWidth, heightused)
585 #if debug: print "wrap is", (availableWidth, availableHeight), result, len(lines)
586 return result
588 def split(self, availableWidth, availableHeight):
589 style = self.style
590 leading = style.leading
591 @@ -1102,7 +1120,6 @@
592 return [self]
594 def draw(self):
595 - from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
596 style = self.style
597 lines = self.lines
598 rightIndent = style.rightIndent
599 @@ -1158,10 +1175,12 @@
600 #textobject.textOut(text)
601 y = y-leading
602 c.drawText(textobject)
604 def getSpaceBefore(self):
605 #if debug:
606 # print "got space before", self.spaceBefore
607 return self.style.spaceBefore
609 def getSpaceAfter(self):
610 #print "got space after", self.spaceAfter
611 return self.style.spaceAfter
612 @@ -1174,15 +1193,39 @@
613 result[stylenamekey] = styles[stylenamevalue]
614 return result
616 +def buildContext(stylesheet=None):
617 + result = {}
618 + from reportlab.lib.styles import getSampleStyleSheet
619 + from reportlab.lib.styles import StyleSheet1
620 + if stylesheet is not None:
621 + if isinstance(stylesheet, StyleSheet1):
622 + result.update(stylesheet.byName.copy())
623 + result.update(stylesheet.byAlias.copy())
624 + else:
625 + if hasattr(stylesheet, 'copy'):
626 + result.update(stylesheet.copy())
627 + else:
628 + stylesheet = {}
629 + styles = getSampleStyleSheet()
630 + for (stylenamekey, stylenamevalue) in DEFAULT_ALIASES.items():
631 + # Copy styles with the same name as aliases
632 + if stylesheet.has_key(stylenamevalue):
633 + result[stylenamekey] = stylesheet[stylenamevalue]
634 + # Then, fill in defaults if they were not filled yet.
635 + if not result.has_key(stylenamekey) and styles.has_key(stylenamevalue):
636 + result[stylenamekey] = styles[stylenamevalue]
638 + return result
640 class Para(Flowable):
642 spaceBefore = 0
643 spaceAfter = 0
645 def __init__(self, style, parsedText=None, bulletText=None, state=None, context=None, baseindent=0):
646 #print id(self), "para", parsedText
647 self.baseindent = baseindent
648 - if context is None:
649 - context = defaultContext()
650 - self.context = context
651 + self.context = buildContext(context)
652 self.parsedText = parsedText
653 self.bulletText = bulletText
654 self.style1 = style # make sure Flowable doesn't use this unless wanted! call it style1 NOT style
655 @@ -1199,15 +1242,18 @@
656 # print "spaceBefore is", self.spaceBefore, self.parsedText
657 self.bold = 0
658 self.italic = 0
659 - self.face = "times"
660 - self.size = 10
661 + self.face = style.fontName
662 + self.size = style.fontSize
664 def getSpaceBefore(self):
665 #if debug:
666 # print "got space before", self.spaceBefore
667 return self.spaceBefore
669 def getSpaceAfter(self):
670 #print "got space after", self.spaceAfter
671 return self.spaceAfter
673 def wrap(self, availableWidth, availableHeight):
674 if debug:
675 print "WRAPPING", id(self), availableWidth, availableHeight
676 @@ -1242,7 +1288,8 @@
677 if not program:
678 self.program = program = self.compileProgram(parsedText)
679 if not self.formattedProgram:
680 - (formattedProgram, remainder, laststate, heightused) = p.format(availableWidth, availableHeight, program, leading)
681 + (formattedProgram, remainder, \
682 + laststate, heightused) = p.format(availableWidth, availableHeight, program, leading)
683 self.formattedProgram = formattedProgram
684 self.height = heightused
685 self.laststate = laststate
686 @@ -1259,7 +1306,8 @@
687 height = availableHeight + 1
688 #print "laststate is", laststate
689 #print "saving remainder", remainder
690 - self.remainder = Para(self.style1, parsedText=None, bulletText=None, state=laststate)
691 + self.remainder = Para(self.style1, parsedText=None, bulletText=None, \
692 + state=laststate, context=self.context)
693 self.remainder.program = remainder
694 self.remainder.spaceAfter = self.spaceAfter
695 self.spaceAfter = 0
696 @@ -1277,6 +1325,7 @@
697 print "exact match???" + repr(availableHeight, h)
698 print "wrap is", (availableWidth, availableHeight), result
699 return result
701 def split(self, availableWidth, availableHeight):
702 #if debug:
703 # print "SPLITTING", id(self), availableWidth, availableHeight
704 @@ -1300,6 +1349,7 @@
705 result= [self]
706 #if debug: print "split is", result
707 return result
709 def draw(self):
710 p = self.myengine #paragraphEngine()
711 formattedProgram = self.formattedProgram
712 @@ -1362,40 +1412,15 @@
713 # now look for a place where to insert the unindent after the first line
714 if style.firstLineIndent:
715 count = 0
716 - from types import StringType, InstanceType
717 for x in program:
718 count = count+1
719 tx = type(x)
720 - if tx is StringType or tx is InstanceType:
721 + if tx in (StringType, UnicodeType, InstanceType):
722 break
723 program.insert( count, ("indent", -style.firstLineIndent ) ) # defaults to end if no visibles
724 - #print "="*8, id(self), "program is"
725 - #for x in program:
726 - # print x
727 -## print "="*11
728 -## # check pushes and pops
729 -## stackcount = 0
730 -## dump = 0
731 -## from types import TupleType
732 -## for x in program:
733 -## if dump:
734 -## print "dump:", x
735 -## if type(x) is TupleType:
736 -## i = x[0]
737 -## if i=="push":
738 -## stackcount = stackcount+1
739 -## print " "*stackcount, "push", stackcount
740 -## if i=="pop":
741 -## stackcount = stackcount-1
742 -## print " "*stackcount, "pop", stackcount
743 -## if stackcount<0:
744 -## dump=1
745 -## print "STACK UNDERFLOW!"
746 -## if dump: stop
747 return program
749 def linearize(self, program = None, parsedText=None):
750 - #print "LINEARIZING", self
751 - #program = self.program = []
752 if parsedText is None:
753 parsedText = self.parsedText
754 style = self.style1
755 @@ -1417,23 +1442,22 @@
756 program.append( ("leading", 0) )
757 program.append( ("nextLine", 0) )
758 program.append( ("pop",) )
760 def compileComponent(self, parsedText, program):
761 - import types
762 ttext = type(parsedText)
763 - #program = self.program
764 - if ttext is types.StringType:
765 + if ttext in (StringType, UnicodeType):
766 # handle special characters here...
767 # short cut
768 if parsedText:
769 - stext = parsedText.strip() #string.strip(parsedText)
770 + stext = parsedText.strip()
771 if not stext:
772 program.append(" ") # contract whitespace to single space
773 else:
774 handleSpecialCharacters(self, parsedText, program)
775 - elif ttext is types.ListType:
776 + elif ttext is ListType:
777 for e in parsedText:
778 self.compileComponent(e, program)
779 - elif ttext is types.TupleType:
780 + elif ttext is TupleType:
781 (tagname, attdict, content, extra) = parsedText
782 if not attdict:
783 attdict = {}
784 @@ -1455,10 +1479,11 @@
785 a("</%s>" % tagname)
786 else:
787 a("/>")
788 - t = string.join(L, "")
789 + t = ''.join(L)
790 handleSpecialCharacters(self, t, program)
791 else:
792 raise ValueError, "don't know how to handle tag " + repr(tagname)
794 def shiftfont(self, program, face=None, bold=None, italic=None):
795 oldface = self.face
796 oldbold = self.bold
797 @@ -1481,26 +1506,29 @@
798 # "anonymous" tag: just do the content
799 for e in content:
800 self.compileComponent(e, program)
801 - #compile_para = compile_ # at least for now...
803 def compile_pageNumber(self, attdict, content, extra, program):
804 program.append(PageNumberObject())
806 def compile_b(self, attdict, content, extra, program):
807 (f,b,i) = self.shiftfont(program, bold=1)
808 for e in content:
809 self.compileComponent(e, program)
810 self.shiftfont(program, bold=b)
812 def compile_i(self, attdict, content, extra, program):
813 (f,b,i) = self.shiftfont(program, italic=1)
814 for e in content:
815 self.compileComponent(e, program)
816 self.shiftfont(program, italic=i)
818 def compile_u(self, attdict, content, extra, program):
819 # XXXX must eventually add things like alternative colors
820 - #program = self.program
821 program.append( ('lineOperation', UNDERLINE) )
822 for e in content:
823 self.compileComponent(e, program)
824 program.append( ('endLineOperation', UNDERLINE) )
826 def compile_sub(self, attdict, content, extra, program):
827 size = self.size
828 self.size = newsize = size * 0.7
829 @@ -1515,18 +1543,15 @@
830 program.append( ('rise', rise) )
832 def compile_ul(self, attdict, content, extra, program, tagname="ul"):
833 - # by transformation
834 - #print "compile", tagname, attdict
835 atts = attdict.copy()
836 bulletmaker = bulletMaker(tagname, atts, self.context)
837 # now do each element as a separate paragraph
838 - import types
839 for e in content:
840 te = type(e)
841 - if te is types.StringType:
842 - if e.strip(): #string.strip(e):
843 + if te in (StringType, UnicodeType):
844 + if e.strip():
845 raise ValueError, "don't expect CDATA between list elements"
846 - elif te is types.TupleType:
847 + elif te is TupleType:
848 (tagname, attdict1, content1, extra) = e
849 if tagname!="li":
850 raise ValueError, "don't expect %s inside list" % repr(tagname)
851 @@ -1534,57 +1559,59 @@
852 if attdict1:
853 newatts.update(attdict1)
854 bulletmaker.makeBullet(newatts)
855 - self.compile_para(newatts, content1, extra, program)
856 + self.compile_li(newatts, content1, extra, program)
858 def compile_ol(self, attdict, content, extra, program):
859 return self.compile_ul(attdict, content, extra, program, tagname="ol")
861 + def compile_li(self, attdict, content, extra, program):
862 + self.compile_para(attdict, content, extra, program)
864 def compile_dl(self, attdict, content, extra, program):
865 - # by transformation
866 - #print "compile", tagname, attdict
867 - atts = attdict.copy()
868 - # by transformation
869 - #print "compile", tagname, attdict
870 atts = attdict.copy()
871 bulletmaker = bulletMaker("dl", atts, self.context)
872 # now do each element as a separate paragraph
873 - import types
874 contentcopy = list(content) # copy for destruction
875 bullet = ""
876 while contentcopy:
877 e = contentcopy[0]
878 del contentcopy[0]
879 te = type(e)
880 - if te is types.StringType:
881 - if e.strip(): #string.strip(e):
882 + if te in (StringType, UnicodeType):
883 + if e.strip():
884 raise ValueError, "don't expect CDATA between list elements"
885 elif not contentcopy:
886 break # done at ending whitespace
887 else:
888 continue # ignore intermediate whitespace
889 - elif te is types.TupleType:
890 + elif te is TupleType:
891 (tagname, attdict1, content1, extra) = e
892 if tagname!="dd" and tagname!="dt":
893 - raise ValueError, "don't expect %s here inside list, expect 'dd' or 'dt'" % repr(tagname)
894 + raise ValueError, "don't expect %s here inside list, expect 'dd' or 'dt'" % \
895 + repr(tagname)
896 if tagname=="dt":
897 if bullet:
898 raise ValueError, "dt will not be displayed unless followed by a dd: "+repr(bullet)
899 if content1:
900 - if len(content1)!=1:
901 - raise ValueError, "only simple strings supported in dd content currently: "+repr(content1)
902 - bullet = content1[0]
903 - if type(bullet) is not types.StringType:
904 - raise ValueError, "only simple strings supported in dd content currently: "+repr(content1)
905 + self.compile_dt(attdict1, content1, extra, program)
906 + # raise ValueError, \
907 + # "only simple strings supported in dd content currently: "+repr(content1)
908 elif tagname=="dd":
909 newatts = atts.copy()
910 if attdict1:
911 newatts.update(attdict1)
912 bulletmaker.makeBullet(newatts, bl=bullet)
913 - self.compile_para(newatts, content1, extra, program)
914 + self.compile_dd(newatts, content1, extra, program)
915 bullet = "" # don't use this bullet again
916 if bullet:
917 raise ValueError, "dt will not be displayed unless followed by a dd"+repr(bullet)
919 + def compile_dt(self, attdict, content, extra, program):
920 + self.compile_para(attdict, content, extra, program)
922 + def compile_dd(self, attdict, content, extra, program):
923 + self.compile_para(attdict, content, extra, program)
925 def compile_super(self, attdict, content, extra, program):
926 size = self.size
927 self.size = newsize = size * 0.7
928 @@ -1597,6 +1624,7 @@
929 program.append( ('size', size) )
930 self.size = size
931 program.append( ('rise', -rise) )
933 def compile_font(self, attdict, content, extra, program):
934 #program = self.program
935 program.append( ("push",) ) # store current data
936 @@ -1618,6 +1646,7 @@
937 for e in content:
938 self.compileComponent(e, program)
939 program.append( ("pop",) ) # restore as before
941 def compile_a(self, attdict, content, extra, program):
942 url = attdict["href"]
943 colorname = attdict.get("color", "blue")
944 @@ -1632,6 +1661,7 @@
945 program.append( ('endLineOperation', UNDERLINE) )
946 program.append( ('endLineOperation', Link) )
947 program.append( ("pop",) ) # restore as before
949 def compile_link(self, attdict, content, extra, program):
950 dest = attdict["destination"]
951 colorname = attdict.get("color", None)
952 @@ -1647,6 +1677,7 @@
953 program.append( ('endLineOperation', UNDERLINE) )
954 program.append( ('endLineOperation', Link) )
955 program.append( ("pop",) ) # restore as before
957 def compile_setLink(self, attdict, content, extra, program):
958 dest = attdict["destination"]
959 colorname = attdict.get("color", "blue")
960 @@ -1664,43 +1695,55 @@
961 program.append( ('endLineOperation', UNDERLINE) )
962 program.append( ('endLineOperation', Link) )
963 program.append( ("pop",) ) # restore as before
965 #def compile_p(self, attdict, content, extra, program):
966 # # have to be careful about base indent here!
967 # not finished
969 def compile_bullet(self, attdict, content, extra, program):
970 - from types import StringType
971 ### eventually should allow things like images and graphics in bullets too XXXX
972 - if len(content)!=1 or type(content[0]) is not StringType:
973 + if len(content)!=1 or type(content[0]) not in (StringType, UnicodeType):
974 raise ValueError, "content for bullet must be a single string"
975 text = content[0]
976 self.do_bullet(text, program)
978 def do_bullet(self, text, program):
979 style = self.style1
980 - #program = self.program
981 indent = style.bulletIndent + self.baseindent
982 font = style.bulletFontName
983 size = style.bulletFontSize
984 program.append( ("bullet", text, indent, font, size) )
986 def compile_tt(self, attdict, content, extra, program):
987 (f,b,i) = self.shiftfont(program, face="Courier")
988 for e in content:
989 self.compileComponent(e, program)
990 self.shiftfont(program, face=f)
992 def compile_greek(self, attdict, content, extra, program):
993 self.compile_font({"face": "symbol"}, content, extra, program)
995 def compile_evalString(self, attdict, content, extra, program):
996 program.append( EvalStringObject(attdict, content, extra, self.context) )
998 def compile_name(self, attdict, content, extra, program):
999 program.append( NameObject(attdict, content, extra, self.context) )
1001 def compile_getName(self, attdict, content, extra, program):
1002 program.append( GetNameObject(attdict, content, extra, self.context) )
1004 def compile_seq(self, attdict, content, extra, program):
1005 program.append( SeqObject(attdict, content, extra, self.context) )
1007 def compile_seqReset(self, attdict, content, extra, program):
1008 program.append( SeqResetObject(attdict, content, extra, self.context) )
1010 def compile_seqDefault(self, attdict, content, extra, program):
1011 program.append( SeqDefaultObject(attdict, content, extra, self.context) )
1013 def compile_para(self, attdict, content, extra, program, stylename = "para.defaultStyle"):
1014 + if attdict is None:
1015 + attdict = {}
1016 context = self.context
1017 stylename = attdict.get("style", stylename)
1018 style = context[stylename]
1019 @@ -1708,45 +1751,37 @@
1020 newstyle.addAttributes(attdict)
1021 bulletText = attdict.get("bulletText", None)
1022 mystyle = self.style1
1023 - #newstyle.bulletIndent = mystyle.leftIndent+newstyle.bulletIndent
1024 - #print "attdict", attdict
1025 - #print "leftindent, baseindent", mystyle.leftIndent
1026 - #print "bulletIndent", newstyle.bulletIndent
1027 - thepara = Para(newstyle, content, context=context, bulletText=bulletText) # possible ref loop on context, break later
1028 + thepara = Para(newstyle, content, context=context, bulletText=bulletText)
1029 + # possible ref loop on context, break later
1030 # now compile it and add it to the program
1031 mybaseindent = self.baseindent
1032 self.baseindent = thepara.baseindent = mystyle.leftIndent + self.baseindent
1033 thepara.linearize(program=program)
1034 - #print "program so far"
1035 - #for x in program:
1036 - # print x
1037 program.append( ("nextLine", 0) )
1038 self.baseindent = mybaseindent
1041 class bulletMaker:
1043 def __init__(self, tagname, atts, context):
1044 self.tagname = tagname
1045 - #print "context is", context
1046 - style = "li.defaultStyle"
1047 + self.context = context
1048 + style = context.has_key(tagname) and tagname or "%s.defaultStyle" % tagname
1049 self.style = style = atts.get("style", style)
1050 - typ = {"ul": "disc", "ol": "1", "dl": None}[tagname]
1051 - #print tagname, "bulletmaker type is", typ
1052 - self.typ =typ = atts.get("type", typ)
1053 - #print tagname, "bulletmaker type is", typ
1054 + typ = {"ul": "disc", "ol": "1"}.get(tagname, None)
1055 + self.typ = typ = atts.get("type", typ)
1056 if not atts.has_key("leftIndent"):
1057 # get the style so you can choose an indent length
1058 - thestyle = context[style]
1059 from reportlab.pdfbase.pdfmetrics import stringWidth
1060 - size = thestyle.fontSize
1061 + size = self.context[self.style].fontSize
1062 indent = stringWidth("XXX", "Courier", size)
1063 atts["leftIndent"] = str(indent)
1064 self.count = 0
1066 def makeBullet(self, atts, bl=None):
1067 count = self.count = self.count+1
1068 typ = self.typ
1069 tagname = self.tagname
1070 - #print "makeBullet", tagname, typ, count
1071 + if bl == 'm': raise ValueError
1072 # forget space before for non-first elements
1073 if count>1:
1074 atts["spaceBefore"] = "0"
1075 @@ -1758,7 +1793,7 @@
1076 else:
1077 raise ValueError, "unordered list type %s not implemented" % repr(typ)
1078 if not atts.has_key("bulletFontName"):
1079 - atts["bulletFontName"] = "ZapfDingbats"
1080 + atts["bulletFontName"] = self.context[self.style].bulletFontName or "ZapfDingbats"
1081 elif tagname=="ol":
1082 if typ=="1": bl = repr(count)
1083 elif typ=="a":
1084 @@ -1778,7 +1813,9 @@
1086 class EvalStringObject:
1087 "this will only work if rml2pdf is present"
1089 tagname = "evalString"
1091 def __init__(self, attdict, content, extra, context):
1092 if not attdict:
1093 attdict = {}
1094 @@ -1786,11 +1823,13 @@
1095 self.content = content
1096 self.context = context
1097 self.extra = extra
1099 def getOp(self, tuple, engine):
1100 from rlextra.rml2pdf.rml2pdf import Controller
1101 #print "tuple", tuple
1102 op = self.op = Controller.processTuple(tuple, self.context, {})
1103 return op
1105 def width(self, engine):
1106 from reportlab.pdfbase.pdfmetrics import stringWidth
1107 content = self.content
1108 @@ -1803,10 +1842,12 @@
1109 #print self
1110 s = str(op)
1111 return stringWidth(s, engine.fontName, engine.fontSize)
1113 def execute(self, engine, textobject, canvas):
1114 textobject.textOut(str(self.op))
1116 class SeqObject(EvalStringObject):
1118 def getOp(self, tuple, engine):
1119 from reportlab.lib.sequencer import getSequencer
1120 globalsequencer = getSequencer()
1121 @@ -1830,6 +1871,7 @@
1122 pass # name doesn't produce any output
1124 class SeqDefaultObject(NameObject):
1126 def getOp(self, tuple, engine):
1127 from reportlab.lib.sequencer import getSequencer
1128 globalsequencer = getSequencer()
1129 @@ -1843,6 +1885,7 @@
1130 return ""
1132 class SeqResetObject(NameObject):
1134 def getOp(self, tuple, engine):
1135 from reportlab.lib.sequencer import getSequencer
1136 import math
1137 @@ -1864,11 +1907,14 @@
1138 tagname = "getName"
1140 class PageNumberObject:
1142 def __init__(self, example="XXX"):
1143 self.example = example # XXX SHOULD ADD THE ABILITY TO PASS IN EXAMPLES
1145 def width(self, engine):
1146 from reportlab.pdfbase.pdfmetrics import stringWidth
1147 return stringWidth(self.example, engine.fontName, engine.fontSize)
1149 def execute(self, engine, textobject, canvas):
1150 n = canvas.getPageNumber()
1151 textobject.textOut(str(n))
1152 @@ -1890,11 +1936,10 @@
1153 mystyle.addAttributes(attdict)
1154 bulletText = attdict.get("bulletText", None)
1155 # can we use the fast implementation?
1156 - import types
1157 result = None
1158 if not bulletText and len(content)==1:
1159 text = content[0]
1160 - if type(text) is types.StringType and "&" not in text:
1161 + if type(text) in (StringType, UnicodeType) and "&" not in text:
1162 result = FastPara(mystyle, text)
1163 if result is None:
1164 result = Para(mystyle, content, context=context, bulletText=bulletText) # possible ref loop on context, break later
1165 @@ -2119,7 +2164,7 @@
1166 for fragment in amptext:
1167 if not first:
1168 # check for special chars
1169 - semi = string.find(fragment, ";")
1170 + semi = fragment.find(";")
1171 if semi>0:
1172 name = fragment[:semi]
1173 if greeks.has_key(name):
1174 @@ -2128,7 +2173,7 @@
1175 (f,b,i) = engine.shiftfont(program, face="symbol")
1176 program.append(greeksub)
1177 engine.shiftfont(program, face=f)
1178 - if fragment and fragment[0] in string.whitespace:
1179 + if fragment and fragment[0] in WHITESPACE:
1180 program.append(" ") # follow the greek with a space
1181 else:
1182 # add back the &
1183 @@ -2143,10 +2188,10 @@
1184 # does the last one need a space?
1185 if sfragment and fragment:
1186 # reader 3 used to go nuts if you don't special case the last frag, but it's fixed?
1187 - if fragment[-1] in string.whitespace: # or fragment==lastfrag:
1188 + if fragment[-1] in WHITESPACE: # or fragment==lastfrag:
1189 program.append( sfragment[-1]+" " )
1190 else:
1191 - last = sfragment[-1].strip() #string.strip(sfragment[-1])
1192 + last = sfragment[-1].strip()
1193 if last:
1194 #print "last is", repr(last)
1195 program.append( last )
1196 @@ -2154,7 +2199,7 @@
1197 #print "HANDLED", program
1198 return program
1200 -def Paragraph(text, style, bulletText=None, frags=None):
1201 +def Paragraph(text, style, bulletText=None, frags=None, context=None):
1202 """ Paragraph(text, style, bulletText=None)
1203 intended to be like a platypus Paragraph but better.
1205 @@ -2165,7 +2210,7 @@
1206 # use the fully featured one.
1207 from reportlab.lib import rparsexml
1208 parsedpara = rparsexml.parsexmlSimple(text)
1209 - return Para(style, parsedText=parsedpara, bulletText=bulletText, state=None)
1210 + return Para(style, parsedText=parsedpara, bulletText=bulletText, state=None, context=context)
1212 ##class Paragraph(Para):
1213 ## """ Paragraph(text, style, bulletText=None)
1214 @@ -2206,8 +2251,10 @@
1215 UNDERLINE = UnderLineHandler()
1217 class HotLink(UnderLineHandler):
1219 def __init__(self, url):
1220 self.url = url
1222 def end_at(self, x, y, para, canvas, textobject):
1223 fontsize = para.fontSize
1224 rect = [self.xStart, self.yStart, x,y+fontsize]
1225 @@ -2215,27 +2262,31 @@
1226 print "LINKING RECTANGLE", rect
1227 #canvas.rect(self.xStart, self.yStart, x-self.xStart,y+fontsize-self.yStart, stroke=1)
1228 self.link(rect, canvas)
1230 def link(self, rect, canvas):
1231 canvas.linkURL(self.url, rect, relative=1)
1233 class InternalLink(HotLink):
1235 def link(self, rect, canvas):
1236 destinationname = self.url
1237 contents = ""
1238 canvas.linkRect(contents, destinationname, rect, Border="[0 0 0]")
1240 class DefDestination(HotLink):
1242 defined = 0
1244 def link(self, rect, canvas):
1245 destinationname = self.url
1246 if not self.defined:
1247 [x, y, x1, y1] = rect
1248 - canvas.bookmarkHorizontal(destinationname, x,y1) # use the upper y
1249 + canvas.bookmarkHorizontal(destinationname, x, y1) # use the upper y
1250 self.defined = 1
1252 def splitspace(text):
1253 # split on spacing but include spaces at element ends
1254 - stext = string.split(text)
1255 + stext = text.split()
1256 result = []
1257 for e in stext:
1258 result.append(e+" ")