Skip to content

Vertical alignment and the concept of a "parent" font and style #291

@valadaptive

Description

@valadaptive

There was some discussion in #25 about 1) vertical alignment of inline boxes and 2) a tree-based vs. flat style structure. That discussion seemed to show a preference for a tree-based API, but #279 suggests that the layout algorithm will eventually want to operate on a flat list of style spans.

I need to implement some sort of vertical alignment for inline boxes, and ran into an API design issue when looking at the way CSS does it (and this library seems to have the goal of matching CSS' API).

I still don't fully understand the way that the CSS inline layout algorithm works, but vertical alignment of an "inline-level box" (in Parley's case, either an InlineBox or a span of text) is done relative to the baselines of its "parent". See 4. Baseline Alignment (emphasis mine):

While most CSS formatting contexts position content by aligning boxes with respect to their container’s edges, inline layout positions boxes in the block axis by aligning them with respect to each other using their baselines.

More specifically, (unless using a line-relative shift value) each glyph or inline-level box is aligned in the block axis by positioning its alignment baseline to match the corresponding baseline of its parent (which is its alignment context), and then is potentially shifted from that position according to its post-alignment shift.

When aligning a box, the alignment baseline is chosen according to its alignment-baseline and baseline-source values (see shorthand vertical-align), and defaults to matching the parent’s dominant-baseline. For a glyph, the alignment baseline is always determined by the parent’s dominant baseline.

When aligning inline boxes with other inline boxes, their baseline sets are also based on inherited font settings:

The first/last baseline set of a line box is generated from the dominant baseline and the font settings of its root inline box.

If my mental model of CSS is correct, then a workable API for Parley that would allow implementing HTML/CSS layout on top of it would be:

  • A Layout has an explicit "root style"/"parent style". Right now, RangedStyleBuilder and TreeStyleBuilder have a default and root style respectively, but they're conceptually treated the same as any other style node, when they need to be treated specially for the purpose of doing layout.
    • Beyond this, I think it's OK to use a flattened set of styled spans for everything else.
  • We can then use this "root style" to get the font metrics / baseline set for alignment purposes.
    • This implies that Style (or at least ResolvedStyle) should have an API for fetching font metrics (if only for use internally). Right now, there doesn't seem to be a way to get them until shaping actually occurs. They depend on font variations, but those will probably also be specified in Style.
  • Layout could have APIs to access its root style and its baseline sets.
  • InlineBox would allow you to specify its baseline sets. Combined with the above API, this would allow the API consumer to implement nested layout by recursively rendering Layouts inside-out, starting with the leaf nodes and turning them into InlineBoxes positioned in the higher-up Layouts.

Does this sound like a reasonable API surface?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions