Skip to content

Support inline box layout #25

@nicoburns

Description

@nicoburns

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 to LayoutContext
    • Add a push_inline_box(box: InlineBox) method RangedBuilder which pushes to the inline_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 to LayoutData.runs_or_boxes using the new enum
    • Update shape::shape_text to push inline boxes to LayoutData.runs_or_boxes
  • 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 to LayoutData.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)
  • Update alignment
    • Update BreakLines::finish to account for boxes when performing alignment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions