module System.Taffybar.IconImages (
ColorRGBA,
scalePixbuf,
pixBufFromEWMHIcon,
pixelsARGBToBytesABGR,
pixBufFromColor,
pixBufFromFile,
selectEWMHIcon
) where
import Data.Bits
import qualified Data.List as L
import Data.Ord ( comparing )
import Data.Word
import Foreign.C.Types (CUChar(..))
import Foreign.Marshal.Array
import Foreign.Ptr
import Foreign.Storable
import qualified Graphics.UI.Gtk as Gtk
import System.Information.EWMHDesktopInfo
type ColorRGBA = (Word8, Word8, Word8, Word8)
scalePixbuf :: Int -> Gtk.Pixbuf -> IO Gtk.Pixbuf
scalePixbuf imgSize pixbuf = do
h <- Gtk.pixbufGetHeight pixbuf
w <- Gtk.pixbufGetWidth pixbuf
if h /= imgSize || w /= imgSize
then
Gtk.pixbufScaleSimple pixbuf imgSize imgSize Gtk.InterpBilinear
else
return pixbuf
sampleBits :: Int
sampleBits = 8
hasAlpha :: Bool
hasAlpha = True
colorspace :: Gtk.Colorspace
colorspace = Gtk.ColorspaceRgb
pixBufFromEWMHIcon :: EWMHIcon -> IO Gtk.Pixbuf
pixBufFromEWMHIcon EWMHIcon {width = w, height = h, pixelsARGB = px} = do
wPtr <- pixelsARGBToBytesABGR px (w*h)
let pixelsPerRow = w
bytesPerPixel = 4
rowStride = pixelsPerRow * bytesPerPixel
cPtr = castPtr wPtr
Gtk.pixbufNewFromData cPtr colorspace hasAlpha sampleBits w h rowStride
pixBufFromColor :: Int -> ColorRGBA -> IO Gtk.Pixbuf
pixBufFromColor imgSize (r, g, b, a) = do
pixbuf <- Gtk.pixbufNew colorspace hasAlpha sampleBits imgSize imgSize
Gtk.pixbufFill pixbuf r g b a
return pixbuf
pixelsARGBToBytesABGR
:: (Storable a, Bits a, Num a, Integral a)
=> Ptr a -> Int -> IO (Ptr CUChar)
pixelsARGBToBytesABGR ptr size = do
target <- mallocArray (size * 4)
let writeIndex i = do
bits <- peekElemOff ptr i
let b = toByte bits
g = toByte $ bits `shift` (-8)
r = toByte $ bits `shift` (-16)
a = toByte $ bits `shift` (-24)
baseTarget = 4 * i
doPoke offset = pokeElemOff target (baseTarget + offset)
toByte = fromIntegral . (.&. 0xFF)
doPoke 0 r
doPoke 1 g
doPoke 2 b
doPoke 3 a
writeIndexAndNext i
| i >= size = return ()
| otherwise = writeIndex i >> writeIndexAndNext (i + 1)
writeIndexAndNext 0
return target
pixBufFromFile :: Int -> FilePath -> IO Gtk.Pixbuf
pixBufFromFile imgSize file =
Gtk.pixbufNewFromFileAtScale file imgSize imgSize False
selectEWMHIcon :: Int -> [EWMHIcon] -> EWMHIcon
selectEWMHIcon imgSize icons = head prefIcon
where sortedIcons = L.sortBy (comparing height) icons
smallestLargerIcon = take 1 $ dropWhile ((<= imgSize) . height) sortedIcons
largestIcon = take 1 $ reverse sortedIcons
prefIcon = smallestLargerIcon ++ largestIcon