~jaro/balkon

31b3de038b0d395c6ba188738f757c68165025a6 — Jaro 1 year, 9 months ago a006f79
Upgrade Fragment to contain pen position.
M .golden/czechHelloParagraph/golden => .golden/czechHelloParagraph/golden +2 -2
@@ 1,5 1,5 @@
ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0}, spanLayouts = [
    SpanLayout [(Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0},
    SpanLayout [Fragment {fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
        [(GlyphInfo {codepoint = 36, cluster = 0, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 663, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 75, cluster = 1, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 571, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 82, cluster = 2, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 590, y_advance = 0, x_offset = 0, y_offset = 0}),


@@ 12,5 12,5 @@ ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274
        (GlyphInfo {codepoint = 87, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 392, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 72, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 4, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 276, y_advance = 0, x_offset = 0, y_offset = 0})]
    )]
    }]
]}

M .golden/mixedLanguageLTRParagraph/golden => .golden/mixedLanguageLTRParagraph/golden +4 -4
@@ 1,5 1,5 @@
ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 6113, y_size = 0}, spanLayouts = [
    SpanLayout [(Rect {x_origin = 0, y_origin = 0, x_size = 4837, y_size = 0},
    SpanLayout [Fragment {fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 4837, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
        [(GlyphInfo {codepoint = 77, cluster = 4, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 86, cluster = 5, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 72, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0}),


@@ 11,10 11,10 @@ ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 6113
        (GlyphInfo {codepoint = 92, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 497, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 15, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 246, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 3, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})]
    )],
    SpanLayout [(Rect {x_origin = 4837, y_origin = 0, x_size = 1276, y_size = 0},
    }],
    SpanLayout [Fragment {fragmentRect = Rect {x_origin = 4837, y_origin = 0, x_size = 1276, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
        [(GlyphInfo {codepoint = 0, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 500, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 0, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 500, y_advance = 0, x_offset = 0, y_offset = 0}),
        (GlyphInfo {codepoint = 4, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 276, y_advance = 0, x_offset = 0, y_offset = 0})]
    )]
    }]
]}

M balkon.cabal => balkon.cabal +1 -0
@@ 97,6 97,7 @@ library
    -- Modules exported by the library.
    exposed-modules:
        Data.Text.ParagraphLayout,
        Data.Text.ParagraphLayout.Fragment,
        Data.Text.ParagraphLayout.Plain,
        Data.Text.ParagraphLayout.Rect,
        Data.Text.ParagraphLayout.ResolvedSpan,

A src/Data/Text/ParagraphLayout/Fragment.hs => src/Data/Text/ParagraphLayout/Fragment.hs +39 -0
@@ 0,0 1,39 @@
module Data.Text.ParagraphLayout.Fragment (Fragment(..))
where

import Data.Int (Int32)
import Data.Text.Glyphize (GlyphInfo, GlyphPos)

import Data.Text.ParagraphLayout.Rect

-- | Box fragment or fragment (CSS3), except that continuous text even within
-- one line can be split into multiple fragments because of spans or changes in
-- script.
data Fragment = Fragment
    { fragmentRect :: Rect Int32
    -- ^ Physical position of the fragment within the paragraph, calculated
    -- using all glyph advances in this fragment and the calculated line height.
    --
    -- This is the space that the glyphs "take up" and is probably what you
    -- want to use for detecting position-based events such as mouse clicks.
    --
    -- Beware that actual glyphs will not be drawn exactly to the borders of
    -- this rectangle -- they may be offset inwards and they can also extend
    -- outwards!
    --
    -- These are not the typographic bounding boxes that you use for determining
    -- the area to draw on -- you need FreeType or a similar library for that.
    --
    -- The origin coordinates are relative to the paragraph.
    --
    -- The sizes can be positive or negative, depending on the text direction.
    --
    -- X coordinates increase from left to right.
    -- Y coordinates increase from bottom to top.
    , fragmentPen :: (Int32, Int32)
    -- ^ Coordinates of the initial pen position, from which the first glyph
    -- should be drawn. That glyph's `x_advance` or `y_advance` are then used
    -- to move the pen position for the next glyph.
    , fragmentGlyphs :: [(GlyphInfo, GlyphPos)]
    }
    deriving (Eq, Read, Show)

