def test4(self): styleSheet = getSampleStyleSheet() bt = styleSheet['BodyText'] bfn = bt.fontName = 'Helvetica' bfs = bt.fontSize bfl = bt.leading canv = Canvas(outputfile('test_platypus_paragraph_line_lengths.pdf')) canv.setFont('Courier', bfs, bfl) pageWidth, pageHeight = canv._pagesize y = pageHeight - 15 x = stringWidth('999: ', 'Courier', bfs) + 5 aW = int(pageWidth) - 2 * x def doPara(x, text, wc, ns, n, hrep=' ', crep=' ', hdw=0, cdw=0): if '{H}' in text: text = text.replace('{H}', hrep) wc += hdw if '{C}' in text: text = text.replace('{C}', crep) wc += cdw p = Paragraph(text, bt) w, h = p.wrap(aW, 1000) annotations[:] = [] if measuring: ends[:] = [] p.drawOn(canv, x, y - h) canv.saveState() canv.setLineWidth(0.1) canv.setStrokeColorRGB(1, 0, 0) canv.rect(x, y - h, wc, h) if n is not None: canv.setFillColorRGB(0, 1, 0) canv.drawRightString(x, y - h, '%3d: ' % n) if annotations: canv.setLineWidth(0.1) canv.setStrokeColorRGB(0, 1, 0) canv.setFillColorRGB(0, 0, 1) canv.setFont('Helvetica', 0.2) for info in annotations: cur_x = info['cur_x'] + x cur_y = info['cur_y'] + y - h canv.drawCentredString(cur_x, cur_y + 0.3, '%.2f' % (cur_x - x)) canv.line(cur_x, cur_y, cur_x, cur_y + 0.299) if measuring: if not ends: errors.append( 'Paragraph measurement failure no ends found for %s\n%r' % (ns, text)) elif len(ends) > 1: errors.append( 'Paragraph measurement failure no len(ends)==%d for %s\n%r' % (len(ends), ns, text)) else: cur_x = ends[0]['cur_x'] adiff = abs(wc - cur_x) length_errors.append(adiff) if adiff > 1e-8: errors.append( 'Paragraph measurement error wc=%.4f measured=%.4f for %s\n%r' % (wc, cur_x, ns, text)) canv.restoreState() return h swc = lambda t: stringWidth(t, 'Courier', bfs) swcbo = lambda t: stringWidth(t, 'Courier-BoldOblique', bfs) swh = lambda t: stringWidth(t, 'Helvetica', bfs) swhbo = lambda t: stringWidth(t, 'Helvetica-BoldOblique', bfs) swt = lambda t: stringWidth(t, 'Times-Roman', bfs) swtb = lambda t: stringWidth(t, 'Times-Bold', bfs) apat = re.compile("(<a\\s+name='a\\d+'/>)") argv = sys.argv[1:] data = ( (0, "<span fontName='Courier'>Hello{C}</span> World.", swc('Hello ') + swh('World.')), (1, "<span fontName='Courier'>Hello</span>{H}World.", swc('Hello') + swh(' World.')), (2, " <a name='a2'/><span fontName='Courier'>Hello{C}</span> World.", swc('Hello ') + swh('World.')), (3, " <a name='a3'/><span fontName='Courier'>Hello</span>{H}World.", swc('Hello') + swh(' World.')), (4, "<span fontName='Courier'><a name='a4'/>Hello{C}</span> World.", swc('Hello ') + swh('World.')), (5, "<span fontName='Courier'><a name='a5'/>Hello</span>{H}World.", swc('Hello') + swh(' World.')), (6, "<span fontName='Courier'>Hello<a name='a6'/>{C}</span> World.", swc('Hello ') + swh('World.')), (7, "<span fontName='Courier'>Hello<a name='a7'/></span>{H}World.", swc('Hello') + swh(' World.')), (8, "<span fontName='Courier'>Hello{C}<a name='a8'/></span> World.", swc('Hello ') + swh('World.')), (9, "<span fontName='Courier'>Hello</span><a name='a9'/>{H}World.", swc('Hello') + swh(' World.')), (10, "<span fontName='Courier'>Hello{C}</span> <a name='a10'/>World.", swc('Hello ') + swh('World.')), (11, "<span fontName='Courier'>Hello</span>{H}<a name='a11'/>World.", swc('Hello') + swh(' World.')), (12, "<span fontName='Courier'>Hello{C}</span> World. <a name='a12'/>", swc('Hello ') + swh('World.')), (13, "<span fontName='Courier'>Hello</span>{H}World. <a name='a13'/>", swc('Hello') + swh(' World.')), (14, " <a name='a2'/> <span fontName='Courier'>Hello{C}</span> World.", swc('Hello ') + swh('World.')), (15, " <a name='a3'/> <span fontName='Courier'>Hello</span>{H}World.", swc('Hello') + swh(' World.')), (16, " <a name='a2'/> <span fontName='Courier'>Hello{C}<a name='b'/> </span> <a name='b'/> World.", swc('Hello ') + swh('World.')), (17, " <a name='a3'/> <span fontName='Courier'>Hello</span>{H}<a name='b'/> World.", swc('Hello') + swh(' World.')), (30, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (31, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (32, " <a name='a2'/><span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (33, " <a name='a3'/><span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (34, "<span fontName='Courier'><a name='a4'/>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span> </span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (35, "<span fontName='Courier'><a name='a5'/>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (36, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span><a name='a6'/> </span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (37, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span><a name='a7'/></span>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (38, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}<a name='a8'/></span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (39, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span><a name='a9'/>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (40, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> <a name='a10'/>World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (41, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}<a name='a11'/>World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (42, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World. <a name='a12'/>", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (43, "<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span> World.{H}<a name='a13'/>", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (44, " <a name='a2'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (45, " <a name='a3'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), (46, " <a name='a2'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}<a name='b'/> </span> <a name='b'/> World.", swt('l') + swtb('lo') + swc('He ') + swh('World.')), (47, " <a name='a3'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}<a name='b'/> World.", swt('l') + swtb('lo') + swc('He') + swh(' World.')), ) _exceptions = { 1: { 8: swh(' '), 12: swh(' '), 13: swh(' '), 14: swh(' '), 15: swh(' '), 16: swh(' '), 17: swh(' '), 38: swh(' '), 42: swh(' '), 43: swh(' '), 44: swh(' '), 45: swh(' '), 46: swh(' '), 47: swh(' '), }, } def gex(n, v): return _exceptions[1].get(v, 0) x1 = x + max(_tmp[2] for _tmp in data) + 5 x2 = x1 + max(_tmp[2] + 10 + gex(1, _tmp[0]) for _tmp in data) + 5 x3 = x2 + max(_tmp[2] + 10 + gex(2, _tmp[0]) for _tmp in data) + 5 x4 = x3 + max(_tmp[2] + 20 + gex(3, _tmp[0]) for _tmp in data) + 5 annotations = [] ends = [] errors = [] measuring = True length_errors = [] def _onDrawFunc(canv, name, label): if measuring and label == 'end': ends.append(canv._curr_tx_info) annotations.append(canv._curr_tx_info) canv._onDrawFunc = _onDrawFunc rep0 = '<ondraw name="_onDrawFunc"/>\\1' for n, text, wc in data: if argv and str(n) not in argv: continue text0 = (apat.sub(rep0, text) if rep0 else text) + ('<ondraw name="_onDrawFunc" label="end"/>' if measuring else '') ns = str(n) h = doPara(x, text0, wc, ns, n) if '<a' in text: text1 = apat.sub( '<img width="10" height="5" src="pythonpowered.gif"/>', text0) doPara(x1, text1, wc + 10 + gex(1, n), ns + '.11', None) text2 = apat.sub( '\\1<img width="10" height="5" src="pythonpowered.gif"/>', text0) doPara(x2, text1, wc + 10 + gex(2, n), ns + '.12', None) text3 = apat.sub( '\\1<img width="10" height="5" src="pythonpowered.gif"/><img width="10" height="5" src="pythonpowered.gif"/>\\1', text0) doPara(x3, text3, wc + 20 + gex(3, n), ns + '.13', None) doPara( x4, text3, wc + 20 + gex(3, n), ns + '.14', None, hrep='<span face="Courier-BoldOblique"> </span>', crep='<span face="Helvetica-BoldOblique"> </span>', hdw=swcbo(' ') - swhbo(' '), cdw=swhbo(' ') - swcbo(' '), ) else: doPara( x1, text0, wc, ns + '.21', None, hrep='<span face="Courier-BoldOblique"> </span>', crep='<span face="Helvetica-BoldOblique"> </span>', hdw=swcbo(' ') - swhbo(' '), cdw=swhbo(' ') - swcbo(' '), ) y -= h + 1 canv.showPage() canv.save() if errors: raise ValueError('\n'.join(errors))
def test4(self): styleSheet = getSampleStyleSheet() bt = styleSheet['BodyText'] bfn = bt.fontName = 'Helvetica' bfs = bt.fontSize bfl = bt.leading canv=Canvas(outputfile('test_platypus_paragraph_line_lengths.pdf')) canv.setFont('Courier',bfs,bfl) pageWidth, pageHeight = canv._pagesize y = pageHeight - 15 x = stringWidth('999: ','Courier',bfs) + 5 aW = int(pageWidth)-2*x def doPara(x,text,wc,ns,n,hrep=' ',crep=' ',hdw=0,cdw=0): if '{H}' in text: text = text.replace('{H}',hrep) wc += hdw if '{C}' in text: text = text.replace('{C}',crep) wc += cdw p = Paragraph(text,bt) w,h = p.wrap(aW,1000) annotations[:] = [] if measuring: ends[:] = [] p.drawOn(canv,x,y-h) canv.saveState() canv.setLineWidth(0.1) canv.setStrokeColorRGB(1,0,0) canv.rect(x,y-h,wc,h) if n is not None: canv.setFillColorRGB(0,1,0) canv.drawRightString(x,y-h,'%3d: ' % n) if annotations: canv.setLineWidth(0.1) canv.setStrokeColorRGB(0,1,0) canv.setFillColorRGB(0,0,1) canv.setFont('Helvetica',0.2) for info in annotations: cur_x = info['cur_x']+x cur_y = info['cur_y']+y-h canv.drawCentredString(cur_x, cur_y+0.3,'%.2f' % (cur_x-x)) canv.line(cur_x,cur_y,cur_x,cur_y+0.299) if measuring: if not ends: errors.append('Paragraph measurement failure no ends found for %s\n%r' % (ns,text)) elif len(ends)>1: errors.append('Paragraph measurement failure no len(ends)==%d for %s\n%r' % (len(ends),ns,text)) else: cur_x = ends[0]['cur_x'] adiff = abs(wc-cur_x) length_errors.append(adiff) if adiff>1e-8: errors.append('Paragraph measurement error wc=%.4f measured=%.4f for %s\n%r' % (wc,cur_x,ns,text)) canv.restoreState() return h swc = lambda t: stringWidth(t,'Courier',bfs) swcbo = lambda t: stringWidth(t,'Courier-BoldOblique',bfs) swh = lambda t: stringWidth(t,'Helvetica',bfs) swhbo = lambda t: stringWidth(t,'Helvetica-BoldOblique',bfs) swt = lambda t: stringWidth(t,'Times-Roman',bfs) swtb = lambda t: stringWidth(t,'Times-Bold',bfs) apat = re.compile("(<a\\s+name='a\\d+'/>)") argv = sys.argv[1:] data = ( (0,"<span fontName='Courier'>Hello{C}</span> World.", swc('Hello ')+swh('World.')), (1,"<span fontName='Courier'>Hello</span>{H}World.", swc('Hello')+swh(' World.')), (2," <a name='a2'/><span fontName='Courier'>Hello{C}</span> World.", swc('Hello ')+swh('World.')), (3," <a name='a3'/><span fontName='Courier'>Hello</span>{H}World.", swc('Hello')+swh(' World.')), (4,"<span fontName='Courier'><a name='a4'/>Hello{C}</span> World.", swc('Hello ')+swh('World.')), (5,"<span fontName='Courier'><a name='a5'/>Hello</span>{H}World.", swc('Hello')+swh(' World.')), (6,"<span fontName='Courier'>Hello<a name='a6'/>{C}</span> World.", swc('Hello ')+swh('World.')), (7,"<span fontName='Courier'>Hello<a name='a7'/></span>{H}World.", swc('Hello')+swh(' World.')), (8,"<span fontName='Courier'>Hello{C}<a name='a8'/></span> World.", swc('Hello ')+swh('World.')), (9,"<span fontName='Courier'>Hello</span><a name='a9'/>{H}World.", swc('Hello')+swh(' World.')), (10,"<span fontName='Courier'>Hello{C}</span> <a name='a10'/>World.", swc('Hello ')+swh('World.')), (11,"<span fontName='Courier'>Hello</span>{H}<a name='a11'/>World.", swc('Hello')+swh(' World.')), (12,"<span fontName='Courier'>Hello{C}</span> World. <a name='a12'/>", swc('Hello ')+swh('World.')), (13,"<span fontName='Courier'>Hello</span>{H}World. <a name='a13'/>", swc('Hello')+swh(' World.')), (14," <a name='a2'/> <span fontName='Courier'>Hello{C}</span> World.", swc('Hello ')+swh('World.')), (15," <a name='a3'/> <span fontName='Courier'>Hello</span>{H}World.", swc('Hello')+swh(' World.')), (16," <a name='a2'/> <span fontName='Courier'>Hello{C}<a name='b'/> </span> <a name='b'/> World.", swc('Hello ')+swh('World.')), (17," <a name='a3'/> <span fontName='Courier'>Hello</span>{H}<a name='b'/> World.", swc('Hello')+swh(' World.')), (30,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (31,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (32," <a name='a2'/><span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (33," <a name='a3'/><span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (34,"<span fontName='Courier'><a name='a4'/>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span> </span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (35,"<span fontName='Courier'><a name='a5'/>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (36,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span><a name='a6'/> </span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (37,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span><a name='a7'/></span>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (38,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}<a name='a8'/></span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (39,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span><a name='a9'/>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (40,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> <a name='a10'/>World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (41,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}<a name='a11'/>World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (42,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World. <a name='a12'/>", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (43,"<span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span> World.{H}<a name='a13'/>", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (44," <a name='a2'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}</span> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (45," <a name='a3'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), (46," <a name='a2'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span>{C}<a name='b'/> </span> <a name='b'/> World.", swt('l')+swtb('lo')+swc('He ')+swh('World.')), (47," <a name='a3'/> <span fontName='Courier'>He<span face='Times-Roman' color='red'>l</span><span face='Times-Bold' color='orange'>lo</span></span>{H}<a name='b'/> World.", swt('l')+swtb('lo')+swc('He')+swh(' World.')), ) _exceptions = { 1: { 8: swh(' '), 12: swh(' '), 13: swh(' '), 14: swh(' '), 15: swh(' '), 16: swh(' '), 17: swh(' '), 38: swh(' '), 42: swh(' '), 43: swh(' '), 44: swh(' '), 45: swh(' '), 46: swh(' '), 47: swh(' '), }, } def gex(n,v): return _exceptions[1].get(v,0) x1 = x + max(_tmp[2] for _tmp in data) + 5 x2 = x1 + max(_tmp[2]+10+gex(1,_tmp[0]) for _tmp in data) + 5 x3 = x2 + max(_tmp[2]+10+gex(2,_tmp[0]) for _tmp in data) + 5 x4 = x3 + max(_tmp[2]+20+gex(3,_tmp[0]) for _tmp in data) + 5 annotations = [] ends = [] errors = [] measuring = True length_errors = [] def _onDrawFunc(canv,name,label): if measuring and label=='end': ends.append(canv._curr_tx_info) annotations.append(canv._curr_tx_info) canv._onDrawFunc = _onDrawFunc rep0 = '<ondraw name="_onDrawFunc"/>\\1' for n,text,wc in data: if argv and str(n) not in argv: continue text0 = (apat.sub(rep0,text) if rep0 else text)+('<ondraw name="_onDrawFunc" label="end"/>' if measuring else '') ns = str(n) h = doPara(x,text0,wc,ns,n) if '<a' in text: text1 = apat.sub('<img width="10" height="5" src="pythonpowered.gif"/>',text0) doPara(x1,text1,wc+10+gex(1,n),ns+'.11',None) text2 = apat.sub('\\1<img width="10" height="5" src="pythonpowered.gif"/>',text0) doPara(x2,text1,wc+10+gex(2,n),ns+'.12',None) text3 = apat.sub('\\1<img width="10" height="5" src="pythonpowered.gif"/><img width="10" height="5" src="pythonpowered.gif"/>\\1',text0) doPara(x3,text3,wc+20+gex(3,n),ns+'.13',None) doPara(x4,text3,wc+20+gex(3,n),ns+'.14',None, hrep='<span face="Courier-BoldOblique"> </span>', crep='<span face="Helvetica-BoldOblique"> </span>', hdw = swcbo(' ') - swhbo(' '), cdw = swhbo(' ') - swcbo(' '), ) else: doPara(x1,text0,wc,ns+'.21',None, hrep='<span face="Courier-BoldOblique"> </span>', crep='<span face="Helvetica-BoldOblique"> </span>', hdw = swcbo(' ') - swhbo(' '), cdw = swhbo(' ') - swcbo(' '), ) y -= h+1 canv.showPage() canv.save() if errors: raise ValueError('\n'.join(errors))