module Wumpus.Drawing.Text.Base
(
advtext
, textVector
, charVector
, multilineHeight
, textObjectPos
, borderedTextObjectPos
, centerToBaseline
, centerSpinePoints
) where
import Wumpus.Drawing.Chains
import Wumpus.Basic.Kernel
import Wumpus.Core
import Wumpus.Core.Text.GlyphIndices
import Data.VectorSpace
import Control.Applicative
import Data.Char
import qualified Data.Map as Map
import Data.Maybe
advtext :: FromPtSize u => EscapedText -> AdvGraphic u
advtext esc = lift0R1 (textVector esc) >>= \v -> replaceAns v $ escapedline esc
textVector :: FromPtSize u => EscapedText -> DrawingInfo (AdvanceVec u)
textVector esc =
cwLookupTable >>= \table ->
let cs = destrEscapedText id esc
in return $ foldr (\c v -> v ^+^ (charWidth table c)) (vec 0 0) cs
charVector :: FromPtSize u => EscapedChar -> DrawingInfo (AdvanceVec u)
charVector ch = cwLookupTable >>= \table -> return $ charWidth table ch
charWidth :: FromPtSize u
=> CharWidthTable u -> EscapedChar -> AdvanceVec u
charWidth fn (CharLiteral c) = fn $ ord c
charWidth fn (CharEscInt i) = fn i
charWidth fn (CharEscName s) = fn ix
where
ix = fromMaybe (1) $ Map.lookup s ps_glyph_indices
multilineHeight :: (Real u, Floating u, FromPtSize u)
=> Int -> DrawingInfo u
multilineHeight line_count
| line_count < 1 = return 0
| line_count == 1 = glyphVerticalSpan
| otherwise = fn <$> glyphVerticalSpan <*> baselineSpacing
where
fn h1 bspan = let rest_spans = bspan * fromIntegral (line_count 1)
in h1 + rest_spans
textObjectPos :: (Real u, Floating u, FromPtSize u)
=> Int -> u -> DrawingInfo (ObjectPos u)
textObjectPos line_count w =
fmap (0.5*) (multilineHeight line_count) >>= \hh ->
let hw = 0.5 * w
in return $ ObjectPos hw hw hh hh
borderedTextObjectPos :: (Real u, Floating u, FromPtSize u)
=> Int -> u -> DrawingInfo (ObjectPos u)
borderedTextObjectPos line_count w =
multilineHeight line_count >>= \h ->
getTextMargin >>= \(xsep,ysep) ->
let hw = (2 * xsep) + (0.5 * w)
hh = (2 * ysep) + (0.5 * h)
in return $ ObjectPos hw hw hh hh
centerToBaseline :: (Fractional u, FromPtSize u) => DrawingInfo u
centerToBaseline =
(\ch vspan -> ch 0.5 * vspan) <$> glyphCapHeight <*> glyphVerticalSpan
centerSpinePoints :: Floating u
=> Int -> Radian -> LocChain u
centerSpinePoints n theta
| n <= 1 = promoteR1 $ \ctr -> return [ctr]
| otherwise = promoteR1 $ \ctr ->
baselineSpacing >>= \h1 ->
let dist_top = h1 * centerCount n
top = thetaNorthwards dist_top theta ctr
in return (take n $ iterate (thetaSouthwards h1 theta) top)
centerCount :: Fractional u => Int -> u
centerCount i = (fromIntegral i) / 2 0.5