packages feed

typograffiti 0.2.0.0 → 0.2.0.1

raw patch · 6 files changed

+85/−43 lines, 6 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Typograffiti: [atlasScale] :: Atlas -> (Float, Float)
+ Typograffiti: [fontScale] :: Font -> (Float, Float)
+ Typograffiti: [glyphOffset] :: GlyphMetrics -> V2 Int
+ Typograffiti: [lineHeight] :: Font -> Float
+ Typograffiti.Atlas: [atlasScale] :: Atlas -> (Float, Float)
+ Typograffiti.Atlas: [glyphOffset] :: GlyphMetrics -> V2 Int
+ Typograffiti.Store: [fontScale] :: Font -> (Float, Float)
+ Typograffiti.Store: [lineHeight] :: Font -> Float
- Typograffiti: Atlas :: GLuint -> V2 Int -> IntMap GlyphMetrics -> Atlas
+ Typograffiti: Atlas :: GLuint -> V2 Int -> IntMap GlyphMetrics -> (Float, Float) -> Atlas
- Typograffiti: Font :: Font -> FT_Face -> TMVar [(IntSet, Atlas)] -> Font
+ Typograffiti: Font :: Font -> FT_Face -> TMVar [(IntSet, Atlas)] -> Float -> (Float, Float) -> Font
- Typograffiti: GlyphMetrics :: (V2 Int, V2 Int) -> V2 Int -> GlyphMetrics
+ Typograffiti: GlyphMetrics :: (V2 Int, V2 Int) -> V2 Int -> V2 Int -> GlyphMetrics
- Typograffiti: allocAtlas :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => GlyphRetriever m -> [Word32] -> m Atlas
+ Typograffiti: allocAtlas :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => GlyphRetriever m -> [Word32] -> (Float, Float) -> m Atlas
- Typograffiti: varItalic :: [Char]
+ Typograffiti: varItalic :: String
- Typograffiti: varOptSize :: [Char]
+ Typograffiti: varOptSize :: String
- Typograffiti: varSlant :: [Char]
+ Typograffiti: varSlant :: String
- Typograffiti: varWeight :: [Char]
+ Typograffiti: varWeight :: String
- Typograffiti: varWidth :: [Char]
+ Typograffiti: varWidth :: String
- Typograffiti.Atlas: Atlas :: GLuint -> V2 Int -> IntMap GlyphMetrics -> Atlas
+ Typograffiti.Atlas: Atlas :: GLuint -> V2 Int -> IntMap GlyphMetrics -> (Float, Float) -> Atlas
- Typograffiti.Atlas: GlyphMetrics :: (V2 Int, V2 Int) -> V2 Int -> GlyphMetrics
+ Typograffiti.Atlas: GlyphMetrics :: (V2 Int, V2 Int) -> V2 Int -> V2 Int -> GlyphMetrics
- Typograffiti.Atlas: allocAtlas :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => GlyphRetriever m -> [Word32] -> m Atlas
+ Typograffiti.Atlas: allocAtlas :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => GlyphRetriever m -> [Word32] -> (Float, Float) -> m Atlas
- Typograffiti.Store: Font :: Font -> FT_Face -> TMVar [(IntSet, Atlas)] -> Font
+ Typograffiti.Store: Font :: Font -> FT_Face -> TMVar [(IntSet, Atlas)] -> Float -> (Float, Float) -> Font
- Typograffiti.Store: allocAtlas' :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => TMVar [(IntSet, Atlas)] -> FT_Face -> IntSet -> m Atlas
+ Typograffiti.Store: allocAtlas' :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) => TMVar [(IntSet, Atlas)] -> FT_Face -> IntSet -> (Float, Float) -> m Atlas
- Typograffiti.Text: varItalic :: [Char]
+ Typograffiti.Text: varItalic :: String
- Typograffiti.Text: varOptSize :: [Char]
+ Typograffiti.Text: varOptSize :: String
- Typograffiti.Text: varSlant :: [Char]
+ Typograffiti.Text: varSlant :: String
- Typograffiti.Text: varWeight :: [Char]
+ Typograffiti.Text: varWeight :: String
- Typograffiti.Text: varWidth :: [Char]
+ Typograffiti.Text: varWidth :: String

