module Wumpus.Drawing.Text.CatText
(
CatText
, leftAlign
, centerAlign
, rightAlign
, blank
, space
, string
, (<>)
, (<+>)
, fontColour
) where
import Wumpus.Drawing.Chains
import Wumpus.Drawing.Text.Base
import Wumpus.Basic.Kernel
import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl )
import qualified Wumpus.Basic.Utils.JoinList as JL
import Wumpus.Core
import Data.Char ( ord )
type CatPrim u = CF (u, AdvGraphic u)
newtype CatText u = CatText { getCatText :: JoinList (CatPrim u) }
type HMove u = u -> u -> u
leftAMove :: Num u => HMove u
leftAMove half_max _ = negate half_max
centerAMove :: Fractional u => HMove u
centerAMove _ elt_w = negate $ 0.5 * elt_w
rightAMove :: Num u => HMove u
rightAMove half_max elt_w = half_max elt_w
leftAlign :: (Real u, FromPtSize u, Floating u)
=> [CatText u] -> PosImage u (BoundingBox u)
leftAlign = drawMulti leftAMove
centerAlign :: (Real u, FromPtSize u, Floating u)
=> [CatText u] -> PosImage u (BoundingBox u)
centerAlign = drawMulti centerAMove
rightAlign :: (Real u, FromPtSize u, Floating u)
=> [CatText u] -> PosImage u (BoundingBox u)
rightAlign = drawMulti rightAMove
drawMulti :: (Real u, FromPtSize u, Floating u)
=> HMove u -> [CatText u] -> PosImage u (BoundingBox u)
drawMulti moveF xs = promoteR2 $ \start rpos ->
evalAllLines xs >>= \all_lines ->
centerToBaseline >>= \down ->
borderedTextObjectPos line_count (fst all_lines) >>= \opos ->
let chn = centerSpinePoints line_count 0
gs = positionHLines moveF down all_lines
gf = unchainZip emptyLocGraphic gs chn
posG = makePosImage opos gf
bbox = objectPosBounds start rpos opos
in replaceAns bbox $ atStartPos posG start rpos
where
line_count = length xs
positionHLines :: Fractional u
=> HMove u -> u -> (u,[(u, AdvGraphic u)]) -> [LocGraphic u]
positionHLines mkH down (max_w,xs) = map fn xs
where
half_max = 0.5 * max_w
moveF w1 = let v = vec (mkH half_max w1) (down)
in moveStart $ displaceVec v
fn (elt_w, gf) = ignoreAns $ moveF elt_w $ gf
evalAllLines :: (Num u, Ord u)
=> [CatText u] -> DrawingInfo (u, [(u, AdvGraphic u)])
evalAllLines = fmap post . mapM evalLine
where
post xs = let mx = foldr (\(a,_) x -> max a x) 0 xs in (mx,xs)
evalLine :: Num u => CatText u -> DrawingInfo (u, AdvGraphic u)
evalLine ct = case viewl $ getCatText ct of
EmptyL -> return (0, replaceAns (hvec 0) $ emptyLocGraphic)
af :< rest -> af >>= \a -> go a (viewl rest)
where
go acc EmptyL = return acc
go (dx,af) (mf :< ms) = let moveF = moveStart (displaceH dx)
in mf >>= \(u,gf) ->
go (dx+u, af `oplus` moveF gf) (viewl ms)
blank :: Num u => CatText u
blank = catOne $ return (0, replaceAns (hvec 0) $ emptyLocGraphic)
space :: FromPtSize u => CatText u
space = catOne $
charVector (CharEscInt $ ord ' ') >>= \v ->
return (advanceH v, replaceAns v $ emptyLocGraphic)
string :: FromPtSize u => String -> CatText u
string = catOne . stringPrim
infixr 6 <>, <+>
(<>) :: CatText u -> CatText u -> CatText u
a <> b = CatText $ JL.join (getCatText a) (getCatText b)
(<+>) :: FromPtSize u => CatText u -> CatText u -> CatText u
a <+> b = a <> space <> b
catOne :: CatPrim u -> CatText u
catOne = CatText . JL.one
stringPrim :: FromPtSize u => String -> CatPrim u
stringPrim = escapedPrim . escapeString
escapedPrim :: FromPtSize u => EscapedText -> CatPrim u
escapedPrim esc = textVector esc >>= \v ->
return (vector_x v, replaceAns v $ escapedline esc)
catMap :: (AdvGraphic u -> AdvGraphic u) -> CatText u -> CatText u
catMap f = CatText . fmap (fmap (\(u,ag) -> (u, f $ ag))) . getCatText
catlocal :: DrawingContextF -> CatText u -> CatText u
catlocal fn = catMap (localize fn)
fontColour :: RGBi -> CatText u -> CatText u
fontColour rgb = catlocal (strokeColour rgb)