{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TemplateHaskell #-}
---------------------------------------------------------
-- |
-- Copyright   : (c) 2006-2016, alpheccar.org
-- License     : BSD-style
--
-- Maintainer  : misc@NOSPAMalpheccar.org
-- Stability   : experimental
-- Portability : portable
--
-- AFM Parser
---------------------------------------------------------
module Graphics.PDF.Fonts.Encoding(
      getEncoding
    , Encodings(..)
    , PostscriptName
    , parseMacEncoding
    ) where

import Data.ByteString (ByteString)
import Data.FileEmbed (embedFile)
import Graphics.PDF.LowLevel.Types
import qualified Data.Map.Strict as M
import qualified Data.ByteString.Char8 as C
import Data.Char(digitToInt)
import Data.Maybe(mapMaybe)

type PostscriptName = String

data Encodings = AdobeStandardEncoding
               | ZapfDingbatsEncoding
               deriving(Encodings -> Encodings -> Bool
(Encodings -> Encodings -> Bool)
-> (Encodings -> Encodings -> Bool) -> Eq Encodings
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Encodings -> Encodings -> Bool
$c/= :: Encodings -> Encodings -> Bool
== :: Encodings -> Encodings -> Bool
$c== :: Encodings -> Encodings -> Bool
Eq)

isLine :: C.ByteString -> Bool
isLine :: ByteString -> Bool
isLine ByteString
c | Bool -> Bool
not (ByteString -> Bool
C.null ByteString
c) = ByteString -> Char
C.head ByteString
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'#'
         | Bool
otherwise = Bool
False

from4Hexa :: C.ByteString -> Int
from4Hexa :: ByteString -> Int
from4Hexa ByteString
a = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> ([(Int, Int)] -> [Int]) -> [(Int, Int)] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> Int) -> [(Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
x,Int
y) -> Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
y) ([(Int, Int)] -> Int) -> [(Int, Int)] -> Int
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt ([Char] -> [Int]) -> (ByteString -> [Char]) -> ByteString -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Char]
C.unpack (ByteString -> [Int]) -> ByteString -> [Int]
forall a b. (a -> b) -> a -> b
$ ByteString
a)  ((Integer -> Int) -> [Integer] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Integer
x -> Int
16Int -> Integer -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
x) ([Integer
3,Integer
2,Integer
1,Integer
0] :: [Integer]))

from3Octal:: C.ByteString -> Int
from3Octal :: ByteString -> Int
from3Octal ByteString
a = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> ([(Int, Int)] -> [Int]) -> [(Int, Int)] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> Int) -> [(Int, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
x,Int
y) -> Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
y) ([(Int, Int)] -> Int) -> [(Int, Int)] -> Int
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt ([Char] -> [Int]) -> (ByteString -> [Char]) -> ByteString -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Char]
C.unpack (ByteString -> [Int]) -> ByteString -> [Int]
forall a b. (a -> b) -> a -> b
$ ByteString
a)  ((Integer -> Int) -> [Integer] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Integer
x -> Int
8Int -> Integer -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
x) ([Integer
2,Integer
1,Integer
0] :: [Integer]))


toData :: [C.ByteString] -> Maybe (PostscriptName,Char)
toData :: [ByteString] -> Maybe ([Char], Char)
toData (ByteString
a:ByteString
b:[ByteString]
_) = ([Char], Char) -> Maybe ([Char], Char)
forall a. a -> Maybe a
Just (ByteString -> [Char]
C.unpack ByteString
a,Int -> Char
forall a. Enum a => Int -> a
toEnum (Int -> Char) -> (ByteString -> Int) -> ByteString -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int
from4Hexa (ByteString -> Char) -> ByteString -> Char
forall a b. (a -> b) -> a -> b
$ ByteString
b)
toData [ByteString]
_ = Maybe ([Char], Char)
forall a. Maybe a
Nothing

