module Data.Text.ParagraphLayout.RichSpec (spec) where import Data.Int (Int32) import Data.Text.Glyphize (Direction (DirLTR, DirRTL)) import Test.Hspec import System.FilePath (()) import Data.Text.ParagraphLayout import Data.Text.ParagraphLayout.FontLoader import Data.Text.ParagraphLayout.Internal.Paginable (paginateAll) import Data.Text.ParagraphLayout.PrettyShow import Data.Text.ParagraphLayout.PrettyShow.Golden import Data.Text.ParagraphLayout.Rect import Data.Text.ParagraphLayout.Rich import Data.Text.ParagraphLayout.Rich.ParagraphData fragmentRects :: ParagraphLayout d -> [(d, Rect Int32)] fragmentRects p = map toItem $ paragraphFragments p where toItem (Fragment { fragmentUserData = d, fragmentRect = r }) = (d, r) 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 fontSmall <- runIO $ loadFont latinFont 0 testingOptionsSmall it "wraps lorem ipsum at 20em" $ do let opts = defaultParagraphOptions { paragraphMaxWidth = 20000 } let input = loremIpsumParagraph font opts let result = layoutRich input result `shouldBeGolden` "loremIpsum20em" it "handles mixed sizes" $ do let opts = defaultParagraphOptions let input = mixedSizesParagraph (font, fontSmall) opts let result = layoutRich input result `shouldBeGolden` "mixedSizes" it "handles mixed script" $ do let opts = defaultParagraphOptions let input = mixedScriptParagraph font opts let result = layoutRich input result `shouldBeGolden` "mixedScript" it "handles mixed script with line wraps" $ do let opts = defaultParagraphOptions { paragraphMaxWidth = 5000 } let input = mixedScriptParagraph font opts let result = layoutRich input result `shouldBeGolden` "mixedScriptWrap" it "handles nested boxes" $ do let opts = defaultParagraphOptions let input = nestedBoxesParagraph font opts let result = layoutRich input result `shouldBeGolden` "nestedBoxes" it "handles hard break in LTR boxes" $ do let opts = defaultParagraphOptions let input = hardBoxBreakLTRParagraph font opts let result = layoutRich input result `shouldBeGolden` "hardBoxBreakLTR" it "breaks line early if box spacing does not fit" $ do let lineH = -1121 let lineY n = lineH * (n - 1) let wordAdvancesWithSpace = [3134, 2954, 2659, 1332, 2601] let spaceAdvance = 231 let wordW n = wordAdvancesWithSpace !! (n - 1) let wordW_ n = wordW n - spaceAdvance let originX = 0 let wordX n = originX + (sum $ take (n - 1) wordAdvancesWithSpace) let endX = originX + (sum wordAdvancesWithSpace) -- A paragraph exactly wide enough to fit the whole text. let opts = defaultParagraphOptions { paragraphMaxWidth = endX } -- Small spacing that should push one word onto the next line. let s = 5 -- Large spacing that should push two words onto the next line. let s' = wordW 5 + spaceAdvance + 1 let inputNoSpacing = softBreakParagraph 0 font opts let inputSmallSpacing = softBreakParagraph s font opts let inputLargeSpacing = softBreakParagraph s' font opts let resultNoSpacing = layoutRich inputNoSpacing let resultSmallSpacing = layoutRich inputSmallSpacing let resultLargeSpacing = layoutRich inputLargeSpacing fragmentRects resultNoSpacing `shouldBe` [ ("text1", Rect (wordX 1) (lineY 1) (wordW 1) lineH) , ("text2", Rect (wordX 2) (lineY 1) (wordW 2) lineH) , ("text3", Rect (wordX 3) (lineY 1) (wordW 3) lineH) , ("text4", Rect (wordX 4) (lineY 1) (wordW 4) lineH) , ("text5", Rect (wordX 5) (lineY 1) (wordW 5) lineH) ] fragmentRects resultSmallSpacing `shouldBe` [ ("text1", Rect (wordX 1) (lineY 1) (wordW 1) lineH) , ("text2", Rect (wordX 2) (lineY 1) (wordW 2) lineH) , ("text3", Rect (wordX 3 + s) (lineY 1) (wordW 3) lineH) , ("text4", Rect (wordX 4 + s) (lineY 1) (wordW_ 4) lineH) , ("text5", Rect originX (lineY 2) (wordW 5) lineH) ] fragmentRects resultLargeSpacing `shouldBe` [ ("text1", Rect (wordX 1) (lineY 1) (wordW 1) lineH) , ("text2", Rect (wordX 2) (lineY 1) (wordW 2) lineH) , ("text3", Rect (wordX 3 + s') (lineY 1) (wordW_ 3) lineH) , ("text4", Rect originX (lineY 2) (wordW 4) lineH) , ("text5", Rect (originX + wordW 4) (lineY 2) (wordW 5) lineH) ] describe "with Arabic font" $ do font <- runIO $ loadFont arabicFont 0 testingOptions it "handles hard break in RTL boxes" $ do let opts = defaultParagraphOptions let input = hardBoxBreakRTLParagraph font opts let result = layoutRich input result `shouldBeGolden` "hardBoxBreakRTL" it "handles simple mixed direction in RTL paragraph" $ do let opts = defaultParagraphOptions let input = mixedDirectionSimpleParagraph DirRTL font opts let result = layoutRich input result `shouldBeGolden` "mixedDirectionSimpleRTL" it "handles simple mixed direction in LTR paragraph" $ do let opts = defaultParagraphOptions let input = mixedDirectionSimpleParagraph DirLTR font opts let result = layoutRich input result `shouldBeGolden` "mixedDirectionSimpleLTR" it "handles complex mixed direction in RTL paragraph" $ do let opts = defaultParagraphOptions let input = mixedDirectionComplexParagraph DirRTL font opts let result = layoutRich input result `shouldBeGolden` "mixedDirectionComplexRTL" it "handles complex mixed direction in LTR paragraph" $ do let opts = defaultParagraphOptions let input = mixedDirectionComplexParagraph DirLTR font opts let result = layoutRich input result `shouldBeGolden` "mixedDirectionComplexLTR" describe "paginate" $ do let goldenDir = ".golden" "paginatedRichParagraphLayout" shouldBeGolden = goldenTest goldenDir getRichPages RichPages describe "with Latin font" $ do font <- runIO $ loadFont latinFont 0 testingOptions it "wraps lorem ipsum at 20em" $ do let opts = defaultParagraphOptions { paragraphMaxWidth = 20000 } let input = loremIpsumParagraph font opts let pl = layoutRich input let popts = PageOptions { pageCurrentHeight = 2500 , pageNextHeight = 8500 , pageOrphans = 2 , pageWidows = 3 } let pages = paginateAll popts pl pages `shouldBeGolden` "loremIpsum20em"