~jaro/balkon

13b3a637336eb3490d6379a76472c90e54a1c01b — Jaro 10 months ago 0cf536e
Store vertical offsets inside ProtoFragment.

Intended to make these offsets manipulable during layout.
M src/Data/Text/ParagraphLayout/Internal/Layout.hs => src/Data/Text/ParagraphLayout/Internal/Layout.hs +29 -28
@@ 189,33 189,7 @@ positionFragmentH line originY originX (WithBoxes lbs (WithSpan rs pf) rbs) =
            , VO.baseline = baseline
            , VO.fontBottom = fontBottom
            , VO.layoutBottom = layoutBottom
            } = VO.alignLayoutTop originY $ verticalOffsets (WithSpan rs pf)

-- | Vertical offsets for the given fragment, with baseline set to 0.
verticalOffsets :: ProtoFragmentWithSpan d -> VO.VerticalOffsets
verticalOffsets (WithSpan rs pf) = VO.VerticalOffsets
    { VO.layoutTop = ascent + topHalfLeading
    , VO.fontTop = ascent
    , VO.baseline = 0
    , VO.fontBottom = - descent
    , VO.layoutBottom = - descent - bottomHalfLeading
    }
    where
        -- non-negative leading values iff `lineHeight` > `normalLineHeight`
        leading = lineHeight - normalLineHeight
        topHalfLeading = -((-leading) `div` 2)
        bottomHalfLeading = leading `div` 2
        -- `normalLineHeight` > 0 for horizontal fonts
        normalLineHeight = ascent + descent
        -- `ascent` >= 0 for horizontal fonts
        ascent = ascender extents
        -- `descent` >= 0 for horizontal fonts
        descent = - descender extents
        extents = fontExtentsForDir (textFont opts) (Just $ PF.direction pf)
        lineHeight = case textLineHeight opts of
            Normal -> normalLineHeight
            Absolute h -> h
        opts = RS.spanTextOptions rs
            } = VO.alignLayoutTop originY $ PF.verticalOffsets pf

ancestorBoxes
    :: [RB.ResolvedBox d]


@@ 385,12 359,39 @@ layoutRunsH runs = fmap layoutRunH runs
layoutRunH :: WithSpan d Run -> ProtoFragmentWithSpan d
layoutRunH (WithSpan rs run) = WithSpan rs pf
    where
        pf = PF.protoFragmentH dir lvl glyphs hard
        pf = PF.protoFragmentH dir lvl vo glyphs hard
        glyphs = shapeRun (WithSpan rs run)
        dir = runDirection run
        lvl = runLevel run
        vo = verticalOffsets rs dir
        hard = runHardBreak run

-- | Vertical offsets for the given fragment, with baseline set to 0.
verticalOffsets :: RS.ResolvedSpan d -> Direction -> VO.VerticalOffsets
verticalOffsets rs dir = VO.VerticalOffsets
    { VO.layoutTop = ascent + topHalfLeading
    , VO.fontTop = ascent
    , VO.baseline = 0
    , VO.fontBottom = - descent
    , VO.layoutBottom = - descent - bottomHalfLeading
    }
    where
        -- non-negative leading values iff `lineHeight` > `normalLineHeight`
        leading = lineHeight - normalLineHeight
        topHalfLeading = -((-leading) `div` 2)
        bottomHalfLeading = leading `div` 2
        -- `normalLineHeight` > 0 for horizontal fonts
        normalLineHeight = ascent + descent
        -- `ascent` >= 0 for horizontal fonts
        ascent = ascender extents
        -- `descent` >= 0 for horizontal fonts
        descent = - descender extents
        extents = fontExtentsForDir (textFont opts) (Just dir)
        lineHeight = case textLineHeight opts of
            Normal -> normalLineHeight
            Absolute h -> h
        opts = RS.spanTextOptions rs

-- | Calculate layout for the given run independently of its position.
shapeRun :: WithSpan d Run -> [(GlyphInfo, GlyphPos)]
shapeRun (WithSpan rs run) = shape font buffer features

M src/Data/Text/ParagraphLayout/Internal/ProtoFragment.hs => src/Data/Text/ParagraphLayout/Internal/ProtoFragment.hs +12 -4
@@ 1,5 1,5 @@
module Data.Text.ParagraphLayout.Internal.ProtoFragment
    ( ProtoFragment (direction, advance, glyphs, hardBreak)
    ( ProtoFragment (direction, verticalOffsets, advance, glyphs, hardBreak)
    , protoFragmentH
    )
where


@@ 8,6 8,7 @@ import Data.Int (Int32)
import Data.Text.Glyphize (Direction (..), GlyphInfo, GlyphPos (x_advance))

import qualified Data.Text.ParagraphLayout.Internal.BiDiLevels as BiDi
import qualified Data.Text.ParagraphLayout.Internal.VerticalOffsets as VO

-- | A box fragment which has not been positioned yet.
data ProtoFragment = ProtoFragment


@@ 16,6 17,8 @@ data ProtoFragment = ProtoFragment
    , level :: BiDi.Level
    -- ^ BiDi embedding level.
    -- Should be even for LTR fragments and odd for RTL fragments.
    , verticalOffsets :: VO.VerticalOffsets
    -- ^ Vertical offsets used for aligning the fragment within its line.
    , advance :: Int32
    -- ^ Total advance of glyphs in this fragment,
    -- depending on the text direction.


@@ 26,9 29,14 @@ data ProtoFragment = ProtoFragment

-- | Construct a `ProtoFragment`, automatically calculating the total advance
-- for a horizontal text direction.
protoFragmentH :: Direction -> BiDi.Level -> [(GlyphInfo, GlyphPos)] -> Bool ->
    ProtoFragment
protoFragmentH dir lvl gs hard = ProtoFragment dir lvl adv gs hard
protoFragmentH
    :: Direction
    -> BiDi.Level
    -> VO.VerticalOffsets
    -> [(GlyphInfo, GlyphPos)]
    -> Bool
    -> ProtoFragment
protoFragmentH dir lvl vo gs hard = ProtoFragment dir lvl vo adv gs hard
    where
        adv = sum $ map (x_advance . snd) gs