@@ 22,7 22,7 @@ import Control.Concurrent.STM (TMVar, atomically, newTMVar, putTMVar,
import Control.Monad.Except (MonadError (..), runExceptT, ExceptT (..))
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Fail (MonadFail (..))
-import Control.Monad (unless)
+import Control.Monad (unless, forM)
import Data.Map (Map)
import qualified Data.Map as M
import qualified Data.IntSet as IS
@@ 135,12 135,46 @@ allocAtlas' atlases font glyphset = do
putTMVar atlases $ ((glyphset, atlas):a)
return atlas
+-- | Frees fonts identified by filepath, index, and\/or fontsize.
+-- Returns the glyphsets covered by their newly-freed atlases in case
+-- callers wish to make an informed reallocation.
+freeFonts :: (MonadIO m, MonadError TypograffitiError m) =>
+ FontStore n -> Maybe FilePath -> Maybe Int -> Maybe GlyphSize -> m IS.IntSet
+freeFonts store filepath index size = do
+ let test (filepath', size', index', _) = case (filepath, index, size) of
+ (Just f, Just i, Just s) -> filepath' == f && index' == i && size' == s
+ (Nothing,Just i, Just s) -> index' == i && size' == s
+ (Just f, Nothing,Just s) -> filepath' == f && size' == s
+ (Nothing,Nothing,Just s) -> size' == s
+ (Just f, Just i, Nothing)-> filepath' == f && index' == i
+ (Nothing,Just i, Nothing)-> index' == i
+ (Just f, Nothing,Nothing)-> filepath' == f
+ (Nothing,Nothing,Nothing)-> True
+ fonts <- liftIO $ atomically $ do
+ fonts <- readTMVar $ fontMap store
+ putTMVar (fontMap store) $ M.filterWithKey (\k _ -> not $ test k) fonts
+ return fonts
+
+ glyphsets <- forM [v | (k, v) <- M.toList fonts, test k] $ \font -> do
+ liftFreetype $ ft_Done_Face $ freetype font
+ -- Harfbuzz font auto-frees.
+ atlases' <- liftIO $ atomically $ readTMVar $ atlases font
+ glyphsets <- forM atlases' $ \(glyphset, atlas) -> do
+ freeAtlas atlas
+ return glyphset
+ return $ IS.unions glyphsets
+ return $ IS.unions glyphsets
+
-- | Runs the given callback with a new `FontStore`.
-- Due to FreeType limitations this font store should not persist outside the callback.
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)
+withFontStore cb = ft_With_FreeType $ \lib -> runExceptT $ do
+ store <- newFontStore lib
+ ret <- cb store
+ freeFonts store Nothing Nothing Nothing
+ return ret
-- | Allocates a new FontStore wrapping given FreeType state.
newFontStore :: (MonadIO m, MonadError TypograffitiError m,