packages feed

gridland-0.1.0.3: src/GridLand/SDL.hs

{-# LANGUAGE CPP #-}

module GridLand.SDL where

import qualified Graphics.UI.SDL as SDL
import GridLand.Import
import GridLand.Data

setColorKey :: (Word8, Word8, Word8) -> SDL.Surface -> IO SDL.Surface
setColorKey (r, g, b) sur = mapRGB sur r g b >>= SDL.setColorKey sur [SDL.SrcColorKey] >> return sur

mapRGB :: SDL.Surface -> Word8 -> Word8 -> Word8 -> IO SDL.Pixel
mapRGB = SDL.mapRGB . SDL.surfaceGetPixelFormat

surfacePixelFormat :: SDL.Surface -> IO PixelFormat
surfacePixelFormat sur = do
    let fmt = SDL.surfaceGetPixelFormat sur
    rShift <- pixelFormatGetRShift fmt
    bShift <- pixelFormatGetBShift fmt
    gShift <- pixelFormatGetGShift fmt
    aShift <- pixelFormatGetAShift fmt
    return $ case (rShift, gShift, bShift, aShift) of
        ( 0,  8, 16, 24) -> ABGR
        (16,  8,  0, 24) -> ARGB
        (24, 16,  8,  0) -> RGBA
        ( 8, 16, 24,  0) -> BGRA
        _ -> ABGR -- default

copySurface :: SDL.Surface -> IO SDL.Surface
copySurface sur = do
    copy <- copyFromSurface sur
    SDL.blitSurface sur Nothing copy Nothing
    return copy

copyFromSurface :: SDL.Surface -> IO SDL.Surface
copyFromSurface sur = do
    let fmt = SDL.surfaceGetPixelFormat sur
    bpp <- fromIntegral `liftM` SDL.pixelFormatGetBitsPerPixel fmt
    rMask <- pixelFormatGetRMask fmt
    gMask <- pixelFormatGetGMask fmt
    bMask <- pixelFormatGetBMask fmt
    flags <- SDL.surfaceGetFlags sur
    aMask <- if elem SDL.SrcColorKey flags then return 0 else pixelFormatGetAMask fmt
    SDL.createRGBSurface [SDL.SWSurface] (SDL.surfaceGetWidth sur) (SDL.surfaceGetHeight sur) bpp rMask gMask bMask aMask

pixelFormatGetBytes :: Storable a => Int -> SDL.PixelFormat -> IO a
pixelFormatGetBytes offset fmt = withForeignPtr fmt (\ptr -> peekByteOff ptr offset)

pixelFormatGetRShift, pixelFormatGetGShift, pixelFormatGetBShift, pixelFormatGetAShift :: SDL.PixelFormat -> IO Word8
#ifdef ARCH_64
pixelFormatGetRShift = pixelFormatGetBytes 14
pixelFormatGetGShift = pixelFormatGetBytes 15
pixelFormatGetBShift = pixelFormatGetBytes 16
pixelFormatGetAShift = pixelFormatGetBytes 17
#endif
#ifdef ARCH_32
pixelFormatGetRShift = pixelFormatGetBytes 10
pixelFormatGetGShift = pixelFormatGetBytes 11
pixelFormatGetBShift = pixelFormatGetBytes 12
pixelFormatGetAShift = pixelFormatGetBytes 13
#endif

pixelFormatGetRMask, pixelFormatGetGMask, pixelFormatGetBMask, pixelFormatGetAMask :: SDL.PixelFormat -> IO Word32
#ifdef ARCH_64
pixelFormatGetRMask = pixelFormatGetBytes 20
pixelFormatGetGMask = pixelFormatGetBytes 24
pixelFormatGetBMask = pixelFormatGetBytes 28
pixelFormatGetAMask = pixelFormatGetBytes 32
#endif
#ifdef ARCH_32
pixelFormatGetRMask = pixelFormatGetBytes 16
pixelFormatGetGMask = pixelFormatGetBytes 20
pixelFormatGetBMask = pixelFormatGetBytes 24
pixelFormatGetAMask = pixelFormatGetBytes 28
#endif

getPixel32 :: Int -> Int -> SDL.Surface -> IO SDL.Pixel
getPixel32 x y s = do
    pixels <- castPtr `liftM` SDL.surfaceGetPixels s
    SDL.Pixel `liftM` peekElemOff pixels ((y * SDL.surfaceGetWidth s) + x)

putPixel32 :: Int -> Int -> SDL.Pixel -> SDL.Surface -> IO ()
putPixel32 x y (SDL.Pixel pixel) s = do
    pixels <- castPtr `liftM` SDL.surfaceGetPixels s
    pokeElemOff pixels ((y * SDL.surfaceGetWidth s) + x) pixel