    ----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Util.Image
    -- Copyright   :  (c) 2010 Alejandro Serrano
    -- License     :  BSD-style (see xmonad/LICENSE)
    --
    -- Maintainer  :  trupill@gmail.com
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Utilities for manipulating [[Bool]] as images
    --
    -----------------------------------------------------------------------------

    module XMonad.Util.Image
        ( -- * Usage:
          -- $usage
          Placement(..),
          iconPosition,
          drawIcon,
        ) where

    import XMonad
    import XMonad.Util.Font (stringToPixel,fi)

    -- | Placement of the icon in the title bar
    data Placement = OffsetLeft Int Int   -- ^ An exact amount of pixels from the upper left corner
                     | OffsetRight Int Int  -- ^ An exact amount of pixels from the right left corner
                     | CenterLeft Int        -- ^ Centered in the y-axis, an amount of pixels from the left
                     | CenterRight Int       -- ^ Centered in the y-axis, an amount of pixels from the right
                       deriving (Show, Read)

    -- $usage
    -- This module uses matrices of boolean values as images. When drawing them,
    -- a True value tells that we want the fore color, and a False value that we
    -- want the background color to be painted.
    -- In the module we suppose that those matrices are represented as [[Bool]],
    -- so the lengths of the inner lists must be the same.
    --
    -- See "Xmonad.Layout.Decoration" for usage examples

    -- | Gets the ('width', 'height') of an image
    imageDims :: [[Bool]] -> (Int, Int)
    imageDims img = (length (head img), length img)

    -- | Return the 'x' and 'y' positions inside a 'Rectangle' to start drawing
    --   the image given its 'Placement'
    iconPosition :: Rectangle -> Placement -> [[Bool]] -> (Position,Position)
    iconPosition (Rectangle _ _ _ _) (OffsetLeft x y) _ = (fi x, fi y)
    iconPosition (Rectangle _ _ w _) (OffsetRight x y) icon =
      let (icon_w, _) = imageDims icon
      in (fi w - fi x - fi icon_w, fi y)
    iconPosition (Rectangle _ _ _ h) (CenterLeft x) icon =
      let (_, icon_h) = imageDims icon
      in  (fi x, fi (h `div` 2) - fi (icon_h `div` 2))
    iconPosition (Rectangle _ _ w h) (CenterRight x) icon =
      let (icon_w, icon_h) = imageDims icon
      in  (fi w - fi x - fi icon_w, fi (h `div` 2) - fi (icon_h `div` 2))

    -- | Converts an image represented as [[Bool]] to a series of points
    --   to be painted (the ones with True values)
    iconToPoints :: [[Bool]] -> [Point]
    iconToPoints icon =
      let labels_inside = map (zip (iterate (1+) 0)) icon
          filtered_inside = map (\l -> [x | (x, t) <- l, t]) labels_inside
          labels_outside = zip (iterate (1+) 0) filtered_inside
      in [Point x y | (y, l) <- labels_outside, x <- l]

    -- | Displaces a point ('a', 'b') along a vector ('x', 'y')
    movePoint :: Position -> Position -> Point -> Point
    movePoint x y (Point a b) = Point (a + x) (b + y)

    -- | Displaces a list of points along a vector 'x', 'y'
    movePoints :: Position -> Position -> [Point] -> [Point]
    movePoints x y points = map (movePoint x y) points

    -- | Draw an image into a X surface
    drawIcon :: (Functor m, MonadIO m) => Display -> Drawable -> GC -> String
                ->String -> Position -> Position -> [[Bool]] -> m ()
    drawIcon dpy drw gc fc bc x y icon = do
      let (i_w, i_h) = imageDims icon
      fcolor <- stringToPixel dpy fc
      bcolor <- stringToPixel dpy bc
      io $ setForeground dpy gc bcolor
      io $ fillRectangle dpy drw gc x y (fi i_w) (fi i_h)
      io $ setForeground dpy gc fcolor
      io $ drawPoints dpy drw gc (movePoints x y (iconToPoints icon)) coordModeOrigin