packages feed

FontyFruity 0.5.2 → 0.5.3

raw patch · 4 files changed

+354/−345 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Graphics.Text.TrueType: _a :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _b :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _baselineHeight :: BoundingBox -> {-# UNPACK #-} !Float
- Graphics.Text.TrueType: _c :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _d :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _descriptorFamilyName :: FontDescriptor -> Text
- Graphics.Text.TrueType: _descriptorStyle :: FontDescriptor -> FontStyle
- Graphics.Text.TrueType: _e :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _f :: CompositeScaling -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType: _fontStyleBold :: FontStyle -> !Bool
- Graphics.Text.TrueType: _fontStyleItalic :: FontStyle -> !Bool
- Graphics.Text.TrueType: _rawGlyphCompositionScale :: RawGlyph -> ![CompositeScaling]
- Graphics.Text.TrueType: _rawGlyphContour :: RawGlyph -> ![Vector (Int16, Int16)]
- Graphics.Text.TrueType: _rawGlyphIndex :: RawGlyph -> !Int
- Graphics.Text.TrueType: _xMax :: BoundingBox -> {-# UNPACK #-} !Float
- Graphics.Text.TrueType: _xMin :: BoundingBox -> {-# UNPACK #-} !Float
- Graphics.Text.TrueType: _yMax :: BoundingBox -> {-# UNPACK #-} !Float
- Graphics.Text.TrueType: _yMin :: BoundingBox -> {-# UNPACK #-} !Float
- Graphics.Text.TrueType: getPointSize :: PointSize -> Float
- Graphics.Text.TrueType: instance Eq BoundingBox
- Graphics.Text.TrueType: instance Eq PointSize
- Graphics.Text.TrueType: instance Show PointSize
- Graphics.Text.TrueType.Internal: _fHdrChecksumAdjust :: FontHeader -> !Word32
- Graphics.Text.TrueType.Internal: _fHdrCreateTime :: FontHeader -> !Word64
- Graphics.Text.TrueType.Internal: _fHdrFlags :: FontHeader -> !HeaderFlags
- Graphics.Text.TrueType.Internal: _fHdrFontDirectionHint :: FontHeader -> !Int16
- Graphics.Text.TrueType.Internal: _fHdrFontRevision :: FontHeader -> !Fixed
- Graphics.Text.TrueType.Internal: _fHdrGlyphDataFormat :: FontHeader -> !Int16
- Graphics.Text.TrueType.Internal: _fHdrIndexToLocFormat :: FontHeader -> !Int16
- Graphics.Text.TrueType.Internal: _fHdrLowestRecPPEM :: FontHeader -> !Word16
- Graphics.Text.TrueType.Internal: _fHdrMacStyle :: FontHeader -> !FontStyle
- Graphics.Text.TrueType.Internal: _fHdrMagicNumber :: FontHeader -> !Word32
- Graphics.Text.TrueType.Internal: _fHdrModificationTime :: FontHeader -> !Word64
- Graphics.Text.TrueType.Internal: _fHdrVersionNumber :: FontHeader -> !Fixed
- Graphics.Text.TrueType.Internal: _fHdrXMax :: FontHeader -> !FWord
- Graphics.Text.TrueType.Internal: _fHdrYMax :: FontHeader -> !FWord
- Graphics.Text.TrueType.Internal: _fHdrYMin :: FontHeader -> !FWord
- Graphics.Text.TrueType.Internal: _fHdrxMin :: FontHeader -> !FWord
- Graphics.Text.TrueType.Internal: _fUnitsPerEm :: FontHeader -> !Word16
- Graphics.Text.TrueType.Internal: _fontGlyph :: Font -> Maybe (Vector Glyph)
- Graphics.Text.TrueType.Internal: _fontHeader :: Font -> Maybe FontHeader
- Graphics.Text.TrueType.Internal: _fontHorizontalHeader :: Font -> Maybe HorizontalHeader
- Graphics.Text.TrueType.Internal: _fontHorizontalMetrics :: Font -> Maybe HorizontalMetricsTable
- Graphics.Text.TrueType.Internal: _fontLoca :: Font -> Maybe (Vector Word32)
- Graphics.Text.TrueType.Internal: _fontMap :: Font -> Maybe CharacterMaps
- Graphics.Text.TrueType.Internal: _fontMaxp :: Font -> Maybe MaxpTable
- Graphics.Text.TrueType.Internal: _fontNames :: Font -> Maybe NameTable
- Graphics.Text.TrueType.Internal: _fontOffsetTable :: Font -> !OffsetTable
- Graphics.Text.TrueType.Internal: _fontTables :: Font -> ![(ByteString, ByteString)]
- Graphics.Text.TrueType.Internal: _glyphMetrics :: HorizontalMetricsTable -> !(Vector HorizontalMetric)
- Graphics.Text.TrueType.Internal: _hfAlterAdvance :: HeaderFlags -> !Bool
- Graphics.Text.TrueType.Internal: _hfBaselineY0 :: HeaderFlags -> !Bool
- Graphics.Text.TrueType.Internal: _hfForcePPEM :: HeaderFlags -> !Bool
- Graphics.Text.TrueType.Internal: _hfInstrDependPointSize :: HeaderFlags -> !Bool
- Graphics.Text.TrueType.Internal: _hfLeftSideBearing :: HeaderFlags -> !Bool
- Graphics.Text.TrueType.Internal: _hheaAdvanceWidthMax :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaAscent :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaCaretOffset :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaCaretSlopeRise :: HorizontalHeader -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType.Internal: _hheaCaretSlopeRun :: HorizontalHeader -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType.Internal: _hheaDescent :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaLineGap :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaLongHorMetricCount :: HorizontalHeader -> {-# UNPACK #-} !Word16
- Graphics.Text.TrueType.Internal: _hheaMetricDataFormat :: HorizontalHeader -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType.Internal: _hheaMinLeftSideBearing :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaMinRightSideBearing :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hheaXmaxExtent :: HorizontalHeader -> {-# UNPACK #-} !FWord
- Graphics.Text.TrueType.Internal: _hmtxAdvanceWidth :: HorizontalMetric -> {-# UNPACK #-} !Word16
- Graphics.Text.TrueType.Internal: _hmtxLeftSideBearing :: HorizontalMetric -> {-# UNPACK #-} !Int16
- Graphics.Text.TrueType.Internal: _maxpTableVersion :: MaxpTable -> !Fixed
- Graphics.Text.TrueType.Internal: _maxpmaxComponentDepth :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxComponentElements :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxCompositeContours :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxCompositePoints :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxContours :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxFunctionDefs :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxInstructionDefs :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxPoints :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxSizeOfInstructions :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxStackElements :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxStorage :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxTwilightPoints :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpmaxZones :: MaxpTable -> !Word16
- Graphics.Text.TrueType.Internal: _maxpnumGlyphs :: MaxpTable -> !Word16
+ Graphics.Text.TrueType: [_a] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_b] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_baselineHeight] :: BoundingBox -> {-# UNPACK #-} !Float
+ Graphics.Text.TrueType: [_c] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_d] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_descriptorFamilyName] :: FontDescriptor -> !Text
+ Graphics.Text.TrueType: [_descriptorStyle] :: FontDescriptor -> !FontStyle
+ Graphics.Text.TrueType: [_e] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_f] :: CompositeScaling -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType: [_fontStyleBold] :: FontStyle -> !Bool
+ Graphics.Text.TrueType: [_fontStyleItalic] :: FontStyle -> !Bool
+ Graphics.Text.TrueType: [_rawGlyphCompositionScale] :: RawGlyph -> ![CompositeScaling]
+ Graphics.Text.TrueType: [_rawGlyphContour] :: RawGlyph -> ![Vector (Int16, Int16)]
+ Graphics.Text.TrueType: [_rawGlyphIndex] :: RawGlyph -> !Int
+ Graphics.Text.TrueType: [_xMax] :: BoundingBox -> {-# UNPACK #-} !Float
+ Graphics.Text.TrueType: [_xMin] :: BoundingBox -> {-# UNPACK #-} !Float
+ Graphics.Text.TrueType: [_yMax] :: BoundingBox -> {-# UNPACK #-} !Float
+ Graphics.Text.TrueType: [_yMin] :: BoundingBox -> {-# UNPACK #-} !Float
+ Graphics.Text.TrueType: [getPointSize] :: PointSize -> Float
+ Graphics.Text.TrueType: instance GHC.Classes.Eq Graphics.Text.TrueType.BoundingBox
+ Graphics.Text.TrueType: instance GHC.Classes.Eq Graphics.Text.TrueType.PointSize
+ Graphics.Text.TrueType: instance GHC.Show.Show Graphics.Text.TrueType.PointSize
+ Graphics.Text.TrueType.Internal: [_fHdrChecksumAdjust] :: FontHeader -> !Word32
+ Graphics.Text.TrueType.Internal: [_fHdrCreateTime] :: FontHeader -> !Word64
+ Graphics.Text.TrueType.Internal: [_fHdrFlags] :: FontHeader -> !HeaderFlags
+ Graphics.Text.TrueType.Internal: [_fHdrFontDirectionHint] :: FontHeader -> !Int16
+ Graphics.Text.TrueType.Internal: [_fHdrFontRevision] :: FontHeader -> !Fixed
+ Graphics.Text.TrueType.Internal: [_fHdrGlyphDataFormat] :: FontHeader -> !Int16
+ Graphics.Text.TrueType.Internal: [_fHdrIndexToLocFormat] :: FontHeader -> !Int16
+ Graphics.Text.TrueType.Internal: [_fHdrLowestRecPPEM] :: FontHeader -> !Word16
+ Graphics.Text.TrueType.Internal: [_fHdrMacStyle] :: FontHeader -> !FontStyle
+ Graphics.Text.TrueType.Internal: [_fHdrMagicNumber] :: FontHeader -> !Word32
+ Graphics.Text.TrueType.Internal: [_fHdrModificationTime] :: FontHeader -> !Word64
+ Graphics.Text.TrueType.Internal: [_fHdrVersionNumber] :: FontHeader -> !Fixed
+ Graphics.Text.TrueType.Internal: [_fHdrXMax] :: FontHeader -> !FWord
+ Graphics.Text.TrueType.Internal: [_fHdrYMax] :: FontHeader -> !FWord
+ Graphics.Text.TrueType.Internal: [_fHdrYMin] :: FontHeader -> !FWord
+ Graphics.Text.TrueType.Internal: [_fHdrxMin] :: FontHeader -> !FWord
+ Graphics.Text.TrueType.Internal: [_fUnitsPerEm] :: FontHeader -> !Word16
+ Graphics.Text.TrueType.Internal: [_fontGlyph] :: Font -> Maybe (Vector Glyph)
+ Graphics.Text.TrueType.Internal: [_fontHeader] :: Font -> Maybe FontHeader
+ Graphics.Text.TrueType.Internal: [_fontHorizontalHeader] :: Font -> Maybe HorizontalHeader
+ Graphics.Text.TrueType.Internal: [_fontHorizontalMetrics] :: Font -> Maybe HorizontalMetricsTable
+ Graphics.Text.TrueType.Internal: [_fontLoca] :: Font -> Maybe (Vector Word32)
+ Graphics.Text.TrueType.Internal: [_fontMap] :: Font -> Maybe CharacterMaps
+ Graphics.Text.TrueType.Internal: [_fontMaxp] :: Font -> Maybe MaxpTable
+ Graphics.Text.TrueType.Internal: [_fontNames] :: Font -> Maybe NameTable
+ Graphics.Text.TrueType.Internal: [_fontOffsetTable] :: Font -> !OffsetTable
+ Graphics.Text.TrueType.Internal: [_fontTables] :: Font -> ![(ByteString, ByteString)]
+ Graphics.Text.TrueType.Internal: [_glyphMetrics] :: HorizontalMetricsTable -> !(Vector HorizontalMetric)
+ Graphics.Text.TrueType.Internal: [_hfAlterAdvance] :: HeaderFlags -> !Bool
+ Graphics.Text.TrueType.Internal: [_hfBaselineY0] :: HeaderFlags -> !Bool
+ Graphics.Text.TrueType.Internal: [_hfForcePPEM] :: HeaderFlags -> !Bool
+ Graphics.Text.TrueType.Internal: [_hfInstrDependPointSize] :: HeaderFlags -> !Bool
+ Graphics.Text.TrueType.Internal: [_hfLeftSideBearing] :: HeaderFlags -> !Bool
+ Graphics.Text.TrueType.Internal: [_hheaAdvanceWidthMax] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaAscent] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaCaretOffset] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaCaretSlopeRise] :: HorizontalHeader -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType.Internal: [_hheaCaretSlopeRun] :: HorizontalHeader -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType.Internal: [_hheaDescent] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaLineGap] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaLongHorMetricCount] :: HorizontalHeader -> {-# UNPACK #-} !Word16
+ Graphics.Text.TrueType.Internal: [_hheaMetricDataFormat] :: HorizontalHeader -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType.Internal: [_hheaMinLeftSideBearing] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaMinRightSideBearing] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hheaXmaxExtent] :: HorizontalHeader -> {-# UNPACK #-} !FWord
+ Graphics.Text.TrueType.Internal: [_hmtxAdvanceWidth] :: HorizontalMetric -> {-# UNPACK #-} !Word16
+ Graphics.Text.TrueType.Internal: [_hmtxLeftSideBearing] :: HorizontalMetric -> {-# UNPACK #-} !Int16
+ Graphics.Text.TrueType.Internal: [_maxpTableVersion] :: MaxpTable -> !Fixed
+ Graphics.Text.TrueType.Internal: [_maxpmaxComponentDepth] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxComponentElements] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxCompositeContours] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxCompositePoints] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxContours] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxFunctionDefs] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxInstructionDefs] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxPoints] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxSizeOfInstructions] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxStackElements] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxStorage] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxTwilightPoints] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpmaxZones] :: MaxpTable -> !Word16
+ Graphics.Text.TrueType.Internal: [_maxpnumGlyphs] :: MaxpTable -> !Word16
- Graphics.Text.TrueType: FontDescriptor :: Text -> FontStyle -> FontDescriptor
+ Graphics.Text.TrueType: FontDescriptor :: !Text -> !FontStyle -> FontDescriptor