toMacData :: [C.ByteString] -> Maybe (PostscriptName,GlyphCode)
toMacData :: [ByteString] -> Maybe ([Char], GlyphCode)
toMacData (ByteString
name:ByteString
_:ByteString
mac:[ByteString]
_) | ByteString -> [Char]
C.unpack ByteString
mac [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"-" = Maybe ([Char], GlyphCode)
forall a. Maybe a
Nothing
                         | Bool
otherwise = ([Char], GlyphCode) -> Maybe ([Char], GlyphCode)
forall a. a -> Maybe a
Just (ByteString -> [Char]
C.unpack ByteString
name,Int -> GlyphCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
from3Octal ByteString
mac))
toMacData [ByteString]
_ = Maybe ([Char], GlyphCode)
forall a. Maybe a
Nothing

parseGlyphListEncoding :: ByteString -> IO (M.Map PostscriptName Char)
parseGlyphListEncoding :: ByteString -> IO (Map [Char] Char)
parseGlyphListEncoding ByteString
l = Map [Char] Char -> IO (Map [Char] Char)
forall (m :: * -> *) a. Monad m => a -> m a
return ([([Char], Char)] -> Map [Char] Char
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([([Char], Char)] -> Map [Char] Char)
-> (ByteString -> [([Char], Char)])
-> ByteString
-> Map [Char] Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe ([Char], Char))
-> [ByteString] -> [([Char], Char)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([ByteString] -> Maybe ([Char], Char)
toData  ([ByteString] -> Maybe ([Char], Char))
-> (ByteString -> [ByteString])
-> ByteString
-> Maybe ([Char], Char)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> [ByteString]
C.split Char
';') ([ByteString] -> [([Char], Char)])
-> (ByteString -> [ByteString]) -> ByteString -> [([Char], Char)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Bool) -> [ByteString] -> [ByteString]
forall a. (a -> Bool) -> [a] -> [a]
filter ByteString -> Bool
isLine ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
C.lines (ByteString -> Map [Char] Char) -> ByteString -> Map [Char] Char
forall a b. (a -> b) -> a -> b
$ ByteString
l)

pdfencodings :: ByteString
pdfencodings :: ByteString
pdfencodings = $(embedFile "Encodings/pdfencodings.txt")

parseMacEncoding :: IO (M.Map PostscriptName GlyphCode)
parseMacEncoding :: IO (Map [Char] GlyphCode)
parseMacEncoding = do
    Map [Char] GlyphCode -> IO (Map [Char] GlyphCode)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map [Char] GlyphCode -> IO (Map [Char] GlyphCode))
-> (ByteString -> Map [Char] GlyphCode)
-> ByteString
-> IO (Map [Char] GlyphCode)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [([Char], GlyphCode)] -> Map [Char] GlyphCode
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([([Char], GlyphCode)] -> Map [Char] GlyphCode)
-> (ByteString -> [([Char], GlyphCode)])
-> ByteString
-> Map [Char] GlyphCode
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe ([Char], GlyphCode))
-> [ByteString] -> [([Char], GlyphCode)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([ByteString] -> Maybe ([Char], GlyphCode)
toMacData ([ByteString] -> Maybe ([Char], GlyphCode))
-> (ByteString -> [ByteString])
-> ByteString
-> Maybe ([Char], GlyphCode)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> [ByteString]
C.split Char
'\t') ([ByteString] -> [([Char], GlyphCode)])
-> (ByteString -> [ByteString])
-> ByteString
-> [([Char], GlyphCode)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [ByteString]
forall a. [a] -> [a]
tail ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
C.lines (ByteString -> IO (Map [Char] GlyphCode))
-> ByteString -> IO (Map [Char] GlyphCode)
forall a b. (a -> b) -> a -> b
$ ByteString
pdfencodings

glyphlist :: ByteString
glyphlist :: ByteString
glyphlist = $(embedFile "Encodings/glyphlist.txt")

zapfdingbats :: ByteString
zapfdingbats :: ByteString
zapfdingbats = $(embedFile "Encodings/zapfdingbats.txt")

getEncoding :: Encodings -> IO (M.Map PostscriptName Char)
getEncoding :: Encodings -> IO (Map [Char] Char)
getEncoding Encodings
AdobeStandardEncoding = ByteString -> IO (Map [Char] Char)
parseGlyphListEncoding ByteString
glyphlist
getEncoding Encodings
ZapfDingbatsEncoding= ByteString -> IO (Map [Char] Char)
parseGlyphListEncoding ByteString
zapfdingbats