{-# LANGUAGE LambdaCase #-} module Image.LaTeX.Render.Pandoc ( -- * Data URIs convertFormulaDataURI , convertAllFormulaeDataURI -- * Separate Files , convertFormulaFiles , convertAllFormulaeFiles -- ** Name Supplies , NameSupply , newNameSupply -- * Scaling , ShrinkSize ) where import Text.Pandoc.Definition import Text.Pandoc.Walk import Image.LaTeX.Render import Codec.Picture import Control.Applicative import Data.IORef import System.FilePath import qualified Data.ByteString.Base64.Lazy as B64 import qualified Data.ByteString.Lazy.Char8 as BS dims :: Image a -> (Int,Int) dims = liftA2 (,) imageWidth imageHeight dimensions :: DynamicImage -> (Int,Int) dimensions (ImageRGB8 i) = dims i dimensions (ImageRGBA8 i) = dims i dimensions (ImageRGB16 i) = dims i dimensions (ImageRGBA16 i) = dims i dimensions (ImageY8 i) = dims i dimensions (ImageY16 i) = dims i dimensions (ImageYA8 i) = dims i dimensions (ImageYA16 i) = dims i dimensions _ = error "Unsupported image format somehow!" -- | Denominator for various dimensions. For high DPI displays, it can be useful to use values of 2 or 4, so that the dimensions -- of the image are a fraction of the actual image size, and the image appears more crisp. Otherwise, a value of 1 will always -- produce sensible, if somewhat pixelated results. type ShrinkSize = Int -- | Convert a formula in a pandoc document to an image, embedding the image into the HTML using Data URIs. convertFormulaDataURI :: ShrinkSize -- ^ Denominator for all dimensions. Useful for displaying high DPI images in small sizes, for retina displays. Otherwise set to 1. -> EnvironmentOptions -- ^ System environment settings -> (MathType -> FormulaOptions) -- ^ LaTeX environment settings for each equation type (display and inline) -> Inline -> IO Inline convertFormulaDataURI sh o1 o2 (Math t s) = imageForFormula o1 (o2 t) s >>= \case Left e -> return $ Str (show e) Right (b,i) -> let Right bs = encodeDynamicPng i dataUri = "data:image/png;base64," ++ BS.unpack (B64.encode bs) (ow,oh) = dimensions i (w,h) = (ow `div` sh, oh `div` sh) in return $ RawInline (Format "html") $ " "display-math") ++ " style=\"margin:0; vertical-align:-" ++ show (b `div` sh) ++ "px;\"/>" convertFormulaDataURI sh o1 o2 x = return x -- | Convert all formulae in a pandoc document to images, embedding the images into the HTML using Data URIs. convertAllFormulaeDataURI :: ShrinkSize -- ^ Denominator for all dimensions. Useful for displaying high DPI images in small sizes, for retina displays. Otherwise set to 1. -> EnvironmentOptions -- ^ System environment settings -> (MathType -> FormulaOptions) -- ^ LaTeX environment settings for each equation type (display and inline) -> Pandoc -> IO Pandoc convertAllFormulaeDataURI a b c = walkM $ convertFormulaDataURI a b c -- | If we use files for the images, we need some way of naming the image files we produce -- A NameSupply provides us with a source of unique names via an ever-increasing integer. -- It's important that any invocation of 'convertFormulaFiles' or 'convertAllFormulaeFiles' -- that shares the same image storage directory will also use the same name supply, or they -- will overwrite each others images. type NameSupply = IORef Int -- | Create a new name supply. newNameSupply :: IO NameSupply newNameSupply = newIORef 0 -- | Convert a formula in a pandoc document to an image, embedding the image into the HTML using Data URIs. convertFormulaFiles :: NameSupply -- ^ Unique file name supply. Reuse this for every invocation that shares the same image directory. -> FilePath -- ^ Name of image directory where images will be stored -> ShrinkSize -- ^ Denominator for all dimensions. Useful for displaying high DPI images in small sizes, for retina displays. Otherwise set to 1. -> EnvironmentOptions -- ^ System environment settings -> (MathType -> FormulaOptions) -- ^ LaTeX environment settings for each equation type (display and inline) -> Inline -> IO Inline convertFormulaFiles ns bn sh o1 o2 (Math t s) = imageForFormula o1 (o2 t) s >>= \case Left e -> return $ Str (show e) Right (b,i) -> do fn <- readIORef ns modifyIORef ns (+1) let uri = bn show fn <.> "png" (ow,oh) = dimensions i (w,h) = (ow `div` sh, oh `div` sh) _ <- writeDynamicPng uri i return $ RawInline (Format "html") $ " "display-math") ++ " style=\"margin:0; vertical-align:-" ++ show (b `div` sh) ++ "px;\"/>" convertFormulaFiles _ _ _ _ _ x = return x convertAllFormulaeFiles :: NameSupply -- ^ Unique file name supply. Reuse this for every invocation that shares the same image directory. -> FilePath -- ^ Name of image directory where images will be stored -> ShrinkSize -- ^ Denominator for all dimensions. Useful for displaying high DPI images in small sizes, for retina displays. Otherwise set to 1. -> EnvironmentOptions -- ^ System environment settings -> (MathType -> FormulaOptions) -- ^ LaTeX environment settings for each equation type (display and inline) -> Pandoc -> IO Pandoc convertAllFormulaeFiles x y a b c = walkM $ convertFormulaFiles x y a b c