hpdft-0.1.1.1: 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 Debug.Trace
import PDF.Definition
type SID = Integer
test f = do
c <- BS.readFile f
return $ encoding c
encoding :: ByteString -> Encoding
encoding c =
Encoding $ map findEncodings $ zip charset encodings
where
ds = parseTopDictInd c
encodings = concatMap (parseEncoding c) ds
charset = concatMap (parseCharset c) ds
fontname = concat $ map (parseFontname c) ds
strings = case parseOnly stringInd c of
Right arr -> arr
Left e -> error "Failed to parse STRING Index"
findEncodings :: (SID, Char) -> (Char, String)
findEncodings (char,enc) =
case char of
s | s > 390 -> (enc, stringToText $ strings !! fromInteger (char - 390 - 1))
| s > 95 -> (enc, sidToText s)
| otherwise -> (enc, [enc])
-- defined in String INDEX of each font
stringToText "a113" = "‡"
stringToText "a114" = "・"
stringToText "trianglesolid" = "▲"
stringToText x = "[CFF:String " <> x <> "]"
-- pre-defined in Appendix C of CFF specs
sidToText n = [complementSID 0 predefinedChars !! fromInteger n]
parseTopDictInd :: ByteString -> [ByteString]
parseTopDictInd c = case parseOnly (header >> index *> index) c of
Right ds -> ds
Left e -> error "Can not find Top DICT INDEX"
parseEncoding :: ByteString -> ByteString -> [Char]
parseEncoding c d = case parseOnly (many1 dict) d of
-- '16' is key for 'Encoding' in Top DICT
Right dictData -> case lookup [16] dictData of
Just (DictInt 0:[]) -> []
Just (DictInt 1:[]) -> [] -- Expert Encoding (not supported)
Just (DictInt n:[]) -> -- n is offset
case parseOnly encodingArray $ BS.drop n c of
Right arr -> map (chr . fromInteger) arr
Left e -> error "Failed to parse Encoding Array"
Just a -> error (show a)
Nothing -> error $ "No Encodind Array in " ++ show dictData
Left _ -> error "Failed to parse Top DICT in CFF"
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 -> arr !! (n - 390 - 1) -- 390 seems to be a magic number
Left e -> error "Failed to parse Fontname"
Just a -> error (show a)
Nothing -> error $ "No Fontname in " <> show dictData
Left _ -> error "Failed to parse Top DICT in CFF"
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 offset c of
Right arr -> arr
Left _ -> error ""
Just a -> error (show a)
Nothing -> error $ "No Charset in " <> show dictData
Left _ -> error "Failed to parse Top DICT in CFF"
charStringsInd c dictData =
case lookup [17] dictData of
Just (DictInt offset:[]) ->
case parseOnly index (BS.drop offset c) of
Right [] -> error "failed to get CharStrings"
Right ind -> ind
Left "" -> error "failed to get CharStrings"
Nothing -> error $ "No CharStrings in " <> show dictData
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 _ p = error "CFF Supplement Format is not supported."
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 = error (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, 'ž')
]