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)

Reply via email to