{-# LANGUAGE TupleSections, GeneralizedNewtypeDeriving #-}
module Data.Font (
Font,
font,glyph,glyph'
) where
import Definitive
import Data.Raster
import Graphics.Rendering.TrueType.STB hiding (Font,findGlyph)
import qualified Graphics.Rendering.TrueType.STB as TT
import Control.Exception (SomeException)
import qualified Data.Vector.Storable as V
import Codec.Picture
newtype Font = Font [TT.Font]
deriving (Semigroup,Monoid)
font :: Chunk -> Either SomeException Font
font s = by thunk $ catch (return . Left) $ Right . Font <$> do
let tt = TrueType s
enumerateFonts tt >>= traverse (initFont tt)
glyph :: Font -> (Char,Float) -> Maybe Raster
glyph (Font fs) = \(c,sc) -> foldMap (charBM c sc) fs
where charBM c sc f = fg f c <&> \g -> bm f g (scl sc,scl sc) & bitmap2Image
where scl = scaleForPixelHeight (getFontVerticalMetrics f^.thunk)
fg = map2 (by thunk) TT.findGlyph
bm = map3 (fst.by thunk) TT.newGlyphBitmap
glyph' :: Font -> (Char,Float) -> Raster
glyph' = map2 (maybe undefined id) glyph
bitmap2Image :: Bitmap -> Raster
bitmap2Image (Bitmap (w,h) p) = ImageY8 (Image w h v')^.raster
where v' = V.concat (reverse $ zipWith mkSlice posts (tail posts))
v = V.unsafeFromForeignPtr0 p (w*h)
posts = [0,w..V.length v]
mkSlice a b = V.slice a (b-a) v