Jason Harrop created FOP-3354:
---------------------------------
Summary: NoSuchElementException in LMiter.next when a side float's
end falls inside a table
Key: FOP-3354
URL: https://issues.apache.org/jira/browse/FOP-3354
Project: FOP
Issue Type: Bug
Components: layout/page
Affects Versions: main, 2.11
Reporter: Jason Harrop
When a side float outlasts the paragraph it is anchored in and the content
beside it continues into an fo:table, the float's end falls between two rows.
PageBreaker.handleFloatLayout then reads the element list again from that break
(FlowLayoutManager.getNextKnuthElements with a restart position inside the
table). TableLayoutManager cannot be restarted (isRestartable() is false, as
AbstractBreaker.containsNonRestartableLM checks for the IPD-change restart);
the generic restart in BlockStackingLayoutManager.getNextKnuthElements asks
setCurrentChildLM for the table's child layout manager, and the table's child
iterator, already exhausted, throws:
{noformat}
java.util.NoSuchElementException
at org.apache.fop.layoutmgr.LMiter.next(LMiter.java:69)
at org.apache.fop.layoutmgr.LMiter.next(LMiter.java:27)
at
org.apache.fop.layoutmgr.AbstractLayoutManager.setCurrentChildLM(AbstractLayoutManager.java:132)
at
org.apache.fop.layoutmgr.BlockStackingLayoutManager.getNextKnuthElements(BlockStackingLayoutManager.java:278)
at
org.apache.fop.layoutmgr.FlowLayoutManager.getNextChildElements(FlowLayoutManager.java:225)
at
org.apache.fop.layoutmgr.FlowLayoutManager.addChildElements(FlowLayoutManager.java:148)
at
org.apache.fop.layoutmgr.FlowLayoutManager.getNextKnuthElements(FlowLayoutManager.java:121)
at
org.apache.fop.layoutmgr.PageBreaker.getNextKnuthElements(PageBreaker.java:270)
at
org.apache.fop.layoutmgr.AbstractBreaker.getNextBlockList(AbstractBreaker.java:723)
at
org.apache.fop.layoutmgr.PageBreaker.getNextBlockList(PageBreaker.java:179)
at
org.apache.fop.layoutmgr.PageBreaker.handleFloatLayout(PageBreaker.java:822)
{noformat}
No output is produced. Minimal FO (A4, 72pt margins, Times 12pt):
{noformat}
<fo:block line-height="14pt" space-after="10pt"><fo:float
float="right"><fo:block line-height="40pt"
padding-start="200pt">BOX</fo:block></fo:float>Heading</fo:block>
<fo:table table-layout="fixed" width="200pt"
border-collapse="collapse"><fo:table-column column-width="200pt"/>
<fo:table-body>five of: <fo:table-row><fo:table-cell border="0.5pt
solid"><fo:block>cell N</fo:block>
</fo:table-cell></fo:table-row></fo:table-body></fo:table>
<fo:block>after</fo:block>
{noformat}
The 40pt float outlasts the heading's 14pt line and its 10pt space, so its end
falls after the second row. clear="both" on the table makes no difference.
*Fix (pull request to follow)*
PageBreakingAlgorithm.considerLegalBreak: a legal break between two boxes of
the same layout manager that cannot be restarted is not taken as the float's
edge; the edge waits for the first legal break after it. The rows below the
float keep the table's width, which the table set once for all its rows, so
nothing is drawn differently from a re-layout at the row, and the block after
the table is laid out at full width.
Measured on main with the change: the FO above lays out, five rows at the
table's width, "after" at full width below the table. Layout engine test
float_edge-inside-table.xml, which threw before. The fop-core suite passes
(3679 tests) and checkstyle is clean.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)