FreeTypeGL-0.0.1: Graphics/Rendering/FreeTypeGL.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
-- | A higher-level interface wrapping the low-level C API
module Graphics.Rendering.FreeTypeGL
( FontDesc(..), fontDescFindFileName
, Shader, newShader
, Font, loadFont, textSize
, Vector2(..)
, Markup(..), noMarkup, Color4(..)
, TextRenderer, textRenderer, textRendererSize, renderText
, initialize
) where
import Control.Applicative
import Foreign.C.String (withCString)
import Foreign.C.Types (CInt(..))
import Foreign.ForeignPtr (ForeignPtr)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Error (throwIf_)
import Foreign.Storable (peek, poke)
import Graphics.Rendering.FreeTypeGL.Internal.Markup (Markup(..), noMarkup)
import Graphics.Rendering.FreeTypeGL.Internal.Shader (Shader)
import Graphics.Rendering.FreeTypeGL.Internal.TextureFont (IsLCD(..))
import Graphics.Rendering.OpenGL.GL (Color4(..), Vector2(..))
import Paths_FreeTypeGL (getDataFileName)
import System.IO.Unsafe (unsafePerformIO) -- for pure textWidth
import qualified Graphics.Rendering.FreeTypeGL.Internal.FontDesc as IFD
import qualified Graphics.Rendering.FreeTypeGL.Internal.Shader as Shader
import qualified Graphics.Rendering.FreeTypeGL.Internal.TextBuffer as ITB
import qualified Graphics.Rendering.FreeTypeGL.Internal.TextureFont as ITF
-- FontDesc:
data FontDesc = FontDesc
{ fdFamily :: String
, fdSize :: Float
, fdBold :: Bool
, fdItalic :: Bool
}
fontDescFindFileName :: FontDesc -> IO String
fontDescFindFileName (FontDesc family size bold italic) =
withCString family $ \familyPtr ->
IFD.fontDescFindFileName $ IFD.FontDesc familyPtr size bold italic
-- Shader:
#include "shader.h"
foreign import ccall "freetypegl_init"
c_freetypegl_init :: IO CInt
initialize :: IO ()
initialize = throwIf_ (/= 0) (("freetypegl_init returned" ++) . show) c_freetypegl_init
-- TODO: Use Paths_module
newShader :: IO Shader
newShader = do
initialize
textVert <- getDataFileName "shaders/text.vert"
textFrag <- getDataFileName "shaders/text.frag"
Shader.load textVert textFrag
-- Font:
data Font = Font
{ _fShader :: Shader
, fFont :: ForeignPtr ITF.TextureFont
}
loadFont :: Shader -> FilePath -> Float -> IO Font
loadFont shader fileName size = do
textureFont <- ITF.new NotLCD fileName size
return $ Font shader textureFont
data TextRenderer = TextRenderer
{ trBuffer :: ForeignPtr ITB.TextBuffer
, trSize :: Vector2 Float
}
textRenderer :: Vector2 Float -> Markup -> Font -> String -> TextRenderer
textRenderer pos markup (Font shader font) str = unsafePerformIO $
alloca $ \pen ->
alloca $ \markupPtr -> do
poke pen pos
poke markupPtr markup
textBuffer <- ITB.new shader (Vector2 512 512) 1
ITB.addText textBuffer markupPtr font pen str
newPos <- peek pen
return $ TextRenderer textBuffer ((-) <$> newPos <*> pos)
renderText :: TextRenderer -> IO ()
renderText = ITB.render . trBuffer
textRendererSize :: TextRenderer -> Vector2 Float
textRendererSize = trSize
textSize :: Font -> String -> Vector2 Float
textSize font str =
unsafePerformIO $ ITF.textSize (fFont font) str