From e1e85a256529d73d676750940101567be9d73c87 Mon Sep 17 00:00:00 2001 From: Jaro Date: Fri, 10 Feb 2023 08:09:44 +0100 Subject: [PATCH] Separate modules. --- balkon.cabal | 5 +- src/Data/Text/ParagraphLayout.hs | 96 +-------------------------- src/Data/Text/ParagraphLayout/Run.hs | 84 +++++++++++++++++++++++ src/Data/Text/ParagraphLayout/Span.hs | 21 ++++++ 4 files changed, 111 insertions(+), 95 deletions(-) create mode 100644 src/Data/Text/ParagraphLayout/Run.hs create mode 100644 src/Data/Text/ParagraphLayout/Span.hs diff --git a/balkon.cabal b/balkon.cabal index db3c909..607bea1 100644 --- a/balkon.cabal +++ b/balkon.cabal @@ -55,7 +55,10 @@ library exposed-modules: Data.Text.ParagraphLayout -- Modules included in this library but not exported. - other-modules: Data.Text.Script + other-modules: + Data.Text.ParagraphLayout.Run, + Data.Text.ParagraphLayout.Span, + Data.Text.Script -- LANGUAGE extensions used by modules in this package. -- other-extensions: diff --git a/src/Data/Text/ParagraphLayout.hs b/src/Data/Text/ParagraphLayout.hs index b600606..e7dad87 100644 --- a/src/Data/Text/ParagraphLayout.hs +++ b/src/Data/Text/ParagraphLayout.hs @@ -4,50 +4,14 @@ where import Data.Text.Glyphize (Buffer(..) ,ContentType(ContentTypeUnicode) - ,Direction(..) - ,Font ,GlyphInfo ,GlyphPos ,defaultBuffer ,shape ) -import qualified Data.Text.ICU.Char as ICUChar -import Data.Text.Lazy (Text) -import qualified Data.Text.Lazy as Text -import Data.Text.Script (charScript) -type ScriptCode = String -type Language = String - --- Paragraph is broken into spans by the caller. --- --- Each span could have a different font family, size, style, text decoration, --- colour, language, etc. --- --- TODO: Add all relevant attributes. --- -data Span = Span - { spanText :: Text - , spanFont :: Font - , spanLanguage :: Maybe Language - } - deriving (Eq, Show) - --- Each span can be broken into one or more runs by Balkón. --- --- Each run could have a different script, language, or direction. --- -data Run = Run - { runText :: Text - , runDirection :: Maybe Direction - , runScript :: Maybe ScriptCode - , runOriginalSpan :: Span - } - deriving (Eq, Show) - -type ProtoRun = (String, Maybe Direction, ScriptCode) - -data Merged a = Incompatible | Merged a +import Data.Text.ParagraphLayout.Run +import Data.Text.ParagraphLayout.Span data Position = Beginning | Middle | End | Only deriving (Eq) @@ -61,62 +25,6 @@ data Position = Beginning | Middle | End | Only layout :: [Span] -> [[(GlyphInfo, GlyphPos)]] layout = layoutRuns . concat . map spanToRuns --- TODO: Optimise and preserve the Data.Text.Lazy structure. -spanToRuns :: Span -> [Run] -spanToRuns s = map run $ protoRuns chars - where - chars = reverse $ Text.unpack $ spanText s - run (t, d, sc) = Run - { runText = Text.pack t - , runDirection = d - , runScript = Just sc - , runOriginalSpan = s - } - --- TODO: Try to avoid reversing. -protoRuns :: [Char] -> [ProtoRun] -protoRuns = reverse . map (\(t, d, s) -> (reverse t, d, s)) . foldr foldRun [] - -foldRun :: Char -> [ProtoRun] -> [ProtoRun] -foldRun c [] = - -- If there are no runs, create a new run with a single character. - [([c], charDirection c, charScript c)] -foldRun c (r@(oldString, d1, s1):rs) = - case (mergeDirections d1 d2, mergeScripts s1 s2) of - -- If direction & script are compatible, add to existing run. - (Merged d, Merged s) -> ((c:oldString, d, s):rs) - -- Otherwise create a new run. - _ -> (([c], d2, s2):r:rs) - where - d2 = charDirection c - s2 = charScript c - --- Simplified detection of text direction for unidirectional text. -mergeDirections :: Maybe Direction -> Maybe Direction -> Merged (Maybe Direction) -mergeDirections Nothing Nothing = Merged Nothing -mergeDirections (Just d1) Nothing = Merged (Just d1) -mergeDirections Nothing (Just d2) = Merged (Just d2) -mergeDirections (Just d1) (Just d2) - | d1 == d2 = Merged (Just d1) - | otherwise = Incompatible - --- TODO: Implement proper inheritance rules. -mergeScripts :: ScriptCode -> ScriptCode -> Merged ScriptCode -mergeScripts "Zyyy" s2 = Merged s2 -mergeScripts s1 "Zyyy" = Merged s1 -mergeScripts s1 "Zinh" = Merged s1 -mergeScripts s1 s2 - | s1 == s2 = Merged s1 - | otherwise = Incompatible - --- TODO: Use the BiDi algorithm to support bidirectional text. -charDirection :: Char -> Maybe Direction -charDirection c = case ICUChar.direction c of - ICUChar.LeftToRight -> Just DirLTR - ICUChar.RightToLeft -> Just DirRTL - ICUChar.RightToLeftArabic -> Just DirRTL - _ -> Nothing - layoutRuns :: [Run] -> [[(GlyphInfo, GlyphPos)]] layoutRuns [] = [] layoutRuns [s] = [layoutOneRun Only s] diff --git a/src/Data/Text/ParagraphLayout/Run.hs b/src/Data/Text/ParagraphLayout/Run.hs new file mode 100644 index 0000000..a360f86 --- /dev/null +++ b/src/Data/Text/ParagraphLayout/Run.hs @@ -0,0 +1,84 @@ +module Data.Text.ParagraphLayout.Run (Run(..), spanToRuns) +where + +import Data.Text.Glyphize (Direction(..)) +import qualified Data.Text.ICU.Char as ICUChar +import Data.Text.Lazy (Text) +import qualified Data.Text.Lazy as Text +import Data.Text.Script (charScript) + +import Data.Text.ParagraphLayout.Span + +type ScriptCode = String + +-- Each span can be broken into one or more runs by Balkón. +-- +-- Each run could have a different script, language, or direction. +-- +data Run = Run + { runText :: Text + , runDirection :: Maybe Direction + , runScript :: Maybe ScriptCode + , runOriginalSpan :: Span + } + deriving (Eq, Show) + +type ProtoRun = (String, Maybe Direction, ScriptCode) + +data Merged a = Incompatible | Merged a + +-- TODO: Optimise and preserve the Data.Text.Lazy structure. +spanToRuns :: Span -> [Run] +spanToRuns s = map run $ protoRuns chars + where + chars = reverse $ Text.unpack $ spanText s + run (t, d, sc) = Run + { runText = Text.pack t + , runDirection = d + , runScript = Just sc + , runOriginalSpan = s + } + +-- TODO: Try to avoid reversing. +protoRuns :: [Char] -> [ProtoRun] +protoRuns = reverse . map (\(t, d, s) -> (reverse t, d, s)) . foldr foldRun [] + +foldRun :: Char -> [ProtoRun] -> [ProtoRun] +foldRun c [] = + -- If there are no runs, create a new run with a single character. + [([c], charDirection c, charScript c)] +foldRun c (r@(oldString, d1, s1):rs) = + case (mergeDirections d1 d2, mergeScripts s1 s2) of + -- If direction & script are compatible, add to existing run. + (Merged d, Merged s) -> ((c:oldString, d, s):rs) + -- Otherwise create a new run. + _ -> (([c], d2, s2):r:rs) + where + d2 = charDirection c + s2 = charScript c + +-- Simplified detection of text direction for unidirectional text. +mergeDirections :: Maybe Direction -> Maybe Direction -> Merged (Maybe Direction) +mergeDirections Nothing Nothing = Merged Nothing +mergeDirections (Just d1) Nothing = Merged (Just d1) +mergeDirections Nothing (Just d2) = Merged (Just d2) +mergeDirections (Just d1) (Just d2) + | d1 == d2 = Merged (Just d1) + | otherwise = Incompatible + +-- TODO: Implement proper inheritance rules. +mergeScripts :: ScriptCode -> ScriptCode -> Merged ScriptCode +mergeScripts "Zyyy" s2 = Merged s2 +mergeScripts s1 "Zyyy" = Merged s1 +mergeScripts s1 "Zinh" = Merged s1 +mergeScripts s1 s2 + | s1 == s2 = Merged s1 + | otherwise = Incompatible + +-- TODO: Use the BiDi algorithm to support bidirectional text. +charDirection :: Char -> Maybe Direction +charDirection c = case ICUChar.direction c of + ICUChar.LeftToRight -> Just DirLTR + ICUChar.RightToLeft -> Just DirRTL + ICUChar.RightToLeftArabic -> Just DirRTL + _ -> Nothing diff --git a/src/Data/Text/ParagraphLayout/Span.hs b/src/Data/Text/ParagraphLayout/Span.hs new file mode 100644 index 0000000..6787ab9 --- /dev/null +++ b/src/Data/Text/ParagraphLayout/Span.hs @@ -0,0 +1,21 @@ +module Data.Text.ParagraphLayout.Span (Span(..)) +where + +import Data.Text.Glyphize (Font) +import Data.Text.Lazy (Text) + +type Language = String + +-- Paragraph is broken into spans by the caller. +-- +-- Each span could have a different font family, size, style, text decoration, +-- colour, language, etc. +-- +-- TODO: Add all relevant attributes. +-- +data Span = Span + { spanText :: Text + , spanFont :: Font + , spanLanguage :: Maybe Language + } + deriving (Eq, Show) -- 2.30.2