{-# OPTIONS -fwarn-incomplete-patterns #-} -- | Helper functions for rendering bitmaps module Graphics.Gloss.Internals.Render.Bitmap ( reverseRGBA , bitmapPath , freeBitmapData ) where import Foreign import qualified Data.ByteString as B -- | Generates the point path to display the bitmap centred bitmapPath :: Float -> Float -> [(Float, Float)] bitmapPath width height = [(-width', -height'), (width', -height'), (width', height'), (-width', height')] where width' = width / 2 height' = height / 2 -- | This is necessary as OpenGL reads pixel data as ABGR, rather than RGBA reverseRGBA :: B.ByteString -> IO (Ptr Word8) reverseRGBA orig = do ptr <- newArray $ B.unpack orig reverseRGBA' (B.length orig `div` 4) (castPtr ptr) 0 return ptr -- | Parses through pixel values, shifting the bytes into OpenGL ABGR order reverseRGBA' :: Int -> Ptr Word32 -> Int -> IO () reverseRGBA' len ptr count | count < len = do curr <- peekElemOff ptr count let byte0 = shift (isolateByte0 curr) 24 let byte1 = shift (isolateByte1 curr) 8 let byte2 = shift (isolateByte2 curr) (-8) let byte3 = shift (isolateByte3 curr) (-24) pokeElemOff ptr count (byte0 .|. byte1 .|. byte2 .|. byte3) reverseRGBA' len ptr (count + 1) | otherwise = return () -- | Frees the allocated memory given to OpenGL to avoid a memory leak freeBitmapData :: Ptr Word8 -> IO () {-# INLINE freeBitmapData #-} freeBitmapData p = free p -- | These functions work as bit masks to isolate the Word8 components isolateByte0 :: Word32 -> Word32 isolateByte0 word = word .&. (255 :: Word32) isolateByte1 :: Word32 -> Word32 isolateByte1 word = word .&. (65280 :: Word32) isolateByte2 :: Word32 -> Word32 isolateByte2 word = word .&. (16711680 :: Word32) isolateByte3 :: Word32 -> Word32 isolateByte3 word = word .&. (4278190080 :: Word32)