In keynote, line spacing is specified per-paragraph. Paragraphs are line-wrapped into physical lines.
For now, we're only interested in text boxes where spacing is specified in “lines.”
For a physical line β and a character γ:
- Dᵧ is the “hhea descender” of γ.
- Gᵧ is the “hhea line gap” of γ.
- Aᵦ is the max “hhea ascender” for all characters in β
- Dᵦ is the min “hhea descender” of all characters in β
- Eᵦ is the max of Gᵧ-Dᵧ over all characters γ on the line β:
- Lᵦ is the keynote line spacing in lines.
The distance between baselines i and i+1 is (Lᵢ-1)(Aᵢ - Dᵢ) + Eᵢ + Aᵢ₊₁
The distance from the top of text box to the baseline of line 0 is a constant A₀. Therefore, this distance should be represented by margin-top values on the content of the first non-empty descendant of the text box that is a block element.
Note that there's really no way to account for differences in this value
across span-level elements, even using display: inline-block
, unless you
can be sure that the lines don't wrap.
However, some text boxes, such as headings, aren't expressed in HTML using any embedded block elements. In these cases, the top margin of the absolutely-positioned element can be used to create the top-of-box gap (https:stackoverflow.com/questions/25944865/why-does-margin-top-affect-the-placement-of-an-absolute-div). Fortunately this seems to function exactly as a non-absolutely-posititioned child <p>'s top margin would be used.
Keynote has an absolute paragraph above/below spacing setting that acts roughly like top/bottom margins do in CSS, except that they have no effect at the top or bottom of a text box. These spacing values are added to any line spacing that would ordinarily be in effect across the last/first lines of adjacent paragraphs.
Keynote text boxes rendered in HTML are formatted with position: absolute
in order to match placement. Absolutely-positioned elements are not
subject to margin collapsing, which means any top margin on the text box's
first child, along with the box's own padding, regulates the child's vertical
position within the box.
Keynote's “text inset” setting corresponds exactly to CSS padding, and applies to the whole text box, on all sides.
Text that is part of the Keynote layout is generated using CSS text injection on ::before and ::after pseudo-elements. Because pseudo-elements don't get their own ::before and ::after elements, “trim” amounts need to be built into their positioning, margins, or padding.