module Data.Text.ParagraphLayout (Span(..), layout)
where
import Data.Text.Glyphize
(Buffer(..)
,ContentType(ContentTypeUnicode)
,GlyphInfo
,GlyphPos
,defaultBuffer
,shape
)
import Data.Text.ParagraphLayout.Run
import Data.Text.ParagraphLayout.Span
data Position = Beginning | Middle | End | Only
deriving (Eq)
-- TODO: Add maximum line length as input.
-- TODO: Compute and return bounding box for each provided span.
-- More if implementing the CSS Box Model.
-- TODO: Also compute and return overall bounding box, in addition to individual
-- ones.
-- TODO: Allow a run across multiple spans (e.g. if they only differ by colour).
layout :: [Span] -> [[(GlyphInfo, GlyphPos)]]
layout = layoutRuns . concat . map spanToRuns
layoutRuns :: [Run] -> [[(GlyphInfo, GlyphPos)]]
layoutRuns [] = []
layoutRuns [s] = [layoutOneRun Only s]
-- TODO: What if there are no visible characters in the edge runs?
layoutRuns (s1:s2:ss) = (layoutOneRun Beginning s1):(layoutRemainingRuns s2 ss)
layoutRemainingRuns :: Run -> [Run] -> [[(GlyphInfo, GlyphPos)]]
layoutRemainingRuns s [] = [layoutOneRun End s]
layoutRemainingRuns s1 (s2:ss) = (layoutOneRun Middle s1):(layoutRemainingRuns s2 ss)
layoutOneRun :: Position -> Run -> [(GlyphInfo, GlyphPos)]
layoutOneRun pos run = shape font buffer features
where
originalSpan = runOriginalSpan run
font = spanFont originalSpan
lang = spanLanguage originalSpan
buffer = defaultBuffer { text = runText run
, contentType = Just ContentTypeUnicode
, direction = runDirection run
, script = runScript run
, language = lang
, beginsText = pos == Beginning || pos == Only
, endsText = pos == End || pos == Only
}
features = []