module Graphics.Text.TrueType.Name
( NameTable
, NameRecords
) where
import Control.Applicative( (<$>), (<*>), pure )
import Control.Monad( when, replicateM )
import Data.Function( on )
import Data.List( maximumBy )
import Data.Monoid( mempty )
import Data.Binary( Binary( .. ) )
import Data.Binary.Get( getWord16be, getByteString )
import Data.Binary.Put( putWord16be )
import Data.Word( Word16 )
import qualified Data.Vector as V
import qualified Data.ByteString as B
data NameTable = NameTable
{ _ntRecords :: !(V.Vector NameRecords) }
deriving Show
instance Binary NameTable where
put _ = fail "Binary.put NameTable - unimplemented"
get = do
nameFormatId <- getWord16be
when (nameFormatId /= 0) $
fail "Invalid name table format"
count <- getWord16be
stringOffset <- getWord16be
records <- replicateM (fromIntegral count) get
let maxRec = maximumBy (compare `on` _nrOffset) records
toFetch = fromIntegral (_nrOffset maxRec) + fromIntegral (_nrLength maxRec)
fromIntegral stringOffset
strTable <- getByteString toFetch
let fetcher r = r { _nrString = B.take iLength $ B.drop iOffset strTable }
where iLength = fromIntegral $ _nrLength r
iOffset = fromIntegral $ _nrOffset r
return . NameTable . V.fromListN (fromIntegral count) $ map fetcher records
data NameRecords = NameRecords
{ _nrPlatoformId :: !Word16
, _nrPlatformSpecificId :: !Word16
, _nrLanguageId :: !Word16
, _nrNameId :: !Word16
, _nrLength :: !Word16
, _nrOffset :: !Word16
, _nrString :: !B.ByteString
}
deriving Show
instance Binary NameRecords where
get = NameRecords <$> g16 <*> g16 <*> g16
<*> g16 <*> g16 <*> g16
<*> pure mempty
where g16 = getWord16be
put (NameRecords p ps l n len ofs _) =
p16 p >> p16 ps >> p16 l >> p16 n >> p16 len >> p16 ofs
where p16 = putWord16be