1#Copyright ReportLab Europe Ltd. 2000-2017 2#see license.txt for license details 3"""Tests for the reportlab.platypus.paragraphs module. 4""" 5__version__='3.3.0' 6from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation 7setOutDir(__name__) 8import sys, os, unittest 9from operator import truth 10from reportlab.pdfgen.canvas import Canvas 11from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont, registerFontFamily 12from reportlab.pdfbase.ttfonts import TTFont 13from reportlab.platypus.paraparser import ParaParser 14from reportlab.platypus.flowables import Flowable, DocAssert 15from reportlab.lib.colors import Color 16from reportlab.lib.units import cm 17from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY 18from reportlab.lib.utils import _className, asBytes, asUnicode, asNative 19from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 20from reportlab.platypus.xpreformatted import XPreformatted 21from reportlab.platypus.frames import Frame, ShowBoundaryValue 22from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate, PageBreak, NextPageTemplate 23from reportlab.platypus import tableofcontents 24from reportlab.platypus.tableofcontents import TableOfContents 25from reportlab.platypus.tables import TableStyle, Table 26from reportlab.platypus.paragraph import Paragraph, _getFragWords, _splitWord, _fragWordSplitRep, ABag, pyphen 27from reportlab.rl_config import rtlSupport, trustedHosts, trustedSchemes 28 29def myMainPageFrame(canvas, doc): 30 "The page frame used for all PDF documents." 31 32 canvas.saveState() 33 34 canvas.rect(2.5*cm, 2.5*cm, 15*cm, 25*cm) 35 canvas.setFont('Times-Roman', 12) 36 pageNumber = canvas.getPageNumber() 37 canvas.drawString(10*cm, cm, str(pageNumber)) 38 39 canvas.restoreState() 40 41class MyDocTemplate(BaseDocTemplate): 42 _invalidInitArgs = ('pageTemplates',) 43 44 def __init__(self, filename, **kw): 45 frame1 = Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1') 46 frame2 = Frame(2.5*cm, 2.5*cm, 310, 25*cm, id='F2') 47 self.allowSplitting = 0 48 BaseDocTemplate.__init__(self, filename, **kw) 49 template = PageTemplate('normal', [frame1], myMainPageFrame) 50 template1 = PageTemplate('special', [frame2], myMainPageFrame) 51 template2 = PageTemplate('template2', [Frame(395, 108, 165, 645, id='second2')]) 52 self.addPageTemplates([template,template1,template2]) 53 54class ParagraphCorners(unittest.TestCase): 55 "some corner cases which should parse" 56 def check(self,text,bt = getSampleStyleSheet()['BodyText']): 57 try: 58 P = Paragraph(text,style=bt) 59 except: 60 raise AssertionError("'%s' should parse"%text) 61 62 def test0(self): 63 self.check('<para />') 64 self.check('<para/>') 65 self.check('\t\t\t\n\n\n<para />') 66 self.check('\t\t\t\n\n\n<para/>') 67 self.check('<para\t\t\t\t/>') 68 self.check('<para></para>') 69 self.check('<para> </para>') 70 self.check('\t\t\n\t\t\t <para> </para>') 71 72 def test1(self): 73 "This makes several special paragraphs." 74 75 # Build story. 76 story = [] 77 styleSheet = getSampleStyleSheet() 78 bt = styleSheet['BodyText'] 79 btN = ParagraphStyle('BodyTextTTNone',parent=bt,textTransform='none') 80 btL = ParagraphStyle('BodyTextTTLower',parent=bt,textTransform='lowercase') 81 btU = ParagraphStyle('BodyTextTTUpper',parent=bt,textTransform='uppercase') 82 btC = ParagraphStyle('BodyTextTTCapitalize',parent=bt,textTransform='capitalize') 83 story.append(Paragraph('''This should be ORDINARY text.''',style=bt)) 84 story.append(Paragraph('''This should be ORDINARY text.''',style=btN)) 85 story.append(Paragraph('''This should be LOWER text.''',style=btL)) 86 story.append(Paragraph('''This should be upper text.''',style=btU)) 87 story.append(Paragraph('''This should be cAPITALIZED text.''',style=btC)) 88 89 story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>ORDINARY</b> text.''',style=bt)) 90 story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>ORDINARY</b> text.''',style=btN)) 91 story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>LOWER</b> text.''',style=btL)) 92 story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>upper</b> text.''',style=btU)) 93 story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>cAPITALIZED</b> text.''',style=btC)) 94 doc = MyDocTemplate(outputfile('test_platypus_specialparagraphs.pdf')) 95 doc.multiBuild(story) 96 97 def test2(self): 98 '''CJK splitting in multi-frag case''' 99 style = ParagraphStyle('test', wordWrap = 'CJK') 100 p = Paragraph('bla <i>blub</i> '*130 , style) 101 aW,aH=439.275590551,121.88976378 102 w,h=p.wrap(aW,aH) 103 S=p.split(aW,aH) 104 assert len(S)==2, 'Multi frag CJK splitting failed' 105 w0,h0=S[0].wrap(aW,aH) 106 assert h0<=aH,'Multi-frag CJK split[0] has wrong height %s >= available %s' % (H0,aH) 107 w1,h1=S[1].wrap(aW,aH) 108 assert h0+h1==h, 'Multi-frag-CJK split[0].height(%s)+split[1].height(%s) don\'t add to original %s' % (h0,h1,h) 109 110 def test3(self): 111 '''compare CJK splitting in some edge cases''' 112 from reportlab.platypus.paragraph import Paragraph 113 from reportlab.lib.styles import ParagraphStyle 114 from reportlab.pdfbase import pdfmetrics 115 from reportlab.lib.enums import TA_LEFT 116 sty = ParagraphStyle('A') 117 sty.fontSize = 15 118 sty.leading = sty.fontSize*1.2 119 sty.fontName = 'Courier' 120 sty.alignment = TA_LEFT 121 sty.wordWrap = 'CJK' 122 p0=Paragraph('ABCDEFGHIJKL]N',sty) 123 p1=Paragraph('AB<font color="red">C</font>DEFGHIJKL]N',sty) 124 canv = Canvas(outputfile('test_platypus_paragraph_cjk3.pdf')) 125 ix = len(canv._code) 126 aW = pdfmetrics.stringWidth('ABCD','Courier',15) 127 w,h=p0.wrap(aW,1000000) 128 y = canv._pagesize[1]-72-h 129 p0.drawOn(canv,72,y) 130 w,h=p1.wrap(aW,1000000) 131 y -= h+10 132 p1.drawOn(canv,72,y) 133 w,h=p0.wrap(aW*0.25-2,1000000) 134 y -= h+10 135 p0.drawOn(canv,72,y) 136 w,h=p1.wrap(aW/4.-2,1000000) 137 y -= h+10 138 p1.drawOn(canv,72,y) 139 assert canv._code[ix:]==['q', '1 0 0 1 72 697.8898 cm', 'q', '0 0 0 rg', 'BT 1 0 0 1 0 57 Tm /F2 15 Tf 18 TL (ABCD) Tj T* (EFGH) Tj T* (IJKL]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 615.8898 cm', 'q', 'BT 1 0 0 1 0 57 Tm 18 TL /F2 15 Tf 0 0 0 rg (AB) Tj 1 0 0 rg (C) Tj 0 0 0 rg (D) Tj T* (EFGH) Tj T* (IJKL]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 353.8898 cm', 'q', '0 0 0 rg', 'BT 1 0 0 1 0 237 Tm /F2 15 Tf 18 TL (A) Tj T* (B) Tj T* (C) Tj T* (D) Tj T* (E) Tj T* (F) Tj T* (G) Tj T* (H) Tj T* (I) Tj T* (J) Tj T* (K) Tj T* (L) Tj T* (]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 91.88976 cm', 'q', 'BT 1 0 0 1 0 237 Tm 18 TL /F2 15 Tf 0 0 0 rg (A) Tj T* (B) Tj T* 1 0 0 rg (C) Tj T* 0 0 0 rg (D) Tj T* (E) Tj T* (F) Tj T* (G) Tj T* (H) Tj T* (I) Tj T* (J) Tj T* (K) Tj T* (L) Tj T* (]) Tj T* (N) Tj T* ET', 'Q', 'Q'] 140 canv.showPage() 141 canv.save() 142 143 def test4(self): 144 from reportlab.platypus.paragraph import _SHYIndexedStr, stringWidth, _SHYWord, ABag, _shyUnsplit 145 fontName = 'Helvetica' 146 fontSize = 10 147 f = ABag(fontName=fontName,fontSize=fontSize) 148 sW = lambda _: stringWidth(_,fontName,fontSize) 149 text = u'Super\xadcali\xadfragi\xadlistic\xadexpi\xadali\xaddocious' 150 u = _SHYIndexedStr(text) 151 self.assertEqual(u,u'Supercalifragilisticexpialidocious','_SHYIndexStr not as expected') 152 self.assertEqual(u._shyIndices,[5, 9, 14, 20, 24, 27], '_SHYIndexStr._shyIndices are wrong') 153 shyW = _SHYWord([sW(u),(f,u)]) 154 hsw = shyW.shyphenate(shyW[0],50) 155 self.assertTrue(hsw,'shyphenate failed') 156 self.assertTrue( 157 hsw[0][0] == 45.01 158 and hsw[0][1][0].__dict__== ABag(fontName='Helvetica', fontSize=10).__dict__ 159 and hsw[0][1][1]==u'Supercali-' 160 and hsw[0][1][1]._shyIndices==[5,9], 'left part of shyphenate split failed') 161 self.assertTrue( 162 hsw[1][0] == 101.69000000000001 163 and hsw[1][1][0].__dict__== ABag(fontName='Helvetica', fontSize=10).__dict__ 164 and hsw[1][1][1]==u'fragilisticexpialidocious' 165 and hsw[1][1][1]._shyIndices== [5, 11, 15, 18], 'right part of shyphenate split failed') 166 uj = _shyUnsplit(hsw[0][1][1],hsw[1][1][1]) 167 self.assertTrue( 168 uj == u 169 and uj._shyIndices==u._shyIndices, '_shyUnsplit failed') 170 171 def test5(self): 172 '''some soft hyphenation''' 173 from reportlab.pdfgen import canvas 174 from reportlab.platypus import Frame, ShowBoundaryValue, Paragraph 175 from reportlab.lib.styles import ParagraphStyle 176 177 pagesize = (80+20, 400) 178 c = canvas.Canvas( outputfile('test_platypus_soft_hyphenation.pdf'), pagesize=pagesize) 179 f = Frame(10, 0, 68, 400, 180 showBoundary=ShowBoundaryValue(dashArray=(1,1)), 181 leftPadding=0, 182 rightPadding=0, 183 topPadding=0, 184 bottomPadding=0, 185 ) 186 style = ParagraphStyle( 187 'normal', fontName='Helvetica', fontSize=12, 188 embeddedHyphenation=1, splitLongWords=0, hyphenationLang='en-GB') 189 shy = asNative(u'\xad') 190 text = shy.join(('Super','cali','fragi','listic','expi','ali','docious')) 191 f.addFromList([Paragraph(text, style)], c) 192 text = u'<span color="red">Super</span><span color="pink">­cali­</span>fragi­listic­expi­ali­docious' 193 f.addFromList([Paragraph(text, style)], c) 194 c.showPage() 195 c.save() 196 197 def test_platypus_paragraphs_embedded2(self): 198 from hashlib import md5 as hashlib_md5 199 200 fontName = 'Helvetica' 201 fontSize = 10 202 203 texts = [asUnicode(text) for text 204 in [ 205 b'UU\xc2\xadDIS\xc2\xadTU\xc2\xadSA\xc2\xadLA JA TAI\xc2\xadMIK\xc2\xadKO', 206 b'NUO\xc2\xadRI KAS\xc2\xadVA\xc2\xadTUS\xc2\xadMET\xc2\xadSIK\xc2\xadK\xc3\x96', 207 b'VART\xc2\xadTU\xc2\xadNUT KAS\xc2\xadVA\xc2\xadTUS\xc2\xadMET\xc2\xadSIK\xc2\xadK\xc3\x96', 208 b'UU\xc2\xadDIS\xc2\xadTUS-KYP\xc2\xadS\xc3\x84 MET\xc2\xadSIK\xc2\xadK\xc3\x96', 209 b'SIE\xc2\xadMEN- JA SUO-JUS\xc2\xadPUU-MET\xc2\xadSIK\xc2\xadK\xc3\x96', 210 b'E\xc2\xadRI-I\xc2\xadK\xc3\x84\xc2\xadIS-RA\xc2\xadKEN\xc2\xadTEI\xc2\xadNEN MET\xc2\xadSIK\xc2\xadK\xc3\x96', 211 ] 212 ] 213 maxWidth = stringWidth('VARTTUNUT KAS', fontName, fontSize)+0.5 214 span = lambda _t, _c: "<span color='%s'>%s</span>" % (_c, _t) 215 216 pagesize = (20+maxWidth, 800) 217 c = Canvas(outputfile('test_platypus_paragraphs_embedded2.pdf'), pagesize=pagesize) 218 219 expected = [ 220 (163, b':\n\x16\x8c\xa9\x87\xf4C\xe0\xe6\xfd/\x07\xe7\xde8'), 221 (163, b'4\x98_\t\xd0\xde\x9a:8\xa7E\xfc\x13\xad\xfbk'), 222 (163, b'9m\xec\xdfX\xe4\x85\xe9tL,\xe5ob\x13w'), 223 (163, b"\xf39*6\x85\xd2\xf9`:<\xe8'\xa9\x8a\xec["), 224 (163, b'\x85\x07\x83\xee\x8d\x11Bp\xd0p\xaa\xcbp\x98\xf4\xb7'), 225 (163, b'\xf0"wp\x91vN\xc8<\xef\xe7\xc8s\xae\xf8\x10'), 226 ] 227 observed = [] 228 for eh in 0, 1, 2: 229 for slw in 0, 1: 230 f = Frame(10, 10, maxWidth, 780, 231 showBoundary=ShowBoundaryValue(dashArray=(1,1)), 232 leftPadding=0, 233 rightPadding=0, 234 topPadding=0, 235 bottomPadding=0, 236 ) 237 style = ParagraphStyle( 238 'normal', fontName=fontName, fontSize=fontSize, 239 embeddedHyphenation=eh, splitLongWords=slw, 240 hyphenationLang=None) 241 f.addFromList([Paragraph('slw=%d eh=%d' % (slw,eh), style)], c) 242 for text in texts: 243 f.addFromList([Paragraph(text, style)], c) 244 mfText = text.split(u'\xad') 245 mfText[0] = span(mfText[0],'red') 246 if len(mfText)>1: 247 mfText[1] = span(mfText[1],'pink') 248 if len(mfText)>2: 249 mfText[-1] = span(mfText[-1],'blue') 250 mfText = u'­'.join(mfText) 251 f.addFromList([Paragraph(mfText, style)], c) 252 observed.append((len(c._code), hashlib_md5(b"".join((asBytes(b,"latin1") for b in c._code))).digest())) 253 c.showPage() 254 c.save() 255 self.assertEqual(observed, expected) 256 257 def test_lele_img(self): 258 from reportlab.pdfgen.canvas import Canvas 259 from reportlab.platypus import Paragraph 260 from reportlab.lib.styles import getSampleStyleSheet 261 from reportlab.rl_config import defaultPageSize 262 from reportlab.lib.units import cm 263 from reportlab.lib.testutils import testsFolder 264 265 styles = getSampleStyleSheet() 266 c = Canvas(outputfile('test_lele_img.pdf'), pagesize=defaultPageSize) 267 s = styles["Normal"] 268 t = '<img src="%s/pythonpowered.gif" valign="middle"/>' % testsFolder 269 p = Paragraph(t, s) 270 owh = p.wrap(cm,cm) 271 cx0 = len(c._code) 272 p.drawOn(c, cm, 2*cm) 273 xcode = ['q', '1 0 0 1 28.34646 56.69291 cm', 'q', 'q', '110 0 0 44 0 -16 cm', '/FormXob.00cb676cb2b2da8ec875fe2c13cf2496 Do', 'Q', 'BT 1 0 0 1 0 2 Tm 12 TL 110 0 Td /F1 10 Tf 12 TL T* -110 0 Td ET', 'Q', 'Q'] 274 xwh = (28.346456692913385, 12) 275 ocode = c._code[cx0:] 276 c.showPage() 277 c.save() 278 self.assertEqual((owh,ocode),(xwh,xcode), 279 "\n(owh,ocode)=%r\nfor test_lele_img.pdf doesn't match expected\n(xwh,xcode)=%r" %( 280 (xwh,xcode),(owh,ocode))) 281 282DEJAVUSANS = ('DejaVuSans','DejaVuSans-Bold','DejaVuSans-Oblique','DejaVuSans-BoldOblique') 283def haveDejaVu(): 284 from reportlab.pdfbase.ttfonts import TTFont 285 for x in DEJAVUSANS: 286 try: 287 TTFont(x,x+'.ttf') 288 except: 289 return False 290 return True 291 292class ParagraphSplitTestCase(unittest.TestCase): 293 "Test multi-page splitting of paragraphs (eyeball-test)." 294 295 def test0(self): 296 "ParagraphSplitTestCase.test0" 297 298 # Build story. 299 story = [] 300 styleSheet = getSampleStyleSheet() 301 bt = styleSheet['BodyText'] 302 text = '''If you imagine that the box of X's tothe left is 303an image, what I want to be able to do is flow a 304series of paragraphs around the image 305so that once the bottom of the image is reached, then text will flow back to the 306left margin. I know that it would be possible to something like this 307using tables, but I can't see how to have a generic solution. 308There are two examples of this in the demonstration section of the reportlab 309site. 310If you look at the "minimal" euro python conference brochure, at the end of the 311timetable section (page 8), there are adverts for "AdSu" and "O'Reilly". I can 312see how the AdSu one might be done generically, but the O'Reilly, unsure... 313I guess I'm hoping that I've missed something, and that 314it's actually easy to do using platypus. 315''' 316 from reportlab.platypus.flowables import ParagraphAndImage, Image 317 from reportlab.lib.testutils import testsFolder 318 gif = os.path.join(testsFolder,'pythonpowered.gif') 319 story.append(ParagraphAndImage(Paragraph(text,bt),Image(gif))) 320 phrase = 'This should be a paragraph spanning at least three pages. ' 321 description = ''.join([('%d: '%i)+phrase for i in range(250)]) 322 story.append(ParagraphAndImage(Paragraph(description, bt),Image(gif),side='left')) 323 324 doc = MyDocTemplate(outputfile('test_platypus_paragraphandimage.pdf')) 325 doc.multiBuild(story) 326 327 def test1(self): 328 "ParagraphSplitTestCase.test1" 329 330 # Build story. 331 story = [] 332 styleSheet = getSampleStyleSheet() 333 h3 = styleSheet['Heading3'] 334 bt = styleSheet['BodyText'] 335 st=ParagraphStyle( 336 name="base", 337 fontName="Helvetica", 338 leading=12, 339 leftIndent=0, 340 firstLineIndent=0, 341 spaceBefore = 9.5, 342 fontSize=9.5, 343 ) 344 text = b'''If you imagine that the box of X's to the left is 345an image, what I want to be able to do is flow a 346series of paragraphs around the image 347so that once the bottom of the image is reached, then text will flow back to the 348left margin. I know that it would be possible to something like this 349using tables, but I can't see how to have a generic solution. 350There are two examples of this in the demonstration section of the reportlab 351site. 352If you look at the "minimal" euro python conference brochure, at the end of the 353timetable section (page 8), there are adverts for "AdSu" and "O'Reilly". I can 354see how the AdSu one might be done generically, but the O'Reilly, unsure... 355I guess I'm hoping that I've missed something, and that 356it's actually easy to do using platypus.We can do greek letters <greek>mDngG</greek>. This should be a 357u with a dieresis on top <unichar code=0xfc/>="<unichar code="0xfc"/>" and this &#xfc;="ü" and this \\xc3\\xbc="\xc3\xbc". On the other hand this 358should be a pound sign &pound;="£" and this an alpha &alpha;="α". You can have links in the page <link href="http://www.reportlab.com" color="blue">ReportLab</link> & <a href="http://www.reportlab.org" color="green">ReportLab.org</a>. 359Use scheme "pdf:" to indicate an external PDF link, "http:", "https:" to indicate an external link eg something to open in 360your browser. If an internal link begins with something that looks like a scheme, precede with "document:". Empty hrefs should be allowed ie <a href=""><a href="">test</a></a> should be allowed. 361<u>This text should be underlined.</u><br/> 362<strike>This text should have a strike through it.</strike><br/> 363<span backcolor="yellow"><strike>This text should have a strike through it and be highlighted.</strike></span><br/> 364<span backcolor="yellow"><strike><u>This text should have a strike through it and be highlighted and underlined.</u></strike></span><br/> 365This should be a mailto link <a href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a>.<br/> 366This should be an underlined mailto link <a underline="1" href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a>.<br/> 367This should be a highlighted mailto link <span backcolor="yellow"><a href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a></span>.<br/> 368This should be a highlighted & underlined mailto link <span backcolor="yellow"><a underline="1" ucolor="red" uwidth="0.01*F" href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a></span>.<br/> 369<u offset="-.125*F">Underlined <font size="-1">Underlined</font></u><br/> 370This is A<sup><u>underlined</u></sup> as is A<u><sup>this</sup></u> 371<u color="red">This is A<sup><u>underlined</u></sup> as is A<u><sup>this</sup></u></u> 372''' 373 from reportlab.platypus.flowables import ImageAndFlowables, Image 374 from reportlab.lib.testutils import testsFolder 375 gif = os.path.join(testsFolder,'pythonpowered.gif') 376 heading = Paragraph('This is a heading',h3) 377 story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)])) 378 phrase = 'This should be a paragraph spanning at least three pages. ' 379 description = ''.join([('%d: '%i)+phrase for i in range(250)]) 380 story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(description, bt)],imageSide='left')) 381 story.append(NextPageTemplate('special')) 382 story.append(PageBreak()) 383 VERA = ('Vera','VeraBd','VeraIt','VeraBI') 384 for v in VERA: 385 registerFont(TTFont(v,v+'.ttf')) 386 registerFontFamily(*(VERA[:1]+VERA)) 387 story.append(ImageAndFlowables( 388 Image(gif,width=280,height=120), 389 Paragraph('''<font name="Vera">The <b>concept</b> of an <i>integrated</i> one <b><i>box</i></b> solution for <i><b>advanced</b></i> voice and 390data applications began with the introduction of the IMACS. The 391IMACS 200 carries on that tradition with an integrated solution 392optimized for smaller port size applications that the IMACS could not 393economically address. An array of the most popular interfaces and 394features from the IMACS has been bundled into a small 2U chassis 395providing the ultimate in ease of installation.</font>''', 396 style=st, 397 ), 398 imageSide='left', 399 ) 400 ) 401 story.append(Paragraph('Width 240 single frag',h3)) 402 story.append(ImageAndFlowables( 403 Image(gif,width=240,height=120), 404 Paragraph('''The concept of an integrated one box solution for advanced voice and 405data applications began with the introduction of the IMACS. The 406IMACS 200 carries on that tradition with an integrated solution 407optimized for smaller port size applications that the IMACS could not 408economically address. An array of the most popular interfaces and 409features from the IMACS has been bundled into a small 2U chassis 410providing the ultimate in ease of installation.''', 411 style=st, 412 ), 413 imageSide='left', 414 ) 415 ) 416 417 story.append(PageBreak()) 418 story.append(Paragraph('Image larger than the frame',h3)) 419 story.append(ImageAndFlowables( 420 Image(gif,width=6*110,height=6*44), 421 Paragraph('''The concept of an integrated one box solution for advanced voice and 422data applications began with the introduction of the IMACS. The 423IMACS 200 carries on that tradition with an integrated solution 424optimized for smaller port size applications that the IMACS could not 425economically address. An array of the most popular interfaces and 426features from the IMACS has been bundled into a small 2U chassis 427providing the ultimate in ease of installation.''', 428 style=st, 429 ), 430 imageSide='left', 431 ) 432 ) 433 text = '''With this clarification, an important property of these three types of 434EC can be defined in such a way as to impose problems of phonemic and 435morphological analysis. Another superficial similarity is the interest 436in simulation of behavior, this analysis of a formative as a pair of 437sets of features does not readily tolerate a stipulation to place the 438constructions into these various categories. We will bring evidence in 439favor of the following thesis: the earlier discussion of deviance is 440not to be considered in determining the extended c-command discussed in 441connection with (34). Another superficial similarity is the interest in 442simulation of behavior, relational information may remedy and, at the 443same time, eliminate a descriptive fact. There is also a different 444approach to the [unification] problem, the descriptive power of the base 445component delimits the traditional practice of grammarians.''' 446 gif = os.path.join(testsFolder,'pythonpowered.gif') 447 heading = Paragraph('This is a heading',h3) 448 story.append(NextPageTemplate('template2')) 449 story.append(PageBreak()) 450 story.append(heading) 451 story.append(ImageAndFlowables(Image(gif,width=66,height=81),[Paragraph(text,bt)],imageSide='left',imageRightPadding=10)) 452 453 story.append(NextPageTemplate('special')) 454 story.append(PageBreak()) 455 story.append(Paragraph('Width 240, multi-frag free hyphenation',h3)) 456 story.append(ImageAndFlowables( 457 Image(gif,width=240,height=120), 458 Paragraph('''The concept of an <span color="red">integ</span><span color="green">rated</span> one box solution for advanced voice and 459data applications began with the introduction of the IMACS. The 460IMACS 200 carries on that tradition with an integrated solution 461<span color="pink">optimized</span> for smaller port size applications that the IMACS could not 462<span color="lightgreen">eco</span><span color="blue">nomically</span> address. An array of the most popular interfaces and 463features from the IMACS has been bundled into a small 2U chassis 464providing the ultimate in ease of installation.''', 465 style=st, 466 ), 467 imageSide='left', 468 ) 469 ) 470 story.append(PageBreak()) 471 story.append(Paragraph('Width 240, multi-frag soft hyphenation',h3)) 472 story.append(ImageAndFlowables( 473 Image(gif,width=240,height=120), 474 Paragraph(u'''The concept of an <span color="red">integ</span><span color="green">\xadrated</span> one box solution for advanced voice and 475data applica\xadtions began with the in\xadtroduction of the IMACS. The 476IMACS 200 carries on that tradition with an integrated solution 477<span color="pink">op\xadtimized</span> for smaller port size applications that the IMACS could not 478<span color="lightgreen">eco</span><span color="blue">\xadnomically</span> address. An array of the most popular interfaces and 479fea\xadtures from the IMACS has been bundled into a small 2U chassis 480providing the ultimate in ease of installation.''', 481 style=st, 482 ), 483 imageSide='left', 484 ) 485 ) 486 story.append(PageBreak()) 487 story.append(Paragraph('Width 240, single-frag soft hyphenation',h3)) 488 story.append(ImageAndFlowables( 489 Image(gif,width=240,height=120), 490 Paragraph(u'''The concept of an integ\xadrated one box solution for advanced voice and 491data applica\xadtions began with the in\xadtroduction of the IMACS. The 492IMACS 200 carries on that tradition with an integrated solution 493op\xadtimized for smaller port size applications that the IMACS could not 494eco\xadnomically address. An array of the most popular interfaces and 495fea\xadtures from the IMACS has been bundled into a small 2U chassis 496providing the ultimate in ease of installation.''', 497 style=st, 498 ), 499 imageSide='left', 500 ) 501 ) 502 doc = MyDocTemplate(outputfile('test_platypus_imageandflowables.pdf'),showBoundary=1) 503 doc.multiBuild(story) 504 505 @unittest.skipUnless(rtlSupport,'s') 506 def test1_RTL(self): 507 "ParagraphSplitTestCase.test_RTL" 508 from reportlab.platypus.flowables import ImageAndFlowables, Image 509 from reportlab.lib.testutils import testsFolder 510 from test_paragraphs import getAFont 511 # Build story. 512 fontName = getAFont() 513 story = [] 514 styleSheet = getSampleStyleSheet() 515 h3 = styleSheet['Heading3'] 516 bt = styleSheet['BodyText'] 517 h3.wordWrap = bt.wordWrap = 'RTL' 518 h3.alignment = bt.alignment = TA_RIGHT 519 h3.fontName = bt.fontName = fontName 520 st=ParagraphStyle( 521 name="base", 522 fontName="Helvetica", 523 leading=12, 524 leftIndent=0, 525 firstLineIndent=0, 526 spaceBefore = 9.5, 527 fontSize=9.5, 528 wordWrap='RTL', 529 alignment=TA_RIGHT, 530 ) 531 text=b'''\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\xaa \xd7\x90\xd7\x99\xd7\xa0\xd7\x98\xd7\xa8\xd7\xa0\xd7\x98 \xd7\xa2\xd7\x9c 532 \xd7\xa9\xd7\x9e\xd7\x95. \xd7\x91\xd7\x94 \xd7\xa2\xd7\x96\xd7\x94 \xd7\x90\xd7\x97\xd7\xa8\xd7\x95\xd7\xaa 533 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x99\xd7\x9b\xd7\xaa \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d, 534 \xd7\x94\xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94 \xd7\x9e\xd7\x99\xd7\x95\xd7\x97\xd7\x93\xd7\x99\xd7\x9d 535 \xd7\x9e\xd7\x9e\xd7\x95\xd7\xa0\xd7\xa8\xd7\x9b\xd7\x99\xd7\x94 \xd7\x91 \xd7\x90\xd7\xaa\xd7\x94. \xd7\xa2\xd7\x9c 536 \xd7\xa6'\xd7\x98 \xd7\x9c\xd7\xa8\xd7\x90\xd7\x95\xd7\xaa \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d 537 \xd7\xa4\xd7\x99\xd7\x9c\xd7\x95\xd7\xa1\xd7\x95\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa8\xd7\x91\xd7\x94 538 \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 \xd7\x9e\xd7\x93\xd7\xa8\xd7\x99\xd7\x9b\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d. 539 \xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x99\xd7\x93\xd7\x95\xd7\xa8 540 \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 541 \xd7\x90\xd7\x9c \xd7\xa9\xd7\x9e\xd7\x95, \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 542 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x97\xd7\xa8\xd7\x98\xd7\x95\xd7\x9e\xd7\x99\xd7\x9d 543 \xd7\x96\xd7\x9b\xd7\xa8 \xd7\x90\xd7\x9c. \xd7\x91 \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d 544 \xd7\x95\xd7\x9e\xd7\x93\xd7\xa2\xd7\x99\xd7\x9d \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94 545 \xd7\x91\xd7\x93\xd7\xa3, \xd7\xa2\xd7\x96\xd7\x94 \xd7\xa8\xd7\x99\xd7\xa7\xd7\x95\xd7\x93 546 \xd7\x91\xd7\x93\xd7\xa4\xd7\x99\xd7\x9d \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x90\xd7\xaa. 547 \xd7\xa9\xd7\x9e\xd7\x95 \xd7\x91 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa 548 \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\xa9\xd7\x99\xd7\x97\xd7\x94\xd7\xa6\xd7\xa4\xd7\x94, \xd7\x91\xd7\x93\xd7\xa3 549 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa \xd7\x9e\xd7\x95\xd7\xa0\xd7\x97\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d 550 \xd7\x9e\xd7\x99\xd7\xaa\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 \xd7\x90\xd7\x95, \xd7\x9e\xd7\xaa\xd7\x9f 551 \xd7\x90\xd7\x95 \xd7\x95\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\x94 \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa. 552 \xd7\xa6\xd7\xa2\xd7\x93 \xd7\x94\xd7\x97\xd7\x9c\xd7\x9c \xd7\xa7\xd7\x95\xd7\x93\xd7\x9e\xd7\x95\xd7\xaa 553 \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99 \xd7\x91, \xd7\x90\xd7\x9c 554 \xd7\x91\xd7\x99\xd7\xa9\xd7\x95\xd7\x9c \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d 555 \xd7\xa2\xd7\x95\xd7\x93, \xd7\x9e\xd7\xaa\xd7\x9f \xd7\x9e\xd7\x94 \xd7\x9e\xd7\xaa\xd7\x95\xd7\x9a 556 \xd7\xa9\xd7\x95\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x99\xd7\xa8. \xd7\x91\xd7\xa7\xd7\xa8 557 \xd7\xa2\xd7\xa1\xd7\xa7\xd7\x99\xd7\x9d \xd7\x97\xd7\x99\xd7\xa0\xd7\x95\xd7\x9a \xd7\xaa\xd7\x90\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 558 \xd7\x91, \xd7\x90\xd7\x99\xd7\x98\xd7\x9c\xd7\x99\xd7\x94 \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa 559 \xd7\x9c\xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\x99\xd7\x9d \xd7\x90\xd7\xaa \xd7\x9b\xd7\xaa\xd7\x91. \xd7\x90\xd7\x95 560 \xd7\xa4\xd7\xa0\xd7\x90\xd7\x99 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\xa2\xd7\x95\xd7\x93, \xd7\x91\xd7\x94 561 \xd7\x9e\xd7\xaa\xd7\x9f \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d 562 \xd7\x98\xd7\x91\xd7\x9c\xd7\x90\xd7\x95\xd7\xaa. \xd7\xa6'\xd7\x98 \xd7\xa9\xd7\x9c \xd7\x95\xd7\x99\xd7\xa7\xd7\x99 563 \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d. \xd7\xa9\xd7\xa2\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x95\xd7\x9a 564 \xd7\x92\xd7\x99\xd7\x90\xd7\x95\xd7\x92\xd7\xa8\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x90\xd7\xaa 565 \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\x91\xd7\x92\xd7\xa8\xd7\xa1\xd7\x94 \xd7\xa1\xd7\xa4\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa, 566 \xd7\xa8\xd7\xa7\xd7\x98\xd7\x95\xd7\xaa \xd7\xaa\xd7\x99\xd7\xa7\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d 567 \xd7\x96\xd7\x90\xd7\xaa. \xd7\x9e\xd7\x94 \xd7\x91\xd7\x94\xd7\x91\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 568 \xd7\xa9\xd7\xaa\xd7\x99, \xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 569 \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x97\xd7\xa4\xd7\xa9 \xd7\x91. \xd7\x90\xd7\x9d 570 \xd7\x90\xd7\xaa\xd7\x94 \xd7\x94\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa 571 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d. \xd7\xa6\xd7\x99\xd7\x95\xd7\xa8 \xd7\x91\xd7\xa8\xd7\x99\xd7\xaa 572 \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c \xd7\xa2\xd7\x9c. 573 \xd7\xa6'\xd7\x98 \xd7\x90\xd7\x9c \xd7\x9b\xd7\x9c\xd7\xa9\xd7\x94\xd7\x95 \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d 574 \xd7\x94\xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x94, \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d 575 \xd7\xa7\xd7\x9c\xd7\x90\xd7\xa1\xd7\x99\xd7\x99\xd7\x9d 576 \xd7\xa2\xd7\x9c \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x90\xd7\x95 \xd7\xa7\xd7\xa8\xd7\x9f \xd7\x9c\xd7\x9b\xd7\x90\xd7\x9f 577 \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99. \xd7\x90\xd7\xaa\xd7\x94 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 578 \xd7\x95\xd7\x91\xd7\x9e\xd7\xaa\xd7\x9f \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa \xd7\x90\xd7\x9c, \xd7\xa9\xd7\x9c 579 \xd7\x94\xd7\xa8\xd7\x95\xd7\x97 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa 580 \xd7\xa6'\xd7\x98. \xd7\x90\xd7\xaa \xd7\xaa\xd7\x95\xd7\xa8\xd7\xaa \xd7\x9c\xd7\x9e\xd7\xaa\xd7\x97\xd7\x99\xd7\x9c\xd7\x99\xd7\x9d 581 \xd7\xa9\xd7\x9b\xd7\x9c, \xd7\x94\xd7\x99\xd7\x90 \xd7\x90\xd7\x95 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 582 \xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x9c\xd7\x97\xd7\x99\xd7\x91\xd7\x95\xd7\xa8 583 \xd7\x90\xd7\xa0\xd7\x92\xd7\x9c\xd7\x99\xd7\xaa \xd7\x9e\xd7\x94 \xd7\xa6'\xd7\x98, \xd7\x90\xd7\xa0\xd7\x90 584 \xd7\xaa\xd7\x95\xd7\x9b\xd7\x9c \xd7\x9e\xd7\x95\xd7\xa2\xd7\x9e\xd7\x93\xd7\x99\xd7\x9d 585 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d \xd7\xa2\xd7\x9c, \xd7\x93\xd7\xaa 586 \xd7\x94\xd7\x97\xd7\x95\xd7\x9c \xd7\xa2\xd7\xa8\xd7\x91\xd7\x99\xd7\xaa \xd7\x94\xd7\x9e\xd7\xa9\xd7\xa4\xd7\x98 587 \xd7\x91\xd7\x93\xd7\xa3. \xd7\x94\xd7\x90\xd7\xa8\xd7\xa5 \xd7\x91\xd7\x99\xd7\x95\xd7\xa0\xd7\x99 588 \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x93\xd7\xaa \xd7\xa8\xd7\x91\xd7\x94, \xd7\xa2\xd7\x96\xd7\x94 589 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 \xd7\x95\xd7\x90\xd7\x9c\xd7\xa7\xd7\x98\xd7\xa8\xd7\x95\xd7\xa0\xd7\x99\xd7\xa7\xd7\x94 590 \xd7\x90\xd7\xaa. \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\x9e\xd7\x91\xd7\x95\xd7\xa7\xd7\xa9\xd7\x99\xd7\x9d 591 \xd7\x9b\xd7\xaa\xd7\x91 \xd7\x90\xd7\xaa. \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 592 \xd7\xa4\xd7\x95\xd7\x9c\xd7\x99\xd7\x98\xd7\x99\xd7\xa7\xd7\x94 \xd7\x91\xd7\x94 \xd7\x9b\xd7\xaa\xd7\x91, 593 \xd7\x9c\xd7\x95\xd7\x97 \xd7\xa9\xd7\x9c \xd7\x94\xd7\x97\xd7\x95\xd7\xa4\xd7\xa9\xd7\x99\xd7\xaa 594 \xd7\x90\xd7\xaa\xd7\xa0\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94. \xd7\x91 \xd7\x96\xd7\x9b\xd7\xa8 595 \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa 596 \xd7\x9c\xd7\x99\xd7\xa6\xd7\x99\xd7\xa8\xd7\xaa\xd7\x94. \xd7\x96\xd7\x9b\xd7\xa8 597 \xd7\x91\xd7\x99\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 598 \xd7\x95\xd7\x94\xd7\x92\xd7\x95\xd7\x9c\xd7\xa9\xd7\x99\xd7\x9d \xd7\x93\xd7\xaa, \xd7\x90\xd7\x97\xd7\x93 599 \xd7\xa2\xd7\x9c \xd7\x92\xd7\xa8\xd7\x9e\xd7\xa0\xd7\x99\xd7\xaa \xd7\x94\xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. 600 \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\xa2\xd7\x99\xd7\xa6\xd7\x95\xd7\x91. 601 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\xa9\xd7\x9c \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 \xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94, 602 \xd7\xa9\xd7\x9c \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8 \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94 603 \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x9e\xd7\x94 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\x99\xd7\x99\xd7\x93\xd7\x99\xd7\xa9 604 \xd7\x94\xd7\x9e\xd7\x9c\xd7\x97\xd7\x9e\xd7\x94 \xd7\x98\xd7\x9b\xd7\xa0\xd7\x99\xd7\x99\xd7\x9d. 605 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa \xd7\x9c\xd7\x9e\xd7\x97\xd7\x99\xd7\xa7\xd7\x94 \xd7\x9e\xd7\x94 606 \xd7\x97\xd7\xa4\xd7\xa9, \xd7\x9e\xd7\x94 \xd7\xa2\xd7\x95\xd7\x93 \xd7\x90\xd7\xa7\xd7\xa8\xd7\x90\xd7\x99 607 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94, 608 \xd7\x90\xd7\x95 \xd7\x9e\xd7\xa4\xd7\xaa\xd7\x97 \xd7\x9c\xd7\x99\xd7\x9e\xd7\x95\xd7\x93\xd7\x99\xd7\x9d 609 \xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c. 610 \xd7\x93\xd7\xa8\xd7\x9b\xd7\x94 \xd7\xa9\xd7\x99\xd7\xaa\xd7\x95\xd7\xa4\xd7\x99\xd7\xaa 611 \xd7\x90\xd7\xaa\xd7\x94 \xd7\x93\xd7\xaa.''' 612 613 text1=b'''\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\xaa \xd7\x90\xd7\x99\xd7\xa0\xd7\x98\xd7\xa8\xd7\xa0\xd7\x98 English \xd7\xa2\xd7\x9c 614 \xd7\xa9\xd7\x9e\xd7\x95. \xd7\x91\xd7\x94 \xd7\xa2\xd7\x96\xd7\x94 \xd7\x90\xd7\x97\xd7\xa8\xd7\x95\xd7\xaa 615 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x99\xd7\x9b\xd7\xaa \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d, 616 \xd7\x94\xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94 \xd7\x9e\xd7\x99\xd7\x95\xd7\x97\xd7\x93\xd7\x99\xd7\x9d 617 \xd7\x9e\xd7\x9e\xd7\x95\xd7\xa0\xd7\xa8\xd7\x9b\xd7\x99\xd7\x94 \xd7\x91 \xd7\x90\xd7\xaa\xd7\x94. \xd7\xa2\xd7\x9c 618 \xd7\xa6'\xd7\x98 \xd7\x9c\xd7\xa8\xd7\x90\xd7\x95\xd7\xaa \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d 619 \xd7\xa4\xd7\x99\xd7\x9c\xd7\x95\xd7\xa1\xd7\x95\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa8\xd7\x91\xd7\x94 620 \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 \xd7\x9e\xd7\x93\xd7\xa8\xd7\x99\xd7\x9b\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d. 621 \xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x99\xd7\x93\xd7\x95\xd7\xa8 622 \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 623 \xd7\x90\xd7\x9c \xd7\xa9\xd7\x9e\xd7\x95, \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 624 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x97\xd7\xa8\xd7\x98\xd7\x95\xd7\x9e\xd7\x99\xd7\x9d 625 \xd7\x96\xd7\x9b\xd7\xa8 \xd7\x90\xd7\x9c. \xd7\x91 \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d 626 \xd7\x95\xd7\x9e\xd7\x93\xd7\xa2\xd7\x99\xd7\x9d \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94 627 \xd7\x91\xd7\x93\xd7\xa3, English \xd7\xa2\xd7\x96\xd7\x94 \xd7\xa8\xd7\x99\xd7\xa7\xd7\x95\xd7\x93 628 \xd7\x91\xd7\x93\xd7\xa4\xd7\x99\xd7\x9d \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x90\xd7\xaa. 629 \xd7\xa9\xd7\x9e\xd7\x95 \xd7\x91 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa 630 \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\xa9\xd7\x99\xd7\x97\xd7\x94\xd7\xa6\xd7\xa4\xd7\x94, \xd7\x91\xd7\x93\xd7\xa3 631 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa \xd7\x9e\xd7\x95\xd7\xa0\xd7\x97\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d 632 \xd7\x9e\xd7\x99\xd7\xaa\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 \xd7\x90\xd7\x95, \xd7\x9e\xd7\xaa\xd7\x9f 633 \xd7\x90\xd7\x95 \xd7\x95\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\x94 \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa. 634 \xd7\xa6\xd7\xa2\xd7\x93 \xd7\x94\xd7\x97\xd7\x9c\xd7\x9c \xd7\xa7\xd7\x95\xd7\x93\xd7\x9e\xd7\x95\xd7\xaa 635 \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99 \xd7\x91, \xd7\x90\xd7\x9c 636 \xd7\x91\xd7\x99\xd7\xa9\xd7\x95\xd7\x9c \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d 637 \xd7\xa2\xd7\x95\xd7\x93, \xd7\x9e\xd7\xaa\xd7\x9f \xd7\x9e\xd7\x94 \xd7\x9e\xd7\xaa\xd7\x95\xd7\x9a 638 \xd7\xa9\xd7\x95\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x99\xd7\xa8. \xd7\x91\xd7\xa7\xd7\xa8 639 \xd7\xa2\xd7\xa1\xd7\xa7\xd7\x99\xd7\x9d \xd7\x97\xd7\x99\xd7\xa0\xd7\x95\xd7\x9a \xd7\xaa\xd7\x90\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 640 \xd7\x91, \xd7\x90\xd7\x99\xd7\x98\xd7\x9c\xd7\x99\xd7\x94 \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa 641 \xd7\x9c\xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\x99\xd7\x9d \xd7\x90\xd7\xaa \xd7\x9b\xd7\xaa\xd7\x91. \xd7\x90\xd7\x95 642 \xd7\xa4\xd7\xa0\xd7\x90\xd7\x99 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\xa2\xd7\x95\xd7\x93, \xd7\x91\xd7\x94 643 \xd7\x9e\xd7\xaa\xd7\x9f \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d 644 \xd7\x98\xd7\x91\xd7\x9c\xd7\x90\xd7\x95\xd7\xaa. \xd7\xa6'\xd7\x98 \xd7\xa9\xd7\x9c \xd7\x95\xd7\x99\xd7\xa7\xd7\x99 645 \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d. \xd7\xa9\xd7\xa2\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x95\xd7\x9a 646 \xd7\x92\xd7\x99\xd7\x90\xd7\x95\xd7\x92\xd7\xa8\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x90\xd7\xaa 647 \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\x91\xd7\x92\xd7\xa8\xd7\xa1\xd7\x94 \xd7\xa1\xd7\xa4\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa, 648 \xd7\xa8\xd7\xa7\xd7\x98\xd7\x95\xd7\xaa \xd7\xaa\xd7\x99\xd7\xa7\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d 649 \xd7\x96\xd7\x90\xd7\xaa. \xd7\x9e\xd7\x94 \xd7\x91\xd7\x94\xd7\x91\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 650 \xd7\xa9\xd7\xaa\xd7\x99, \xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 651 \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x97\xd7\xa4\xd7\xa9 \xd7\x91. \xd7\x90\xd7\x9d 652 \xd7\x90\xd7\xaa\xd7\x94 \xd7\x94\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa 653 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d. \xd7\xa6\xd7\x99\xd7\x95\xd7\xa8 \xd7\x91\xd7\xa8\xd7\x99\xd7\xaa 654 \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c \xd7\xa2\xd7\x9c. 655 \xd7\xa6'\xd7\x98 \xd7\x90\xd7\x9c \xd7\x9b\xd7\x9c\xd7\xa9\xd7\x94\xd7\x95 \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d 656 \xd7\x94\xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x94, \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d 657 \xd7\xa7\xd7\x9c\xd7\x90\xd7\xa1\xd7\x99\xd7\x99\xd7\x9d 658 \xd7\xa2\xd7\x9c \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x90\xd7\x95 \xd7\xa7\xd7\xa8\xd7\x9f \xd7\x9c\xd7\x9b\xd7\x90\xd7\x9f 659 \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99. \xd7\x90\xd7\xaa\xd7\x94 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 660 \xd7\x95\xd7\x91\xd7\x9e\xd7\xaa\xd7\x9f \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa \xd7\x90\xd7\x9c, \xd7\xa9\xd7\x9c 661 \xd7\x94\xd7\xa8\xd7\x95\xd7\x97 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa 662 \xd7\xa6'\xd7\x98. \xd7\x90\xd7\xaa \xd7\xaa\xd7\x95\xd7\xa8\xd7\xaa \xd7\x9c\xd7\x9e\xd7\xaa\xd7\x97\xd7\x99\xd7\x9c\xd7\x99\xd7\x9d 663 \xd7\xa9\xd7\x9b\xd7\x9c, \xd7\x94\xd7\x99\xd7\x90 \xd7\x90\xd7\x95 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 664 \xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x9c\xd7\x97\xd7\x99\xd7\x91\xd7\x95\xd7\xa8 665 \xd7\x90\xd7\xa0\xd7\x92\xd7\x9c\xd7\x99\xd7\xaa \xd7\x9e\xd7\x94 \xd7\xa6'\xd7\x98, \xd7\x90\xd7\xa0\xd7\x90 666 \xd7\xaa\xd7\x95\xd7\x9b\xd7\x9c \xd7\x9e\xd7\x95\xd7\xa2\xd7\x9e\xd7\x93\xd7\x99\xd7\x9d 667 \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d \xd7\xa2\xd7\x9c, \xd7\x93\xd7\xaa 668 \xd7\x94\xd7\x97\xd7\x95\xd7\x9c \xd7\xa2\xd7\xa8\xd7\x91\xd7\x99\xd7\xaa \xd7\x94\xd7\x9e\xd7\xa9\xd7\xa4\xd7\x98 669 \xd7\x91\xd7\x93\xd7\xa3. \xd7\x94\xd7\x90\xd7\xa8\xd7\xa5 \xd7\x91\xd7\x99\xd7\x95\xd7\xa0\xd7\x99 670 \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x93\xd7\xaa \xd7\xa8\xd7\x91\xd7\x94, \xd7\xa2\xd7\x96\xd7\x94 671 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 \xd7\x95\xd7\x90\xd7\x9c\xd7\xa7\xd7\x98\xd7\xa8\xd7\x95\xd7\xa0\xd7\x99\xd7\xa7\xd7\x94 672 \xd7\x90\xd7\xaa. \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\x9e\xd7\x91\xd7\x95\xd7\xa7\xd7\xa9\xd7\x99\xd7\x9d 673 \xd7\x9b\xd7\xaa\xd7\x91 \xd7\x90\xd7\xaa. \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 674 \xd7\xa4\xd7\x95\xd7\x9c\xd7\x99\xd7\x98\xd7\x99\xd7\xa7\xd7\x94 \xd7\x91\xd7\x94 \xd7\x9b\xd7\xaa\xd7\x91, 675 \xd7\x9c\xd7\x95\xd7\x97 \xd7\xa9\xd7\x9c \xd7\x94\xd7\x97\xd7\x95\xd7\xa4\xd7\xa9\xd7\x99\xd7\xaa 676 \xd7\x90\xd7\xaa\xd7\xa0\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94. \xd7\x91 \xd7\x96\xd7\x9b\xd7\xa8 677 \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa 678 \xd7\x9c\xd7\x99\xd7\xa6\xd7\x99\xd7\xa8\xd7\xaa\xd7\x94. \xd7\x96\xd7\x9b\xd7\xa8 679 \xd7\x91\xd7\x99\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 680 \xd7\x95\xd7\x94\xd7\x92\xd7\x95\xd7\x9c\xd7\xa9\xd7\x99\xd7\x9d \xd7\x93\xd7\xaa, \xd7\x90\xd7\x97\xd7\x93 681 \xd7\xa2\xd7\x9c \xd7\x92\xd7\xa8\xd7\x9e\xd7\xa0\xd7\x99\xd7\xaa \xd7\x94\xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. 682 \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\xa2\xd7\x99\xd7\xa6\xd7\x95\xd7\x91. 683 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\xa9\xd7\x9c \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 \xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94, 684 \xd7\xa9\xd7\x9c \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8 \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94 685 \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x9e\xd7\x94 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\x99\xd7\x99\xd7\x93\xd7\x99\xd7\xa9 686 \xd7\x94\xd7\x9e\xd7\x9c\xd7\x97\xd7\x9e\xd7\x94 \xd7\x98\xd7\x9b\xd7\xa0\xd7\x99\xd7\x99\xd7\x9d. 687 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa \xd7\x9c\xd7\x9e\xd7\x97\xd7\x99\xd7\xa7\xd7\x94 \xd7\x9e\xd7\x94 688 \xd7\x97\xd7\xa4\xd7\xa9, \xd7\x9e\xd7\x94 \xd7\xa2\xd7\x95\xd7\x93 \xd7\x90\xd7\xa7\xd7\xa8\xd7\x90\xd7\x99 689 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94, 690 \xd7\x90\xd7\x95 \xd7\x9e\xd7\xa4\xd7\xaa\xd7\x97 \xd7\x9c\xd7\x99\xd7\x9e\xd7\x95\xd7\x93\xd7\x99\xd7\x9d 691 \xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c. 692 \xd7\x93\xd7\xa8\xd7\x9b\xd7\x94 \xd7\xa9\xd7\x99\xd7\xaa\xd7\x95\xd7\xa4\xd7\x99\xd7\xaa 693 \xd7\x90\xd7\xaa\xd7\x94 \xd7\x93\xd7\xaa.''' 694 gif = os.path.join(testsFolder,'pythonpowered.gif') 695 heading = Paragraph(b'\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) 696 story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)])) 697 heading = Paragraph(b'\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) 698 story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text1,bt)])) 699 doc = MyDocTemplate(outputfile('test_platypus_imageandflowables_rtl.pdf'),showBoundary=1) 700 doc.multiBuild(story) 701 702 @unittest.skipUnless(rtlSupport and haveDejaVu(),'s') 703 def test2_RTL(self): 704 '''example & bugfix contributed by Moshe Uminer < mosheduminer at gmail.com >''' 705 from reportlab.platypus import Paragraph, PageBreak 706 from reportlab.lib.enums import TA_JUSTIFY, TA_RIGHT, TA_CENTER, TA_LEFT 707 from reportlab.pdfbase import pdfmetrics 708 from reportlab.pdfbase.ttfonts import TTFont 709 from reportlab.lib.pagesizes import LETTER 710 from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet 711 from reportlab.platypus.doctemplate import SimpleDocTemplate 712 from reportlab.lib.colors import toColor 713 pdfmetrics.registerFont(TTFont("DejaVuSans", "DejaVuSans.ttf")) 714 715 text = u'\u05e9\u05dc\u05d5\u05dd! \u05d6\u05d5 \u05ea\u05d4\u05d9\u05d4 \u05e4\u05e1\u05e7\u05d4 \u05e9\u05d4\u05e9\u05d5\u05e8\u05d4 \u05d4\u05d0\u05d7\u05e8\u05d5\u05e0\u05d4 \u05e9\u05dc\u05d4 \u05dc\u05d0 \u05ea\u05d5\u05e6\u05d3\u05e7 \u05db\u05d4\u05dc\u05db\u05d4.' 716 text = u' '.join((text,text)) 717 718 doc = SimpleDocTemplate( 719 outputfile("test_platypus_paragraphs_rtl_2.pdf"), 720 pagesize=LETTER, 721 rightMargin=72, 722 leftMargin=72, 723 topMargin=72, 724 bottomMargin=72, 725 ) 726 styles = getSampleStyleSheet() 727 hebrew_j = ParagraphStyle( 728 parent=styles["Normal"], 729 name="NormalHebrew", 730 wordWrap="RTL", 731 alignment=TA_JUSTIFY, 732 fontName="DejaVuSans", 733 fontSize=14, 734 underlineWidth=0.5, 735 underlineColor=toColor('red'), 736 strikeWidth=0.4, 737 strikeColor=toColor('orange'), 738 ) 739 latin = hebrew_j.clone('latin',alignment=TA_LEFT,wordWrap='LTR') 740 hebrew_r = hebrew_j.clone('nhr', alignment=TA_RIGHT) 741 hebrew_rd = hebrew_r.clone('nhrd', endDots='.') 742 hebrew_jd = hebrew_j.clone('nhjd', endDots='.') 743 hebrew_c = hebrew_j.clone('nhc', alignment=TA_CENTER) 744 hebrew_cd = hebrew_c.clone('nhc', endDots='.') 745 746 rtext = text.replace(u'\u05db\u05d4\u05dc\u05db\u05d4',u'<span color=red>\u05db\u05d4\u05dc\u05db\u05d4</span>') 747 _utext = u''.join((u'<u>',text,u'</u>')) 748 utext = u''.join(('<u color=green>',text,'</u>')) 749 stext = u''.join(('<strike>',text,'</strike>')) 750 urtext = u''.join(('<u color=blue>',rtext,'</u>')) 751 srtext = u''.join(('<strike color=magenta>',rtext,'</strike>')) 752 flowables = [ 753 Paragraph('justified',latin), 754 Paragraph(text, hebrew_j), 755 Paragraph(_utext, hebrew_j), #single frag takes defaults 756 Paragraph(stext, hebrew_j), #single frag takes defaults 757 Paragraph(utext, hebrew_j), 758 Paragraph(rtext, hebrew_j), 759 Paragraph(urtext, hebrew_j), 760 Paragraph(srtext, hebrew_j), 761 762 Paragraph('right',latin), 763 Paragraph(text, hebrew_r), 764 Paragraph(_utext, hebrew_r), #single frag takes defaults 765 Paragraph(stext, hebrew_r), #single frag takes defaults 766 Paragraph(utext, hebrew_r), 767 Paragraph(rtext, hebrew_r), 768 Paragraph(urtext, hebrew_r), 769 Paragraph(srtext, hebrew_r), 770 771 Paragraph('center',latin), 772 Paragraph(text, hebrew_c), 773 Paragraph(_utext, hebrew_c), #single frag takes defaults 774 Paragraph(stext, hebrew_c), #single frag takes defaults 775 Paragraph(utext, hebrew_c), 776 Paragraph(rtext, hebrew_c), 777 Paragraph(urtext, hebrew_c), 778 Paragraph(srtext, hebrew_c), 779 780 PageBreak(), 781 Paragraph('justified dots',latin), 782 Paragraph(text, hebrew_jd), 783 Paragraph(_utext, hebrew_jd), #single frag takes defaults 784 Paragraph(stext, hebrew_jd), #single frag takes defaults 785 Paragraph(utext, hebrew_jd), 786 Paragraph(rtext, hebrew_jd), 787 Paragraph(urtext, hebrew_jd), 788 Paragraph(srtext, hebrew_jd), 789 790 Paragraph('right dots',latin), 791 Paragraph(text, hebrew_rd), 792 Paragraph(_utext, hebrew_rd), #single frag takes defaults 793 Paragraph(stext, hebrew_rd), #single frag takes defaults 794 Paragraph(utext, hebrew_rd), 795 Paragraph(rtext, hebrew_rd), 796 Paragraph(urtext, hebrew_rd), 797 Paragraph(srtext, hebrew_rd), 798 799 Paragraph('center dots',latin), 800 Paragraph(text, hebrew_cd), 801 Paragraph(_utext, hebrew_cd), #single frag takes defaults 802 Paragraph(stext, hebrew_cd), #single frag takes defaults 803 Paragraph(utext, hebrew_cd), 804 Paragraph(rtext, hebrew_cd), 805 Paragraph(urtext, hebrew_cd), 806 Paragraph(srtext, hebrew_cd), 807 ] 808 doc.build(flowables) 809 810 def test_splitJustBug(self): 811 """test that justified paragraphs with </br>last line split properly 812 bug reported by Niharika Singh <nsingh@shoobx.com> 813 """ 814 measures = [] 815 def _odW(canv,name,label): 816 measures.append((label,canv._curr_tx_info['cur_x'])) 817 text = '''<para><onDraw name="_odW" label="start"/>First line<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>Second line<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>split here<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>Third line should not be justified<onDraw name="_odW" label="end"/><br/></para>''' 818 normal = getSampleStyleSheet()['BodyText'] 819 normal.fontName = "Helvetica" 820 normal.fontSize = 10 821 normal.leading = 12 822 normal.alignment = TA_JUSTIFY 823 canv = Canvas(outputfile('test_splitJustBug.pdf')) 824 canv._odW = _odW 825 W, H = canv._pagesize 826 aW = W-2*72 827 aH = H-2*72 828 x = 72 829 y = H-72 830 P = Paragraph(text,normal) 831 w,h = P.wrap(aW,aH) 832 P.drawOn(canv,x,y) 833 M0 = measures[:] 834 measures[:] = [] 835 y -= h 836 aH -= h 837 P = Paragraph(text,normal) 838 w,h = P.wrap(W-2*72,H-2*72) 839 P1,P2 = P.split(aW,37) 840 w,h = P1.wrap(aW,37) 841 P1.drawOn(canv,x,y) 842 y -= h 843 aH -= h 844 w,h = P2.wrap(aW,aH) 845 P2.drawOn(canv,x,y) 846 y -= h 847 aH -= h 848 canv.save() 849 self.assertEqual(M0,measures,"difference detected in justified split Paragraph rendering") 850 851 def test_unicharCodeSafety(self): 852 """test a bug reported by ravi prakash giri <raviprakashgiri@gmail.com>""" 853 normal = getSampleStyleSheet()['BodyText'] 854 self.assertRaises(Exception,Paragraph, 855 """<unichar code="open('/tmp/test.txt','w').write('Hello from unichar')"/>""", 856 normal) 857 858 @unittest.skipUnless(trustedHosts,'s') 859 def test_badUri0(self): 860 """test we catch bad hosts""" 861 normal = getSampleStyleSheet()['BodyText'] 862 self.assertRaises(Exception,Paragraph, 863 """<img src='https://badhost.com'/>""", 864 normal) 865 self.assertRaises(Exception,Paragraph, 866 """<img src='https://127.0.0.1:5000'/>""", 867 normal) 868 self.assertRaises(Exception,Paragraph, 869 """<img src='https://www.reportlab.com:5000'/>""", 870 normal) 871 872 @unittest.skipUnless(trustedSchemes,'s') 873 def test_badUri1(self): 874 """test we catch bad schemes""" 875 normal = getSampleStyleSheet()['BodyText'] 876 self.assertRaises(Exception,Paragraph, 877 """<img src='badscheme://badhost.com'/>""", 878 normal) 879 self.assertRaises(Exception,Paragraph, 880 """<img src='badscheme://127.0.0.1:5000'/>""", 881 normal) 882 self.assertRaises(Exception,Paragraph, 883 """<img src='myscheme://www.reportlab.com'/>""", 884 normal) 885 886 887class TwoFrameDocTemplate(BaseDocTemplate): 888 "Define a simple document with two frames per page." 889 890 def __init__(self, filename, **kw): 891 m = 2*cm 892 from reportlab.lib import pagesizes 893 PAGESIZE = pagesizes.landscape(pagesizes.A4) 894 cw, ch = (PAGESIZE[0]-2*m)/2., (PAGESIZE[1]-2*m) 895 ch -= 14*cm 896 f1 = Frame(m, m+0.5*cm, cw-0.75*cm, ch-1*cm, id='F1', 897 leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0, 898 showBoundary=True 899 ) 900 f2 = Frame(cw+2.7*cm, m+0.5*cm, cw-0.75*cm, ch-1*cm, id='F2', 901 leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0, 902 showBoundary=True 903 ) 904 BaseDocTemplate.__init__(self, filename, **kw) 905 template = PageTemplate('template', [f1, f2]) 906 self.addPageTemplates(template) 907 908 909class SplitFrameParagraphTest(unittest.TestCase): 910 "Test paragraph split over two frames." 911 912 def test(self): 913 stylesheet = getSampleStyleSheet() 914 normal = stylesheet['BodyText'] 915 normal.fontName = "Helvetica" 916 normal.fontSize = 12 917 normal.leading = 16 918 normal.alignment = TA_JUSTIFY 919 920 text = b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch <font color='red'>nur</font> <font color='green'>ein</font> Dampfschiffkapit\xc3\xa4n." 921 tagFormat = '%s' 922 # strange behaviour when using next code line 923 # (same for '<a href="http://www.reportlab.org">%s</a>' 924 tagFormat = '<font color="red">%s</font>' 925 926 #text = " ".join([tagFormat % w for w in text.split()]) 927 928 story = [Paragraph((text.decode('utf8') + u" ") * 3, style=normal)] 929 930 from reportlab.lib import pagesizes 931 PAGESIZE = pagesizes.landscape(pagesizes.A4) 932 933 doc = TwoFrameDocTemplate(outputfile('test_paragraphs_splitframe.pdf'), pagesize=PAGESIZE) 934 doc.build(story) 935 936class FragmentTestCase(unittest.TestCase): 937 "Test fragmentation of paragraphs." 938 939 def test0(self): 940 "Test empty paragraph." 941 942 styleSheet = getSampleStyleSheet() 943 B = styleSheet['BodyText'] 944 text = '' 945 P = Paragraph(text, B) 946 frags = [f.text for f in P.frags] 947 assert frags == [] 948 949 def test1(self): 950 "Test simple paragraph." 951 952 styleSheet = getSampleStyleSheet() 953 B = styleSheet['BodyText'] 954 text = "X<font name=Courier>Y</font>Z" 955 P = Paragraph(text, B) 956 frags = [f.text for f in P.frags] 957 assert frags == ['X', 'Y', 'Z'] 958 959 def test2(self): 960 '''test _splitWord''' 961 self.assertEqual(_splitWord(u'd\'op\u00e9ration',30,[30],0,'Helvetica',12),[u'', u"d'op\xe9", u'ratio', u'n']) 962 self.assertEqual(_splitWord(b'd\'op\xc3\xa9ration',30,[30],0,'Helvetica',12),[u'', u"d'op\xe9", u'ratio', u'n']) 963 964 def test3(self): 965 '''test _fragWordSplitRep''' 966 BF = ABag(rise=0,fontName='Helvetica',fontSize=12) 967 nF = BF.clone 968 ww = 'unused width' 969 W = [ww,(nF(cbDefn=ABag(kind='index',width=0)),''),(BF,'a'),(nF(fontSize=10),'bbb'),(nF(fontName='Helvetica-Bold'),'ccccc')] 970 self.assertEqual(_fragWordSplitRep(W),(u'abbbccccc',((2, 0), (3, 1), (3, 1), (3, 1), (4, 4), (4, 4), (4, 4), (4, 4), (4, 4)))) 971 W[1][0].rise=2 972 self.assertEqual(_fragWordSplitRep(W),None) 973 W = [ww,(nF(cbDefn=ABag(kind='img',width=1)),''),(BF,'a'),(BF,'bbb'),(BF,'ccccc')] 974 self.assertEqual(_fragWordSplitRep(W),None) 975 976 def test4(self): 977 from reportlab.platypus.paragraph import _hy_letters_pat, _hy_shy_letters_pat, _hy_letters, _hy_pfx_pat, _hy_sfx_pat 978 self.assertIsNotNone(_hy_shy_letters_pat.match(_hy_letters),'pre-hyphenated word match should succeed') 979 self.assertIsNone(_hy_letters_pat.match(_hy_letters),'all letters word match should fail') 980 self.assertIsNotNone(_hy_letters_pat.match(_hy_letters.replace(u'-',u'')),'all letters word match should succeed') 981 pfx = u'\'"([{\xbf\u2018\u201a\u201c\u201e' 982 m = _hy_pfx_pat.match(pfx) 983 self.assertIsNotNone(m,'pfx pattern should match') 984 self.assertEqual(len(m.group(0)),len(pfx),'pfx pattern should match %d characters not %d' %(len(pfx),len(m.group(0)))) 985 sfx = u']\'")}?!.,;:\u2019\u201b\u201d\u201f' 986 m = _hy_sfx_pat.search(sfx) 987 self.assertIsNotNone(m,'sfx pattern should match') 988 self.assertEqual(len(m.group(0)),len(sfx),'sfx pattern should match %d characters not %d' %(len(sfx),len(m.group(0)))) 989 990 def test5(self): 991 from reportlab.platypus.paragraph import _hyphenateWord, _hyphenateFragWord, _rebuildFragWord, stringWidth, ABag 992 w = 'https://www.reportlab.com/pypi/packages' 993 fontName = 'Helvetica' 994 fontSize = 12 995 AF = ABag(rise=0,fontName=fontName,fontSize=fontSize) 996 BF = AF.clone(fontName='Helvetica-Bold') 997 998 def applyTest(w, uriWasteReduce, embeddedHyphenation, ex, split=None): 999 if not split: 1000 ww = stringWidth(w,fontName,fontSize) 1001 r = _hyphenateWord(None,fontName,fontSize,w,ww,ww+10,ww+5, uriWasteReduce, embeddedHyphenation) 1002 elif split: 1003 i = int(len(w)*split) 1004 fw = _rebuildFragWord([(AF,w[:i]),(BF,w[i:])]) 1005 #print('%s %s %r %r' % (split,fw[0],fw[1][1],fw[2][1])) 1006 ww = fw[0] 1007 r = _hyphenateFragWord(None,fw,ww+10,ww+5, uriWasteReduce, embeddedHyphenation) 1008 if r is not None: 1009 _r = r 1010 r = [u''.join((_[1] for _ in _fw[1:])) for _fw in _r] 1011 self.assertEqual(r,ex,'hyphenation of w=%r u=%r e=%r ex=%r split=%r failed'%(w,uriWasteReduce,embeddedHyphenation,ex,split)) 1012 for split in (None,0.001,0.1,0.5,0.8,0.9,1.0): 1013 applyTest('https://www.reportlab.com/pypi/packages', 0.3, True, [u'https://www.reportlab.com/pypi/', u'packages'],split=split) 1014 applyTest('https://www.reportlab.com/pypi/packages', False, True, None,split=split) 1015 applyTest('https://www.repor-tlab.com/pypi/packages', 0.3, True, [u'https://www.repor-tlab.com/pypi/', u'packages'],split=split) 1016 applyTest('https//www.repor-tlab.com/pypi/packages', 0.3, True, None,split=split) #not a uri (no :) and contains - and non letters 1017 applyTest('httpsSSwwwDrepor-tlabDcomSpypiSpackages', 0.3, True, [u'httpsSSwwwDrepor-', u'tlabDcomSpypiSpackages'],split=split) #should succeed because '-' with no non-letters 1018 applyTest('httpsSSwwwDrepor-tlabDcomSpypiSpackages', 0.3, False, None, split=split) #fails because embeddedHyphenation=False 1019 1020 @unittest.skipUnless(pyphen,'s') 1021 def test6(self): 1022 bt = getSampleStyleSheet()['BodyText'] 1023 bt.fontName = 'Helvetica' 1024 bt.fontSize = 10 1025 bt.leading = 12 1026 bt.alignment = TA_JUSTIFY 1027 canv = Canvas(outputfile('test_platypus_paragraphs_hyphenations.pdf')) 1028 x = 72 1029 y = canv._pagesize[1] - 72 1030 1031 def _t(p,x,y,aW,aH=0x7fffffff,dy=5): 1032 w, h = p.wrap(aW,aH) 1033 y0 = y 1034 y -= h 1035 canv.saveState() 1036 canv.setLineWidth(0.5) 1037 if aH!=0x7fffffff: 1038 canv.setLineWidth(1) 1039 canv.setStrokeColor((1,0,0)) 1040 canv.rect(x,y0-aH,aW,aH) 1041 ny = y0 - max(aH,h) 1042 else: 1043 ny = y 1044 canv.setLineWidth(0.5) 1045 canv.setStrokeColor((0.5,0.5,0.5)) 1046 canv.rect(x,y,w,h) 1047 p.drawOn(canv,x,y) 1048 canv.restoreState() 1049 return ny-dy 1050 def t(x,y,aW,aH=0x7fffffff,style=bt): 1051 p = Paragraph(text,style=style) 1052 return _t(p,x,y,aW,aH=aH) 1053 1054 raw = """This is a splittable word 'disestablishment'!""" 1055 for text in ("""This is a splittable word '<span color="red">dis</span><span color="blue">estab</span><span color="green">lish</span><span color="magenta">ment</span>'!""", 1056 """This is a splittable word 'd<span color="red">ise</span><span color="blue">stabl</span><span color="green">ishm</span><span color="magenta">ent</span>'!""", 1057 """This is a splittable word 'di<span color="red">ses</span><span color="blue">tabli</span><span color="green">shme</span><span color="magenta">ent</span>'!""", 1058 """This is a splittable word 'disestablishment'!""", 1059 ): 1060 aW = stringWidth("This is a splittable word 'dis",bt.fontName,bt.fontSize) 1061 y = t(x,y,aW) 1062 aW = stringWidth("This is a splittable word 'dise",bt.fontName,bt.fontSize) 1063 y = t(x,y,aW) 1064 aW = stringWidth("This is a splittable word 'disestabl",bt.fontName,bt.fontSize) 1065 y = t(x,y,aW) 1066 aW = stringWidth("This is a splittable word 'disestabli",bt.fontName,bt.fontSize) 1067 y = t(x,y,aW) 1068 aW = stringWidth("This is a splittable word 'disestablishm",bt.fontName,bt.fontSize) 1069 y = t(x,y,aW) 1070 1071 canv.showPage() 1072 y = canv._pagesize[1] - 72 1073 nt = bt.clone('nt',fontName='Helvetica', fontSize = 12,leading = 16, alignment = TA_JUSTIFY) 1074 naW, naH = 342.992125984252, 56.69291338582681 1075 for ntext in ( b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch <font color='red'>nur</font> <font color='green'>ein</font> Dampfschiffkapit\xc3\xa4n.", 1076 b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch nur ein Dampfschiffkapit\xc3\xa4n.", 1077 ): 1078 ntext = (ntext.decode('utf8') + u" ") * 3 1079 p = Paragraph(ntext,style=nt) 1080 y = _t(p,x,y,naW,aH=naH) 1081 1082 S = p.split(naW,naH) 1083 self.assertEqual(len(S),2) 1084 y = _t(S[0],x,y,naW,aH=naH) 1085 y = _t(S[1],x,y,naW,aH=naH) 1086 canv.save() 1087 1088 @unittest.skipUnless(pyphen,'s') 1089 def test7(self): 1090 """test various ways to adjust the hypenationMinWordLength""" 1091 registerFont(TTFont("Vera", "Vera.ttf")) 1092 aW = 51.0236220472 1093 text = u'\u0440\u044b\u0431\u0430 \u043f\u0438\u043b\u0430 \u0438 \u0431\u0430\u0431\u0443 \u0434\u0430\u0436\u0435 \u0432\u0435\u043b\u0430 \u043d\u0430 \u043c\u0430\u044f\u043a' 1094 text1 = u'\u0440\u044b\u0431\u0430 <span color="blue">\u043f\u0438\u043b\u0430</span> \u0438 \u0431\u0430\u0431\u0443 \u0434\u0430\u0436\u0435 \u0432\u0435\u043b\u0430 \u043d\u0430 \u043c\u0430\u044f\u043a' 1095 tmpls = [ 1096 u'%(text)s', 1097 u'<para hyphenationMinWordLength="%(hymwl)d">%(text)s</para>', 1098 u'<para>%(text)s</para>', 1099 u'%(text1)s', 1100 u'<para hyphenationMinWordLength="%(hymwl)d">%(text1)s</para>', 1101 u'<para>%(text1)s</para>', 1102 ] 1103 for ex,x,hymwl in [ 1104 (72,0,None), #default is 5 1105 (72,0,5), 1106 (60,0,4), 1107 (72,2,None), #default is 5 1108 (72,1,5), 1109 (60,1,4), 1110 (72,3,None), #default is 5 1111 (72,4,5), 1112 (60,5,4), 1113 ]: 1114 kwds = dict(hyphenationMinWordLength=hymwl) if hymwl!=None else {} 1115 template = tmpls[x] 1116 t = template % locals() 1117 p = Paragraph( 1118 template % locals(), 1119 style = ParagraphStyle('P10H5', fontSize=10, fontName="Vera", hyphenationLang="ru_RU",**kwds), 1120 ) 1121 w,h = p.wrap(aW,0x7fffffff) 1122 self.assertEqual(h,ex,'Russion hyphenation test failed for ex=%(ex)s template=%(template)r hymwl=%(hymwl)r h=%(h)s\ntext=%(t)r' % locals()) 1123 1124 @unittest.skipUnless(pyphen,'s') 1125 def test8(self): 1126 """display splitting of hyphenated words""" 1127 from reportlab.lib.pagesizes import A4 1128 from reportlab.lib.styles import ParagraphStyle 1129 from reportlab.lib.utils import isBytes 1130 import hashlib 1131 from reportlab.pdfgen.canvas import Canvas 1132 from reportlab.platypus.paragraph import Paragraph 1133 pW, pH = A4 1134 canv = Canvas(outputfile('test_platypus_paragraphs_hysplit.pdf'),pagesize=(pW,pH)) 1135 text = u'Supercalifragilisticexpialidocious' 1136 mtext = u'<span color="red">Super</span>califragilisticexpialidocious' 1137 mtext1 = u'Supercalifragilisticexpiali<span color="green">docious</span>' 1138 stext = u'Super\xadcali\xadfragi\xadlistic\xadexpi\xadali\xaddocious' 1139 mstext = u'<span color="red">Super\xad</span>cali\xadfragi\xadlistic\xadexpi\xadali\xaddocious' 1140 mstext1 = u'Super\xadcali\xadfragi\xadlistic\xadexpi\xadali\xad<span color="green">docious</span>' 1141 text = u'Supercalifragilisticexpialidocious' 1142 mtext2 = 'converted to a <b>Python</b> <font name=Courier><nobr>string</nobr></font>.' 1143 mtext3 = 'This one uses fonts with size "14pt" and also uses the em and strong tags: Here comes <font face="Helvetica" size="14pt">Helvetica 14</font> with <Strong>strong</Strong> <em>emphasis</em>.' 1144 textF = 'Figure [seq template="%(Chapter)s-%(FigureNo+)s"/] - Multi-level templates' 1145 mtextF = 'Figure <seq template="%(Chapter)s-%(FigureNo+)s"/> - Multi-level templates' 1146 sty0=ParagraphStyle( 1147 name="base", 1148 fontName="Helvetica", 1149 leading=12, 1150 leftIndent=0, 1151 firstLineIndent=0, 1152 spaceBefore = 9.5, 1153 fontSize=10, 1154 hyphenationLang="en_GB", 1155 ) 1156 sty1=ParagraphStyle( 1157 name="base", 1158 fontName="Times-Roman", 1159 leading=12, 1160 leftIndent=0, 1161 firstLineIndent=0, 1162 spaceBefore = 9.5, 1163 fontSize=10, 1164 hyphenationLang="en_GB", 1165 ) 1166 styN = ParagraphStyle('normal', hyphenationLang="en_GB") 1167 styF=ParagraphStyle( 1168 name = 'styF', 1169 fontName='Courier', 1170 fontSize=8, 1171 leading=9.6, 1172 hyphenationLang="en_GB", 1173 ) 1174 def box(x, y, aW, h): 1175 canv.saveState() 1176 canv.setDash(1,1) 1177 canv.setLineWidth(0.1) 1178 canv.rect(x,y,aW,h) 1179 canv.restoreState() 1180 1181 def doPara(P,x,y,aW, wc=1): 1182 for _ in range(wc): 1183 w,h = P.wrap(aW,900) 1184 #print('w=%s h=%s' % (w,h)) 1185 y -= h 1186 box(x, y, aW, h) 1187 P.drawOn(canv, x, y) 1188 return y 1189 1190 def doTest(msg, t,x,y,aW, st=None, split=True, wc=1): 1191 if not st: st = sty0 1192 canv.drawString(x+aW+5,y-12,msg) 1193 P = Paragraph(t,st) 1194 y = doPara(P, x, y, aW, wc=wc) - 5 1195 if split: 1196 P = Paragraph(t,st) 1197 S = P.split(aW, st.leading*2+0.1) 1198 y = doPara(S[0], x, y, aW) - 5 1199 y = doPara(S[1], x, y, aW) - 5 1200 return y 1201 1202 aW = 55 1203 x = 72 1204 y = pH - 72 1205 1206 cp0 = len(canv._code) 1207 y = doTest('Single Frag Free Hyphenation', text, x, y, aW) - 5 1208 y = doTest('Single Frag Soft Hyphenation', stext, x, y, aW) - 5 1209 y = doTest('Multi Frag Free Hyphenation', mtext, x, y, aW) - 5 1210 y = doTest('Multi Frag Free Hyphenation 1', mtext1, x, y, aW) - 5 1211 y = doTest('Multi Frag Free Hyphenation 2', mtext2, x, y, 77, st=sty1, split=False, wc=2) - 5 1212 y = doTest('Multi Frag Free Hyphenation 3', mtext3, x, y, 439.27559055118115, st=styN, split=False, wc=1) - 5 1213 y = doTest('Multi Frag Soft Hyphenation', mstext, x, y, aW) - 5 1214 y = doTest('Multi Frag Soft Hyphenation 1', mstext1, x, y, aW) - 5 1215 y = doTest('Single Frag Free F', textF, x, y, 158.13921259842525, st=styF, split=False, wc=3) - 5 1216 y = doTest('Multi Frag Free F', mtextF, x, y, 158.13921259842525, st=styF, split=False, wc=3) - 5 1217 c = '\n'.join(canv._code[cp0:]) 1218 if not isBytes(c): 1219 c = c.encode('utf8') 1220 h = hashlib.md5(c).hexdigest() 1221 canv.showPage() 1222 canv.save() 1223 #xh = '32e0e490cc4a53c31bb19f1cc52debdd' 1224 xh = 'eee06395aa68a727d58e688006c85d79' 1225 self.assertEqual(xh, h, 'test8 code is no longer correct %s != expected %s' % (h,xh)) 1226 1227class ULTestCase(unittest.TestCase): 1228 "Test underlining and overstriking of paragraphs." 1229 def testUl(self): 1230 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1231 from reportlab.lib.units import inch 1232 from reportlab.platypus.flowables import AnchorFlowable 1233 class MyDocTemplate(BaseDocTemplate): 1234 _invalidInitArgs = ('pageTemplates',) 1235 1236 def __init__(self, filename, **kw): 1237 self.allowSplitting = 0 1238 kw['showBoundary']=1 1239 BaseDocTemplate.__init__(self, filename, **kw) 1240 self.addPageTemplates( 1241 [ 1242 PageTemplate('normal', 1243 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1244 ), 1245 ]) 1246 1247 styleSheet = getSampleStyleSheet() 1248 normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal']) 1249 normal_sp = ParagraphStyle(name='normal_sp',parent=normal,alignment=TA_JUSTIFY,spaceBefore=12) 1250 normal_just = ParagraphStyle(name='normal_just',parent=normal,alignment=TA_JUSTIFY) 1251 normal_right = ParagraphStyle(name='normal_right',parent=normal,alignment=TA_RIGHT) 1252 normal_center = ParagraphStyle(name='normal_center',parent=normal,alignment=TA_CENTER) 1253 normal_indent = ParagraphStyle(name='normal_indent',firstLineIndent=0.5*inch,parent=normal) 1254 normal_indent_lv_2 = ParagraphStyle(name='normal_indent_lv_2',firstLineIndent=1.0*inch,parent=normal) 1255 texts = ['''Furthermore, a subset of <font size="14">English sentences</font> interesting on quite 1256independent grounds is not quite equivalent to a stipulation to place 1257the constructions into these various categories.''', 1258 '''We will bring evidence in favor of 1259The following thesis: most of the methodological work in modern 1260linguistics can be defined in such a way as to impose problems of 1261phonemic and morphological analysis.'''] 1262 story =[] 1263 a = story.append 1264 a(Paragraph("This should <a href=\"#theEnd\" color=\"blue\"><a href=\"#theEnd\" color=\"blue\">jump</a></a> jump to the end!",style=normal)) 1265 a(XPreformatted("This should <a href=\"#theEnd\" color=\"blue\"><a href=\"#theEnd\" color=\"blue\">jump</a></a> jump to the end!",style=normal)) 1266 a(Paragraph("<a href=\"#theEnd\"><u><font color=\"blue\">ditto</font></u></a>",style=normal)) 1267 a(XPreformatted("<a href=\"#theEnd\"><u><font color=\"blue\">ditto</font></u></a>",style=normal)) 1268 a(Paragraph("This <font color='CMYKColor(0,0.6,0.94,0)'>should</font> <a href=\"#thePenultimate\" color=\"blue\"><a href=\"#thePenultimate\" color=\"blue\">jump</a></a> jump to the penultimate page!",style=normal)) 1269 a(Paragraph("This should <a href=\"#theThird\" color=\"blue\"><a href=\"#theThird\" color=\"blue\">jump</a></a> jump to a justified para!",style=normal)) 1270 a(Paragraph("This should <a href=\"#theFourth\" color=\"blue\"><a href=\"#theFourth\" color=\"blue\">jump</a></a> jump to an indented para!",style=normal)) 1271 for mode in (0,1): 1272 text0 = texts[0] 1273 text1 = texts[1] 1274 if mode: 1275 text0 = text0.replace('English sentences','<b>English sentences</b>').replace('quite equivalent','<i>quite equivalent</i>') 1276 text1 = text1.replace('the methodological work','<b>the methodological work</b>').replace('to impose problems','<i>to impose problems</i>') 1277 for t in ('u','strike'): 1278 for n in range(6): 1279 for s in (normal,normal_center,normal_right,normal_just,normal_indent, normal_indent_lv_2): 1280 for autoLeading in ('','min','max'): 1281 if n==4 and s==normal_center and t=='strike' and mode==1: 1282 a(Paragraph("<font color=green>The second jump at the beginning should come here <a name=\"thePenultimate\"/><a name=\"thePenultimate\"/>!</font>",style=normal)) 1283 elif n==4 and s==normal_just and t=='strike' and mode==1: 1284 a(Paragraph("<font color=green>The third jump at the beginning should come just below here to a paragraph with just an a tag in it!</font>",style=normal)) 1285 a(Paragraph("<a name=\"theThird\"/>",style=normal)) 1286 elif n==4 and s==normal_indent and t=='strike' and mode==1: 1287 a(Paragraph("<font color=green>The fourth jump at the beginning should come just below here!</font>",style=normal)) 1288 a(AnchorFlowable('theFourth')) 1289 a(Paragraph('n=%d style=%s(autoLeading=%s) tag=%s'%(n,s.name,autoLeading,t),style=normal_sp)) 1290 a(Paragraph('<para autoleading="%s">%s<%s>%s</%s>. %s <%s>%s</%s>. %s</para>' % ( 1291 autoLeading, 1292 (s==normal_indent_lv_2 and '<seq id="document" inc="no"/>.<seq id="document_lv_2"/>' or ''), 1293 t,' '.join((n+1)*['A']),t,text0,t,' '.join((n+1)*['A']),t,text1), 1294 style=s)) 1295 a(Paragraph("The jump at the beginning should come here <a name=\"theEnd\"/><a name=\"theEnd\"/>!",style=normal)) 1296 a(Paragraph('Underlining <span fontSize="11"><u color="red">A<u color="green">B</u><u color="blue">C</u>D<sup><strike width="0.5" color="magenta">2</strike><sup><u color="darkgreen" width="0.2">3</u></sup></sup></u></span>',normal)) 1297 a(Paragraph('<para autoLeading="max" spaceAfter="10">this is in 12 <font size=30>this is in 30</font> <u offset="-0.5" width="0.5" color="red"><u offset="-1.5" width="0.5" color="blue">and</u></u> <link underline="1" ucolor="blue" href="http://google.com/">the link box<sup><a color="red" ucolor="green" underline="1" href="https://www.reportlab.com">2</a></sup> is right (twice).</link></para>''',normal)) 1298 a(Paragraph('<para autoLeading="max" spaceAfter="10">this is in 12 <font size=30>this is in 30</font> and <link underline="1" ucolor="blue" href="http://google.com/">the link box is right.</link></para>''',normal)) 1299 a(Paragraph('Underlining <u><span color="red">underlined in red? <span color="blue"><u>or blue</u></span> or red again?</span></u>',normal)) 1300 a(Paragraph('Link <a href="#theEnd" color="blue">jump</a> to end.<br/>Underlined link <a href="#theEnd" underline="1" ucolor="red" color="blue">jump</a> to end!',style=normal)) 1301 a(Paragraph('<para autoleading=""><u>A</u>. Furthermore, a subset of <font size="14">English sentences</font> interesting on quite\nindependent grounds is not quite equivalent to a stipulation to place\nthe constructions into these various categories. <u>A</u>. We will bring evidence in favor of\nThe following thesis: most of the methodological work in modern\nlinguistics can be defined in such a way as to impose problems of\nphonemic and morphological analysis.</para>',normal)) 1302 a(Paragraph('<para autoleading=""><u>A</u>. Furthermore, a subset of <font size="14">English sentences</font> interesting on quite<br/><u>A</u>.</para>',normal)) 1303 a(Paragraph(u"<para>This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.</para>",normal)) 1304 a(Paragraph('<span fontSize="11"><u color="green"><strike color="blue">AAAAAA</strike></u></span>',normal)) 1305 a(Paragraph("Underlining & width proportional to first use font size ('f' suffix) <u offset='-0.125*f' width='0.05*f'>underlined <span size=14>underlined</span></u>!",style=normal)) 1306 a(Paragraph("Underlining & width proportional to first use font size ('F' suffix) <u offset='-0.125*F' width='0.05*F'>underlined <span size=14>underlined</span></u>!",style=normal)) 1307 a(Paragraph('''<para spaceBefore="10">This is underlined <sup>: a<sup><u><span color="red">sup</span></u></sup></para>''',style=normal)) 1308 a(Paragraph('''<para spaceBefore="10">This is <u>underlined</u></para>''',style=normal)) 1309 a(Paragraph('''<para spaceBefore="10">This is <u kind="double">underlined double</u></para>''',style=normal)) 1310 a(Paragraph('''<para spaceBefore="10">This is <strike>striken</strike></para>''',style=normal)) 1311 a(Paragraph('''<para spaceBefore="10">This is <strike><u>both</u></strike></para>''',style=normal)) 1312 a(Paragraph('''<para spaceBefore="10">This is <u width="0.5" offset="-1" kind="double">underlined kind="double"</u></para>''',style=normal)) 1313 a(Paragraph('''<para spaceBefore="10">This is <u width="0.25" offset="-1" kind="double">double underlined with thinner lines</u></para>''',style=normal)) 1314 a(Paragraph('''<para spaceBefore="10">This is <u width="0.5" offset="-0.5" color="red">underlined in red</u></para>''',style=normal)) 1315 a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" color="red">overstruck in red</strike></para>''',style=normal)) 1316 a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" color="red" kind="double">doubly overstruck in red</strike></para>''',style=normal)) 1317 a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" offset="0.125*F" color="red" kind="triple" gap="0.5">triply overstruck in red</strike></para>''',style=normal)) 1318 a(Paragraph('''<para autoLeading="max" spaceAfter="10" spaceBefore="30">this is in 12 <font size="30">this is in 30</font> <u offset="-0.5" width="0.5" color="red"><u offset="-1.5" width="0.5" color="blue">and</u></u> <link underline="1" ucolor="blue" href="http://google.com/">the link box<sup><a color="red" ucolor="green" underline="1" href="https://www.reportlab.com">2</a></sup> is right (twice).</link></para>''',style=normal)) 1319 a(Paragraph("",style=normal)) 1320 # 3.5.x had a bug with leftIndent and underlines, check that 1321 left_indent = ParagraphStyle(name='left_indent',leftIndent=80,parent=styleSheet['Normal']) 1322 a(Paragraph("<u>Replicating a left indent underline bug.</u>",style=left_indent)) 1323 1324 #testing PR 49 1325 a(Paragraph("This paragraph contains <strike>really</strike> large <u>spaces</u> <strike color='blue' offset='1' width='0.5'><u color='red' offset='-1' width='0.5'>between words</u></strike>. ThisLongWordDoesntFitIntoPreviousLineCausingWordsSpread",style=normal_just)) 1326 1327 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_ul.pdf')) 1328 doc.build(story) 1329 1330class AutoLeadingTestCase(unittest.TestCase): 1331 "Test underlining and overstriking of paragraphs." 1332 def testAutoLeading(self): 1333 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1334 from reportlab.lib.units import inch 1335 from reportlab.platypus.flowables import AnchorFlowable 1336 class MyDocTemplate(BaseDocTemplate): 1337 _invalidInitArgs = ('pageTemplates',) 1338 1339 def __init__(self, filename, **kw): 1340 self.allowSplitting = 0 1341 kw['showBoundary']=1 1342 BaseDocTemplate.__init__(self, filename, **kw) 1343 self.addPageTemplates( 1344 [ 1345 PageTemplate('normal', 1346 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1347 ), 1348 ]) 1349 1350 from reportlab.lib.testutils import testsFolder 1351 styleSheet = getSampleStyleSheet() 1352 normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal']) 1353 normal_sp = ParagraphStyle(name='normal_sp',parent=normal,alignment=TA_JUSTIFY,spaceBefore=12) 1354 texts = ['''Furthermore, a subset of <font size="14">English sentences</font> interesting on quite 1355independent grounds is not quite equivalent to a stipulation to place 1356<font color="blue">the constructions <img src="%(testsFolder)s/../docs/images/testimg.gif"/> into these various categories.</font>'''%dict(testsFolder=testsFolder), 1357 '''We will bring <font size="18">Ugly Things</font> in favor of 1358The following thesis: most of the methodological work in Modern 1359Linguistics can be <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="baseline" /> defined in such <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="10" /> a way as to impose problems of 1360phonemic and <u>morphological <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="top"/> </u> analysis.'''%dict(testsFolder=testsFolder)] 1361 story =[] 1362 a = story.append 1363 t = 'u' 1364 n = 1 1365 for s in (normal,normal_sp): 1366 for autoLeading in ('','min','max'): 1367 a(Paragraph('style=%s(autoLeading=%s)'%(s.name,autoLeading),style=normal_sp)) 1368 a(Paragraph('<para autoleading="%s"><%s>%s</%s>. %s <%s>%s</%s>. %s</para>' % ( 1369 autoLeading, 1370 t,' '.join((n+1)*['A']),t,texts[0],t,' '.join((n+1)*['A']),t,texts[1]), 1371 style=s)) 1372 a(Paragraph('''<img src="%(testsFolder)s/../docs/images/testimg.gif" valign="top"/> image is very first thing in the line.'''%dict(testsFolder=testsFolder), style=normal)) 1373 a(Paragraph('some text.... some more.... some text.... some more....', normal)) 1374 a(Paragraph('<img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="0.19in" /> some text <br /> '%dict(testsFolder=testsFolder), normal)) 1375 a(Paragraph('some text.... some more.... some text.... some more....', normal)) 1376 a(Paragraph('<img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="0.19in" /> <br /> '%dict(testsFolder=testsFolder), normal)) 1377 a(Paragraph('some text.... some more.... some text.... some more....', normal)) 1378 1379 #Volker Haas' valign tests 1380 fmt = '''<font color="red">%(valign)s</font>: Furthermore, a <u>subset</u> <strike>of</strike> <font size="14">English sentences</font> interesting on quite 1381independent grounds is not quite equivalent to a stipulation to place <img src="%(testsFolder)s/../docs/images/redsquare.png" width="0.5in" height="0.5in" valign="%(valign)s"/> 1382the constructions into these <u>various</u> categories. We will bring <font size="18">Ugly Things</font> in favor of 1383The following thesis: most of the methodological work in Modern 1384Linguistics can be defined in such a way as to impose problems of 1385phonemic and <u>morphological</u> <strike>analysis</strike>.''' 1386 1387 p_style= ParagraphStyle('Normal') 1388 p_style.autoLeading = 'max' 1389 for valign in ( 1390 'baseline', 1391 'sub', 1392 'super', 1393 'top', 1394 'text-top', 1395 'middle', 1396 'bottom', 1397 'text-bottom', 1398 '0%', 1399 '2in', 1400 ): 1401 a(Paragraph(fmt % dict(valign=valign,testsFolder=testsFolder),p_style)) 1402 a(XPreformatted(fmt % dict(valign=valign,testsFolder=testsFolder),p_style)) 1403 1404 a(Paragraph('<br/><b>Some Paragraph tests of <sup rise="pts" size="pts"</b>...', normal)) 1405 a(Paragraph("<br/>This is a <sup><span color='red'>sup</span></sup>.",p_style)) 1406 a(XPreformatted("This is a <sup><span color='red'>sup</span></sup>.",p_style)) 1407 a(Paragraph("This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.",p_style)) 1408 a(XPreformatted("This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.",p_style)) 1409 a(Paragraph("This is a <sup rise=6><span color='red'>sup</span></sup>rise=6.",p_style)) 1410 a(XPreformatted("This is a <sup rise=6><span color='red'>sup</span></sup>rise=6.",p_style)) 1411 a(Paragraph("This is a <sup rise=7><span color='red'>sup</span></sup>rise=7.",p_style)) 1412 a(XPreformatted("This is a <sup rise=7><span color='red'>sup</span></sup>rise=7.",p_style)) 1413 a(Paragraph("This is a <sup rise=8><span color='red'>sup</span></sup>rise=8.",p_style)) 1414 a(XPreformatted("This is a <sup rise=8><span color='red'>sup</span></sup>rise=8.",p_style)) 1415 a(Paragraph("This is a <sup rise=9><span color='red'>sup</span></sup>rise=9.",p_style)) 1416 a(XPreformatted("This is a <sup rise=9><span color='red'>sup</span></sup>rise=9.",p_style)) 1417 a(Paragraph("This is a <sup size=7><span color='red'>sup</span></sup>size=7.",p_style)) 1418 a(XPreformatted("This is a <sup size=7><span color='red'>sup</span></sup>size=7.",p_style)) 1419 a(Paragraph("This is a <sup rise=5 size=7><span color='red'>sup</span></sup>rise=5 size=7.",p_style)) 1420 a(XPreformatted("This is a <sup rise=5 size=7><span color='red'>sup</span></sup>rise=5 size=7.",p_style)) 1421 a(Paragraph("This is a <sup rise=6 size=7><span color='red'>sup</span></sup>rise=6 size=7.",p_style)) 1422 a(XPreformatted("This is a <sup rise=6 size=7><span color='red'>sup</span></sup>rise=6 size=7.",p_style)) 1423 a(Paragraph("This is a <sup rise=7 size=7><span color='red'>sup</span></sup>rise=7 size=7.",p_style)) 1424 a(XPreformatted("This is a <sup rise=7 size=7><span color='red'>sup</span></sup>rise=7 size=7.",p_style)) 1425 a(Paragraph("This is a <sup rise=8 size=7><span color='red'>sup</span></sup>rise=8 size=7.",p_style)) 1426 a(XPreformatted("This is a <sup rise=8 size=7><span color='red'>sup</span></sup>rise=8 size=7.",p_style)) 1427 a(Paragraph("This is a <sup rise=9 size=7><span color='red'>sup</span></sup>rise=9 size=7.",p_style)) 1428 a(XPreformatted("This is a <sup rise=9 size=7><span color='red'>sup</span></sup>rise=9 size=7.",p_style)) 1429 a(Paragraph("This is a <sup rise=90% size=70%><span color='red'>sup</span></sup>rise=90% size=70%.",p_style)) 1430 a(Paragraph("This is a <sup rise=-2 size=-2><span color='red'>sup</span></sup>rise=-2 size=-2.",p_style)) 1431 a(Paragraph("This is a <sup rise=-4 size=-3><span color='red'>sup</span></sup>rise=-4 size=-3.",p_style)) 1432 a(PageBreak()) 1433 1434 a(Paragraph('<br/><b>Some Paragraph tests of <img width="x%" height="x%"</b>...', normal)) 1435 a(Paragraph('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normal)) 1436 a(Paragraph('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normal)) 1437 a(Paragraph('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1438 a(Paragraph('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1439 a(Paragraph('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1440 a(Paragraph('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normal)) 1441 a(Paragraph('<br/><b>Some XPreformatted tests of <img width="x%" height="x%"</b>...', normal)) 1442 a(XPreformatted('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normal)) 1443 a(XPreformatted('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normal)) 1444 a(XPreformatted('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1445 a(XPreformatted('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1446 a(XPreformatted('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normal)) 1447 a(XPreformatted('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normal)) 1448 a(Paragraph('<br/><b>Some CJK Paragraph tests of <img width="x%" height="x%"</b>...', normal)) 1449 normalCJK = ParagraphStyle('normalCJK', parent=normal, wordWrap = 'CJK') 1450 a(Paragraph('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1451 a(Paragraph('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1452 a(Paragraph('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1453 a(Paragraph('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1454 a(Paragraph('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1455 a(Paragraph('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normalCJK)) 1456 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_autoleading.pdf')) 1457 doc.build(story) 1458 1459def alphaSortedItems(d): 1460 return (i[1] for i in sorted((j[0].lower(),j) for j in d.items())) 1461 1462def tentities(title, b, fn): 1463 from reportlab.platypus.paraparser import greeks 1464 from reportlab.platypus.doctemplate import SimpleDocTemplate 1465 from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont, registerFontFamily 1466 from reportlab.pdfbase.ttfonts import TTFont 1467 from reportlab.platypus.tables import TableStyle, Table 1468 from reportlab.platypus.paragraph import Paragraph 1469 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 1470 from reportlab import ascii 1471 1472 for v in DEJAVUSANS: 1473 registerFont(TTFont(v,v+'.ttf')) 1474 registerFontFamily(*(DEJAVUSANS[:1]+DEJAVUSANS)) 1475 1476 def bu(s): 1477 return asUnicode(s) if not b else asBytes(s) 1478 1479 bt = getSampleStyleSheet()['BodyText'] 1480 bt.fontName = 'DejaVuSans' 1481 doc = SimpleDocTemplate(fn) 1482 story = [Paragraph('<b>%s</b>' % asNative(title),bt)] 1483 story.extend([Paragraph(bu('&%s; = <span color="red">&%s;</span>' % (k,k)), bt) for k, v in alphaSortedItems(greeks)]) 1484 doc.build(story) 1485 1486class JustifyTestCase(unittest.TestCase): 1487 "Test justification of paragraphs." 1488 def testUl(self): 1489 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1490 from reportlab.lib.units import inch 1491 class MyDocTemplate(BaseDocTemplate): 1492 _invalidInitArgs = ('pageTemplates',) 1493 1494 def __init__(self, filename, **kw): 1495 self.allowSplitting = 0 1496 BaseDocTemplate.__init__(self, filename, **kw) 1497 self.addPageTemplates( 1498 [ 1499 PageTemplate('normal', 1500 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1501 ), 1502 ]) 1503 1504 styleSheet = getSampleStyleSheet() 1505 normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal']) 1506 normal_just = ParagraphStyle(name='normal_just',parent=normal,alignment=TA_JUSTIFY,spaceAfter=12) 1507 text0 = '''Furthermore, a subset of English sentences interesting on quite 1508independent grounds is not quite equivalent to a stipulation to place 1509the constructions into these various categories. We will bring evidence in favor of 1510The following thesis: most of the methodological work in modern 1511linguistics can be defined in such a way as to impose problems of 1512phonemic and morphological analysis.''' 1513 story =[] 1514 a = story.append 1515 for mode in (0,1,2,3,4,5,6,7): 1516 text = text0 1517 paraStyle = normal_just 1518 if mode==1: 1519 text = text.replace('English sentences','<b>English sentences</b>').replace('quite equivalent','<i>quite equivalent</i>') 1520 text = text.replace('the methodological work','<b>the methodological work</b>').replace('to impose problems','<i>to impose problems</i>') 1521 a(Paragraph('Justified paragraph in normal/bold/italic font',style=normal)) 1522 elif mode==2: 1523 text = '<b>%s</b>' % text 1524 a(Paragraph('Justified paragraph in bold font',style=normal)) 1525 elif mode==3: 1526 text = '<i>%s</i>' % text 1527 a(Paragraph('Justified paragraph in italic font',style=normal)) 1528 elif mode==4: 1529 text = text.replace('English ','English ').replace('quite ','quite ') 1530 text = text.replace(' methodological',' methodological').replace(' impose',' impose') 1531 a(Paragraph('Justified paragraph in normal font & some hard spaces',style=normal)) 1532 elif mode in (5,6,7): 1533 text = text.replace('as to impose','<br/>as to impose').replace(' most of the','<br/>most of the') 1534 text = text.replace(' grounds','<br/>grounds').replace(' various','<br/>various') 1535 if mode in (6,7): 1536 msg = [] 1537 msg.append('justifyBreaks=1') 1538 paraStyle = paraStyle.clone('paraStyle6',paraStyle,justifyBreaks=1) 1539 if mode==7: 1540 msg.append('justifyLastLine=3') 1541 paraStyle = paraStyle.clone('paraStyle7',paraStyle,justifyLastLine=3) 1542 msg = '(%s) ' % (' '.join(msg)) 1543 else: 1544 a(PageBreak()) 1545 msg = ' ' 1546 1547 a(Paragraph('Justified%swith some <br/> tags' % msg,style=normal)) 1548 else: 1549 a(Paragraph('Justified paragraph in normal font',style=normal)) 1550 1551 a(Paragraph(text,style=paraStyle)) 1552 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_just.pdf')) 1553 doc.build(story) 1554 1555 def testAutoPageTemplate(self): 1556 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1557 from reportlab.lib.units import inch 1558 class onPage: 1559 def __init__(self,label): 1560 self.label = label 1561 def __call__(self,canv,doc): 1562 canv.drawString(72,72,'This is pageTemplate(%s)' % (self.label,)) 1563 class MyDocTemplate(BaseDocTemplate): 1564 _invalidInitArgs = ('pageTemplates',) 1565 1566 def __init__(self, filename, **kw): 1567 self.allowSplitting = 0 1568 BaseDocTemplate.__init__(self, filename, **kw) 1569 self.addPageTemplates( 1570 [ 1571 PageTemplate('normal', 1572 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1573 onPage = onPage('normal'), 1574 ), 1575 PageTemplate('auto', 1576 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1577 onPage = onPage('auto'), 1578 autoNextPageTemplate = 'autoFollow', 1579 ), 1580 PageTemplate('autoFollow', 1581 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))], 1582 onPage = onPage('autoFollow'), 1583 ), 1584 ]) 1585 styleSheet = getSampleStyleSheet() 1586 normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal']) 1587 story =[] 1588 a = story.append 1589 a(Paragraph('should be on page template normal', normal)) 1590 a(NextPageTemplate('auto')) 1591 a(PageBreak()) 1592 a(Paragraph('should be on page template auto', normal)) 1593 a(PageBreak()) 1594 a(DocAssert('doc.pageTemplate.id=="autoFollow"','expected doc.pageTemplate.id=="autoFollow"')) 1595 a(Paragraph('should be on page template autoFollow 1', normal)) 1596 a(PageBreak()) 1597 a(Paragraph('should be on page template autoFollow 2', normal)) 1598 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_AutoNextPageTemplate.pdf')) 1599 doc.build(story) 1600 1601 def testParaBrFlowing(self): 1602 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1603 from reportlab.lib.units import inch 1604 class MyDocTemplate(BaseDocTemplate): 1605 _invalidInitArgs = ('pageTemplates',) 1606 1607 def __init__(self, filename, **kw): 1608 self.allowSplitting = 0 1609 BaseDocTemplate.__init__(self, filename, **kw) 1610 self.addPageTemplates( 1611 [ 1612 PageTemplate('normal', 1613 [ 1614 Frame(inch, 4.845*inch, 3*inch, 3.645*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1615 Frame(4.27*inch, 4.845*inch, 3*inch, 3.645*inch, id='second',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1616 Frame(inch, inch, 3*inch, 3.645*inch, id='third',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1617 Frame(4.27*inch, inch, 3*inch, 3.645*inch, id='fourth',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")) 1618 ], 1619 ), 1620 ]) 1621 styleSheet = getSampleStyleSheet() 1622 normal = ParagraphStyle(name='normal',fontName='Helvetica',fontSize=10,leading=12,parent=styleSheet['Normal']) 1623 bold = ParagraphStyle(name='bold',fontName='Helvetica-Bold',fontSize=12,leading=14.4,parent=normal) 1624 brText=u""" 1625Clearly, the natural general principle that will subsume this case is 1626not subject to a parasitic gap construction. Presumably, most of the 1627methodological work in modern linguistics can be defined in such a way 1628as to impose the system of base rules exclusive of the lexicon. In the 1629discussion of resumptive pronouns following (81), the fundamental error 1630of regarding functional notions as categorial is to be regarded as a 1631descriptive <span color="red">fact</span>.<br/>So far, the earlier discussion of deviance is not 1632quite equivalent to a parasitic gap construction. To characterize a 1633linguistic level L, a case of semigrammaticalness of a different sort 1634may remedy and, at the same time, eliminate irrelevant intervening 1635contexts in selectional <span color="red">rules</span>.<br/> 1636Summarizing, then, we assume that the descriptive power of the base 1637component can be defined in such a way as to impose nondistinctness in 1638the sense of distinctive feature theory. A lot of sophistication has 1639been developed about the utilization of machines for complex purposes, 1640the notion of level of grammaticalness delimits an abstract underlying 1641<span color="red">order</span>.<br/>To provide a constituent structure for T(Z,K), a subset of 1642English sentences interesting on quite independent grounds appears to 1643correlate rather closely with problems of phonemic and morphological 1644analysis. For one thing, this analysis of a formative as a pair of sets 1645of features is rather different from a general convention regarding the 1646forms of the grammar. A lot of sophistication has been developed about 1647the utilization of machines for complex purposes, a case of 1648semigrammaticalness of a different sort is not to be considered in 1649determining an important distinction in language <span color="red">use</span>.<br/> 1650We will bring evidence in favor of the following thesis: a subset of 1651English sentences interesting on quite independent grounds delimits a 1652descriptive <span color="red">fact</span>.<br/>To characterize a linguistic level L, the notion of 1653level of grammaticalness is not to be considered in determining a 1654parasitic gap construction. It must be emphasized, once again, that the 1655speaker-hearer's linguistic intuition can be defined in such a way as to 1656impose a stipulation to place the constructions into these various 1657categories. On our assumptions, the appearance of parasitic gaps in 1658domains relatively inaccessible to ordinary extraction raises serious 1659doubts about problems of phonemic and morphological analysis. For one 1660thing, the fundamental error of regarding functional notions as 1661categorial is not quite equivalent to a stipulation to place the 1662constructions into these various <span color="red">categories</span>.<br/> 1663Thus the descriptive power of the base component is unspecified with 1664respect to the strong generative capacity of the theory. Presumably, 1665the theory of syntactic features developed earlier appears to correlate 1666rather closely with a corpus of utterance tokens upon which conformity 1667has been defined by the paired utterance test. To provide a constituent 1668structure for T(Z,K), a case of semigrammaticalness of a different sort 1669is not to be considered in determining the ultimate standard that 1670determines the accuracy of any proposed grammar. For any transformation 1671which is sufficiently diversified in application to be of any interest, 1672a subset of English sentences interesting on quite independent grounds 1673raises serious doubts about the requirement that branching is not 1674tolerated within the dominance scope of a complex symbol. We will bring 1675evidence in favor of the following thesis: an important property of 1676these three types of EC is not to be considered in determining the 1677system of base rules exclusive of the <span color="red">lexicon</span>.<br/> 1678With this clarification, the descriptive power of the base component is 1679not subject to the requirement that branching is not tolerated within 1680the dominance scope of a complex <span color="red">symbol</span>.<br/>In the discussion of 1681resumptive pronouns following (81), this selectionally introduced 1682contextual feature does not readily tolerate a parasitic gap 1683construction. Another superficial similarity is the interest in 1684simulation of behavior, a descriptively adequate grammar does not affect 1685the structure of a corpus of utterance tokens upon which conformity has 1686been defined by the paired utterance <span color="red">test</span>.<br/>From C1, it follows that the 1687speaker-hearer's linguistic intuition is not to be considered in 1688determining the traditional practice of grammarians. Let us continue to 1689suppose that the notion of level of grammaticalness is necessary to 1690impose an interpretation on the system of base rules exclusive of the 1691<span color="red">lexicon</span>.<br/> 1692""" 1693 story =[] 1694 a = story.append 1695 a(Paragraph('Paragraph Flowing', bold)) 1696 a(Paragraph(brText, normal)) 1697 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_para_br_flowing.pdf')) 1698 doc.build(story) 1699 1700 def testParaNBSP(self): 1701 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin 1702 from reportlab.lib.units import inch 1703 class MyDocTemplate(BaseDocTemplate): 1704 _invalidInitArgs = ('pageTemplates',) 1705 1706 def __init__(self, filename, **kw): 1707 self.allowSplitting = 0 1708 BaseDocTemplate.__init__(self, filename, **kw) 1709 self.addPageTemplates( 1710 [ 1711 PageTemplate('normal', 1712 [ 1713 Frame(inch, 4.845*inch, 3*inch, 3.645*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1714 Frame(4.27*inch, 4.845*inch, 3*inch, 3.645*inch, id='second',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1715 Frame(inch, inch, 3*inch, 3.645*inch, id='third',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")), 1716 Frame(4.27*inch, inch, 3*inch, 3.645*inch, id='fourth',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")) 1717 ], 1718 ), 1719 ]) 1720 styleSheet = getSampleStyleSheet() 1721 normal = ParagraphStyle(name='normal',fontName='Helvetica',fontSize=10,leading=12,parent=styleSheet['Normal']) 1722 bold = ParagraphStyle(name='normal',fontName='Helvetica-Bold',fontSize=10,leading=12,parent=styleSheet['Normal']) 1723 registerFontFamily('Helvetica','Helvetica','Helvetica-Bold','Helvetica-Oblique','Helvetica-BoldOblique') 1724 story =[] 1725 a = story.append 1726 a(Paragraph('Paragraph Hard Space Handling', bold)) 1727 a(Paragraph(''' <span backcolor="pink">ABCDEFGHI</span> ''', normal)) 1728 a(Paragraph(''' <span backcolor="palegreen"> ABCDEFGHI </span> ''', normal)) 1729 a(Paragraph('''<span backcolor="lightblue"> </span>''', normal)) 1730 a(Paragraph('''<span backcolor="lightblue"> </span><span backcolor="palegreen"> </span> ''', normal)) 1731 a(Paragraph('''<span backcolor="pink"><b>A</b></span><span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal)) 1732 a(Paragraph('''<span backcolor="pink"><b>A</b></span> <span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal)) 1733 a(Paragraph('''<span backcolor="pink"><b>A</b></span><span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal)) 1734 a(Paragraph('''<span backcolor="pink"><b>A</b></span> <span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal)) 1735 doc = MyDocTemplate(outputfile('test_platypus_paragraphs_nbsp.pdf')) 1736 doc.build(story) 1737 1738 @unittest.skipUnless(haveDejaVu(),'s') 1739 def testParaEntities(self): 1740 tentities(b'unicode formatted paragraphs',False,outputfile('test_platypus_unicode_paragraph_entities.pdf')) 1741 tentities(b'byte formatted paragraphs',True,outputfile('test_platypus_bytes_paragraph_entities.pdf')) 1742 1743 def testXPreUnderlining(self): 1744 styleSheet = getSampleStyleSheet() 1745 bt = styleSheet['BodyText'] 1746 story = [ 1747 XPreformatted("xpre<u><font size='1' color='red'>SS</font> </u>",bt), 1748 XPreformatted("xpre<u><font size='1' color='red'>SS</font> </u>|",bt), 1749 XPreformatted("<u><font size='1' color='red'>SS</font> </u>",bt), 1750 XPreformatted("<u><font size='1' color='red'>SS</font> </u>|",bt), 1751 ] 1752 doc = MyDocTemplate(outputfile('test_platypus_XPreUnderlining.pdf')) 1753 doc.build(story) 1754 1755#noruntests 1756def makeSuite(): 1757 return makeSuiteForClasses(ParagraphCorners,SplitFrameParagraphTest,FragmentTestCase, ParagraphSplitTestCase, ULTestCase, JustifyTestCase, 1758 AutoLeadingTestCase) 1759 1760#noruntests 1761if __name__ == "__main__": 1762 unittest.TextTestRunner().run(makeSuite()) 1763 printLocation() 1764