This issue tracks the implementation of CSS Floats in Parley (/API enhancements that enable CSS Floats to be implemented on top of Parley).
Code Flow
If we go with the latter option (APIs that enable Floats to implemented on top of Parley) then I think the requirements for Parley itself might actually be quite simple. Parley would need to:
Allow the max_advance to be set independently for each line
When a float is present it takes up space meaning that the line is effectively shorter as far as line-breaking is concerned.
Allow each line's Y position to set as a parameter.
Floats may take up all of the space in a line, meaning a line should start further down that it otherwise should.
Allow each line to have an horizontal offset (set externally).
This would be similar to the offset used for end/center alignment, but would be in addition to it (this is to account for left floats which cause the text on lines they intersect to be shifted to the right).
To be able to yield control flow when a "floated box" is encountered in the layout. A "floated box" would be specified like the existing "inline boxes" but a simple enum field would be added to specify whether the box is "inline" or "floated".
Parley would not necessarily need to be able to compute the correct position for the box. But it should yield to external code, making available the following information:
The id of the box
The Y position of the top of the current line
The X advance where the next glyph would be placed if it fit on the current line
The remaining space in the current line.
Use the per-line max_advance (or a separately specified alignment width) for alignment
The wider layout engine (that handles both box layout and text layout) would then be responsible for:
Computing the correct position of the floated box
Fixing up the max_advance and offset of the current line. Parley would be able to rely on the invariant that the new max_advance would be greater than the already-consumed space (and should perhaps enforce that).
Either:
Resuming layout of the current line
Commit the current line and starting layout of a new line
Parley API
In concrete API terms this would probably look like:
Float layout would be feature flagged
BreakLines::break_next would layout up to "the end of the line OR the next floated box". Returning the reason for which it has yielded (line end or floated box).
There would be a new method on BreakLines allowing callers to access the current state of the breaker for the purpose of positioning floated boxes (making this a separate method would keep it out of the way for the float-free case).
There would be methods on BreakLines to set the offset and max_advance of the current line. And to commit the current line.
BreakLines::break_remaining would become the simple implementation ignoring floats
Either a new method like break_remaining but float-aware would be added. Or it would be left up to external code to implement this itself on top of break_next.
Appendix A: The position of the floated box
The position of the floated box would be either:
At the end of the current line (the box fits on the current line and is float: right). In this case:
The line is shortened by the with of the box
Text layout (by parley) of the line is continued.
At the start of the current line (the box fits on the current line and is float: left). In this case:
The line is shortened by the width of the box
The line is offset by the width of the box
Text layout (by parley) of the line is continued.
At the start/end of the next line (the box does not fit on the current line). In this case:
The line is not altered but it is marked as a completed and a new line is started
External layout code will need to be able to specify the start Y position for the new line
External layout code may offset/shorten the new line prior to starting layout to account for tall floats from earlier in the layout that are already taking up space in the next line.
This issue tracks the implementation of CSS Floats in Parley (/API enhancements that enable CSS Floats to be implemented on top of Parley).
Code Flow
If we go with the latter option (APIs that enable Floats to implemented on top of Parley) then I think the requirements for Parley itself might actually be quite simple. Parley would need to:
max_advance
to be set independently for each line When a float is present it takes up space meaning that the line is effectively shorter as far as line-breaking is concerned.offset
(set externally). This would be similar to the offset used for end/center alignment, but would be in addition to it (this is to account forleft
floats which cause the text on lines they intersect to be shifted to the right).To be able to yield control flow when a "floated box" is encountered in the layout. A "floated box" would be specified like the existing "inline boxes" but a simple enum field would be added to specify whether the box is "inline" or "floated".
Parley would not necessarily need to be able to compute the correct position for the box. But it should yield to external code, making available the following information:
max_advance
(or a separately specified alignment width) for alignmentThe wider layout engine (that handles both box layout and text layout) would then be responsible for:
max_advance
andoffset
of the current line. Parley would be able to rely on the invariant that the newmax_advance
would be greater than the already-consumed space (and should perhaps enforce that).Parley API
In concrete API terms this would probably look like:
BreakLines::break_next
would layout up to "the end of the line OR the next floated box". Returning the reason for which it has yielded (line end or floated box).BreakLines
allowing callers to access the current state of the breaker for the purpose of positioning floated boxes (making this a separate method would keep it out of the way for the float-free case).BreakLines
to set theoffset
andmax_advance
of the current line. And to commit the current line.BreakLines::break_remaining
would become the simple implementation ignoring floatsbreak_remaining
but float-aware would be added. Or it would be left up to external code to implement this itself on top ofbreak_next
.Appendix A: The position of the floated box
The position of the floated box would be either:
float: right
). In this case:float: left
). In this case: