-
Notifications
You must be signed in to change notification settings - Fork 45
Description
Motivation
One may wish to mix textual and non-textual content and have the non-textual content laid out in flow with the text. For example, in order to display images or even whole widgets within paragraphs of text. This is necessary in order to implement web-style "inline/flow" layout, but it's use is not limited to web layout contexts: it is a feature that is more generally useful to anyone wishing to layout mixed content.
Notes
The functionality required from the text layout system in order to implement "inline layout" is laying out fixed size boxes, possibly with some kind of supplementary baseline alignment / vertical alignment information. There is no need for the text layout system to size such boxes.
Proposed Implementation
I think we can avoid involving inline boxes in ranged style resolution. Based on that assumption, my proposal is as follows:
- Update Builder
- Define:
struct InlineBox { /// The width and height of the box in pixels size: kurbo::Vec2, /// The index into the text string at which the box should be placed. index: usize, /// An arbitrary user-defined id that consumers of parley can use to determine /// which inline box is which in the resultant layout id: u64, }
- Add an
inline_boxes: Vec<InlineBox>
property toLayoutContext
- Add a
push_inline_box(box: InlineBox)
methodRangedBuilder
which pushes to theinline_boxes
property in the layout context - Sort the inline boxes by index in
RangedBuilder::finish
- Update run-splitting:
- Update
shape::shape_text
to break text runs at text indexes where an inline box is present (in addition to all of the places where it already does so). - Define:
enum RunOrBox { Run(RunData) Box(InlineBox) }
- Change
LayoutData.runs
toLayoutData.runs_or_boxes
using the new enum - Update
shape::shape_text
to push inline boxes toLayoutData.runs_or_boxes
- Update
- Update line breaking
- Define:
struct InlineBoxPosition { /// The x and y position of the box position: kurbo::Vec2, /// The unique id of the box id: u64, } enum LineRunOrBox { Run(LineRunData) Box(InlineBoxPosition) }
- Change
LayoutData.line_runs
toLayoutData.line_runs_or_boxes
using the new enum - Update
BreakLines::break_next
to account for inline boxes when line breaking. This should:- Compute an
(x, y)
location for the box (either global or line-relative) - Affect the position of subsequent runs of text
- Affect the line height of the line (flooring it by the box's height)
- Compute an
- Update alignment
- Update
BreakLines::finish
to account for boxes when performing alignment
- Update