{-# LINE 1 "Graphics/X11/Xft.hsc" #-}
-----------------------------------------------------------------------------
{-# LINE 2 "Graphics/X11/Xft.hsc" #-}
-- |
-- Module      :  Graphics.X11.Xft
--
-- Stability   :  provisional
-- Portability :  portable
--
-- Interface to the Xft library based on the @X11-xft@ binding by
-- Clemens Fruhwirth.  This library builds upon the X11 binding to
-- Xlib ("Graphics.X11") and cannot be used with any other.  A tiny
-- part of Xrender is also exposed, as no Haskell interface exists as
-- of this writing.
--
-- The spirit of this binding is to hide away the fact that the
-- underlying implementation is accessed via the FFI, and create a
-- Haskell-like interface that does not expose many artifacts of the C
-- implementation.  To that end, the only numeric types exposed are
-- high-level (no 'CInt's), and facilities for integrating resource
-- cleanup with the Haskell garbage collector have been defined (see
-- 'XftMgr').
--
-- Another priority has been robustness.  Many naively written FFI
-- bindings to not properly check the return values of the C functions
-- they call.  In particular, null pointers are often assumed to never
-- exist, and oftentimes impossible to check by the user as the
-- underlying pointer is not visible across the module boundary.  In
-- this binding, any Xft function that can return null has been
-- translated into a Haskell function that returns a 'Maybe' value.
--
-- Two kinds of allocator functions are provided: some that use the
-- nomenclature @new@ and some that uses @open@ (for example
-- 'newColorName' versus 'openColorName').  The former require that
-- you explicitly call the corresponding deallocator ('freeColor' in
-- this case), while the latter takes an 'XftMgr' as an additional
-- argument, and automatically calls the deallocator when the value is
-- garbage-collected.  It is an error to call a deallocator on an
-- automatically managed value.
--
-----------------------------------------------------------------------------
module Graphics.X11.Xft
  ( -- * Xft management
    XftMgr (mgrDisplay, mgrScreen)
  , newXftMgr
  , freeXftMgr
  -- * Color handling
  , Color
  , pixel
  , newColorName
  , newColorValue
  , freeColor
  , openColorName
  , openColorValue
  -- * Drawable handling
  , Draw
  , display
  , colormap
  , visual
  , drawable
  , changeDraw
  , newDraw
  , newDrawBitmap
  , newDrawAlpha
  , freeDraw
  , openDraw
  , openDrawBitmap
  , openDrawAlpha
  -- * Font handling
  , Font
  , ascent
  , descent
  , height
  , maxAdvanceWidth
  , newFontName
  , newFontXlfd
  , freeFont
  , openFontName
  , openFontXlfd
  , lockFace
  , unlockFace
  -- * Drawing
  , textExtents
  , textWidth
  , textHeight
  , drawString
  , drawGlyphs
  , drawRect
  -- * XRender bits
  , RenderColor(..)
  , GlyphInfo(..)
  )
  where

import qualified Graphics.X11 as X11

import Codec.Binary.UTF8.String as UTF8

import Control.Exception
import Control.Monad
import Data.IORef
import qualified Data.Map as M

import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Marshal.Utils
import Foreign.Storable
import Data.Int
import Data.Word

import System.IO
import System.IO.Unsafe
import System.Mem.Weak


{-# LINE 117 "Graphics/X11/Xft.hsc" #-}

{-# LINE 118 "Graphics/X11/Xft.hsc" #-}

-- | An 'IORef' containing a map from keys to finalizers.  The idea is
-- that the finalizers remove themselves from this store, and if the
-- store (or whatever owns it) is closed before the finalizers have
-- been run, they will be run immediately.  This combines the
-- ease-of-use of automatic cleanup via finalizers, with the common
-- requirement that some set of objects has been closed at a specific
-- time.
type ObjectStore k = IORef (M.Map k (IO ()))

insertObj :: Ord k => ObjectStore k -> k -> IO () -> IO ()
insertObj ref k v = atomicModifyIORef ref $ \s -> (M.insert k v s, ())

deleteObj :: Ord k => ObjectStore k -> k -> IO ()
deleteObj ref k = atomicModifyIORef ref $ \s -> (k `M.delete` s, ())

-- | A central staging point for Xft object creation.  All Xft object
-- creation functions take as argument an 'XftMgr' value that keeps
-- track of lifetime information.  You are required to manually free
-- the 'XftMgr' via 'freeXftMgr' when you are done with it.
data XftMgr = XftMgr
  { mgrDisplay :: X11.Display
  , mgrScreen  :: X11.Screen
  , xftLock    :: IO ()
  , xftUnlock  :: IO ()
  , xftObjs    :: ObjectStore IntPtr
  }

-- | Create an 'XftMgr' whose objects will be used on the given screen
-- and display.  As Xlib is not re-entrant, a synchronisation
-- mechanism must be used, so the 'XftMgr' includes actions for
-- obtaining and releasing atomic access to the display via two 'IO'
-- actions.  These will be executed before and after objects allocated
-- via the manager are released.  It is recommended to use an
-- 'Control.Concurrent.MVar' to implement a mutex for synchronising
-- the access, but if you are absolutely certain that there will not
-- be any concurrent attempts to access the display, the actions can
-- merely be @return ()@.
newXftMgr :: X11.Display -> X11.Screen
          -> IO () -- ^ Executed before deallocations.
          -> IO () -- ^ Executed after deallocations.
          -> IO XftMgr
newXftMgr dpy scr lock unlock = do
  os <- newIORef M.empty
  return XftMgr { mgrDisplay = dpy
                , mgrScreen  = scr
                , xftLock    = lock
                , xftUnlock  = unlock
                , xftObjs    = os
                }

-- | Free the manager and reclaim any objects associated with it.
-- After an 'XftMgr' has been freed, it is invalid to use any objects
-- created through it.  The lock must currently be held by the thread
-- calling 'freeXftMgr', and it will be repeatedly released and
-- reacquired throughout deallocating any remaining objects in the
-- manager.  When the command returns, the lock will once again be
-- held.
freeXftMgr :: XftMgr -> IO ()
freeXftMgr mgr = withoutLock $ finalizeObjs xftObjs
  where getobjs s = (M.empty, M.elems s)
        withoutLock = bracket_ (xftUnlock mgr) (xftLock mgr)
        finalizeObjs f = sequence_ =<< atomicModifyIORef (f mgr) getobjs

openAny :: Ord k =>
           XftMgr -> (XftMgr -> ObjectStore k)
        -> (a -> IO ()) -> k -> a -> IO a
openAny mgr field close key obj = do
  let finalizer = bracket_ (xftLock mgr) (xftUnlock mgr) $ do
        deleteObj (field mgr) key
        close obj
  obj' <- mkWeak obj (obj, finalizer) (Just finalizer)
  insertObj (field mgr) key (finalize obj')
  return obj

openAnyWith :: Ord k => XftMgr -> (XftMgr -> ObjectStore k)
            -> (c -> IO (Maybe a)) -> (a -> IO ()) -> (a -> IO k) -> c
            -> IO (Maybe a)
openAnyWith mgr field open close keyf v = do
  obj <- open v
  case obj of Nothing   -> return Nothing
              Just obj' -> do key <- keyf obj'
                              key `seq` Just `fmap` openAny mgr field close key obj'

-- | An Xft colour.
newtype Color = Color (Ptr Color)

foreign import ccall "XftColorAllocName"
  xftColorAllocName :: X11.Display -> X11.Visual -> X11.Colormap
                    -> CString -> Color -> IO (Int32)
{-# LINE 208 "Graphics/X11/Xft.hsc" #-}

foreign import ccall "XftColorAllocValue"
  xftColorAllocValue :: X11.Display -> X11.Visual -> X11.Colormap
                     -> (Ptr RenderColor) -> Color -> IO (Int32)
{-# LINE 212 "Graphics/X11/Xft.hsc" #-}

foreign import ccall "XftColorFree"
  xftColorFree :: X11.Display -> X11.Visual -> X11.Colormap -> Color -> IO ()

-- | The core X11 colour contained in an Xft colour.
pixel :: Color -> X11.Pixel
pixel (Color ptr) = fi $ unsafePerformIO $
                    peekCULong ptr (0)
{-# LINE 220 "Graphics/X11/Xft.hsc" #-}

-- | Create a new Xft colour based on a name.  The name may be either
-- a human-readable colour such as "red", "white" or "darkslategray"
-- (all core X colour names are supported) or a hexidecimal name such
-- as "#A9E2AF".  Names are not case-sensitive.  Returns 'Nothing' if
-- the given name is not recognised as a colour.
newColorName :: X11.Display -> X11.Visual -> X11.Colormap -> String
             -> IO (Maybe Color)
newColorName dpy v cm name = do
  ptr <- mallocBytes ((12))
{-# LINE 230 "Graphics/X11/Xft.hsc" #-}
  withCAString name $ \name' -> do
    b <- xftColorAllocName dpy v cm name' $ Color ptr
    if b /= 0 then return $ Just $ Color ptr
              else free ptr >> return Nothing

-- | As 'newColorName', but instead of a name, an XRender color value
-- is used.
newColorValue :: X11.Display -> X11.Visual -> X11.Colormap -> RenderColor
              -> IO (Maybe Color)
newColorValue dpy v cm rc = do
  ptr <- mallocBytes ((12))
{-# LINE 241 "Graphics/X11/Xft.hsc" #-}
  with rc $ \rc' -> do
    b <- xftColorAllocValue dpy v cm rc' $ Color ptr
    if b /= 0 then return $ Just $ Color ptr
              else free ptr >> return Nothing

-- | Free a colour that has been allocated with 'newColorName' or 'newColorValue'.
freeColor :: X11.Display -> X11.Visual -> X11.Colormap -> Color -> IO ()
freeColor dpy v cm col@(Color ptr) = do
  xftColorFree dpy v cm col
  free ptr

-- | As 'newColorName', but automatically freed through the given Xft
-- manager when no longer accessible.
openColorName :: XftMgr -> X11.Visual -> X11.Colormap -> String
              -> IO (Maybe Color)
openColorName mgr vis cm =
  openAnyWith mgr xftObjs open close (\(Color ptr) -> return $ ptrToIntPtr ptr)
  where open = newColorName (mgrDisplay mgr) vis cm
        close = freeColor (mgrDisplay mgr) vis cm

-- | As 'newColorValue', but automatically freed through the given Xft
-- manager when no longer accessible.
openColorValue :: XftMgr -> X11.Visual -> X11.Colormap -> RenderColor
               -> IO (Maybe Color)
openColorValue mgr vis cm =
  openAnyWith mgr xftObjs open close (\(Color ptr) -> return $ ptrToIntPtr ptr)
  where open = newColorValue (mgrDisplay mgr) vis cm
        close = freeColor (mgrDisplay mgr) vis cm

-- | An Xft drawable.
newtype Draw = Draw (Ptr Draw)

foreign import ccall "XftDrawCreate"
  xftDrawCreate :: X11.Display -> X11.Drawable -> X11.Visual -> X11.Colormap -> IO Draw

foreign import ccall "XftDrawCreateBitmap"
  xftDrawCreateBitmap :: X11.Display -> X11.Pixmap -> IO Draw

foreign import ccall "XftDrawCreateAlpha"
  xftDrawCreateAlpha :: X11.Display -> X11.Pixmap -> CInt -> IO Draw

foreign import ccall "XftDrawChange"
  xftDrawChange :: Draw -> X11.Drawable -> IO ()

foreign import ccall "XftDrawDisplay"
  xftDrawDisplay :: Draw -> IO X11.Display -- FIXME correct? Is X11 giving us the underlying Display?

foreign import ccall "XftDrawDrawable"
  xftDrawDrawable :: Draw -> IO X11.Drawable

foreign import ccall "XftDrawColormap"
  xftDrawColormap :: Draw -> IO X11.Colormap

foreign import ccall "XftDrawVisual"
  xftDrawVisual :: Draw -> IO X11.Visual

foreign import ccall "XftDrawDestroy"
  xftDrawDestroy :: Draw -> IO ()

-- | The display for the Xft drawable.
display :: Draw -> X11.Display
display = unsafePerformIO . xftDrawDisplay

-- | The colormap for the Xft drawable.
colormap :: Draw -> X11.Colormap
colormap = unsafePerformIO . xftDrawColormap

-- | The visual for the Xft drawable.
visual :: Draw -> X11.Visual
visual = unsafePerformIO . xftDrawVisual

-- | The X11 drawable underlying the Xft drawable.
drawable :: Draw -> X11.Drawable
drawable = unsafePerformIO . xftDrawDrawable

-- | Create a new Xft drawable on the given display, using the
-- provided 'X11.Drawable' to draw on.  Will return 'Nothing' if the
-- call to @XftDrawCreate@ fails, which it will usually only do if
-- memory cannot be allocated.  The 'Draw' has to be manually freed
-- with 'freeDraw' once you are done with it.
newDraw :: X11.Display -> X11.Drawable -> X11.Visual -> X11.Colormap
        -> IO (Maybe Draw)
newDraw dpy drw vis cm = do
  Draw ptr <- xftDrawCreate dpy drw vis cm
  if ptr == nullPtr then return Nothing
                     else return $ Just $ Draw ptr

-- | Behaves as 'newDraw', except that it uses a 'X11.Pixmap' of color
-- depth 1 instead of a 'X11.Drawable'.
newDrawBitmap :: X11.Display -> X11.Pixmap -> IO (Maybe Draw)
newDrawBitmap dpy pm = do
  Draw ptr <- xftDrawCreateBitmap dpy pm
  if ptr == nullPtr then return Nothing
                    else return $ Just $ Draw ptr

-- | Behaves as 'newDraw', except that it uses a 'X11.Pixmap' of the given depth
-- instead of a 'X11.Drawable'.
newDrawAlpha :: Integral a => X11.Display -> X11.Pixmap -> a -> IO (Maybe Draw)
newDrawAlpha dpy pm k = do
  Draw ptr <- xftDrawCreateAlpha dpy pm $ fi k
  if ptr == nullPtr then return Nothing
                    else return $ Just $ Draw ptr

-- | Free a 'Draw' created with 'newDraw'.  Do not free 'Draw's
-- created with 'openDraw', these are automatically managed.
freeDraw :: Draw -> IO ()
freeDraw = xftDrawDestroy

-- | Change the X11 drawable underlying the Xft drawable.
changeDraw :: Draw -> X11.Drawable -> IO ()
changeDraw = xftDrawChange

-- | As 'newDraw', but automatically freed when no longer used.
openDraw :: XftMgr -> X11.Drawable -> X11.Visual -> X11.Colormap
           -> IO (Maybe Draw)
openDraw mgr drw vis =
  openAnyWith mgr xftObjs open close (\(Draw ptr) -> return $ ptrToIntPtr ptr)
  where open = newDraw (mgrDisplay mgr) drw vis
        close = freeDraw

-- | As 'newDrawBitmap', but automatically freed when no longer used.
openDrawBitmap :: XftMgr -> X11.Drawable -> IO (Maybe Draw)
openDrawBitmap mgr =
  openAnyWith mgr xftObjs open close (\(Draw ptr) -> return $ ptrToIntPtr ptr)
  where open = newDrawBitmap (mgrDisplay mgr)
        close = freeDraw

-- | As 'newDrawBitmap', but automatically freed when no longer used.
openDrawAlpha :: Integral a => XftMgr -> X11.Drawable -> a -> IO (Maybe Draw)
openDrawAlpha mgr drw  =
  openAnyWith mgr xftObjs open close (\(Draw ptr) -> return $ ptrToIntPtr ptr)
  where open = newDrawAlpha (mgrDisplay mgr) drw
        close = freeDraw

-- | An Xft font.
newtype Font = Font (Ptr Font)

foreign import ccall "XftFontOpenName"
  xftFontOpenName :: X11.Display -> CInt -> CString -> IO Font

foreign import ccall "XftFontOpenXlfd"
  xftFontOpenXlfd :: X11.Display -> CInt -> CString -> IO Font

foreign import ccall "XftLockFace"
  xftLockFace :: Font -> IO ()                  -- FIXME XftLockFace returns FT_face not void

foreign import ccall "XftUnlockFace"
  xftUnlockFace :: Font -> IO ()

foreign import ccall "XftFontClose"
  xftFontClose :: X11.Display -> Font -> IO ()

-- | The ascent (vertical distance upwards from the baseline) of a
-- character in the font.
ascent :: Integral a => Font -> a
ascent (Font p) = fi $ unsafePerformIO $ peekCUShort p (0)
{-# LINE 397 "Graphics/X11/Xft.hsc" #-}

-- | The descent (vertical distance downwards from the baseline) of a
-- character in the font.
descent :: Integral a => Font -> a
descent (Font p) = fi $ unsafePerformIO $ peekCUShort p (4)
{-# LINE 402 "Graphics/X11/Xft.hsc" #-}

-- | The ascent plus descent of a character in the font.
height :: Integral a => Font -> a
height (Font p) = fi $ unsafePerformIO $ peekCUShort p (8)
{-# LINE 406 "Graphics/X11/Xft.hsc" #-}

-- | The greatest horizontal width of a character in the font.
maxAdvanceWidth :: Integral a => Font -> a
maxAdvanceWidth (Font p) = fi $ unsafePerformIO $ peekCUShort p (8)
{-# LINE 410 "Graphics/X11/Xft.hsc" #-}

-- | @newFontName dpy scr s@, where @s@ is a Fontconfig pattern
-- string, finds the best match for @s@ and returns a font that can be
-- used to draw on the given screen.  This function very rarely
-- returns 'Nothing', and seems to return some default font even if
-- you feed it utter garbage (or an empty string).
newFontName :: X11.Display -> X11.Screen -> String -> IO (Maybe Font)
newFontName dpy screen fontname =
  withCAString fontname $ \fontname' -> do
    Font ptr <- xftFontOpenName dpy
                (fi (X11.screenNumberOfScreen screen)) fontname'
    if ptr == nullPtr then return Nothing else return $ Just $ Font ptr

-- | As 'newFontName', except that the name should be an X Logical
-- Font Description (the usual fourteen elements produced by
-- @xfontsel@).
newFontXlfd :: X11.Display -> X11.Screen -> String -> IO (Maybe Font)
newFontXlfd dpy screen xlfd =
  withCAString xlfd $ \xlfd' -> do
    Font ptr <- xftFontOpenXlfd dpy
                (fi (X11.screenNumberOfScreen screen)) xlfd'
    if ptr == nullPtr then return Nothing else return $ Just $ Font ptr

-- | Close the given Xft font.
freeFont :: X11.Display -> Font -> IO ()
freeFont = xftFontClose

-- | As 'newFontName', but automatically freed when no longer used.
openFontName :: XftMgr -> String -> IO (Maybe Font)
openFontName mgr =
  openAnyWith mgr xftObjs open close (\(Font ptr) -> return $ ptrToIntPtr ptr)
  where open = newFontName (mgrDisplay mgr) (mgrScreen mgr)
        close = freeFont (mgrDisplay mgr)

-- | As 'newFontXfld', but automatically freed when no longer used.
openFontXlfd :: XftMgr -> String -> IO (Maybe Font)
openFontXlfd mgr =
  openAnyWith mgr xftObjs open close (\(Font ptr) -> return $ ptrToIntPtr ptr)
  where open = newFontXlfd (mgrDisplay mgr) (mgrScreen mgr)
        close = freeFont (mgrDisplay mgr)

-- | Lock the file underlying the Xft font.  I am not certain when you
-- would need this.  The return value is supposed to be an @FT_TYPE@
-- from Freetype, but that binding has not been written yet.
lockFace :: Font -> IO ()
lockFace font = xftLockFace font >> return ()

-- | Unlock a face locked by 'lockFontFace'.
unlockFace :: Font -> IO ()
unlockFace = xftUnlockFace

foreign import ccall "XftTextExtentsUtf8"
  xftTextExtentsUtf8 :: X11.Display -> Font -> CString -> CInt -> Ptr GlyphInfo -> IO ()

-- | Note that the 'glyphWidth'/'glyphHeight' fields are the number of
-- pixels you should advance after drawing a string of this size.
textExtents :: X11.Display -> Font -> String -> IO GlyphInfo
textExtents dpy font s =
  withArrayLen (map fi (UTF8.encode s)) $ \n s' ->
    alloca $ \cglyph -> do
      xftTextExtentsUtf8 dpy font s' (fi n) cglyph
      peek cglyph

-- | Shortcut for calling 'textExtents' and picking out the
-- 'glyphWidth' field of the 'GlyphInfo'.
textWidth :: Integral a => X11.Display -> Font -> String -> IO a
textWidth dpy f = liftM (fi . glyphWidth) . textExtents dpy f

-- | Shortcut for calling 'textExtents' and picking out the
-- 'glyphHeight' field of the 'GlyphInfo'.
textHeight :: Integral a => X11.Display -> Font -> String -> IO a
textHeight dpy f = liftM (fi . glyphHeight) . textExtents dpy f

foreign import ccall "XftDrawGlyphs"
  xftDrawGlyphs :: Draw -> Color -> Font -> CInt -> CInt -> Ptr (Word32) -> CInt -> IO ()

-- | Draw a sequence of glyphs on the given drawable in the specified
-- colour and font.  Drawing begins at the baseline of the string.
drawGlyphs :: (Integral x, Integral y, Integral c) => Draw -> Color -> Font ->
              x -> y -> [c] -> IO ()
drawGlyphs drw col font x y s =
  withArrayLen (map fi s) $ \len s' ->
    xftDrawGlyphs drw col font (fi x) (fi y) s' (fi len)

foreign import ccall "XftDrawStringUtf8"
  xftDrawStringUtf8 :: Draw -> Color -> Font -> CInt -> CInt -> Ptr (Word8) -> CInt -> IO ()

-- | Draw a string on the given drawable in the specified colour and
-- font.  Drawing begins at the baseline of the string.
drawString :: (Integral x, Integral y) => Draw -> Color -> Font ->
              x -> y -> String -> IO ()
drawString drw col font x y s =
  withArrayLen (map fi (UTF8.encode s)) $ \len s' ->
    xftDrawStringUtf8 drw col font (fi x) (fi y) s' (fi len)

foreign import ccall "XftDrawRect"
  xftDrawRect :: Draw -> Color -> CInt -> CInt -> CUInt -> CUInt -> IO ()

-- | @drawRect d c x y w h@ draws a solid rectangle on @d@ with colour
-- @c@, with its upper left corner at @(x,y)@, width @w@ and height
-- @h@.
drawRect :: (Integral x, Integral y, Integral w, Integral h) =>
            Draw -> Color -> x -> y -> w -> h -> IO ()
drawRect d c x y w h = xftDrawRect d c (fi x) (fi y) (fi w) (fi h)

-- | Short-hand for 'fi'.
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral

peekCULong :: Ptr a -> CInt -> IO Int
peekCULong ptr off = do
  v <- peekByteOff ptr (fromIntegral off)
  return (fromIntegral (v::CULong))

peekCUShort :: Ptr a -> CInt -> IO Int
peekCUShort ptr off = do
  v <- peekByteOff ptr (fromIntegral off)
  return (fromIntegral (v::CUShort))

pokeCUShort :: Ptr a -> CInt -> Int -> IO ()
pokeCUShort ptr off v =
  pokeByteOff ptr (fromIntegral off) (fromIntegral v::CUShort)

peekCShort :: Ptr a -> CInt -> IO Int
peekCShort ptr off = do
  v <- peekByteOff ptr (fromIntegral off)
  return (fromIntegral (v::CShort))

pokeCShort :: Ptr a -> CInt -> Int -> IO ()
pokeCShort ptr off v =
  pokeByteOff ptr (fromIntegral off) (fromIntegral v::CShort)

-- | The @XRenderColor@ from the XRender library.  Note that the
-- colour channels are only interpreted as 16-bit numbers when
-- actually used.
data RenderColor = RenderColor {
    red   :: Int
  , green :: Int
  , blue  :: Int
  , alpha :: Int
}

instance Storable RenderColor where
  sizeOf _ = (8)
{-# LINE 554 "Graphics/X11/Xft.hsc" #-}
  alignment _ = alignment (undefined::CInt)
  peek p = do
    r <- peekCUShort p (0)
{-# LINE 557 "Graphics/X11/Xft.hsc" #-}
    g <- peekCUShort p (2)
{-# LINE 558 "Graphics/X11/Xft.hsc" #-}
    b <- peekCUShort p (4)
{-# LINE 559 "Graphics/X11/Xft.hsc" #-}
    a <- peekCUShort p (6)
{-# LINE 560 "Graphics/X11/Xft.hsc" #-}
    return (RenderColor r g b a)
  poke p (RenderColor r g b a) = do
    pokeCUShort p (0) r
{-# LINE 563 "Graphics/X11/Xft.hsc" #-}
    pokeCUShort p (2) g
{-# LINE 564 "Graphics/X11/Xft.hsc" #-}
    pokeCUShort p (4) b
{-# LINE 565 "Graphics/X11/Xft.hsc" #-}
    pokeCUShort p (6) a
{-# LINE 566 "Graphics/X11/Xft.hsc" #-}

-- | The size of some glyph(s).  Note that there's a difference
-- between the logical size, which may include some blank pixels, and
-- the actual bitmap.
data GlyphInfo = GlyphInfo {
    glyphImageWidth  :: Int
  , glyphImageHeight :: Int
  , glyphImageX      :: Int
  , glyphImageY      :: Int
  , glyphWidth       :: Int
  , glyphHeight      :: Int
}

instance Storable GlyphInfo where
  sizeOf _ = (12)
{-# LINE 581 "Graphics/X11/Xft.hsc" #-}
  alignment _ = alignment (undefined::CInt)
  peek p = do
    w  <- peekCUShort p (0)
{-# LINE 584 "Graphics/X11/Xft.hsc" #-}
    h <- peekCUShort p (2)
{-# LINE 585 "Graphics/X11/Xft.hsc" #-}
    x <- peekCShort p (4)
{-# LINE 586 "Graphics/X11/Xft.hsc" #-}
    y <- peekCShort p (6)
{-# LINE 587 "Graphics/X11/Xft.hsc" #-}
    xOff <- peekCShort p (8)
{-# LINE 588 "Graphics/X11/Xft.hsc" #-}
    yOff <- peekCShort p (10)
{-# LINE 589 "Graphics/X11/Xft.hsc" #-}
    return (GlyphInfo w h x y xOff yOff)
  poke p (GlyphInfo w h x y xOff yOff) = do
    pokeCUShort p (0) w
{-# LINE 592 "Graphics/X11/Xft.hsc" #-}
    pokeCUShort p (2) h
{-# LINE 593 "Graphics/X11/Xft.hsc" #-}
    pokeCShort p (4) x
{-# LINE 594 "Graphics/X11/Xft.hsc" #-}
    pokeCShort p (6) y
{-# LINE 595 "Graphics/X11/Xft.hsc" #-}
    pokeCShort p (8) xOff
{-# LINE 596 "Graphics/X11/Xft.hsc" #-}
    pokeCShort p (10) yOff
{-# LINE 597 "Graphics/X11/Xft.hsc" #-}