From 88a5b6c714c5543b01d63d836ad403b5755d8d76 Mon Sep 17 00:00:00 2001 From: Jaro Date: Thu, 1 Jun 2023 05:28:08 +0200 Subject: [PATCH] Test shaping across intra-word breaks. --- .golden/shapedRuns/intraWordBreak.fontInfo | 1 + .golden/shapedRuns/intraWordBreak.golden | 19 ++++++++ .../ParagraphLayout/Rich/ParagraphData.hs | 14 ++++++ test/Data/Text/ParagraphLayout/RichSpec.hs | 46 +++++++++++++++---- 4 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 .golden/shapedRuns/intraWordBreak.fontInfo create mode 100644 .golden/shapedRuns/intraWordBreak.golden diff --git a/.golden/shapedRuns/intraWordBreak.fontInfo b/.golden/shapedRuns/intraWordBreak.fontInfo new file mode 100644 index 0000000..c948834 --- /dev/null +++ b/.golden/shapedRuns/intraWordBreak.fontInfo @@ -0,0 +1 @@ +assets/fonts/plex/IBMPlexSansArabic-Regular.ttf 0 32,32 32,32 diff --git a/.golden/shapedRuns/intraWordBreak.golden b/.golden/shapedRuns/intraWordBreak.golden new file mode 100644 index 0000000..7221496 --- /dev/null +++ b/.golden/shapedRuns/intraWordBreak.golden @@ -0,0 +1,19 @@ +[ (0, -35, + [ (GlyphInfo {codepoint = 373, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 24, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 971, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 14, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 407, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 8, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 89, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 18, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 1363, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 31, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 373, cluster = 4, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 24, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 971, cluster = 2, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 14, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 407, cluster = 0, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 8, y_advance = 0, x_offset = 0, y_offset = 0}) + ]) +, (0, -83, + [ (GlyphInfo {codepoint = 1363, cluster = 28, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 31, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 373, cluster = 26, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 24, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 971, cluster = 24, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 14, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 407, cluster = 22, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 8, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 89, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 18, y_advance = 0, x_offset = 0, y_offset = 0}) + , (GlyphInfo {codepoint = 1363, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 31, y_advance = 0, x_offset = 0, y_offset = 0}) + ]) +] \ No newline at end of file diff --git a/test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs b/test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs index 6c61b37..5921093 100644 --- a/test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs +++ b/test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs @@ -1,6 +1,7 @@ module Data.Text.ParagraphLayout.Rich.ParagraphData ( hardBoxBreakLTRParagraph , hardBoxBreakRTLParagraph + , intraWordBreakParagraph , loremIpsumParagraph , mixedDirectionComplexParagraph , mixedDirectionSimpleParagraph @@ -79,6 +80,19 @@ hardBoxBreakRTLParagraph font = constructParagraph b2 = b_ { boxSpacing = BoxSpacingLeftRight 150 200 } t = tRTL { textFont = font, textLanguage = "zxx" } +-- | For testing that soft wrap preserves the form of Arabic characters. +-- Source: +intraWordBreakParagraph :: Font -> ParagraphOptions -> Paragraph String +intraWordBreakParagraph font = constructParagraph + empty + (rootBox t + [ text "text" "نوشتن_نوشتن_نوشتن" + ] + ) + empty + where + t = tRTL { textFont = font, textLanguage = "fa" } + -- | Filler text using the Latin script. -- Source: loremIpsumParagraph :: Font -> ParagraphOptions -> Paragraph String diff --git a/test/Data/Text/ParagraphLayout/RichSpec.hs b/test/Data/Text/ParagraphLayout/RichSpec.hs index fb50170..b2c0662 100644 --- a/test/Data/Text/ParagraphLayout/RichSpec.hs +++ b/test/Data/Text/ParagraphLayout/RichSpec.hs @@ -1,7 +1,8 @@ module Data.Text.ParagraphLayout.RichSpec (spec) where import Data.Int (Int32) -import Data.Text.Glyphize (Direction (DirLTR, DirRTL)) +import Data.Word (Word32) +import Data.Text.Glyphize (Direction (DirLTR, DirRTL), codepoint) import Test.Hspec import System.FilePath (()) @@ -19,6 +20,9 @@ fragmentRects :: ParagraphLayout d -> [(d, Rect Int32)] fragmentRects p = map toItem $ paragraphFragments p where toItem (Fragment { fragmentUserData = d, fragmentRect = r }) = (d, r) +glyphRuns :: ParagraphLayout d -> [[Word32]] +glyphRuns = map (map (codepoint . fst) . fragmentGlyphs) . paragraphFragments + spec :: Spec spec = do @@ -158,6 +162,27 @@ spec = do let result = layoutRich input result `shouldBeGolden` "mixedDirectionComplexLTR" + it "preserves joining forms across soft breaks" $ do + let opts = defaultParagraphOptions { paragraphMaxWidth = 4500 } + let input = intraWordBreakParagraph font opts + let glyphRunsVisual = glyphRuns $ layoutRich input + let glyphRunsLogical = map reverse glyphRunsVisual + -- Glyph indexes for the corresponding Arabic letters/ligatures: + let n_initial = 407 + let v_final = 971 + let sh_initial = 373 + let tn_final = 1363 + -- Glyph index for the underscore used to break repetitions: + let sp = 89 + -- Unconventional code formatting here shows that there should + -- be three repetitions of the same glyph sequence, unaffected + -- by the line break inserted after an initial form and before + -- a final form. + glyphRunsLogical `shouldBe` + [[n_initial, v_final, sh_initial, tn_final, sp, + n_initial, v_final, sh_initial], [tn_final, sp, + n_initial, v_final, sh_initial, tn_final]] + describe "paginate" $ do let goldenDir = ".golden" "paginatedRichParagraphLayout" @@ -195,13 +220,18 @@ spec = do let fontPath = arabicFont font <- runIO $ loadFont fontPath 0 demoOptions - let - opts = defaultParagraphOptions - input = mixedDirectionComplexParagraph DirRTL font opts - result = layoutRich input - shapedRunsSpec = shapedRunsSpecWithFont fontPath font + let shapedRunsSpec = shapedRunsSpecWithFont fontPath font shapedRunsSpec "handles complex mixed direction in RTL paragraph" - "mixedDirectionComplexRTL" - result + "mixedDirectionComplexRTL" $ + layoutRich $ + mixedDirectionComplexParagraph DirRTL font $ + defaultParagraphOptions + + shapedRunsSpec + "preserves joining forms across soft breaks" + "intraWordBreak" $ + layoutRich $ + intraWordBreakParagraph font $ + defaultParagraphOptions { paragraphMaxWidth = 144 } -- 2.30.2