mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-02-02 13:22:17 +00:00
Added printing requirements
This commit is contained in:
338
reportlab/platypus/xpreformatted.py
Normal file
338
reportlab/platypus/xpreformatted.py
Normal file
@@ -0,0 +1,338 @@
|
||||
#Copyright ReportLab Europe Ltd. 2000-2012
|
||||
#see license.txt for license details
|
||||
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/platypus/xpreformatted.py
|
||||
__version__=''' $Id$ '''
|
||||
__doc__='''A 'rich preformatted text' widget allowing internal markup'''
|
||||
from reportlab.lib import PyFontify
|
||||
from reportlab.platypus.paragraph import Paragraph, cleanBlockQuotedText, _handleBulletWidth, \
|
||||
ParaLines, _getFragWords, stringWidth, getAscentDescent, imgVRange, imgNormV
|
||||
from reportlab.lib.utils import isSeq
|
||||
from reportlab.platypus.flowables import _dedenter
|
||||
|
||||
def _getFragLines(frags):
|
||||
lines = []
|
||||
cline = []
|
||||
W = frags[:]
|
||||
while W != []:
|
||||
w = W[0]
|
||||
t = w.text
|
||||
del W[0]
|
||||
i = t.find('\n')
|
||||
if i>=0:
|
||||
tleft = t[i+1:]
|
||||
cline.append(w.clone(text=t[:i]))
|
||||
lines.append(cline)
|
||||
cline = []
|
||||
if tleft!='':
|
||||
W.insert(0,w.clone(text=tleft))
|
||||
else:
|
||||
cline.append(w)
|
||||
if cline!=[]:
|
||||
lines.append(cline)
|
||||
return lines
|
||||
|
||||
def _split_blPara(blPara,start,stop):
|
||||
f = blPara.clone()
|
||||
for a in ('lines', 'text'):
|
||||
if hasattr(f,a): delattr(f,a)
|
||||
f.lines = blPara.lines[start:stop]
|
||||
return [f]
|
||||
|
||||
# Will be removed shortly.
|
||||
def _countSpaces(text):
|
||||
return text.count(' ')
|
||||
## i = 0
|
||||
## s = 0
|
||||
## while 1:
|
||||
## j = text.find(' ',i)
|
||||
## if j<0: return s
|
||||
## s = s + 1
|
||||
## i = j + 1
|
||||
|
||||
def _getFragWord(frags,maxWidth):
|
||||
''' given a fragment list return a list of lists
|
||||
[size, spaces, (f00,w00), ..., (f0n,w0n)]
|
||||
each pair f,w represents a style and some string
|
||||
'''
|
||||
W = []
|
||||
n = 0
|
||||
s = 0
|
||||
for f in frags:
|
||||
text = f.text[:]
|
||||
W.append((f,text))
|
||||
cb = getattr(f,'cbDefn',None)
|
||||
if cb:
|
||||
_w = getattr(cb,'width',0)
|
||||
if hasattr(_w,'normalizedValue'):
|
||||
_w._normalizer = maxWidth
|
||||
n = n + stringWidth(text, f.fontName, f.fontSize)
|
||||
|
||||
#s = s + _countSpaces(text)
|
||||
s = s + text.count(' ') # much faster for many blanks
|
||||
|
||||
#del f.text # we can't do this until we sort out splitting
|
||||
# of paragraphs
|
||||
return n, s, W
|
||||
|
||||
class XPreformatted(Paragraph):
|
||||
def __init__(self, text, style, bulletText = None, frags=None, caseSensitive=1, dedent=0):
|
||||
self.caseSensitive = caseSensitive
|
||||
cleaner = lambda text, dedent=dedent: '\n'.join(_dedenter(text or '',dedent))
|
||||
self._setup(text, style, bulletText, frags, cleaner)
|
||||
|
||||
def breakLines(self, width):
|
||||
"""
|
||||
Returns a broken line structure. There are two cases
|
||||
|
||||
A) For the simple case of a single formatting input fragment the output is
|
||||
A fragment specifier with
|
||||
- kind = 0
|
||||
- fontName, fontSize, leading, textColor
|
||||
- lines= A list of lines
|
||||
|
||||
Each line has two items:
|
||||
|
||||
1. unused width in points
|
||||
2. a list of words
|
||||
|
||||
B) When there is more than one input formatting fragment the out put is
|
||||
A fragment specifier with
|
||||
- kind = 1
|
||||
- lines = A list of fragments each having fields:
|
||||
|
||||
- extraspace (needed for justified)
|
||||
- fontSize
|
||||
- words=word list
|
||||
- each word is itself a fragment with
|
||||
- various settings
|
||||
|
||||
This structure can be used to easily draw paragraphs with the various alignments.
|
||||
You can supply either a single width or a list of widths; the latter will have its
|
||||
last item repeated until necessary. A 2-element list is useful when there is a
|
||||
different first line indent; a longer list could be created to facilitate custom wraps
|
||||
around irregular objects."""
|
||||
|
||||
if not isSeq(width): maxWidths = [width]
|
||||
else: maxWidths = width
|
||||
lines = []
|
||||
lineno = 0
|
||||
maxWidth = maxWidths[lineno]
|
||||
style = self.style
|
||||
fFontSize = float(style.fontSize)
|
||||
requiredWidth = 0
|
||||
|
||||
#for bullets, work out width and ensure we wrap the right amount onto line one
|
||||
_handleBulletWidth(self.bulletText,style,maxWidths)
|
||||
|
||||
self.height = 0
|
||||
autoLeading = getattr(self,'autoLeading',getattr(style,'autoLeading',''))
|
||||
calcBounds = autoLeading not in ('','off')
|
||||
frags = self.frags
|
||||
nFrags= len(frags)
|
||||
if nFrags==1:
|
||||
f = frags[0]
|
||||
if hasattr(f,'text'):
|
||||
fontSize = f.fontSize
|
||||
fontName = f.fontName
|
||||
ascent, descent = getAscentDescent(fontName,fontSize)
|
||||
kind = 0
|
||||
L=f.text.split('\n')
|
||||
for l in L:
|
||||
currentWidth = stringWidth(l,fontName,fontSize)
|
||||
requiredWidth = max(currentWidth,requiredWidth)
|
||||
extraSpace = maxWidth-currentWidth
|
||||
lines.append((extraSpace,l.split(' '),currentWidth))
|
||||
lineno = lineno+1
|
||||
maxWidth = lineno<len(maxWidths) and maxWidths[lineno] or maxWidths[-1]
|
||||
blPara = f.clone(kind=kind, lines=lines,ascent=ascent,descent=descent,fontSize=fontSize)
|
||||
else:
|
||||
kind = f.kind
|
||||
lines = f.lines
|
||||
for L in lines:
|
||||
if kind==0:
|
||||
currentWidth = L[2]
|
||||
else:
|
||||
currentWidth = L.currentWidth
|
||||
requiredWidth = max(currentWidth,requiredWidth)
|
||||
blPara = f.clone(kind=kind, lines=lines)
|
||||
|
||||
self.width = max(self.width,requiredWidth)
|
||||
return blPara
|
||||
elif nFrags<=0:
|
||||
return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName,
|
||||
textColor=style.textColor, ascent=style.fontSize,descent=-0.2*style.fontSize,
|
||||
lines=[])
|
||||
else:
|
||||
for L in _getFragLines(frags):
|
||||
currentWidth, n, w = _getFragWord(L,maxWidth)
|
||||
f = w[0][0]
|
||||
maxSize = f.fontSize
|
||||
maxAscent, minDescent = getAscentDescent(f.fontName,maxSize)
|
||||
words = [f.clone()]
|
||||
words[-1].text = w[0][1]
|
||||
for i in w[1:]:
|
||||
f = i[0].clone()
|
||||
f.text=i[1]
|
||||
words.append(f)
|
||||
fontSize = f.fontSize
|
||||
fontName = f.fontName
|
||||
if calcBounds:
|
||||
cbDefn = getattr(f,'cbDefn',None)
|
||||
if getattr(cbDefn,'width',0):
|
||||
descent,ascent = imgVRange(imgNormV(cbDefn.height,fontSize),cbDefn.valign,fontSize)
|
||||
else:
|
||||
ascent, descent = getAscentDescent(fontName,fontSize)
|
||||
else:
|
||||
ascent, descent = getAscentDescent(fontName,fontSize)
|
||||
maxSize = max(maxSize,fontSize)
|
||||
maxAscent = max(maxAscent,ascent)
|
||||
minDescent = min(minDescent,descent)
|
||||
|
||||
lineno += 1
|
||||
maxWidth = lineno<len(maxWidths) and maxWidths[lineno] or maxWidths[-1]
|
||||
requiredWidth = max(currentWidth,requiredWidth)
|
||||
extraSpace = maxWidth - currentWidth
|
||||
lines.append(ParaLines(extraSpace=extraSpace,wordCount=n, words=words, fontSize=maxSize, ascent=maxAscent,descent=minDescent,currentWidth=currentWidth))
|
||||
|
||||
self.width = max(self.width,requiredWidth)
|
||||
return ParaLines(kind=1, lines=lines)
|
||||
|
||||
return lines
|
||||
|
||||
breakLinesCJK = breakLines #TODO fixme fixme fixme
|
||||
|
||||
# we need this her to get the right splitter
|
||||
def _get_split_blParaFunc(self):
|
||||
return _split_blPara
|
||||
|
||||
class PythonPreformatted(XPreformatted):
|
||||
"""Used for syntax-colored Python code, otherwise like XPreformatted.
|
||||
"""
|
||||
formats = {
|
||||
'rest' : ('', ''),
|
||||
'comment' : ('<font color="green">', '</font>'),
|
||||
'keyword' : ('<font color="blue"><b>', '</b></font>'),
|
||||
'parameter' : ('<font color="black">', '</font>'),
|
||||
'identifier' : ('<font color="red">', '</font>'),
|
||||
'string' : ('<font color="gray">', '</font>') }
|
||||
|
||||
def __init__(self, text, style, bulletText = None, dedent=0, frags=None):
|
||||
if text:
|
||||
text = self.fontify(self.escapeHtml(text))
|
||||
XPreformatted.__init__(self, text, style,bulletText=bulletText,dedent=dedent,frags=frags)
|
||||
|
||||
def escapeHtml(self, text):
|
||||
s = text.replace('&', '&')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('>', '>')
|
||||
return s
|
||||
|
||||
def fontify(self, code):
|
||||
"Return a fontified version of some Python code."
|
||||
|
||||
if code[0] == '\n':
|
||||
code = code[1:]
|
||||
|
||||
tags = PyFontify.fontify(code)
|
||||
fontifiedCode = ''
|
||||
pos = 0
|
||||
for k, i, j, dummy in tags:
|
||||
fontifiedCode = fontifiedCode + code[pos:i]
|
||||
s, e = self.formats[k]
|
||||
fontifiedCode = fontifiedCode + s + code[i:j] + e
|
||||
pos = j
|
||||
|
||||
fontifiedCode = fontifiedCode + code[pos:]
|
||||
|
||||
return fontifiedCode
|
||||
|
||||
if __name__=='__main__': #NORUNTESTS
|
||||
import sys
|
||||
def dumpXPreformattedLines(P):
|
||||
print('\n############dumpXPreforemattedLines(%s)' % str(P))
|
||||
lines = P.blPara.lines
|
||||
n =len(lines)
|
||||
outw=sys.stdout.write
|
||||
for l in range(n):
|
||||
line = lines[l]
|
||||
words = line.words
|
||||
nwords = len(words)
|
||||
outw('line%d: %d(%d)\n ' % (l,nwords,line.wordCount))
|
||||
for w in range(nwords):
|
||||
outw(" %d:'%s'"%(w,words[w].text))
|
||||
print()
|
||||
|
||||
def dumpXPreformattedFrags(P):
|
||||
print('\n############dumpXPreforemattedFrags(%s)' % str(P))
|
||||
frags = P.frags
|
||||
n =len(frags)
|
||||
for l in range(n):
|
||||
print("frag%d: '%s'" % (l, frags[l].text))
|
||||
|
||||
outw=sys.stdout.write
|
||||
l = 0
|
||||
for L in _getFragLines(frags):
|
||||
n=0
|
||||
for W in _getFragWords(L,360):
|
||||
outw("frag%d.%d: size=%d" % (l, n, W[0]))
|
||||
n = n + 1
|
||||
for w in W[1:]:
|
||||
outw(" '%s'" % w[1])
|
||||
print()
|
||||
l = l + 1
|
||||
|
||||
def try_it(text,style,dedent,aW,aH):
|
||||
P=XPreformatted(text,style,dedent=dedent)
|
||||
dumpXPreformattedFrags(P)
|
||||
w,h = P.wrap(aW, aH)
|
||||
dumpXPreformattedLines(P)
|
||||
S = P.split(aW,aH)
|
||||
dumpXPreformattedLines(P)
|
||||
for s in S:
|
||||
s.wrap(aW,aH)
|
||||
dumpXPreformattedLines(s)
|
||||
aH = 500
|
||||
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
styleSheet = getSampleStyleSheet()
|
||||
B = styleSheet['BodyText']
|
||||
DTstyle = ParagraphStyle("discussiontext", parent=B)
|
||||
DTstyle.fontName= 'Helvetica'
|
||||
for (text,dedent,style, aW, aH, active) in [('''
|
||||
|
||||
|
||||
The <font name=courier color=green>CMYK</font> or subtractive
|
||||
|
||||
method follows the way a printer
|
||||
mixes three pigments (cyan, magenta, and yellow) to form colors.
|
||||
Because mixing chemicals is more difficult than combining light there
|
||||
is a fourth parameter for darkness. For example a chemical
|
||||
combination of the <font name=courier color=green>CMY</font> pigments generally never makes a perfect
|
||||
|
||||
black -- instead producing a muddy color -- so, to get black printers
|
||||
don't use the <font name=courier color=green>CMY</font> pigments but use a direct black ink. Because
|
||||
<font name=courier color=green>CMYK</font> maps more directly to the way printer hardware works it may
|
||||
be the case that &| & | colors specified in <font name=courier color=green>CMYK</font> will provide better fidelity
|
||||
and better control when printed.
|
||||
|
||||
|
||||
''',0,DTstyle, 456.0, 42.8, 0),
|
||||
('''
|
||||
|
||||
This is a non rearranging form of the <b>Paragraph</b> class;
|
||||
<b><font color=red>XML</font></b> tags are allowed in <i>text</i> and have the same
|
||||
|
||||
meanings as for the <b>Paragraph</b> class.
|
||||
As for <b>Preformatted</b>, if dedent is non zero <font color=red size=+1>dedent</font>
|
||||
common leading spaces will be removed from the
|
||||
front of each line.
|
||||
|
||||
''',3, DTstyle, 456.0, 42.8, 0),
|
||||
("""\
|
||||
<font color=blue>class </font><font color=red>FastXMLParser</font>:
|
||||
# Nonsense method
|
||||
def nonsense(self):
|
||||
self.foo = 'bar'
|
||||
""",0, styleSheet['Code'], 456.0, 4.8, 1),
|
||||
]:
|
||||
if active: try_it(text,style,dedent,aW,aH)
|
||||
Reference in New Issue
Block a user