M balkon.cabal => balkon.cabal +4 -1
@@ 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:
M src/Data/Text/ParagraphLayout.hs => src/Data/Text/ParagraphLayout.hs +2 -94
@@ 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]
A src/Data/Text/ParagraphLayout/Run.hs => src/Data/Text/ParagraphLayout/Run.hs +84 -0
@@ 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
A src/Data/Text/ParagraphLayout/Span.hs => src/Data/Text/ParagraphLayout/Span.hs +21 -0
@@ 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)