{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
---------------------------------------------------------
-- |
-- Copyright   : (c) 2006-2016, alpheccar.org
-- License     : BSD-style
--
-- Maintainer  : misc@NOSPAMalpheccar.org
-- Stability   : experimental
-- Portability : portable
--
-- PDF Font
---------------------------------------------------------
{-# 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.AFMParser
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)
                  ]