Jason Harrop created FOP-3355:
---------------------------------
Summary: A side float ends one line too late when a space carries
the next line below its foot, and the space at the float's edge is discarded
Key: FOP-3355
URL: https://issues.apache.org/jira/browse/FOP-3355
Project: FOP
Issue Type: Bug
Components: layout/page
Affects Versions: main, 2.11
Reporter: Jason Harrop
A side float (fo:float float="left") is ended by
PageBreakingAlgorithm.handleBox: the first line box at which the accumulated
height reaches the float's height sets handlingEndOfFloat, and the next legal
break is the float's edge, after which the content is read again at full width
(PageBreaker.handleFloatLayout). Glue is added to the accumulated height
(BreakingAlgorithm.handleGlueAt) but never runs that test. So when the float's
foot falls in the space between two paragraphs, the next paragraph's first line
is still laid out beside the float, although it lies wholly below it.
Minimal FO (A4, 72pt margins, Times 12pt):
{noformat}
<fo:block line-height="16pt" space-after="10pt"><fo:float
float="left"><fo:block line-height="20pt"
padding-end="200pt">BOX</fo:block></fo:float>Heading</fo:block>
<fo:block line-height="16pt">word0 word1 ... word29</fo:block>
{noformat}
The float's foot is at y 92pt. The second paragraph's first line spans 98 to
114, wholly below it, and is set at x 297.3, narrowed by the float; it should
be at x 72.
A second defect at the same edge: when the edge falls on a paragraph boundary
(line-height="20pt" on the heading, so its line itself reaches the foot), the
heading's space-after is lost and the next paragraph starts at 92, not 102.
PageBreaker.addAreasForFloats notifies the SpaceResolver of the edge as a break
(performConditionalsNotification with the edge penalty as the end), so the
conditional space is discarded as at a page break, and the restarted list
begins at the next box. The space-before of the paragraph after the float is
lost the same way: the restarted block is reset and its leading space resolved
as at the start of a page.
*Fix (pull request to follow)*
# PageBreakingAlgorithm.considerLegalBreak: while a float is in force, the
float ends at a legal break if the content height before it plus the glue up to
the next box (as forceNode measures a node) reaches the float's height;
deactivateNode records that height as the float's, so the content after it
starts below the space.
# PageBreaker.addAreasForFloats: the SpaceResolver notification runs to the
last glue before the next box, so the edge's break position is told it is no
break and the space between the paragraphs is resolved and kept.
# The block the list is read again from after the edge keeps the space-before
resolved in the list before and emits none: a LayoutContext.FLOAT_RESTART flag
(a bit of its own), set by PageBreaker and handed by FlowLayoutManager to that
block only, read in BlockStackingLayoutManager.addFirstVisibleMarks and
BlockLayoutManager.
Measured on main with the change: the first line after the space at x 72, y 98;
with the heading line reaching the foot, the next paragraph at 102, the space
kept; the space kept as space-before too. Layout engine test
float_edge-after-space.xml, whose first check fails before. The fop-core suite
passes (3682 tests) and checkstyle is clean.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)