{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE UndecidableInstances #-}

module Data.Sixel.Internal where

import Codec.Picture
import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr
import System.IO.Temp (withSystemTempDirectory)
import System.Process (readProcessWithExitCode)

foreign import ccall "bufsize" c_bufsize :: CInt -> CInt -> IO CInt

foreign import ccall "img2sixel" c_img2sixel :: Ptr () -> Ptr () -> CInt -> CInt -> IO CInt
foreign import ccall "img2palettized_sixel" c_img2palettized_sixel :: Ptr () -> Ptr () -> Ptr () -> CInt -> CInt -> IO CInt

data LatexStr
  = LatexStr
      { LatexStr -> String
toLatexStr :: String,
        LatexStr -> Float
strSize :: Float
      }
  deriving (LatexStr -> LatexStr -> Bool
(LatexStr -> LatexStr -> Bool)
-> (LatexStr -> LatexStr -> Bool) -> Eq LatexStr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LatexStr -> LatexStr -> Bool
== :: LatexStr -> LatexStr -> Bool
$c/= :: LatexStr -> LatexStr -> Bool
/= :: LatexStr -> LatexStr -> Bool
Eq)

latex :: String -> LatexStr
latex :: String -> LatexStr
latex String
str = String -> Float -> LatexStr
LatexStr String
str Float
2.5

math :: String -> LatexStr
math :: String -> LatexStr
math String
str = String -> Float -> LatexStr
LatexStr (String
"$" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"$") Float
2.5

latexStr :: String -> Float -> String
latexStr :: String -> Float -> String
latexStr String
str Float
size =
  String
"\\documentclass[border=2pt]{standalone}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\usepackage{amsmath}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\usepackage{graphicx}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\usepackage{varwidth}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\begin{document}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\begin{varwidth}{\\linewidth}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\scalebox{"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ Float -> String
forall a. Show a => a -> String
show Float
size
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"}{"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\end{varwidth}"
    String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\end{document}"

latex2img :: LatexStr -> IO (Either String DynamicImage)
latex2img :: LatexStr -> IO (Either String DynamicImage)
latex2img (LatexStr String
str Float
size) =
  String
-> (String -> IO (Either String DynamicImage))
-> IO (Either String DynamicImage)
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
String -> (String -> m a) -> m a
withSystemTempDirectory String
"sixel" ((String -> IO (Either String DynamicImage))
 -> IO (Either String DynamicImage))
-> (String -> IO (Either String DynamicImage))
-> IO (Either String DynamicImage)
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
    String -> String -> IO ()
writeFile (String
dir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/sixel.tex") (String -> Float -> String
latexStr String
str Float
size)
    (_, outlog, errlog) <- String -> [String] -> String -> IO (ExitCode, String, String)
readProcessWithExitCode String
"pdflatex" [String
"-output-directory=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dir, String
dir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/sixel.tex"] String
""
    readProcessWithExitCode "gs" ["-dSAFER", "-r75", "-sDEVICE=png16m", "-o", dir ++ "/sixel.png", dir ++ "/sixel.pdf"] ""
    readImage (dir ++ "/sixel.png") >>= \case
      Left String
err -> Either String DynamicImage -> IO (Either String DynamicImage)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String DynamicImage -> IO (Either String DynamicImage))
-> Either String DynamicImage -> IO (Either String DynamicImage)
forall a b. (a -> b) -> a -> b
$ String -> Either String DynamicImage
forall a b. a -> Either a b
Left (String -> Either String DynamicImage)
-> String -> Either String DynamicImage
forall a b. (a -> b) -> a -> b
$ String
"can not read sixel.png. \n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
err String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
errlog String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
outlog
      Right DynamicImage
img -> Either String DynamicImage -> IO (Either String DynamicImage)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String DynamicImage -> IO (Either String DynamicImage))
-> Either String DynamicImage -> IO (Either String DynamicImage)
forall a b. (a -> b) -> a -> b
$ DynamicImage -> Either String DynamicImage
forall a b. b -> Either a b
Right DynamicImage
img