You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by jg...@apache.org on 2026/10/14 17:28:33 UTC
(xmlgraphics-fop) branch main updated: FOP-3354 Fix NoSuchElementException when a side float whose end falls inside a table.
This is an automated email from the ASF dual-hosted git repository.
joao12021996 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/xmlgraphics-fop.git
The following commit(s) were added to refs/heads/main by this push:
new bed50fc76 FOP-3354 Fix NoSuchElementException when a side float whose end falls inside a table.
bed50fc76 is described below
commit bed50fc769d9eb54d77542b1481700d52d600df4
Author: Joao Goncalves <an...@gmail.com>
AuthorDate: Fri Oct 9 14:56:14 2026 -0500
FOP-3354 Fix NoSuchElementException when a side float whose end falls inside a table.
Co-authored-by: Jason Harrop <pl...@users.noreply.github.com>
---
.../fop/layoutmgr/PageBreakingAlgorithm.java | 47 +++++++++++++++++++
.../standard-testcases/float_edge-inside-table.xml | 53 ++++++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
index 925f69ea8..817f57127 100644
--- a/fop-core/src/main/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
+++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
@@ -514,10 +514,57 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
//nop
}
}
+ // A side float's edge is a break after which the content is read again from its layout manager,
+ // which a table cannot do (it is not restartable): a break between two boxes of one such layout
+ // manager is not the edge, which 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.
+ boolean edgeDeferred = handlingEndOfFloat && isInsideNonRestartableLM(elementIdx);
+ if (edgeDeferred) {
+ handlingEndOfFloat = false;
+ }
super.considerLegalBreak(element, elementIdx);
+ if (edgeDeferred) {
+ handlingEndOfFloat = true;
+ }
newFootnotes = false;
}
+ /** Whether the boxes either side of a break both belong to one layout manager that cannot be restarted. */
+ private boolean isInsideNonRestartableLM(int elementIdx) {
+ LayoutManager next = null;
+ for (int i = elementIdx; i < par.size() && next == null; i++) {
+ KnuthElement e = getElement(i);
+ if (e.isBox()) {
+ next = nonRestartableLM(e.getPosition());
+ if (next == null) {
+ return false;
+ }
+ }
+ }
+ if (next == null) {
+ return false;
+ }
+ for (int i = elementIdx - 1; i >= 0; i--) {
+ KnuthElement e = getElement(i);
+ if (e.isBox()) {
+ return next == nonRestartableLM(e.getPosition());
+ }
+ }
+ return false;
+ }
+
+ /** The outermost layout manager in a position's chain that cannot be restarted, or null. */
+ private static LayoutManager nonRestartableLM(Position position) {
+ for (Position p = position; p != null; p = p.getPosition()) {
+ LayoutManager lm = p.getLM();
+ if (lm != null && !lm.isRestartable()) {
+ return lm;
+ }
+ }
+ return null;
+ }
+
/** {@inheritDoc} */
@Override
protected boolean elementCanEndLine(KnuthElement element, int line, int difference) {
diff --git a/fop/test/layoutengine/standard-testcases/float_edge-inside-table.xml b/fop/test/layoutengine/standard-testcases/float_edge-inside-table.xml
new file mode 100644
index 000000000..e1c87e663
--- /dev/null
+++ b/fop/test/layoutengine/standard-testcases/float_edge-inside-table.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+
+ <info>
+ <p>
+ A side float outlasts the paragraph it is anchored in and its space-after, so its end falls between two
+ rows of the table after it. A table cannot be read again from a row, so the float's edge waits for the
+ first break after the table: the rows keep the table's width, and the block after the table is laid out
+ at full width. Before, this threw NoSuchElementException in LMiter.next.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page" page-width="595pt" page-height="842pt" margin="72pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" font-family="Times" font-size="12pt">
+ <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><fo:table-row><fo:table-cell border="0.5pt solid"><fo:block>cell 1</fo:block></fo:table-cell></fo:table-row><fo:table-row><fo:table-cell border="0.5pt solid"><fo:block>cell 2</fo:block></fo:table-cell></fo:table-row><fo:table-row><fo:table-cell border="0.5pt solid"><fo:block>cell 3</fo:block></fo:table-cell></fo:table-row><fo:table-row><fo:table-cell border="0.5pt solid"><fo:block>cell 4</fo:block></fo:table-cell></fo:table-row><fo:table-row><fo:tab [...]
+ </fo:table>
+ <fo:block>after</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="5" xpath="count(//word[. = 'cell'])"/>
+ <eval expected="451000" xpath="//lineArea[text/word = 'after']/../@ipd"/>
+ <eval expected="185012" xpath="//lineArea[text/word = 'Heading']/@end-indent"/>
+ </checks>
+</testcase>
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org