{-# LANGUAGE CPP #-}
module Graphics.Text.TrueType.OffsetTable
( OffsetTableHeader( .. )
, OffsetTable( .. )
, TableDirectoryEntry( .. )
, filterTable
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative( (<*>), (<$>) )
#endif
import Data.Word( Word16, Word32 )
import Data.Binary( Binary( .. ) )
import Data.Binary.Get( getWord16be
, getWord32be
, getByteString
)
import Data.Binary.Put( putWord16be
, putWord32be
, putByteString
)
import qualified Data.Vector as V
import qualified Data.ByteString.Char8 as BC
import Graphics.Text.TrueType.Types
data OffsetTableHeader = OffsetTableHeader
{
_othSfntVersion :: !Fixed
, _othTableCount :: !Word16
, _othSearchRange :: !Word16
, _othEntrySelector :: !Word16
, _othRangeShift :: !Word16
}
deriving (Eq, Show)
instance Binary OffsetTableHeader where
get = OffsetTableHeader <$> get <*> g16 <*> g16 <*> g16 <*> g16
where g16 = getWord16be
put (OffsetTableHeader ver c sr es rs) =
put ver >> p16 c >> p16 sr >> p16 es >> p16 rs
where p16 = putWord16be
data TableDirectoryEntry = TableDirectoryEntry
{
_tdeTag :: !BC.ByteString
, _tdeChecksum :: !Word32
, _tdeOffset :: !Word32
, _tdeLength :: !Word32
}
deriving (Eq, Show)
filterTable :: (BC.ByteString -> Bool) -> OffsetTable
-> OffsetTable
filterTable f table =
table { _otEntries = V.filter (f . _tdeTag) $ _otEntries table }
instance Binary TableDirectoryEntry where
get = TableDirectoryEntry <$> getByteString 4 <*> g32 <*> g32 <*> g32
where g32 = getWord32be
put (TableDirectoryEntry tag chk offset ln) =
putByteString tag >> p32 chk >> p32 offset >> p32 ln
where p32 = putWord32be
data OffsetTable = OffsetTable
{ _otHeader :: !OffsetTableHeader
, _otEntries :: !(V.Vector TableDirectoryEntry)
}
deriving (Eq, Show)
instance Binary OffsetTable where
put (OffsetTable hdr entries) =
put hdr >> V.forM_ entries put
get = do
hdr <- get
let count = fromIntegral $ _othTableCount hdr
OffsetTable hdr <$> V.replicateM count get