~alcinnz/Typograffiti

9b03b9d2b386b503a6401fb4a54c26c505cd220b — Adrian Cochrane 1 year, 10 months ago 61e050e
Fix compilation issues with restructure back to Typograffiti's original.
M src/Typograffiti.hs => src/Typograffiti.hs +24 -0
@@ 0,0 1,24 @@
-- |
-- Module:     Typograffiti
-- Copyright:  (c) 2018 Schell Scivally
-- License:    MIT
-- Maintainer: Schell Scivally <schell@takt.com>
--
-- This module provides easy freetype2-based font rendering with a nice
-- Haskell interface.
module Typograffiti(
    TypograffitiError(..),
    allocAtlas, freeAtlas, stringTris, Atlas(..), GlyphMetrics(..),
    makeDrawGlyphs, AllocatedRendering(..), Layout(..),
    SpatialTransform(..), TextTransform(..), move, scale, rotate, color, alpha,
    withFontStore, newFontStore, FontStore(..), Font(..),
    makeDrawTextIndentedCached, makeDrawTextCached,
        makeDrawAsciiIndentedCached, makeDrawAsciiCached,
    makeDrawTextIndented, makeDrawTextIndented', makeDrawText, makeDrawText',
        makeDrawAsciiIndented, makeDrawAsciiIndented', makeDrawAscii, makeDrawAscii'
) where

import Typograffiti.Atlas
import Typograffiti.Cache
import Typograffiti.Store
import Typograffiti.Text

M src/Typograffiti/Atlas.hs => src/Typograffiti/Atlas.hs +51 -28
@@ 14,6 14,7 @@ module Typograffiti.Atlas where

import           Control.Monad
import           Control.Monad.Except                              (MonadError (..))
import           Control.Monad.Fail                                (MonadFail (..))
import           Control.Monad.IO.Class
import           Data.Maybe                                        (fromMaybe)
import           Data.IntMap                                       (IntMap)


@@ 23,14 24,31 @@ import qualified Data.Vector.Unboxed                               as UV
import           Foreign.Marshal.Utils                             (with)
import           Graphics.GL.Core32
import           Graphics.GL.Types
import           FreeType.Core.Base
import           FreeType.Core.Types                               as BM
import           FreeType.Support.Bitmap                           as BM
import           FreeType.Support.Bitmap.Internal                  as BM
import           Linear
import           Data.Int                                          (Int32)
import           Data.Text.Glyphize                                (GlyphInfo(..), GlyphPos(..))
import           Data.Word                                         (Word32)

import           Foreign.Storable                                  (Storable(..))
import           Foreign.Ptr                                       (castPtr)
import           Foreign.Marshal.Array                             (allocaArray, peekArray)
import           Foreign.C.String                                  (withCString)

import           Typograffiti.GL
import           Typograffiti.Glyph
import           Typograffiti.Utils

data TypograffitiError =
    TypograffitiErrorNoGlyphMetricsForChar Char
  -- ^ The are no glyph metrics for this character. This probably means
  -- the character has not been loaded into the atlas.
  | TypograffitiErrorFreetype String String
  -- ^ There was a problem while interacting with the freetype2 library.
  | TypograffitiErrorGL String
  -- ^ There was a problem while interacting with OpenGL.
  deriving (Show, Eq)

------
--- Atlas


@@ 49,6 67,7 @@ data Atlas = Atlas {
    atlasFilePath :: FilePath
} deriving (Show)

emptyAtlas :: GLuint -> Atlas
emptyAtlas t = Atlas t 0 mempty ""

