Inline Formatting Context (IFC)
The inline formatting context handles mixed text and inline-block children. When a block-level element's children are all inline-level (display: inline or text nodes), the engine builds line boxes.
Line-Box Layout
For a mixed inline context, the engine:
- Collects each child into an
InlineLayoutstruct (text runs via shape, inline-blocks via recursive layout). - Builds a list of
Lineobjects, each containing a slice ofInlineLayoutitems. - Word-wraps each line at the container width, breaking between inline items and at soft-break opportunities within text runs.
- Sizes each line's height from the maximum ascent + descent across its items.
- Vertically aligns items within the line baseline.
struct Line {
items: Vec<InlineLayout>,
width: f32,
ascent: f32,
descent: f32,
y: f32,
}
Word Wrapping
Text runs are shaped with an optional max_width_px. When wrapping is enabled (non-pre white-space), cosmic-text inserts word-boundary breaks. The IFC layer additionally handles wrapping between inline-block elements — when the current line overflows, a new line box starts.
text-align
text-align is applied per line box:
text-align: left | right | center | justify;
Each line's items are shifted horizontally within the container width. For single-text-leaf paragraphs, the entire ShapedRun is translated — a heuristic since proper per-line alignment requires per-line glyph repositioning.
let align_dx = horizontal_align_offset(text_align, container_w, line_width);
Inline-Block Elements
display: inline-block elements are laid out as block boxes but placed inline within the line flow. Each inline-block:
- Is laid out recursively at its content size.
- Contributes its margin box height to the line's ascent/descent.
- Can be broken across lines only if it is wider than the remaining line space.
Anonymous Text Runs
Raw text nodes (those not wrapped in an element) produce anonymous text leaves. Each text leaf:
- Has its
font-family,font-size,font-weight,font-style,color, andletter-spacingresolved from the cascaded style (inherited from ancestors). - Is shaped via
TextContext::shape_and_pack(). - Is placed as a
BoxKind::Textwith the shaped run intext_run.
Rich-Text Paragraph Shaping
When a block contains multiple inline children (e.g., <span>bold</span> normal <em>italic</em>), the engine uses a rich-text path:
- Flattens the inline subtree into
(text, Attrs)spans. - Feeds them to cosmic-text via
set_rich_text()— word-boundary breaks land between spans while preserving per-span attributes. - Re-expands the result into anonymous block boxes for per-line backgrounds and
BoxKind::Textleaves for glyphs, with per-glyph color baked in byshape_paragraph.
Example
<div style="width: 400px; text-align: justify; line-height: 1.6;">
<strong>Bold intro:</strong>
This paragraph has <em>mixed formatting</em>
and an inline-block <span style="display:inline-block;
width:80px; height:30px; background:#ddd;"></span> in the flow.
</div>
The result is a justified 400px-wide block with bold, italic, and normal text on the same lines, plus the 80×30 inline-block aligned to the text baseline.