hpdft-0.4.6.0: src/PDF/CFF.hs
{-# LANGUAGE OverloadedStrings #-}
module PDF.CFF (encoding) where
import Numeric (readInt)
import Data.Char (chr, intToDigit)
import Data.List (isPrefixOf)
import Data.Word
import Data.Bits
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Lazy as BSL
import Data.Attoparsec.ByteString (Parser, parseOnly, word8, string)
import qualified Data.Attoparsec.ByteString as AP
import Data.Attoparsec.Combinator
import Control.Applicative
import qualified Data.Map as Map
import qualified Data.Text as T
import PDF.Definition
type SID = Integer
test f = do
c <- BS.readFile f
return $ encoding c
encoding :: ByteString -> Encoding
encoding c =
case parseOnly (header >> index *> index) c of
Left _ -> NullMap
Right ds | null ds -> NullMap
Right ds ->
let encodings = concatMap (parseEncoding c) ds
charset = concatMap (parseCharset c) ds
strings = case parseOnly stringInd c of
Right arr -> arr
Left _ -> []
in Encoding $ Map.fromListWith (flip const) $
map (findEncodings strings) $ zip charset encodings
where
findEncodings strings (char,enc) =
case char of
s | s > 390 ->
let idx = fromInteger (char - 390 - 1)
in (enc, stringToText $ safeAt strings idx)
| s > 95 -> (enc, sidToText s)
| otherwise -> (enc, T.singleton enc)
safeAt xs i = if i >= 0 && i < length xs then xs !! i else ""
-- defined in String INDEX of each font
stringToText "a113" = "‡"
stringToText "a114" = "・"
stringToText "trianglesolid" = "▲"
stringToText x = "[CFF:String " <> T.pack x <> "]"
-- pre-defined in Appendix C of CFF specs
sidToText n =
let i = fromInteger n
chars = complementSID 0 predefinedChars
in if i >= 0 && i < length chars then T.singleton (chars !! i) else "?"
parseTopDictInd :: ByteString -> [ByteString]
parseTopDictInd c = case parseOnly (header >> index *> index) c of
Right ds -> ds
Left _ -> []
parseEncoding :: ByteString -> ByteString -> [Char]
parseEncoding c d = case parseOnly (many1 dict) d of
Right dictData -> case lookup [16] dictData of
Just (DictInt 0:[]) -> []
Just (DictInt 1:[]) -> []
Just (DictInt n:[]) ->
case parseOnly encodingArray $ BS.drop (fromIntegral n) c of
Right arr -> map (chr . fromInteger) arr
Left _ -> []
Just _ -> []
Nothing -> []
Left _ -> []
parseFontname c d = case parseOnly (many1 dict) d of
Right dictData -> case lookup [2] dictData of
Just (DictInt n:[]) ->
case parseOnly stringInd c of
Right arr ->
let idx = fromIntegral n - 390 - 1
in if idx >= 0 && idx < length arr then [arr !! idx] else []
Left _ -> []
Just _ -> []
Nothing -> []
Left _ -> []
parseCharset c d = case parseOnly (many1 dict) d of
Right dictData -> case lookup [15] dictData of
Just (DictInt offset:[]) ->
case parseOnly (charsetData $ charStringsInd c dictData) $
BS.drop (fromIntegral offset) c of
Right arr -> arr
Left _ -> []
Just _ -> []
Nothing -> []
Left _ -> []
charStringsInd c dictData =
case lookup [17] dictData of
Just (DictInt offset:[]) ->
case parseOnly index (BS.drop (fromIntegral offset) c) of
Right ind -> ind
Left _ -> []
Nothing -> []
nameInd = map BSC.unpack <$> (header *> index)
dictInd = BSC.concat <$> (header >> index *> index)
stringInd = map BSC.unpack <$> (header >> index >> index *> index)
charsetData :: [ByteString] -> Parser [Integer]
charsetData ind = do
format <- getCard 1
charsetObj format
where
-- .notdef must be excluded, so minus one
charsetObj 0 = count (length ind - 1) getSID
encodingArray :: Parser [Integer]
encodingArray = do
format <- getCard 1
p <- fromInteger <$> getCard 1
encodeObj format p
where
encodeObj :: Integer -> Int -> Parser [Integer]
encodeObj 0 p = count (p - 1) (getCard 1)
encodeObj 1 p = concat <$> count p getRange1
encodeObj _ _ = return []
getRange1 :: Parser [Integer]
getRange1 = do
first <- getCard 1
nleft <- getCard 1
return $ [first .. first + nleft]
data DictOp = DictInt Int | DictReal Double
deriving (Show)
dict = (flip (,)) <$> (manyTill dictOp (try $ lookAhead dictKey)) <*> dictKey
dictOp :: Parser DictOp
dictOp = do
b0 <- fromInteger <$> getCard 1
opEnc b0
where
opEnc :: Int -> Parser DictOp
opEnc b0 | b0 >= 32 && b0 <= 246 = return $ DictInt $ b0 - 139
| b0 >= 247 && b0 <= 250 = do
b1 <- fromInteger <$> getCard 1
return $ DictInt $ (b0 - 247) * 256 + b1 + 108
| b0 >= 251 && b0 <= 254 = do
b1 <- fromInteger <$> getCard 1
return $ DictInt $ - (b0 - 251) * 256 - b1 - 108
| b0 == 28 = do
b1 <- fromInteger <$> getCard 1
b2 <- fromInteger <$> getCard 1
return $ DictInt $ b1 `shiftL` 8 .|. b2
| b0 == 29 = do
b1 <- fromInteger <$> getCard 1
b2 <- fromInteger <$> getCard 1
b3 <- fromInteger <$> getCard 1
b4 <- fromInteger <$> getCard 1
return $ DictInt $ b1 `shiftL` 24 .|. b2 `shiftL` 16 .|. b3 `shiftL` 8 .|. b4
| b0 == 30 = do
r <- many1 $ AP.satisfy (\w -> (240 .|. w) `xor` 255 /= 0)
f <- getCard 1
return $ DictReal $ readNibble r f
| otherwise = fail (show b0)
readNibble s1 s2 = 0
dictKey :: Parser [Word8]
dictKey = do
key <- AP.choice [ try $ many1 $ AP.satisfy $ AP.inClass "\0-\5\13-\18"
, try $ (flip (flip (:) . (:[])))
<$> AP.satisfy (==12) <*> (AP.satisfy $ AP.inClass "\0-\8\20-\23\30-\38")
]
return key
index :: Parser [ByteString]
index = do
indexCount <- fromInteger <$> getCard 2
offSize <- fromInteger <$> getCard 1
offsets <- map fromInteger <$> count (indexCount+1) (getCard offSize)
indexData <- repeatFor offsets
return indexData
where
repeatFor ls = sequence $ map AP.take $ differenciate ls
differenciate ls = tail $ zipWith subtract (0:ls) ls
header :: Parser Integer
header = do
major <- getCard 1
minor <- getCard 1
hrdSize <- getCard 1
offSize <- getCard 1
return $ major
getCard :: Int -> Parser Integer
getCard n = fromBytes <$> AP.take n
getSID :: Parser SID
getSID = fromBytes <$> AP.take 2
fromBytes :: ByteString -> Integer
fromBytes = BS.foldl' f 0
where
f a b = a `shiftL` 8 .|. fromIntegral b
complementSID _ [] = []
complementSID i arr@((n,c):rest)
| i == n = c:(complementSID (i+1) rest)
| otherwise = ' ':(complementSID (i+1) arr)
predefinedChars =
[ (1, ' ')
, (2, '!')
, (3, '"')
, (4, '#')
, (5, '$')
, (6, '%')
, (7, '&')
, (8, '’')
, (9, '(')
, (10, ')')
, (11, '*')
, (12, '+')
, (13, ',')
, (14, '-')
, (15, '.')
, (16, '/')
, (17, '0')
, (18, '1')
, (19, '2')
, (20, '3')
, (21, '4')
, (22, '5')
, (23, '6')
, (24, '7')
, (25, '8')
, (26, '9')
, (27, ':')
, (28, ';')
, (29, '<')
, (30, '=')
, (31, '>')
, (32, '?')
, (33, '@')
, (34, 'A')
, (35, 'B')
, (36, 'C')
, (37, 'D')
, (38, 'E')
, (39, 'F')
, (40, 'G')
, (41, 'H')
, (42, 'I')
, (43, 'J')
, (44, 'K')
, (45, 'L')
, (46, 'M')
, (47, 'N')
, (48, 'O')
, (49, 'P')
, (50, 'Q')
, (51, 'R')
, (52, 'S')
, (53, 'T')
, (54, 'U')
, (55, 'V')
, (56, 'W')
, (57, 'X')
, (58, 'Y')
, (59, 'Z')
, (60, '{')
, (61, '/')
, (62, '}')
, (63, '^')
, (64, '_')
, (65, '‘')
, (66, 'a')
, (67, 'b')
, (68, 'c')
, (69, 'd')
, (70, 'e')
, (71, 'f')
, (72, 'g')
, (73, 'h')
, (74, 'i')
, (75, 'j')
, (76, 'k')
, (77, 'l')
, (78, 'm')
, (79, 'n')
, (80, 'o')
, (81, 'p')
, (82, 'q')
, (83, 'r')
, (84, 's')
, (85, 't')
, (86, 'u')
, (87, 'v')
, (88, 'w')
, (89, 'x')
, (90, 'y')
, (91, 'z')
, (92, '[')
, (93, 'ˉ')
, (94, ']')
, (95, '~')
, (96, '¡')
, (97, '¢')
, (98, '£')
, (99, '/')
, (100, '¥')
, (101, 'ƒ')
, (102, '§')
, (103, '$')
, (104, '\'')
, (105, '“')
, (106, '«')
, (107, '‹')
, (108, '›')
, (109, 'fi')
, (110, 'fl')
, (111, '–')
, (112, '†')
, (113, '‡')
, (114, '·')
, (115, '❡')
, (116, '・')
, (117, '‚')
, (118, '„')
, (119, '”')
, (120, '»')
, (121, '…')
, (122, '‰')
, (123, '¿')
, (124, '`')
, (125, '´')
, (126, '^')
, (127, '~')
, (128, '¯')
, (129, '˘')
, (130, '˙')
, (131, '¨')
, (132, '°')
, (133, '¸')
, (134, '˝')
, (135, '˛')
, (136, 'ˇ')
, (137, '—')
, (138, 'Æ')
, (139, 'ª')
, (140, 'Ł')
, (141, 'Ø')
, (142, 'Œ')
, (143, 'º')
, (144, 'æ')
, (145, 'ı')
, (146, 'ł')
, (147, 'ø')
, (148, 'œ')
, (149, 'ẞ')
, (150, '¹')
, (151, '¬')
, (152, 'µ')
, (153, '™')
, (154, 'Ð')
, (155, '½')
, (156, '±')
, (157, 'Þ')
, (158, '¼')
, (159, '÷')
, (160, '¦')
, (161, '°')
, (162, 'þ')
, (163, '¾')
, (164, '²')
, (165, '®')
, (166, '-')
, (167, 'ð')
, (168, '×')
, (169, '³')
, (170, 'Ⓒ')
, (171, 'Á')
, (172, 'Â')
, (173, 'Ä')
, (174, 'À')
, (175, 'Å')
, (176, 'Ã')
, (177, 'Ç')
, (178, 'É')
, (179, 'Ê')
, (180, 'Ë')
, (181, 'È')
, (182, 'Í')
, (183, 'Î')
, (184, 'Ï')
, (185, 'Ì')
, (186, 'Ñ')
, (187, 'Ó')
, (188, 'Ô')
, (189, 'Ö')
, (190, 'Ò')
, (191, 'Õ')
, (192, 'Š')
, (193, 'Ú')
, (194, 'Û')
, (195, 'Ü')
, (196, 'Ù')
, (197, 'Ý')
, (198, 'Ÿ')
, (199, 'Ž')
, (200, 'á')
, (201, 'â')
, (202, 'ä')
, (203, 'à')
, (204, 'å')
, (205, 'ã')
, (206, 'ç')
, (207, 'é')
, (208, 'ê')
, (209, 'ë')
, (210, 'è')
, (211, 'í')
, (212, 'î')
, (213, 'ï')
, (214, 'ì')
, (215, 'ñ')
, (216, 'ó')
, (217, 'ô')
, (218, 'ö')
, (219, 'ò')
, (220, 'õ')
, (221, 'š')
, (222, 'ú')
, (223, 'û')
, (224, 'ü')
, (225, 'ù')
, (226, 'ý')
, (227, 'ÿ')
, (228, 'ž')
]