Files

FontyFruity.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                FontyFruity-version:             0.5.2+version:             0.5.3 synopsis:            A true type file format loader description:              A haskell Truetype file parser.@@ -28,7 +28,7 @@ Source-Repository this     Type:      git     Location:  https://github.com/Twinside/FontyFruity.git-    Tag:       v0.5.2+    Tag:       v0.5.3  library   exposed-modules: Graphics.Text.TrueType
changelog view
@@ -1,5 +1,9 @@ -*-change-log-*- +v0.5.3 February 2016+ * Fix: bug when trying to scan a directory+ * Addition: exposing descriptorOf function+ * Enhancement: Made FontDescriptor strictier.  v0.5.2 August 2015  * Fix: GHC 7.4 compilation
src/Graphics/Text/TrueType/FontFolders.hs view
@@ -5,6 +5,7 @@     , loadWindowsFontFolderList     , fontFolders     , findFont+    , descriptorOf     , FontCache( .. )     , FontDescriptor( .. )     , emptyFontCache@@ -119,9 +120,9 @@ -- in a font cache. data FontDescriptor = FontDescriptor     { -- | The family name of the font-      _descriptorFamilyName :: T.Text+      _descriptorFamilyName :: !T.Text       -- | The desired style-    , _descriptorStyle :: FontStyle+    , _descriptorStyle :: !FontStyle     }     deriving (Eq, Ord, Show) @@ -173,6 +174,15 @@ enumerateFonts :: FontCache -> [FontDescriptor] enumerateFonts (FontCache fs) = M.keys fs ++-- | If possible, returns a descriptor of the Font.+descriptorOf :: Font -> Maybe FontDescriptor+descriptorOf font = do+  hdr <- _fontHeader font+  names <- _fontNames font+  return $ FontDescriptor (fontFamilyName names) (_fHdrMacStyle hdr)++ -- | Look in the system's folder for usable fonts. buildFontCache :: (FilePath -> IO (Maybe Font)) -> IO FontCache buildFontCache loader = do@@ -182,12 +192,6 @@          $ M.fromList [(d, path) | (Just d, path) <- found                                  , _descriptorFamilyName d /= ""]   where-    descriptorOf Font { _fontHeader = Just hdr-                      , _fontNames = Just names} =-        Just $ FontDescriptor (fontFamilyName names)-                              (_fHdrMacStyle hdr)-    descriptorOf _ = Nothing-     build [] = return []     build ((".", _):rest) = build rest     build (("..", _):rest) = build rest@@ -234,6 +238,9 @@         subRez <- searchIn [(s, n </> s) | s <- sub]         findOrRest subRez       else do-        font <- loader n-        findOrRest $ font >>= isMatching n+        isFile <- doesFileExist n+        if isFile then do+          font <- loader n+          findOrRest $ font >>= isMatching n+        else searchIn rest 
src/Graphics/Text/TrueType/Glyph.hs view
@@ -1,333 +1,331 @@-{-# LANGUAGE TupleSections #-}
-{-# LANGUAGE CPP #-}
-module Graphics.Text.TrueType.Glyph
-    ( GlyphHeader( .. )
-    , GlyphContour( .. )
-    , CompositeScaling( .. )
-    , GlyphComposition( .. )
-    , GlyphContent( .. )
-    , Glyph( .. )
-    , GlyphFlag( .. )
-    , extractFlatOutline
-    , emptyGlyph
-    ) where
-
-#if !MIN_VERSION_base(4,8,0)
-import Data.Monoid( mempty )
-import Control.Applicative( (<*>) )
-#endif
-
-import Control.Applicative( (<$>) )
-
-import Control.DeepSeq
-import Data.Bits( setBit, testBit, shiftL )
-import Data.Int( Int16 )
-import Data.List( mapAccumL, mapAccumR, zip4 )
-import Data.Word( Word8, Word16 )
-import Data.Binary( Binary( .. ) )
-import Data.Binary.Get( Get
-                      , getWord8
-                      , getWord16be )
-
-import Data.Binary.Put( putWord8, putWord16be )
-import Data.Tuple( swap )
-
-import qualified Data.Vector as V
-import qualified Data.Vector.Unboxed as VU
-
-{-import Text.Printf-}
-{-import Debug.Trace-}
-
-data GlyphHeader = GlyphHeader
-    { -- | If the number of contours is greater than or equal
-      -- to zero, this is a single glyph; if negative, this is
-      -- a composite glyph.
-      _glfNumberOfContours :: {-# UNPACK #-} !Int16
-      -- | Minimum x for coordinate data.
-    , _glfXMin             :: {-# UNPACK #-} !Int16
-      -- | Minimum y for coordinate data.
-    , _glfYMin             :: {-# UNPACK #-} !Int16
-      -- | Maximum x for coordinate data.
-    , _glfXMax             :: {-# UNPACK #-} !Int16
-      -- | Maximum y for coordinate data.
-    , _glfYMax             :: {-# UNPACK #-} !Int16
-    }
-    deriving (Eq, Show)
-
-instance NFData GlyphHeader where
-  rnf (GlyphHeader {}) = ()
-
-emptyGlyphHeader :: GlyphHeader
-emptyGlyphHeader = GlyphHeader 0 0 0 0 0
-
-instance Binary GlyphHeader where
-    get = GlyphHeader <$> g16 <*> g16 <*> g16 <*> g16 <*> g16
-      where g16 = fromIntegral <$> getWord16be
-
-    put (GlyphHeader count xmini ymini xmaxi ymaxi) =
-        p16 count >> p16 xmini >> p16 ymini >> p16 xmaxi >> p16 ymaxi
-      where p16 = putWord16be . fromIntegral
-
-data GlyphContour = GlyphContour
-    { _glyphInstructions :: !(VU.Vector Word8)
-    , _glyphFlags        :: ![GlyphFlag]
-    , _glyphPoints       :: ![VU.Vector (Int16, Int16)]
-    }
-    deriving (Eq, Show)
-
-instance NFData GlyphContour where
-    rnf (GlyphContour instr fl points) =
-        instr `seq` fl `seq` points `seq` ()
-
--- | Transformation matrix used to transform composite
--- glyph
---
--- @
---   | a b c |
---   | d e f |
--- @
---
-data CompositeScaling = CompositeScaling
-    { _a :: {-# UNPACK #-} !Int16 -- ^ a coeff.
-    , _b :: {-# UNPACK #-} !Int16 -- ^ b coeff.
-    , _c :: {-# UNPACK #-} !Int16 -- ^ c coeff.
-    , _d :: {-# UNPACK #-} !Int16 -- ^ d coeff.
-    , _e :: {-# UNPACK #-} !Int16 -- ^ e coeff.
-    , _f :: {-# UNPACK #-} !Int16 -- ^ f coeff.
-    }
-    deriving (Eq, Show)
-
-data GlyphComposition = GlyphComposition
-    { _glyphCompositeFlag    :: {-# UNPACK #-} !Word16
-    , _glyphCompositeIndex   :: {-# UNPACK #-} !Word16
-    , _glyphCompositionArg   :: {-# UNPACK #-} !(Int16, Int16)
-    , _glyphCompositionScale :: !CompositeScaling
-    }
-    deriving (Eq, Show)
-
-data GlyphContent
-    = GlyphEmpty
-    | GlyphSimple    !GlyphContour
-    | GlyphComposite !(V.Vector GlyphComposition) !(VU.Vector Word8)
-    deriving (Eq, Show)
-
-data Glyph = Glyph
-    { _glyphHeader  :: !GlyphHeader
-    , _glyphContent :: !GlyphContent
-    }
-    deriving (Eq, Show)
-
-instance NFData Glyph where
-  rnf (Glyph hdr cont) =
-      rnf hdr `seq` cont `seq` ()
-
-emptyGlyph :: Glyph
-emptyGlyph = Glyph emptyGlyphHeader GlyphEmpty
-
-getCompositeOutline :: Get GlyphContent
-getCompositeOutline =
-    (\(instr, vals) -> GlyphComposite (V.fromList vals) instr) <$> go
-  where
-    go = do
-      flag <- getWord16be
-      index <- getWord16be
-      args <- fetchArguments flag
-      scaling <- fetchScaling flag
-      let fullScaling = fetchOffset scaling args flag
-          value = GlyphComposition flag index args fullScaling
-
-      if flag `testBit` mORE_COMPONENTS then
-          (\(instr, acc) -> (instr, value : acc )) <$> go
-      else
-        if flag `testBit` wE_HAVE_INSTRUCTIONS then do
-            count <- fromIntegral <$> getWord16be
-            (, [value]) <$> VU.replicateM count getWord8
-        else
-            return (mempty, [value])
-
-
-    fetchArguments flag
-        | flag `testBit` aRG_1_AND_2_ARE_WORDS =
-            (,) <$> getInt16be <*> getInt16be
-        | otherwise =
-            (,) <$> getInt8 <*> getInt8
-
-    fetchScaling flag
-        | flag `testBit` wE_HAVE_A_SCALE =
-            (\v -> CompositeScaling v 0 0 v) <$> getF2Dot14
-        | flag `testBit` wE_HAVE_AN_X_AND_Y_SCALE =
-            (\x y -> CompositeScaling x 0 0 y) <$> getF2Dot14 <*> getF2Dot14
-        | flag `testBit` wE_HAVE_A_TWO_BY_TWO =
-            CompositeScaling <$> getF2Dot14 <*> getF2Dot14
-                             <*> getF2Dot14 <*> getF2Dot14
-        | otherwise = return $ CompositeScaling one 0 0 one
-           where one = 1 `shiftL` 14
-
-    fetchOffset scaling (a1, a2) flag
-        | flag `testBit` aRGS_ARE_XY_VALUES = scaling a1 a2
-        | otherwise = scaling 0 0 -- TODO fix this crap
-
-    {--
-    if (!ARGS_ARE_XY_VALUES)
-        1st short contains the index of matching point in compound being constructed
-        2nd short contains index of matching point in component -}
-
-    getInt16be = fromIntegral <$> getWord16be
-    getF2Dot14 = fromIntegral <$> getWord16be
-    getInt8 = fixByteSign . fromIntegral <$> getWord8
-
-    fixByteSign value = if value >= 0x80 then value - 0x100 else value
-
-    aRG_1_AND_2_ARE_WORDS  = 0
-    aRGS_ARE_XY_VALUES  = 1
-    {-rOUND_XY_TO_GRID  = 2-}
-    wE_HAVE_A_SCALE  = 3
-    {-rESERVED  = 4-}
-    mORE_COMPONENTS  = 5
-    wE_HAVE_AN_X_AND_Y_SCALE  = 6
-    wE_HAVE_A_TWO_BY_TWO  = 7
-    wE_HAVE_INSTRUCTIONS  = 8
-    {-uSE_MY_METRICS  = 9-}
-    {-oVERLAP_COMPOUND  = 10-}
-    {-sCALED_COMPONENT_OFFSET  = 11-}
-    {-uNSCALED_COMPONENT_OFFSET = 12-}
-
-data GlyphFlag = GlyphFlag
-    { -- | If set, the point is on the curve;
-      -- otherwise, it is off the curve.
-      _flagOnCurve :: !Bool
-      -- | If set, the corresponding x-coordinate is 1
-      -- byte long. If not set, 2 bytes.
-    , _flagXshort  :: !Bool
-      -- | If set, the corresponding y-coordinate is 1
-      -- byte long. If not set, 2 bytes.
-    , _flagYShort  :: !Bool
-      -- | If set, the next byte specifies the number of additional
-      -- times this set of flags is to be repeated. In this way, the
-      -- number of flags listed can be smaller than the number of
-      -- points in a character.
-    , _flagRepeat  :: !Bool
-      -- | This flag has two meanings, depending on how the x-Short
-      -- Vector flag is set. If x-Short Vector is set, this bit
-      -- describes the sign of the value, with 1 equalling positive and
-      -- 0 negative. If the x-Short Vector bit is not set and this bit is set,
-      -- then the current x-coordinate is the same as the previous x-coordinate.
-      -- If the x-Short Vector bit is not set and this bit is also not set, the
-      -- current x-coordinate is a signed 16-bit delta vector.
-    , _flagXSame   :: !Bool
-      -- | This flag has two meanings, depending on how the y-Short Vector flag
-      -- is set. If y-Short Vector is set, this bit describes the sign of the
-      -- value, with 1 equalling positive and 0 negative. If the y-Short Vector
-      -- bit is not set and this bit is set, then the current y-coordinate is the
-      -- same as the previous y-coordinate. If the y-Short Vector bit is not set
-      -- and this bit is also not set, the current y-coordinate is a signed
-      -- 16-bit delta vector.
-    , _flagYSame   :: !Bool
-    }
-    deriving (Eq, Show)
-
-instance Binary GlyphFlag where
-    put (GlyphFlag a0 a1 a2 a3 a4 a5) =
-        putWord8 . foldl setter 0 $ zip [0..] [a0, a1, a2, a3, a4, a5]
-      where setter v ( _, False) = v
-            setter v (ix, True) = setBit v ix
-    get = do
-      tester <- testBit <$> getWord8
-      return GlyphFlag
-        { _flagOnCurve = tester 0
-        , _flagXshort  = tester 1
-        , _flagYShort  = tester 2
-        , _flagRepeat  = tester 3
-        , _flagXSame   = tester 4
-        , _flagYSame   = tester 5
-        }
-
-getGlyphFlags :: Int -> Get [GlyphFlag]
-getGlyphFlags count = go 0
-  where
-    go n | n >= count = return []
-    go n = do
-      flag <- get
-      if _flagRepeat flag
-        then do
-          repeatCount <- fromIntegral <$> getWord8
-          let real = min (count - n) (repeatCount + 1)
-          (replicate real flag ++) <$> go (n + real)
-        else (flag :) <$> go (n + 1)
-
-getCoords :: [GlyphFlag] -> Get (VU.Vector (Int16, Int16))
-getCoords flags =
-    VU.fromList <$> (zip <$> go (_flagXSame, _flagXshort) 0 flags
-                         <*> go (_flagYSame, _flagYShort) 0 flags)
-  where
-    go _ _ [] = return []
-    go axx@(isSame, isShort) prevCoord (flag:flagRest) = do
-        let fetcher
-              | isShort flag && isSame flag =
-                  (prevCoord +) . fromIntegral <$> getWord8
-              | isShort flag = 
-                  (prevCoord - ) . fromIntegral <$> getWord8
-              | isSame flag =
-                  return prevCoord
-              | otherwise =
-                  (prevCoord +) . fromIntegral <$> getWord16be
-
-        newCoord <- fetcher
-        (newCoord :) <$> go axx newCoord flagRest
-
-extractFlatOutline :: GlyphContour
-                   -> [VU.Vector (Int16, Int16)]
-extractFlatOutline contour = zipWith (curry go) flagGroup coords
-  where
-    allFlags = _glyphFlags contour
-    coords = _glyphPoints contour
-    (_, flagGroup) =
-      mapAccumL (\acc v -> swap $ splitAt (VU.length v) acc) allFlags coords
-
-    go (flags, coord) 
-      | VU.null coord = mempty
-      | otherwise = VU.fromList . (firstPoint :) $ expand mixed
-      where
-       isOnSide = map _flagOnCurve flags
-       firstOnCurve = head isOnSide
-       lst@(firstPoint:xs) = VU.toList coord
-       mixed = zip4 isOnSide (tail isOnSide) lst xs
-       midPoint (x1, y1) (x2, y2) =
-           ((x1 + x2) `div` 2, (y1 + y2) `div` 2)
-
-       expand [] = []
-       expand [(onp, on, prevPoint, currPoint)]
-        | onp == on = (prevPoint `midPoint` currPoint) : endJunction
-        | otherwise = endJunction
-         where endJunction 
-                | on && firstOnCurve =
-                    [currPoint, currPoint `midPoint` firstPoint, firstPoint]
-                | otherwise = [currPoint, firstPoint]
-       expand ((onp, on, prevPoint, currPoint):rest)
-        | onp == on = prevPoint `midPoint` currPoint : currPoint : expand rest
-        | otherwise = currPoint : expand rest
-
-getSimpleOutline :: Int16 -> Get GlyphContent
-getSimpleOutline counterCount = do
-    endOfPoints <- VU.replicateM (fromIntegral counterCount) getWord16be
-    let pointCount = VU.last endOfPoints + 1
-    instructionCount <- fromIntegral <$> getWord16be
-    instructions <- VU.replicateM instructionCount getWord8
-
-    flags <- getGlyphFlags $ fromIntegral pointCount
-    GlyphSimple . GlyphContour instructions flags
-                . breakOutline endOfPoints <$> getCoords flags
-  where
-    prepender (v, lst) = v : lst
-    breakOutline endPoints coords =
-        prepender . mapAccumR breaker coords . VU.toList $ VU.init endPoints
-          where breaker array ix = VU.splitAt (fromIntegral ix + 1) array
-
-instance Binary Glyph where
-    put _ = fail "Glyph.put - unimplemented"
-    get = do
-      hdr <- get
-      case _glfNumberOfContours hdr of
-        -1 -> Glyph hdr <$> getCompositeOutline
-        n -> Glyph hdr <$> getSimpleOutline n
-
+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-}+module Graphics.Text.TrueType.Glyph+    ( GlyphHeader( .. )+    , GlyphContour( .. )+    , CompositeScaling( .. )+    , GlyphComposition( .. )+    , GlyphContent( .. )+    , Glyph( .. )+    , GlyphFlag( .. )+    , extractFlatOutline+    , emptyGlyph+    ) where++#if !MIN_VERSION_base(4,8,0)+import Data.Monoid( mempty )+import Control.Applicative( (<*>), (<$>) )+#endif++import Control.DeepSeq+import Data.Bits( setBit, testBit, shiftL )+import Data.Int( Int16 )+import Data.List( mapAccumL, mapAccumR, zip4 )+import Data.Word( Word8, Word16 )+import Data.Binary( Binary( .. ) )+import Data.Binary.Get( Get+                      , getWord8+                      , getWord16be )++import Data.Binary.Put( putWord8, putWord16be )+import Data.Tuple( swap )++import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as VU++{-import Text.Printf-}+{-import Debug.Trace-}++data GlyphHeader = GlyphHeader+    { -- | If the number of contours is greater than or equal+      -- to zero, this is a single glyph; if negative, this is+      -- a composite glyph.+      _glfNumberOfContours :: {-# UNPACK #-} !Int16+      -- | Minimum x for coordinate data.+    , _glfXMin             :: {-# UNPACK #-} !Int16+      -- | Minimum y for coordinate data.+    , _glfYMin             :: {-# UNPACK #-} !Int16+      -- | Maximum x for coordinate data.+    , _glfXMax             :: {-# UNPACK #-} !Int16+      -- | Maximum y for coordinate data.+    , _glfYMax             :: {-# UNPACK #-} !Int16+    }+    deriving (Eq, Show)++instance NFData GlyphHeader where+  rnf (GlyphHeader {}) = ()++emptyGlyphHeader :: GlyphHeader+emptyGlyphHeader = GlyphHeader 0 0 0 0 0++instance Binary GlyphHeader where+    get = GlyphHeader <$> g16 <*> g16 <*> g16 <*> g16 <*> g16+      where g16 = fromIntegral <$> getWord16be++    put (GlyphHeader count xmini ymini xmaxi ymaxi) =+        p16 count >> p16 xmini >> p16 ymini >> p16 xmaxi >> p16 ymaxi+      where p16 = putWord16be . fromIntegral++data GlyphContour = GlyphContour+    { _glyphInstructions :: !(VU.Vector Word8)+    , _glyphFlags        :: ![GlyphFlag]+    , _glyphPoints       :: ![VU.Vector (Int16, Int16)]+    }+    deriving (Eq, Show)++instance NFData GlyphContour where+    rnf (GlyphContour instr fl points) =+        instr `seq` fl `seq` points `seq` ()++-- | Transformation matrix used to transform composite+-- glyph+--+-- @+--   | a b c |+--   | d e f |+-- @+--+data CompositeScaling = CompositeScaling+    { _a :: {-# UNPACK #-} !Int16 -- ^ a coeff.+    , _b :: {-# UNPACK #-} !Int16 -- ^ b coeff.+    , _c :: {-# UNPACK #-} !Int16 -- ^ c coeff.+    , _d :: {-# UNPACK #-} !Int16 -- ^ d coeff.+    , _e :: {-# UNPACK #-} !Int16 -- ^ e coeff.+    , _f :: {-# UNPACK #-} !Int16 -- ^ f coeff.+    }+    deriving (Eq, Show)++data GlyphComposition = GlyphComposition+    { _glyphCompositeFlag    :: {-# UNPACK #-} !Word16+    , _glyphCompositeIndex   :: {-# UNPACK #-} !Word16+    , _glyphCompositionArg   :: {-# UNPACK #-} !(Int16, Int16)+    , _glyphCompositionScale :: !CompositeScaling+    }+    deriving (Eq, Show)++data GlyphContent+    = GlyphEmpty+    | GlyphSimple    !GlyphContour+    | GlyphComposite !(V.Vector GlyphComposition) !(VU.Vector Word8)+    deriving (Eq, Show)++data Glyph = Glyph+    { _glyphHeader  :: !GlyphHeader+    , _glyphContent :: !GlyphContent+    }+    deriving (Eq, Show)++instance NFData Glyph where+  rnf (Glyph hdr cont) =+      rnf hdr `seq` cont `seq` ()++emptyGlyph :: Glyph+emptyGlyph = Glyph emptyGlyphHeader GlyphEmpty++getCompositeOutline :: Get GlyphContent+getCompositeOutline =+    (\(instr, vals) -> GlyphComposite (V.fromList vals) instr) <$> go+  where+    go = do+      flag <- getWord16be+      index <- getWord16be+      args <- fetchArguments flag+      scaling <- fetchScaling flag+      let fullScaling = fetchOffset scaling args flag+          value = GlyphComposition flag index args fullScaling++      if flag `testBit` mORE_COMPONENTS then+          (\(instr, acc) -> (instr, value : acc )) <$> go+      else+        if flag `testBit` wE_HAVE_INSTRUCTIONS then do+            count <- fromIntegral <$> getWord16be+            (, [value]) <$> VU.replicateM count getWord8+        else+            return (mempty, [value])+++    fetchArguments flag+        | flag `testBit` aRG_1_AND_2_ARE_WORDS =+            (,) <$> getInt16be <*> getInt16be+        | otherwise =+            (,) <$> getInt8 <*> getInt8++    fetchScaling flag+        | flag `testBit` wE_HAVE_A_SCALE =+            (\v -> CompositeScaling v 0 0 v) <$> getF2Dot14+        | flag `testBit` wE_HAVE_AN_X_AND_Y_SCALE =+            (\x y -> CompositeScaling x 0 0 y) <$> getF2Dot14 <*> getF2Dot14+        | flag `testBit` wE_HAVE_A_TWO_BY_TWO =+            CompositeScaling <$> getF2Dot14 <*> getF2Dot14+                             <*> getF2Dot14 <*> getF2Dot14+        | otherwise = return $ CompositeScaling one 0 0 one+           where one = 1 `shiftL` 14++    fetchOffset scaling (a1, a2) flag+        | flag `testBit` aRGS_ARE_XY_VALUES = scaling a1 a2+        | otherwise = scaling 0 0 -- TODO fix this crap++    {--+    if (!ARGS_ARE_XY_VALUES)+        1st short contains the index of matching point in compound being constructed+        2nd short contains index of matching point in component -}++    getInt16be = fromIntegral <$> getWord16be+    getF2Dot14 = fromIntegral <$> getWord16be+    getInt8 = fixByteSign . fromIntegral <$> getWord8++    fixByteSign value = if value >= 0x80 then value - 0x100 else value++    aRG_1_AND_2_ARE_WORDS  = 0+    aRGS_ARE_XY_VALUES  = 1+    {-rOUND_XY_TO_GRID  = 2-}+    wE_HAVE_A_SCALE  = 3+    {-rESERVED  = 4-}+    mORE_COMPONENTS  = 5+    wE_HAVE_AN_X_AND_Y_SCALE  = 6+    wE_HAVE_A_TWO_BY_TWO  = 7+    wE_HAVE_INSTRUCTIONS  = 8+    {-uSE_MY_METRICS  = 9-}+    {-oVERLAP_COMPOUND  = 10-}+    {-sCALED_COMPONENT_OFFSET  = 11-}+    {-uNSCALED_COMPONENT_OFFSET = 12-}++data GlyphFlag = GlyphFlag+    { -- | If set, the point is on the curve;+      -- otherwise, it is off the curve.+      _flagOnCurve :: !Bool+      -- | If set, the corresponding x-coordinate is 1+      -- byte long. If not set, 2 bytes.+    , _flagXshort  :: !Bool+      -- | If set, the corresponding y-coordinate is 1+      -- byte long. If not set, 2 bytes.+    , _flagYShort  :: !Bool+      -- | If set, the next byte specifies the number of additional+      -- times this set of flags is to be repeated. In this way, the+      -- number of flags listed can be smaller than the number of+      -- points in a character.+    , _flagRepeat  :: !Bool+      -- | This flag has two meanings, depending on how the x-Short+      -- Vector flag is set. If x-Short Vector is set, this bit+      -- describes the sign of the value, with 1 equalling positive and+      -- 0 negative. If the x-Short Vector bit is not set and this bit is set,+      -- then the current x-coordinate is the same as the previous x-coordinate.+      -- If the x-Short Vector bit is not set and this bit is also not set, the+      -- current x-coordinate is a signed 16-bit delta vector.+    , _flagXSame   :: !Bool+      -- | This flag has two meanings, depending on how the y-Short Vector flag+      -- is set. If y-Short Vector is set, this bit describes the sign of the+      -- value, with 1 equalling positive and 0 negative. If the y-Short Vector+      -- bit is not set and this bit is set, then the current y-coordinate is the+      -- same as the previous y-coordinate. If the y-Short Vector bit is not set+      -- and this bit is also not set, the current y-coordinate is a signed+      -- 16-bit delta vector.+    , _flagYSame   :: !Bool+    }+    deriving (Eq, Show)++instance Binary GlyphFlag where+    put (GlyphFlag a0 a1 a2 a3 a4 a5) =+        putWord8 . foldl setter 0 $ zip [0..] [a0, a1, a2, a3, a4, a5]+      where setter v ( _, False) = v+            setter v (ix, True) = setBit v ix+    get = do+      tester <- testBit <$> getWord8+      return GlyphFlag+        { _flagOnCurve = tester 0+        , _flagXshort  = tester 1+        , _flagYShort  = tester 2+        , _flagRepeat  = tester 3+        , _flagXSame   = tester 4+        , _flagYSame   = tester 5+        }++getGlyphFlags :: Int -> Get [GlyphFlag]+getGlyphFlags count = go 0+  where+    go n | n >= count = return []+    go n = do+      flag <- get+      if _flagRepeat flag+        then do+          repeatCount <- fromIntegral <$> getWord8+          let real = min (count - n) (repeatCount + 1)+          (replicate real flag ++) <$> go (n + real)+        else (flag :) <$> go (n + 1)++getCoords :: [GlyphFlag] -> Get (VU.Vector (Int16, Int16))+getCoords flags =+    VU.fromList <$> (zip <$> go (_flagXSame, _flagXshort) 0 flags+                         <*> go (_flagYSame, _flagYShort) 0 flags)+  where+    go _ _ [] = return []+    go axx@(isSame, isShort) prevCoord (flag:flagRest) = do+        let fetcher+              | isShort flag && isSame flag =+                  (prevCoord +) . fromIntegral <$> getWord8+              | isShort flag = +                  (prevCoord - ) . fromIntegral <$> getWord8+              | isSame flag =+                  return prevCoord+              | otherwise =+                  (prevCoord +) . fromIntegral <$> getWord16be++        newCoord <- fetcher+        (newCoord :) <$> go axx newCoord flagRest++extractFlatOutline :: GlyphContour+                   -> [VU.Vector (Int16, Int16)]+extractFlatOutline contour = zipWith (curry go) flagGroup coords+  where+    allFlags = _glyphFlags contour+    coords = _glyphPoints contour+    (_, flagGroup) =+      mapAccumL (\acc v -> swap $ splitAt (VU.length v) acc) allFlags coords++    go (flags, coord) +      | VU.null coord = mempty+      | otherwise = VU.fromList . (firstPoint :) $ expand mixed+      where+       isOnSide = map _flagOnCurve flags+       firstOnCurve = head isOnSide+       lst@(firstPoint:xs) = VU.toList coord+       mixed = zip4 isOnSide (tail isOnSide) lst xs+       midPoint (x1, y1) (x2, y2) =+           ((x1 + x2) `div` 2, (y1 + y2) `div` 2)++       expand [] = []+       expand [(onp, on, prevPoint, currPoint)]+        | onp == on = (prevPoint `midPoint` currPoint) : endJunction+        | otherwise = endJunction+         where endJunction +                | on && firstOnCurve =+                    [currPoint, currPoint `midPoint` firstPoint, firstPoint]+                | otherwise = [currPoint, firstPoint]+       expand ((onp, on, prevPoint, currPoint):rest)+        | onp == on = prevPoint `midPoint` currPoint : currPoint : expand rest+        | otherwise = currPoint : expand rest++getSimpleOutline :: Int16 -> Get GlyphContent+getSimpleOutline counterCount = do+    endOfPoints <- VU.replicateM (fromIntegral counterCount) getWord16be+    let pointCount = VU.last endOfPoints + 1+    instructionCount <- fromIntegral <$> getWord16be+    instructions <- VU.replicateM instructionCount getWord8++    flags <- getGlyphFlags $ fromIntegral pointCount+    GlyphSimple . GlyphContour instructions flags+                . breakOutline endOfPoints <$> getCoords flags+  where+    prepender (v, lst) = v : lst+    breakOutline endPoints coords =+        prepender . mapAccumR breaker coords . VU.toList $ VU.init endPoints+          where breaker array ix = VU.splitAt (fromIntegral ix + 1) array++instance Binary Glyph where+    put _ = fail "Glyph.put - unimplemented"+    get = do+      hdr <- get+      case _glfNumberOfContours hdr of+        -1 -> Glyph hdr <$> getCompositeOutline+        n -> Glyph hdr <$> getSimpleOutline n+