[reportlab-users] Miscalculation when using keepWithNext

Robin Becker robin at reportlab.com
Thu Nov 18 04:49:03 EST 2021


........
>   * Spacer
>   * Table
>   * Spacer
>   * Heading
>   * Paragraph
> 
> The spacers have keepWithNext set to make sure that a heading before a bullet list/table works properly. As a side 
> effect the trailing spacer here will be tied to the following heading. The heading also has keepWithNext set.
> 
>> 2) As you say it would be better to overestimate the required height, but best would be to compute correctly, but that 
>> requires us to check for inclusion in a frame and to work out what the extra height requirement is. Actually we can 
>> find out when we have a frame above us and inspect  whether we are at the top of a frame and what if it would do at 
>> this point if we get added.
>>
>> The overall algorithm is badly designed, but it's probably far too late to adopt a better one.
>>
> 
> How so? The handling of keepWithNext is mostly internal to ReportLab, so it should be possibly to modify rather heavily 
> without affecting users?

I tried fairly hard to make an example like the one you suggest, but it's too complex to really allow easy diagnosis.

Looking at the internal code I was able to check that the KeepTogether class that is used to replace keepWidthNext does 
provide access to the space before and after attributes. Also at least in a really simple case it does work. In the 
example below the keepWithNext group has a height of 31. The heading stays with the body until the frame height, fh, 
falls below 31 ie the required height for the group. When that happens things just break. If you can supply a simple 
example I can try to make it go wrong. It's not clear whether it's using spacers that causes the issue, but I would 
argue that spaceBefore attributes handle that far better than fixed space as they can vanish.

############################################
from reportlab.platypus import BaseDocTemplate, PageTemplate, Flowable, FrameBreak, KeepTogether, PageBreak, Spacer, Frame
from reportlab.platypus import Paragraph, Preformatted
from reportlab.lib.styles import PropertySet, getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, cm
import sys
def test4():
	class Test4Template(BaseDocTemplate):
		_invalidInitArgs = ('pageTemplates',)
		def __init__(self, filename, **kw):
			fh = 12+10+12+7+12 #53 enough for all
			fh = 31 # just enough for the kwn group
			if len(sys.argv)>1:
				fh = float(sys.argv[1])
			frame1 = Frame(inch, 5.6*inch, 6*inch, fh, showBoundary=1, id='F1',
					leftPadding=0,rightPadding=0,topPadding=0,bottomPadding=0)
			frame2 = Frame(inch, 1.0*inch, 6*inch, fh, showBoundary=1,id='F2',
					leftPadding=0,rightPadding=0,topPadding=0,bottomPadding=0)
			BaseDocTemplate.__init__(self,filename,**kw)
			self.addPageTemplates(PageTemplate('normal',[frame1,frame2]))

	sty = ParagraphStyle('simple')
	def mpara(content,spaceBefore=0,spaceAfter=0,kwn=False):
		p = Paragraph(content,sty)
		p.spaceBefore = spaceBefore
		p.spaceAfter = spaceAfter
		p.keepWithNext = kwn
		return p

	story = [
			mpara('top para',8,6),
			mpara('header para',10,7,kwn=True),
			mpara('body para',6,6,kwn=False),
			]

	doc = Test4Template('/home/robin/devel/reportlab/REPOS/reportlab/tests/test_keepwithnext.pdf')
	doc.build(story)

if __name__=='__main__':
	test4()
############################################

I tried arguments 30.999, 31, 52 & 53; the first is the real failure case.

> 
> Regards


-- 
Robin Becker


More information about the reportlab-users mailing list