Files

README.md view
@@ -1,4 +1,5 @@ # Typograffiti+[GitHub](https://github.com/schell/typograffiti/) [Hackage](https://hackage.haskell.org/package/typograffiti) [Mirror](https://git.argonaut-constellation.org/~alcinnz/typograffiti) [alt issue tracker](https://todo.argonaut-constellation.org/~alcinnz/typograffiti) Typograffiti aims to make working with text across a broad range of written languages in multimedia applications easy. Whilst exposing low-level APIs for use by fancier text layout/rendering engines.  Typograffiti is part of [The Argonaut Stack](https://argonaut-constellation.org/) browser engine.@@ -7,5 +8,6 @@ * opengl 3.x * freetype 2.x * harfbuzz 3.3++* LibC++ (for Text dependency)  The demo program additionally requires SDL2.
app/Main.hs view
@@ -32,14 +32,14 @@     let text = pack $ case args of           [] -> unlines [             "Decoder Ring Theatre brings you the continuing adventures",-            "of Canada's greatest superhero, that scourage of the underworld,",+            "of Canada's greatest superhero, that scourge of the underworld,",             "hunter of those who pray upon the innocent,",             "that marvelous masked mystery man",             "known only as The Red Panda!",             "",             "The Red Panda, masked crucader for justice, hides his secret identity",             "as one of the city's wealthiest men in his neverending battle",-            "against crime & corruption. Only his trust driver, Kit Baxter",+            "against crime & corruption. Only his trusty driver, Kit Baxter",             "who joins him in the guise of The Flying Squirrel,",             "knows who wears the mask of The Red Panda!"]           _ -> unwords args
src/Typograffiti/Atlas.hs view
@@ -57,8 +57,10 @@ data GlyphMetrics = GlyphMetrics {     glyphTexBB :: (V2 Int, V2 Int),     -- ^ Bounding box of the glyph in the texture.-    glyphSize :: V2 Int+    glyphSize :: V2 Int,     -- ^ Size of the glyph onscreen.+    glyphOffset :: V2 Int+    -- ^ Left & top bearings. } deriving (Show, Eq)  -- | Cache of rendered glyphs to be composited into place on the GPU.@@ -67,13 +69,15 @@     -- ^ The texture holding the pre-rendered glyphs.     atlasTextureSize :: V2 Int,     -- ^ The size of the texture.-    atlasMetrics :: IntMap GlyphMetrics+    atlasMetrics :: IntMap GlyphMetrics,     -- ^ Mapping from glyphs to their position in the texture.+    atlasScale :: (Float, Float)+    -- ^ Scaling factor for font-units given by Harfbuzz. } deriving (Show)  -- | Initializes an empty atlas. emptyAtlas :: GLuint -> Atlas-emptyAtlas t = Atlas t 0 mempty+emptyAtlas t = Atlas t 0 mempty (0, 0)  -- | Precomputed positioning of glyphs in an `Atlas` texture. data AtlasMeasure = AM {@@ -148,11 +152,10 @@             canon = floor . (* 0.5) . (* 0.015625) . realToFrac . fromIntegral             vecsz = canon <$> V2 (gmWidth metrics) (gmHeight metrics)             vecxb = canon <$> V2 (gmHoriBearingX metrics) (gmHoriBearingY metrics)-            vecyb = canon <$> V2 (gmVertBearingX metrics) (gmVertBearingY metrics)-            vecad = canon <$> V2 (gmHoriAdvance metrics) (gmVertAdvance metrics)             mtrcs = GlyphMetrics {                 glyphTexBB = (pos, pos + vecwh),-                glyphSize = vecsz+                glyphSize = vecsz,+                glyphOffset = vecxb               }         return atlas { atlasMetrics = IM.insert (fromEnum glyph) mtrcs atlasMetrics }     | otherwise = do@@ -165,8 +168,8 @@ -- might need during the life of the 'Atlas'. Character texturization only -- happens once. allocAtlas :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) =>-    GlyphRetriever m -> [Word32] -> m Atlas-allocAtlas cb glyphs = do+    GlyphRetriever m -> [Word32] -> (Float, Float) -> m Atlas+allocAtlas cb glyphs scale = do     AM {..} <- foldM (measure cb 512) emptyAM glyphs     let V2 w h = amWH         xymap = amMap@@ -186,7 +189,7 @@     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 }+    return atlas { atlasTextureSize = V2 w h, atlasScale = scale }  -- | Releases all resources associated with the given 'Atlas'. freeAtlas :: MonadIO m => Atlas -> m ()@@ -202,23 +205,25 @@     case IM.lookup iglyph atlasMetrics of         Nothing -> throwError $ TypograffitiErrorNoMetricsForGlyph iglyph         Just GlyphMetrics {..} -> do-            let x = penx + f x_offset-                y = peny + f y_offset+            let x = penx + f x_offset*fst atlasScale+                y = peny + f y_offset*snd atlasScale                 V2 w h = f' <$> glyphSize+                V2 dx dy = f' <$> glyphOffset+                (x', y') = (x + dx, y - dy)                 V2 aszW aszH = f' <$> atlasTextureSize                 V2 texL texT = f' <$> fst glyphTexBB                 V2 texR texB = f' <$> snd glyphTexBB -                tl = (V2 (x) (y-h), V2 (texL/aszW) (texT/aszH))-                tr = (V2 (x+w) (y-h), V2 (texR/aszW) (texT/aszH))-                br = (V2 (x+w) y, V2 (texR/aszW) (texB/aszH))-                bl = (V2 (x) y, V2 (texL/aszW) (texB/aszH))+                tl = (V2 (x') (y'), V2 (texL/aszW) (texT/aszH))+                tr = (V2 (x'+w) (y'), V2 (texR/aszW) (texT/aszH))+                br = (V2 (x'+w) (y'+h), V2 (texR/aszW) (texB/aszH))+                bl = (V2 (x') (y'+h), V2 (texL/aszW) (texB/aszH)) -            return (penx + f x_advance/150, peny + f y_advance/150,+            return (penx + f x_advance*fst atlasScale, peny + f y_advance*snd atlasScale,                     UV.fromList [tl, tr, br, tl, br, bl] : mLast)   where     f :: Int32 -> Float-    f = fromIntegral+    f =  fromIntegral     f' :: Int -> Float     f' = fromIntegral 
src/Typograffiti/Store.hs view
@@ -31,8 +31,9 @@                                         GlyphInfo(..), GlyphPos(..), FontOptions) import qualified Data.Text.Glyphize     as HB import qualified Data.Text.Lazy         as Txt+import           Foreign.Storable       (peek) import           FreeType.Core.Base-import           FreeType.Core.Types    (FT_Fixed)+import           FreeType.Core.Types    (FT_Fixed, FT_UShort) import           FreeType.Format.Multiple (ft_Set_Var_Design_Coordinates)  import           Typograffiti.Atlas@@ -55,8 +56,12 @@     -- ^ Font as represented by Harfbuzz.     freetype :: FT_Face,     -- ^ Font as represented by FreeType.-    atlases :: TMVar [(IS.IntSet, Atlas)]+    atlases :: TMVar [(IS.IntSet, Atlas)],     -- ^ Glyphs from the font rendered into GPU atleses.+    lineHeight :: Float,+    -- ^ Default lineheight for this font.+    fontScale :: (Float, Float)+    -- ^ Scaling parameters for Harfbuzz layout.   }  -- | Opens a font sized to given value & prepare to render text in it.@@ -67,8 +72,11 @@     m (RichText -> n (AllocatedRendering [TextTransform])) makeDrawTextCached store filepath index fontsize SampleText {..} = do     s <- liftIO $ atomically $ readTMVar $ fontMap store-    font <- case M.lookup (filepath, fontsize, index, fontOptions) s of-        Nothing -> allocFont store filepath index fontsize fontOptions+    let fontOpts' = fontOptions {+        HB.optionScale = Nothing, HB.optionPtEm = Nothing, HB.optionPPEm = Nothing+      }+    font <- case M.lookup (filepath, fontsize, index, fontOpts') s of+        Nothing -> allocFont store filepath index fontsize fontOpts'         Just font -> return font      let glyphs = map (codepoint . fst) $@@ -80,9 +88,10 @@     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 (fontScale font) -    return $ drawLinesWrapper tabwidth minLineHeight $+    let lh = if minLineHeight == 0 then lineHeight font else minLineHeight+    return $ drawLinesWrapper tabwidth lh $         \RichText {..} -> drawGlyphs store atlas $             shape (harfbuzz font) defaultBuffer { HB.text = text } [] @@ -104,8 +113,14 @@     let designCoords = map float2fixed $ HB.fontVarCoordsDesign font'     unless (null designCoords) $ liftIO $ ft_Set_Var_Design_Coordinates font designCoords +    font_ <- liftIO $ peek font+    size <- srMetrics <$> liftIO (peek $ frSize font_)+    let lineHeight = fixed2float $ smHeight size+    let upem = short2float $ frUnits_per_EM font_+    let scale = (short2float (smX_ppem size)/upem/2, short2float (smY_ppem size)/upem/2)+     atlases <- liftIO $ atomically $ newTMVar []-    let ret = Font font' font atlases+    let ret = Font font' font atlases lineHeight scale      atomically $ do         map <- takeTMVar fontMap@@ -114,15 +129,20 @@   where     x2 = (*2)     float2fixed :: Float -> FT_Fixed-    float2fixed = toEnum . fromEnum . (*65536)+    float2fixed = toEnum . fromEnum . (*bits16)+    fixed2float :: FT_Fixed -> Float+    fixed2float = (/bits16) . toEnum . fromEnum+    bits16 = 2**16+    short2float :: FT_UShort -> Float+    short2float = toEnum . fromEnum  -- | Allocates a new Atlas for the given font & glyphset, -- loading it into the atlas cache before returning. allocAtlas' :: (MonadIO m, MonadFail m, MonadError TypograffitiError m) =>-    TMVar [(IS.IntSet, Atlas)] -> FT_Face -> IS.IntSet -> m Atlas-allocAtlas' atlases font glyphset = do+    TMVar [(IS.IntSet, Atlas)] -> FT_Face -> IS.IntSet -> (Float, Float) -> m Atlas+allocAtlas' atlases font glyphset scale = do     let glyphs = map toEnum $ IS.toList glyphset-    atlas <- allocAtlas (glyphRetriever font) glyphs+    atlas <- allocAtlas (glyphRetriever font) glyphs scale      liftIO $ atomically $ do         a <- takeTMVar atlases
src/Typograffiti/Text.hs view
@@ -25,11 +25,12 @@                                         FontOptions (..), defaultFontOptions) import qualified Data.Text.Glyphize     as HB import           FreeType.Core.Base-import           FreeType.Core.Types    (FT_Fixed)+import           FreeType.Core.Types    (FT_Fixed, FT_UShort) import           FreeType.Format.Multiple (ft_Set_Var_Design_Coordinates) import           Data.Text.Lazy         (Text, pack) import qualified Data.Text.Lazy         as Txt import           Data.Word              (Word32)+import           Foreign.Storable       (peek)  import           Typograffiti.Atlas import           Typograffiti.Cache@@ -58,12 +59,12 @@     -- ^ Additional font options offered by Harfbuzz.     minLineHeight :: Float     -- ^ Number of pixels tall each line should be at minimum.-    -- Defaults to 10px.+    -- Defaults to 0 indicate to use the font's default lineheight. }  -- | Constructs a `SampleText` with default values. defaultSample :: SampleText-defaultSample = SampleText [] (pack $ map toEnum [32..126]) 4 defaultFontOptions 10+defaultSample = SampleText [] (pack $ map toEnum [32..126]) 4 defaultFontOptions 0 -- | Appends an OpenType feature callers may use to the `Sample` ensuring its -- glyphs are available. Call after setting `sampleText`. addSampleFeature :: String -> Word32 -> SampleText -> SampleText@@ -133,8 +134,17 @@                                                     (floor $ 26.6 * 2 * h)                                                     (toEnum dpix) (toEnum dpiy) +    font_ <- liftIO $ peek font+    size <- srMetrics <$> liftIO (peek $ frSize font_)+    let lineHeight = if minLineHeight == 0 then fixed2float $ smHeight size else minLineHeight+    let upem = short2float $ frUnits_per_EM font_+    let scale = (short2float (smX_ppem size)/upem/2, short2float (smY_ppem size)/upem/2)+     bytes <- liftIO $ B.readFile filepath-    let font' = HB.createFontWithOptions fontOptions $ HB.createFace bytes $ toEnum index+    let fontOpts' = fontOptions {+            HB.optionScale = Nothing, HB.optionPtEm = Nothing, HB.optionPPEm = Nothing+      }+    let font' = HB.createFontWithOptions fontOpts' $ HB.createFace bytes $ toEnum index     let glyphs = map (codepoint . fst) $             shape font' defaultBuffer {                 HB.text = Txt.replicate (toEnum $ succ $ length sampleFeatures) sampleText@@ -145,17 +155,22 @@     unless (null designCoords) $         liftFreetype $ ft_Set_Var_Design_Coordinates font designCoords -    atlas <- allocAtlas (glyphRetriever font) glyphs'+    atlas <- allocAtlas (glyphRetriever font) glyphs' scale     liftFreetype $ ft_Done_Face font      drawGlyphs <- makeDrawGlyphs-    return $ freeAtlasWrapper atlas $ drawLinesWrapper tabwidth minLineHeight+    return $ freeAtlasWrapper atlas $ drawLinesWrapper tabwidth lineHeight         $ \RichText {..} ->             drawGlyphs atlas $ shape font' defaultBuffer { HB.text = text } features   where     x2 = (*2)     float2fixed :: Float -> FT_Fixed-    float2fixed = toEnum . fromEnum . (*65536)+    float2fixed = toEnum . fromEnum . (*bits16)+    fixed2float :: FT_Fixed -> Float+    fixed2float = (/bits16) . toEnum . fromEnum+    bits16 = 2**16+    short2float :: FT_UShort -> Float+    short2float = toEnum . fromEnum  -- | Variant of `makeDrawText` which initializes FreeType itself. makeDrawText' a b c d =
typograffiti.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12  name:           typograffiti-version:             0.2.0.0+version:             0.2.0.1 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+.@@ -10,9 +10,9 @@ 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+author:         Schell Scivally & Adrian Cochrane+maintainer:     alcinnz@argonaut-constellation.org+copyright:      2018 Schell Scivally, 2023 Adrian Cochrane license:        BSD3 license-file:   LICENSE build-type:     Simple@@ -33,7 +33,7 @@       Typograffiti.Store       Typograffiti.Text       Typograffiti.Rich-  build-depends:       base >=4.12 && <4.13, linear>=1.20, containers >= 0.6,+  build-depends:       base >=4.12 && <4.16, linear>=1.20, containers >= 0.6,                         freetype2 >= 0.2, gl >= 0.8, mtl >= 2.2, stm >= 2.5, text,                         vector >= 0.12, harfbuzz-pure >= 1.0.2, bytestring >= 0.10   hs-source-dirs:      src@@ -42,7 +42,7 @@  executable typograffiti   main-is:             Main.hs-  build-depends:       base >=4.12 && <4.13, typograffiti, sdl2 >= 2.5.4, text, gl, mtl+  build-depends:       base >=4.12 && <4.16, typograffiti, sdl2 >= 2.5.4, text, gl, mtl   hs-source-dirs:      app   default-language:    Haskell2010