~jaro/balkon

0bee8136697d2c892cbb567c2780cfa35cb8d01b — Jaro 11 months ago a44d862
Test Rich layout.
A .golden/richParagraphLayout/nestedBoxes.golden => .golden/richParagraphLayout/nestedBoxes.golden +60 -0
@@ 0,0 1,60 @@
ParagraphLayout
    { paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 14576, y_size = -1121}
    , paragraphFragments =
        [ Fragment
            { fragmentUserData = "text1"
            , fragmentLine = 1
            , fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 8569, y_size = -1121}
            , fragmentPen = (0, -932)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 87, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 402, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 75, cluster = 7, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 571, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 76, cluster = 8, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 86, cluster = 9, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 83, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 589, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 68, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 522, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 85, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 386, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 68, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 522, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 74, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 578, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 85, cluster = 16, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 386, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 68, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 522, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 83, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 589, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 75, cluster = 19, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 571, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 20, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 75, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 571, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 68, cluster = 22, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 522, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 86, cluster = 23, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 24, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentRect = Rect {x_origin = 8569, y_origin = 0, x_size = 3350, y_size = -1121}
            , fragmentPen = (0, -932)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 81, cluster = 25, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 574, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 72, cluster = 26, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 86, cluster = 27, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 87, cluster = 28, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 392, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 72, cluster = 29, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 71, cluster = 30, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 589, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 31, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text3"
            , fragmentLine = 1
            , fragmentRect = Rect {x_origin = 11919, y_origin = 0, x_size = 2657, y_size = -1121}
            , fragmentPen = (0, -932)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 69, cluster = 32, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 589, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 82, cluster = 33, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 573, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 91, cluster = 34, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 490, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 72, cluster = 35, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 86, cluster = 36, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        ]
    }

M balkon.cabal => balkon.cabal +2 -0
@@ 188,6 188,8 @@ test-suite balkon-test
        Data.Text.ParagraphLayout.PrettyShow,
        Data.Text.ParagraphLayout.PrettyShow.Golden,
        Data.Text.ParagraphLayout.RectSpec,
        Data.Text.ParagraphLayout.Rich.ParagraphData,
        Data.Text.ParagraphLayout.RichSpec,
        Data.Text.ParagraphLayout.SpanData

    -- Test dependencies.

M test/Data/Text/ParagraphLayout/PrettyShow.hs => test/Data/Text/ParagraphLayout/PrettyShow.hs +25 -3
@@ 9,8 9,12 @@ where

import Data.List (intersperse)
import Data.Text.ParagraphLayout
import Data.Text.ParagraphLayout.Internal.Fragment (ShapedRun)
import Data.Text.ParagraphLayout.Internal.Fragment
    ( Fragment (Fragment)
    , ShapedRun
    )
import qualified Data.Text.ParagraphLayout.Plain as Plain
import qualified Data.Text.ParagraphLayout.Rich as Rich

class PrettyShow a where
    prettyShow :: a -> String


@@ 82,8 86,8 @@ instance Show d => PrettyShow (Plain.SpanLayout d) where
        , concat $ commaFirstList indent2 $ map prettyShow frags
        ]

instance Show d => PrettyShow (Plain.Fragment d) where
    prettyShow (Plain.Fragment d l r pen glyphs) = concat
instance Show d => PrettyShow (Fragment d) where
    prettyShow (Fragment d l r pen glyphs) = concat
        [ "Fragment"
        , newline
        , indent3


@@ 111,6 115,24 @@ instance Show d => PrettyShow (Plain.Fragment d) where
        , "}"
        ]

instance Show d => PrettyShow (Rich.ParagraphLayout d) where
    prettyShow (Rich.ParagraphLayout pr frags) = concat
        [ "ParagraphLayout"
        , newline
        , indent1
        , "{ paragraphRect = "
        , show pr
        , newline
        , indent1
        , ", paragraphFragments ="
        , newline
        , concat $ commaFirstList indent2 $ map prettyShow frags
        , newline
        , indent1
        , "}"
        , newline
        ]

prettyShowPair :: (Show a, Show b) => (a, b) -> String
prettyShowPair (a, b) = "(" ++ show a ++ ", " ++ show b ++ ")"


A test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs => test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs +43 -0
@@ 0,0 1,43 @@
module Data.Text.ParagraphLayout.Rich.ParagraphData (nestedBoxesParagraph)
where

import Data.Text (pack)
import Data.Text.Glyphize (Font)

import Data.Text.ParagraphLayout.Internal.BoxOptions
import Data.Text.ParagraphLayout.Internal.ParagraphOptions
import Data.Text.ParagraphLayout.Internal.Rich.Paragraph
import Data.Text.ParagraphLayout.Internal.TextOptions
import Data.Text.ParagraphLayout.Internal.TreeOfTexts

t_ :: TextOptions
t_ = defaultTextOptions

b_ :: BoxOptions
b_ = defaultBoxOptions

rootBox :: TextOptions -> [InnerNode d] -> RootNode d
rootBox opts nodes = RootBox (Box nodes opts)

box :: d -> BoxOptions -> TextOptions -> [InnerNode d] -> InnerNode d
box label boxOpts textOpts nodes = InlineBox label (Box nodes textOpts) boxOpts

text :: d -> String -> InnerNode d
text label contents = TextSequence label (pack contents)

nestedBoxesParagraph :: Font -> ParagraphOptions -> Paragraph String
nestedBoxesParagraph font = constructParagraph
    (pack "prefix")
    (rootBox t
        [ text "text1" "this paragraph has "
        , box "box2" b_ t
            [ box "box3" b_ t
                [ text "text2" "nested "
                ]
            , text "text3" "boxes"
            ]
        ]
    )
    (pack "suffix")
    where
        t = t_ { textFont = font, textLanguage = "en" }

A test/Data/Text/ParagraphLayout/RichSpec.hs => test/Data/Text/ParagraphLayout/RichSpec.hs +25 -0
@@ 0,0 1,25 @@
module Data.Text.ParagraphLayout.RichSpec (spec) where

import Test.Hspec
import System.FilePath ((</>))
import Data.Text.ParagraphLayout.FontLoader
import Data.Text.ParagraphLayout.PrettyShow.Golden
import Data.Text.ParagraphLayout.Rich
import Data.Text.ParagraphLayout.Rich.ParagraphData

spec :: Spec
spec = do

    describe "layoutRich" $ do
        let
            goldenDir = ".golden" </> "richParagraphLayout"
            shouldBeGolden = goldenTest goldenDir id id

        describe "with Latin font" $ do
            font <- runIO $ loadFont latinFont 0 testingOptions

            it "handles nested boxes" $ do
                let opts = defaultParagraphOptions
                let input = nestedBoxesParagraph font opts
                let result = layoutRich input
                result `shouldBeGolden` "nestedBoxes"