{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
module Graphics.PDF.Fonts.Type1(
IsFont
, GlyphSize
, Type1Font(..)
, AFMData
, Type1FontStructure(..)
, getAfmData
, mkType1FontStructure
) where
import Graphics.PDF.LowLevel.Types
import Graphics.PDF.Resources
import qualified Data.Map.Strict as M
import Graphics.PDF.Fonts.Font
import Graphics.PDF.Fonts.Encoding
import Graphics.PDF.Fonts.FontTypes
import Graphics.PDF.Fonts.AFMParser (AFMFont, getFont, parseFont)
import Data.List
data Type1Font = Type1Font FontStructure (PDFReference EmbeddedFont)
instance IsFont Type1Font where
getDescent (Type1Font fs _) s = trueSize s $ descent fs
getHeight (Type1Font fs _) s = trueSize s $ height fs
getKern (Type1Font fs _) s a b = trueSize s $ M.findWithDefault 0 (GlyphPair a b) (kernMetrics fs)
glyphWidth (Type1Font fs _) s a = trueSize s $ M.findWithDefault 0 a (widthData fs)
charGlyph (Type1Font fs _) c = M.findWithDefault 0 c (encoding fs)
name (Type1Font fs _) = baseFont fs
hyphenGlyph (Type1Font fs _) = hyphen fs
spaceGlyph (Type1Font fs _) = space fs
data AFMData = AFMData AFMFont
data Type1FontStructure = Type1FontStructure FontData FontStructure
getAfmData :: FilePath -> IO AFMData
getAfmData path = do
Just r <- parseFont (Right path)
return (AFMData r)
mkType1FontStructure :: FontData -> AFMData -> IO (Maybe Type1FontStructure)
mkType1FontStructure pdfRef (AFMData f) = do
theEncoding <- getEncoding AdobeStandardEncoding
maybeFs <- getFont (Right f) theEncoding Nothing
case maybeFs of
Just theFont ->
return . Just $ Type1FontStructure pdfRef theFont
Nothing -> return Nothing
instance PdfResourceObject Type1Font where
toRsrc (Type1Font f ref) =
AnyPdfObject . PDFDictionary . M.fromList $
[(PDFName "Type",AnyPdfObject . PDFName $ "Font")
, (PDFName "Subtype",AnyPdfObject . PDFName $ "Type1")
, (PDFName "BaseFont",AnyPdfObject . PDFName $ baseFont f)
, (PDFName "FirstChar",AnyPdfObject . PDFInteger $ (fromIntegral firstChar))
, (PDFName "LastChar",AnyPdfObject . PDFInteger $ (fromIntegral lastChar))
, (PDFName "Widths",AnyPdfObject $ widths)
, (PDFName "FontDescriptor", AnyPdfObject descriptor)
]
where
codes = map fst . M.toList $ widthData f
firstChar = head . sort $ codes
lastChar = head . reverse . sort $ codes
findWidth c = PDFInteger . fromIntegral $ M.findWithDefault 0 c (widthData f)
widths = map findWidth [firstChar .. lastChar]
bbox = map AnyPdfObject .fontBBox $ f
descriptor = PDFDictionary . M.fromList $
[ (PDFName "Type",AnyPdfObject . PDFName $ "Font")
, (PDFName "Subtype",AnyPdfObject . PDFName $ "Type1")
, (PDFName "BaseFont",AnyPdfObject . PDFName $ baseFont f)
, (PDFName "FontFile", AnyPdfObject ref)
, (PDFName "Flags",AnyPdfObject . PDFInteger . fromIntegral . mkFlags $ f)
, (PDFName "FontBBox",AnyPdfObject $ bbox)
, (PDFName "ItalicAngle",AnyPdfObject $ italicAngle f)
, (PDFName "Ascent",AnyPdfObject . PDFInteger . fromIntegral $ ascent f)
, (PDFName "Descent",AnyPdfObject . PDFInteger . fromIntegral $ descent f)
, (PDFName "CapHeight",AnyPdfObject . PDFInteger . fromIntegral $ capHeight f)
]