data AtlasMeasure = AM {


@@ 64,12 83,15 @@ emptyAM = AM 0 (V2 1 1) 0 mempty
spacing :: Int
spacing = 1

glyphRetriever font glyph = do
    ft_Load_Glyph font (fromIntegral $ fromEnum glyph) FT.FT_LOAD_RENDER
type GlyphRetriever m = Word32 -> m (FT_Bitmap, FT_Glyph_Metrics)
glyphRetriever :: MonadIO m => FT_Face -> GlyphRetriever m
glyphRetriever font glyph = liftIO $ do
    ft_Load_Glyph font (fromIntegral $ fromEnum glyph) FT_LOAD_RENDER
    font' <- peek font
    slot <- peek $ frGlyph font'
    return (gsrBitmap slot, gsrMetrics slot)

measure :: MonadIO m => GlyphRetriever m -> Int -> AtlasMeasure -> Word32 -> m AtlasMeasure
measure cb maxw am@AM{..} glyph
    | Just _ <- IM.lookup (fromEnum glyph) amMap = return am
    | otherwise = do


@@ 92,13 114,14 @@ measure cb maxw am@AM{..} glyph
              }
        return am

texturize :: MonadIO m => GlyphRetriever m -> IntMap (V2 Int) -> Atlas -> Word32 -> m Atlas
texturize cb xymap atlas@Atlas{..} glyph
    | Just pos@(V2 x y) <- IM.lookup (fromIntegral $ fromEnum glyph) xymap = do
        (bmp, metrics) <- cb glyph
        glTexSubImage2D GL.GL_TEXTURE_2D 0
        glTexSubImage2D GL_TEXTURE_2D 0
            (fromIntegral x) (fromIntegral y)
            (fromIntegral $ bWidth bmp) (fromIntegral $ bRows bmp)
            GL.GL_RED GL.GL_UNSIGNED_BYTE
            GL_RED GL_UNSIGNED_BYTE
            (castPtr $ bBuffer bmp)
        let vecwh = fromIntegral <$> V2 (bWidth bmp) (bRows bmp)
            canon = floor . (* 0.5) . (* 0.015625) . realToFrac . fromIntegral


@@ 113,40 136,38 @@ texturize cb xymap atlas@Atlas{..} glyph
              }
        return atlas { atlasMetrics = IM.insert (fromEnum glyph) mtrcs atlasMetrics }
    | otherwise = do
        putStrLn ("Cound not find glyph " ++ show glyph)
        liftIO $ putStrLn ("Cound not find glyph " ++ show glyph)
        return atlas

allocAtlas :: (Int32 -> IO (FT_Bitmap, FT_Glyph_Metrics)) -> [Int32] -> IO Atlas
allocAtlas :: (MonadIO m, MonadFail m) => GlyphRetriever m -> [Word32] -> m Atlas
allocAtlas cb glyphs = do
    AM {..} <- foldM (measure cb 512) emptyAM glyphs
    let V2 w h = amWH
        xymap = amMap

    [t] <- allocaArray 1 $ \ptr -> do
        glGenTextures 1 ptr
        peekArray 1 ptr
    glActiveTexture 0
    glBindTexture GL.GL_TEXTURE_2D t
    t <- allocAndActivateTex 0

    glPixelStorei GL.GL_UNPACK_ALIGNMENT 1
    withCString (replicate (w * h) $ toEnum 0) $
        glTexImage2D GL.GL_TEXTURE_2D 0 GL.GL_RED (fromIntegral w) (fromIntegral h)
                    0 GL.GL_RED GL.GL_UNSIGNED_BYTE . castPtr
    glPixelStorei GL_UNPACK_ALIGNMENT 1
    liftIO $ withCString (replicate (w * h) $ toEnum 0) $
        glTexImage2D GL_TEXTURE_2D 0 GL_RED (fromIntegral w) (fromIntegral h)
                    0 GL_RED GL_UNSIGNED_BYTE . castPtr
    atlas <- foldM (texturize cb xymap) (emptyAtlas t) glyphs

    glGenerateMipmap GL.GL_TEXTURE_2D
    glTexParameteri GL.GL_TEXTURE_2D GL.GL_TEXTURE_WRAP_S GL.GL_REPEAT
    glTexParameteri GL.GL_TEXTURE_2D GL.GL_TEXTURE_WRAP_T GL.GL_REPEAT
    glTexParameteri GL.GL_TEXTURE_2D GL.GL_TEXTURE_MAG_FILTER GL.GL_LINEAR
    glTexParameteri GL.GL_TEXTURE_2D GL.GL_TEXTURE_MIN_FILTER GL.GL_LINEAR
    glBindTexture GL.GL_TEXTURE_2D 0
    glPixelStorei GL.GL_UNPACK_ALIGNMENT 4
    glGenerateMipmap GL_TEXTURE_2D
    glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_REPEAT
    glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_REPEAT
    glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_LINEAR
    glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_LINEAR
    glBindTexture GL_TEXTURE_2D 0
    glPixelStorei GL_UNPACK_ALIGNMENT 4
    return atlas { atlasTextureSize = V2 w h }