M src/Data/Text/ParagraphLayout/Plain.hs => src/Data/Text/ParagraphLayout/Plain.hs +5 -33
@@ 28,7 28,6 @@ import Data.Text.Glyphize
    (Buffer(..)
    ,ContentType(ContentTypeUnicode)
    ,Font
    ,GlyphInfo
    ,GlyphPos(x_advance, y_advance)
    ,defaultBuffer
    ,shape


@@ 36,6 35,7 @@ import Data.Text.Glyphize
import Data.Text.Internal (Text(Text))
import qualified Data.Text.Lazy as Lazy

import Data.Text.ParagraphLayout.Fragment
import Data.Text.ParagraphLayout.Rect
import qualified Data.Text.ParagraphLayout.ResolvedSpan as RS
import Data.Text.ParagraphLayout.Run


@@ 91,36 91,6 @@ data ParagraphLayout = ParagraphLayout
data SpanLayout = SpanLayout [Fragment]
    deriving (Eq, Read, Show)

-- | Box fragment or fragment (CSS3), except that continuous text even within
-- one line can be split into multiple fragments because of spans or changes in
-- script.
type Fragment =
    ( Rect Int32
    -- ^ Physical position of the fragment within the paragraph, calculated
    -- using all glyph advances in this fragment and the calculated line height.
    --
    -- This is the space that the glyphs "take up" and is probably what you
    -- want to use for detecting position-based events such as mouse clicks.
    --
    -- Beware that actual glyphs will not be drawn exactly to the borders of
    -- this rectangle -- they may be offset inwards and they can also extend
    -- outwards!
    --
    -- These are not the typographic bounding boxes that you use for determining
    -- the area to draw on -- you need FreeType or a similar library for that.
    --
    -- The origin coordinates are relative to the paragraph.
    --
    -- The sizes can be positive or negative, depending on the text direction.
    --
    -- X coordinates increase from left to right.
    -- Y coordinates increase from bottom to top.
    , [(GlyphInfo, GlyphPos)]
    )

fragmentRect :: Fragment -> Rect Int32
fragmentRect = fst

spanRects :: SpanLayout -> [Rect Int32]
spanRects (SpanLayout frags) = map fragmentRect frags



@@ 157,8 127,9 @@ layoutPlain paragraph = ParagraphLayout pRect arrangedLayouts
layoutSpan :: RS.ResolvedSpan -> SpanLayout
layoutSpan rs = SpanLayout (map layoutRun $ spanToRuns rs)

-- TODO: Calculate line height and pen position.
layoutRun :: Run -> Fragment
layoutRun run = (rect, glyphs)
layoutRun run = Fragment rect (0, 0) glyphs
    where
        rs = runOriginalSpan run
        rect = containGlyphs $ map snd $ glyphs


@@ 219,7 190,8 @@ arrangeFragmentsH currentX frags = mapAccumL arrangeFragmentH currentX frags
-- | Set the horizontal offset of the given box
-- and return the x coordinate of its other side for continuation.
arrangeFragmentH :: Int32 -> Fragment -> (Int32, Fragment)
arrangeFragmentH currentX (rect, glyphs) = (nextX, (newRect, glyphs))
arrangeFragmentH currentX frag = (nextX, frag { fragmentRect = newRect })
    where
        rect = fragmentRect frag
        nextX = currentX + x_size rect
        newRect = rect { x_origin = currentX }

M test/Data/Text/ParagraphLayout/PlainSpec.hs => test/Data/Text/ParagraphLayout/PlainSpec.hs +12 -6
@@ 7,6 7,7 @@ import Test.Hspec
import Test.Hspec.Golden
import System.FilePath ((</>))
import Data.Text.ParagraphLayout.FontLoader
import Data.Text.ParagraphLayout.Fragment
import Data.Text.ParagraphLayout.ParagraphData
import Data.Text.ParagraphLayout.Plain



@@ 23,23 24,28 @@ prettyShow (ParagraphLayout pr sls) = showParagraphLayout where
        , newline
        ]
    showSpanLayouts = concat $ intersperse commaNewline $ map showSpanLayout sls
    showSpanLayout (SpanLayout boxes) = concat
    showSpanLayout (SpanLayout frags) = concat
        [ indent1
        , "SpanLayout ["
        , concat $ map showBox boxes
        , concat $ map showFrag frags
        , "]"
        ]
    showBox (r, glyphs) = concat
        [ "("
    showFrag (Fragment r pen glyphs) = concat
        [ "Fragment {fragmentRect = "
        , show r
        , commaNewline
        , ", "
        , "fragmentPen = "
        , show pen
        , ", "
        , "fragmentGlyphs ="
        , newline
        , indent2
        , "["
        , showGlyphs glyphs
        , "]"
        , newline
        , indent1
        , ")"
        , "}"
        ]
    showGlyphs = concat . intersperse (commaNewline ++ indent2) . map show
    indent1 = "    "