module Graphics.Text.TrueType.HorizontalInfo
( HorizontalHeader( .. )
, HorizontalMetricsTable( .. )
, HorizontalMetric( .. )
, getHorizontalMetrics
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative( (<*>), (<$>) )
#endif
import Control.DeepSeq( NFData( .. ) )
import Control.Monad( when, replicateM_ )
import Data.Word( Word16 )
import Data.Int( Int16 )
import Data.Binary( Binary( .. ) )
import Data.Binary.Get( Get, getWord16be, getWord32be )
import Data.Binary.Put( putWord16be, putWord32be )
import qualified Data.Vector as V
import Graphics.Text.TrueType.Types
data HorizontalHeader = HorizontalHeader
{
_hheaAscent :: !FWord
, _hheaDescent :: !FWord
, _hheaLineGap :: !FWord
, _hheaAdvanceWidthMax :: !FWord
, _hheaMinLeftSideBearing :: !FWord
, _hheaMinRightSideBearing :: !FWord
, _hheaXmaxExtent :: !FWord
, _hheaCaretSlopeRise :: !Int16
, _hheaCaretSlopeRun :: !Int16
, _hheaCaretOffset :: !FWord
, _hheaMetricDataFormat :: !Int16
, _hheaLongHorMetricCount :: !Word16
}
deriving (Eq, Show)
instance NFData HorizontalHeader where
rnf (HorizontalHeader {}) = ()
instance Binary HorizontalHeader where
put hdr = do
putWord32be 0x00010000
put $ _hheaAscent hdr
put $ _hheaDescent hdr
put $ _hheaLineGap hdr
put $ _hheaAdvanceWidthMax hdr
put $ _hheaMinLeftSideBearing hdr
put $ _hheaMinRightSideBearing hdr
put $ _hheaXmaxExtent hdr
putWord16be . fromIntegral $ _hheaCaretSlopeRise hdr
putWord16be . fromIntegral $ _hheaCaretSlopeRun hdr
put $ _hheaCaretOffset hdr
replicateM_ 4 $ putWord16be 0
putWord16be . fromIntegral $ _hheaMetricDataFormat hdr
putWord16be $ _hheaLongHorMetricCount hdr
get = do
ver <- getWord32be
when (ver /= 0x00010000)
(fail "Invalid HorizontalHeader (hhea) version")
startHdr <- HorizontalHeader
<$> get <*> get <*> get <*> get
<*> get <*> get <*> get
<*> (fromIntegral <$> getWord16be)
<*> (fromIntegral <$> getWord16be)
<*> get
replicateM_ 4 getWord16be
startHdr <$> (fromIntegral <$> getWord16be)
<*> getWord16be
data HorizontalMetric = HorizontalMetric
{ _hmtxAdvanceWidth :: !Word16
, _hmtxLeftSideBearing :: !Int16
}
deriving (Eq, Show)
instance Binary HorizontalMetric where
put (HorizontalMetric adv bear) =
putWord16be adv >> putWord16be (fromIntegral bear)
get = HorizontalMetric <$> g16 <*> (fromIntegral <$> g16)
where g16 = getWord16be
data HorizontalMetricsTable = HorizontalMetricsTable
{ _glyphMetrics :: !(V.Vector HorizontalMetric)
}
deriving (Eq, Show)
getHorizontalMetrics :: Int
-> Int
-> Get HorizontalMetricsTable
getHorizontalMetrics numberOfMetrics glyphCount = do
hMetrics <- V.replicateM numberOfMetrics get
let lastAdvance = _hmtxAdvanceWidth $ V.last hMetrics
run <- V.replicateM sideBearingCount $
HorizontalMetric lastAdvance . fromIntegral <$> getWord16be
return $ HorizontalMetricsTable $ V.concat [hMetrics, run]
where
sideBearingCount = glyphCount numberOfMetrics