freeAtlas a = with (atlasTexture a) $ \ptr -> glDeleteTextures 1 ptr
freeAtlas :: MonadIO m => Atlas -> m ()
freeAtlas a = liftIO $ with (atlasTexture a) $ \ptr -> glDeleteTextures 1 ptr

type Quads = (Float, Float, [(V2 Float, V2 Float)])
makeCharQuad :: Atlas -> Quads -> (GlyphInfo, GlyphPos) -> IO Quads
makeCharQuad :: (MonadIO m, MonadError TypograffitiError m) =>
    Atlas -> Quads -> (GlyphInfo, GlyphPos) -> m Quads
makeCharQuad Atlas {..} (penx, peny, mLast) (GlyphInfo {codepoint=glyph}, GlyphPos {..}) = do
    let iglyph = fromEnum glyph
    case IM.lookup iglyph atlasMetrics of


@@ 172,9 193,11 @@ makeCharQuad Atlas {..} (penx, peny, mLast) (GlyphInfo {codepoint=glyph}, GlyphP
    f' :: Int -> Float
    f' = fromIntegral

stringTris :: Atlas -> [(GlyphInfo, GlyphPos)] -> IO Quads
stringTris :: (MonadIO m, MonadError TypograffitiError m) =>
    Atlas -> [(GlyphInfo, GlyphPos)] -> m Quads
stringTris atlas = foldM (makeCharQuad atlas) (0, 0, [])
stringTris' :: Atlas -> [(GlyphInfo, GlyphPos)] -> IO [(V2 Float, V2 Float)]
stringTris' :: (MonadIO m, MonadError TypograffitiError m) =>
    Atlas -> [(GlyphInfo, GlyphPos)] -> m [(V2 Float, V2 Float)]
stringTris' atlas glyphs = do
    (_, _, ret) <- stringTris atlas glyphs
    return ret

M src/Typograffiti/Cache.hs => src/Typograffiti/Cache.hs +18 -4
@@ 18,6 18,7 @@ module Typograffiti.Cache where
import           Control.Monad          (foldM)
import           Control.Monad.Except   (MonadError (..), liftEither,
                                         runExceptT)
import           Control.Monad.Fail     (MonadFail (..))
import           Control.Monad.IO.Class (MonadIO (..))
import           Data.Bifunctor         (first)
import           Data.ByteString        (ByteString)


@@ 30,13 31,16 @@ import qualified Data.Vector.Unboxed    as UV
import           Foreign.Marshal.Array
import           Graphics.GL
import           Linear
import           Data.Text.Glyphize     (GlyphInfo(..), GlyphPos(..))

import           Typograffiti.Atlas
import           Typograffiti.GL
import           Typograffiti.Glyph

data AllocatedRendering = AllocatedRendering
  { arDraw    :: [TextTransform] -> V2 CInt -> IO ()
class Layout t where
  translate :: t -> V2 Float -> t

data AllocatedRendering t = AllocatedRendering
  { arDraw    :: t -> V2 Int -> IO ()
    -- ^ Draw the text with some transformation in some monad.
  , arRelease :: IO ()
    -- ^ Release the allocated draw function in some monad.


@@ 44,6 48,17 @@ data AllocatedRendering = AllocatedRendering
    -- ^ The size (in pixels) of the drawn text.
  }

makeDrawGlyphs
  :: ( MonadIO m
     , MonadError TypograffitiError m
     , MonadIO n
     , MonadFail n
     , MonadError TypograffitiError n
     )
  => m (Atlas
        -> [(GlyphInfo, GlyphPos)]
        -> n (AllocatedRendering [TextTransform])
       )
makeDrawGlyphs = do
    let position = 0
        uv = 1


@@ 182,7 197,6 @@ alpha =
instance Layout [TextTransform] where
  translate ts (V2 x y) = ts ++ [move x y]


liftGL
  :: ( MonadIO m
     , MonadError TypograffitiError m

M src/Typograffiti/GL.hs => src/Typograffiti/GL.hs +4 -4
@@ 23,6 23,7 @@ import           Graphics.GL.Core32
import           Graphics.GL.Types
import           Linear
import           Linear.V               (Finite, Size, dim, toV)
import           Data.List              (foldl')


allocAndActivateTex :: (MonadIO m, MonadFail m) => GLenum -> m GLuint


@@ 354,10 355,9 @@ orthoProjection (V2 ww wh) =
  in ortho 0 hw hh 0 0 1


boundingBox :: (Unbox a, Real a, Fractional a) => UV.Vector (V2 a) -> (V2 a, V2 a)
boundingBox vs
  | UV.null vs = (0,0)
  | otherwise = UV.foldl' f (br,tl) vs
boundingBox :: (Unbox a, Real a, Fractional a) => [V2 a] -> (V2 a, V2 a)
boundingBox [] = (0, 0)
boundingBox vs = foldl' f (br,tl) vs
  where mn a = min a . realToFrac
        mx a = max a . realToFrac
        f (a, b) c = (mn <$> a <*> c, mx <$> b <*> c)

M src/Typograffiti/Store.hs => src/Typograffiti/Store.hs +45 -103
@@ 3,6 3,7 @@
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE RankNTypes                 #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE RecordWildCards  #-}
-- |
-- Module:     Typograffiti.Monad
-- Copyright:  (c) 2018 Schell Scivally


@@ 10,120 11,46 @@
-- Maintainer: Schell Scivally <schell@takt.com>
--
-- A storage context an ops for rendering text with multiple fonts
-- and sizes, hiding the details of the Atlas and WordCache.
-- and sizes, hiding the details of the Atlas, Cache, and the Harfbuzz library.
module Typograffiti.Store where


import           Control.Concurrent.STM (TMVar, atomically, newTMVar, putTMVar,
                                         readTMVar, takeTMVar)
import           Control.Monad.Except   (MonadError (..), liftEither)
import           Control.Monad.Except   (MonadError (..), liftEither, runExceptT, ExceptT (..))
import           Control.Monad.IO.Class (MonadIO (..))
import           Control.Monad.Fail     (MonadFail (..))
import           Data.Map               (Map)
import qualified Data.Map               as M
import           Data.Set               (Set)
import qualified Data.Set               as S
import qualified Data.IntSet            as IS
import           Linear

import qualified Data.ByteString        as B
import           Data.Text.Glyphize     (defaultBuffer, Buffer(..), shape,
                                        GlyphInfo(..), GlyphPos(..))
import qualified Data.Text.Glyphize     as HB
import           Data.Text.Lazy         (Text, pack)
import           FreeType.Core.Base

import           Typograffiti.Atlas
import           Typograffiti.Cache
import           Typograffiti.Glyph

-- For font registration APIs
import           Typograffiti.Utils
import           FreeType.Support.Bitmap.Internal
import           FreeType.Support.Outline.Internal
import           FreeType.Support.Outline
import           FreeType.Core.Types
import           Data.Maybe             (fromMaybe)
import           System.IO

data GlyphSize = CharSize Float Float Int Int
               | PixelSize Int Int
               deriving (Show, Eq, Ord)

makeDrawTextIndented lib filepath index fontsize features sampletext indent = do
    font <- ft_New_Face lib filepath index
    case fontsize of
        PixelSize w h -> ft_Set_Pixel_Sizes font (toEnum $ x2 w) (toEnum $ x2 h)
        CharSize w h dpix dpiy -> ft_Set_Char_Size font (floor $ 26.6 * 2 * w)
                                                    (floor $ 26.6 * 2 * h)
                                                    (toEnum dpix) (toEnum dpiy)

    bytes <- B.readFile filepath
    let font' = createFont $ createFace bytes $ toEnum $ fromEnum index
    let glyphs = map (codepoint . fst) $
            shape font' defaultBuffer { text = sampletext } features
    let glyphs' = map toEnum $ IS.toList $ IS.fromList $ map fromEnum glyphs
    atlas <- allocAtlas (glyphRetriever font) glyphs'
    ft_Done_Face font
import           Typograffiti.Text      (GlyphSize(..), drawLinesWrapper)

    drawGlyphs <- makeDrawGlyphs
    return $ drawLinesWrapper indent $ \string ->
        drawGlyphs atlas $ shape font' defaultBuffer { text = string } features
  where x2 = (*2)

makeDrawTextIndented' a b c d e f =
    ft_With_FreeType $ \ft -> makeDrawTextIndented ft a b c d e f

makeDrawText a b c d e f = makeDrawTextIndented a b c d e f 4
makeDrawText' a b c d e = ft_With_FreeType $ \ft -> makeDrawText ft a b c d e

-- Note: May glitch upon ligatures.
makeDrawAsciiIndented a b c d e f =
    makeDrawTextIndented a b c d e (map toEnum [32..126]) f
makeDrawAsciiIndented' a b c d e =
    ft_With_FreeType $ \ft -> makeDrawAsciiIndented ft a b c d e
makeDrawAscii a b c d e = makeDrawText a b c d e $ map toEnum [32..126]
makeDrawAscii' a b c d = ft_With_FreeType $ \ft -> makeDrawAscii ft a b c d

drawLinesWrapper indent cb string = do
    renderers <- mapM cb $ map processLine $ lines string
    let drawLine ts wsz y renderer = do
        arDraw renderer (move 0 y:ts) wsz
        let V2 _ height = arSize renderer
        return y + height
    let draw ts wsz = do
        foldM (drawLine ts wsz) 0 renderers
        return ()
    let sizes = map arSize renderers
    let size = V2 (max [x | V2 x _ <- sizes]) (sum [y | V2 _ y <- sizes])
    let release = do
        forM renderers arRelease
        return ()
    return AllocatedRendering {
            arDraw = draw,
            arRelease = release,
            arSize = size
          }
  where
    processLine "" = " " -- enforce nonempty
    processLine cs = expandTabs cs
    -- monospace tabshaping, good enough outside full line-layout.
    expandTabs n cs = case break (== '\t') of
        (pre, '\t':cs') -> let spaces = indent - ((length pre + n) `rem` indent)
            in pre ++ replicate spaces ' ' ++ expandTabs (n + length pre + spaces) cs'
        (tail, _) -> tail

-- Add cache of imported fonts
--- Key by filepath & index
--- Maps to Harfbuzz & FreeType fonts,
--- as well as a list of atlases associated with glyphsets & fontfeatures.

data FontStore = FontStore {
data FontStore n = FontStore {
    fontMap :: TMVar (Map (FilePath, GlyphSize, Int) Font),
    drawGlyphs :: Atlas -> [(GlyphInfo, GlyphPos)] -> IO AllocatedRendering
    drawGlyphs :: Atlas -> [(GlyphInfo, GlyphPos)] -> n (AllocatedRendering [TextTransform]),
    lib :: FT_Library
  }
data Font = Font {
    harfbuzz :: HB.Font,
    freetype :: FT_Font,
    atlases :: TMVar [(IS.IntSet, Atlas)],
    freetype :: FT_Face,
    atlases :: TMVar [(IS.IntSet, Atlas)]
  }

makeDrawTextIndentedCached store filepath index fontsize features sampletext indent = do
    s <- liftIO $ atomically $ readTMVar $ fontMap store
    font <- case M.lookup (filepath, fontsize, index) a of
    font <- case M.lookup (filepath, fontsize, index) s of
        Nothing -> allocFont store filepath index fontsize
        Just font -> return font



@@ 134,13 61,13 @@ makeDrawTextIndentedCached store filepath index fontsize features sampletext ind
    a <- liftIO $ atomically $ readTMVar $ atlases font
    atlas <- case [a' | (gs, a') <- a, glyphset `IS.isSubsetOf` gs] of
        (atlas:_) -> return atlas
        _ -> allocAtlas (atlases font) (freetype font) glyphset
        _ -> allocAtlas' (atlases font) (freetype font) glyphset

    return $ drawLinesWrapper indent $ \string ->
        drawGlyphs store atlas $ shape font' defaultBuffer { text = string } features
    return $ drawLinesWrapper indent $ \string -> drawGlyphs store atlas $
        shape (harfbuzz font) defaultBuffer { text = pack string } features

allocFont FontStore {..} filepath index fontsize = do
    font <- ft_New_Face lib filepath index
    font <- ft_New_Face lib filepath $ toEnum index
    case fontsize of
        PixelSize w h -> ft_Set_Pixel_Sizes font (toEnum $ x2 w) (toEnum $ x2 h)
        CharSize w h dpix dpiy -> ft_Set_Char_Size font (floor $ 26.6 * 2 * w)


@@ 148,27 75,42 @@ allocFont FontStore {..} filepath index fontsize = do
                                                    (toEnum dpix) (toEnum dpiy)

    bytes <- B.readFile filepath
    let font' = createFont $ createFace bytes $ toEnum $ fromEnum index
    let font' = HB.createFont $ HB.createFace bytes $ toEnum index

    atlases <- liftIO $ atomically $ newTMVar []
    let ret = Font font' font atlases
    liftIO $ atomically $ swapTMVar $ M.insert (filepath, fontsize, index) ret

    liftIO $ atomically $ do
        map <- takeTMVar fontMap
        putTMVar fontMap $ M.insert (filepath, fontsize, index) ret map
    return ret
  where x2 = (*2)

allocAtlas atlases font glyphset = do
allocAtlas' :: (MonadIO m, MonadFail m) =>
    TMVar [(IS.IntSet, Atlas)] -> FT_Face -> IS.IntSet -> m Atlas
allocAtlas' atlases font glyphset = do
    let glyphs = map toEnum $ IS.toList glyphset
    atlas <- allocAtlas (glyphRetriever font) glyphs

    liftIO $ atomically $ swapTMVar atlases $ ((glyphset, atlas):)
    liftIO $ atomically $ do
        a <- takeTMVar atlases
        putTMVar atlases $ ((glyphset, atlas):a)
    return atlas

withFontStore cb = ft_With_FreeType $ \lib -> do
    store <- liftIO $ atomically $ newTMVar M.empty
withFontStore :: (MonadIO n, MonadError TypograffitiError n, MonadFail n) =>
    (FontStore n -> ExceptT TypograffitiError IO a) ->
    IO (Either TypograffitiError a)
withFontStore cb = ft_With_FreeType $ \lib -> runExceptT $ (newFontStore lib >>= cb)

newFontStore :: (MonadIO m, MonadError TypograffitiError m,
    MonadIO n, MonadError TypograffitiError n, MonadFail n) => FT_Library -> m (FontStore n)
newFontStore lib = do
    drawGlyphs <- makeDrawGlyphs
    store <- liftIO $ atomically $ newTMVar M.empty

    cb $ FontStore store drawGlyphs lib
    return $ FontStore store drawGlyphs lib

makeDrawTextCached a b c d e f = makeDrawTextIndentedCached a b c d e f 4
makeDrawAsciiIndentedCached a b c d e f =
    makeDrawTextIndentedCached a b c d e (map toEnum [32..126]) f
makeDrawAsciiCached a b c d e = makeDrawTextCached a b c d e $ map toEnum [32..126]
    makeDrawTextIndentedCached a b c d e (pack $ map toEnum [32..126]) f
makeDrawAsciiCached a b c d e = makeDrawTextCached a b c d e $ pack $ map toEnum [32..126]

M typograffiti2.cabal => typograffiti2.cabal +40 -84
@@ 1,91 1,47 @@
-- Initial typograffiti2.cabal generated by cabal init.  For further
-- documentation, see http://haskell.org/cabal/users-guide/

-- The name of the package.
name:                typograffiti2

-- The package version.  See the Haskell package versioning policy (PVP)
-- for standards guiding when and how versions should be incremented.
-- https://wiki.haskell.org/Package_versioning_policy
-- PVP summary:      +-+------- breaking API changes
--                   | | +----- non-breaking API additions
--                   | | | +--- code changes with no API change
version:             0.1.0.0

-- A short (one-line) description of the package.
synopsis:            Just let me draw nice text already

-- A longer description of the package.
-- description:

-- URL for the project homepage or repository.
homepage:            https://argonaut-constellation.org/

-- The license under which the package is released.
license:             BSD3

-- The file containing the license text.
license-file:        LICENSE

-- The package author(s).
author:              Adrian Cochrane

-- An email address to which users can send suggestions, bug reports, and
-- patches.
maintainer:          adrian@openwork.nz

-- A copyright notice.
-- copyright:

category:            Graphics

build-type:          Simple

-- Extra files to be distributed with the package, such as examples or a
-- README.
extra-source-files:  CHANGELOG.md

-- Constraint on the version of Cabal needed to build this package.
cabal-version:       >=1.10

cabal-version: 1.12

name:           typograffiti
version:             0.2.0.0
synopsis:       Just let me draw nice text already
description:    This is a text rendering library that uses OpenGL and freetype2 to render TTF font strings quickly. It is fast enough to render large chunks of text in real time. This library exists because text rendering is one of the biggest hurdles in Haskell graphics programming - and it shouldn't be!
                Typograffiti includes an MTL style typeclass and a default monad transformer. It does not assume you are using any specific windowing solution. It does assume you are using OpenGL 3.3+.
                Pull requests are very welcome :)
                See https://github.com/schell/typograffiti/blob/master/app/Main.hs for an example.
category:       Graphics
homepage:       https://github.com/schell/typograffiti#readme
bug-reports:    https://github.com/schell/typograffiti/issues
author:         Schell Scivally
maintainer:     schell@takt.com
copyright:      2018 Schell Scivally & others
license:        BSD3
license-file:   LICENSE
build-type:     Simple
extra-source-files:
    README.md
    ChangeLog.md

source-repository head
  type: git
  location: https://github.com/schell/typograffiti

library
  -- Modules exported by the library.
  exposed-modules: Graphics.Text.Font.Render

  -- Modules included in this library but not exported.
  -- other-modules:

  -- LANGUAGE extensions used by modules in this package.
  -- other-extensions:

  -- Other library packages from which modules are imported.
  build-depends:       base >=4.12 && <4.13, linear, containers, freetype2, gl,
                        vector, harfbuzz-pure, bytestring

  -- Directories containing source files.
  exposed-modules:
      Typograffiti
      Typograffiti.Atlas
      Typograffiti.Cache
      Typograffiti.GL
      Typograffiti.Store
      Typograffiti.Text
  build-depends:       base >=4.12 && <4.13, linear>=1.20, containers >= 0.6,
                        freetype2 >= 0.2, gl >= 0.8, mtl >= 2.2, stm >= 2.5, text,
                        vector >= 0.12, harfbuzz-pure >= 0.0.7, bytestring >= 0.10
  hs-source-dirs:      src

  -- Base language which the package is written in.
  default-language:    Haskell2010


executable typograffiti2
  -- .hs or .lhs file containing the Main module.
  main-is:             Main.hs

  -- Modules included in this executable, other than Main.
  -- other-modules:

  -- LANGUAGE extensions used by modules in this package.
  -- other-extensions:

  -- Other library packages from which modules are imported.
  build-depends:       base >=4.12 && <4.13, typograffiti2, sdl2, text, gl

  -- Directories containing source files.
  hs-source-dirs:      app

  -- Base language which the package is written in.
  default-language:    Haskell2010
--executable typograffiti
--  main-is:             Main.hs
--  build-depends:       base >=4.12 && <4.13, typograffiti, sdl2 >= 2.5.4, text, gl
--  hs-source-dirs:      app
--  default-language:    Haskell2010