1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# OPTIONS_HADDOCK hide #-}
-- | Data types for representing pictures.
module Graphics.Gloss.Internals.Data.Picture
( Point
, Vector
, Path
, Picture(..)
-- * Bitmaps
, Rectangle(..)
, BitmapData, PixelFormat(..), BitmapFormat(..), RowOrder(..)
, bitmapSize
, bitmapOfForeignPtr
, bitmapDataOfForeignPtr
, bitmapOfByteString
, bitmapDataOfByteString
, bitmapOfBMP
, bitmapDataOfBMP
, loadBMP
, rectAtOrigin )
where
import Graphics.Gloss.Internals.Data.Color
import Graphics.Gloss.Internals.Rendering.Bitmap
import Codec.BMP
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc
import Foreign.Marshal.Utils
import Foreign.Ptr
import Data.Word
import Data.Monoid
import Data.ByteString
import Data.Data
import System.IO.Unsafe
import qualified Data.ByteString.Unsafe as BSU
import Prelude hiding (map)
#if __GLASGOW_HASKELL__ >= 800
import Data.Semigroup
import Data.List.NonEmpty
#endif
-- | A point on the x-y plane.
type Point = (Float, Float)
-- | A vector can be treated as a point, and vis-versa.
type Vector = Point
-- | A path through the x-y plane.
type Path = [Point]
-- | A 2D picture
data Picture
-- Primitives -------------------------------------
-- | A blank picture, with nothing in it.
= Blank
-- | A convex polygon filled with a solid color.
| Polygon Path
-- | A line along an arbitrary path.
| Line Path
-- | A circle with the given radius.
| Circle Float
-- | A circle with the given radius and thickness.
-- If the thickness is 0 then this is equivalent to `Circle`.
| ThickCircle Float Float
-- | A circular arc drawn counter-clockwise between two angles
-- (in degrees) at the given radius.
| Arc Float Float Float
-- | A circular arc drawn counter-clockwise between two angles
-- (in degrees), with the given radius and thickness.
-- If the thickness is 0 then this is equivalent to `Arc`.
| ThickArc Float Float Float Float
-- | Some text to draw with a vector font.
| Text String
-- | A bitmap image.
| Bitmap BitmapData
-- | A subsection of a bitmap image where
-- the first argument selects a sub section in the bitmap,
-- and second argument determines the bitmap data.
| BitmapSection Rectangle BitmapData
-- Color ------------------------------------------
-- | A picture drawn with this color.
| Color Color Picture
-- Transforms -------------------------------------
-- | A picture translated by the given x and y coordinates.
| Translate Float Float Picture
-- | A picture rotated clockwise by the given angle (in degrees).
| Rotate Float Picture
-- | A picture scaled by the given x and y factors.
| Scale Float Float Picture
-- More Pictures ----------------------------------
-- | A picture consisting of several others.
| Pictures [Picture]
deriving (Show, Eq, Data, Typeable)
-- Instances ------------------------------------------------------------------
instance Monoid Picture where
mempty = Blank
mappend a b = Pictures [a, b]
mconcat = Pictures
#if __GLASGOW_HASKELL__ >= 800
instance Semigroup Picture where
a <> b = Pictures [a, b]
sconcat = Pictures . toList
stimes = stimesIdempotent
#endif
-- Bitmaps --------------------------------------------------------------------
-- | O(1). Use a `ForeignPtr` of RGBA data as a bitmap with the given
-- width and height.
--
-- The boolean flag controls whether Gloss should cache the data
-- between frames for speed. If you are programatically generating
-- the image for each frame then use `False`. If you have loaded it
-- from a file then use `True`.
bitmapOfForeignPtr :: Int -> Int -> BitmapFormat -> ForeignPtr Word8 -> Bool -> Picture
bitmapOfForeignPtr width height fmt fptr cacheMe =
Bitmap $
bitmapDataOfForeignPtr width height fmt fptr cacheMe
--Bitmap width height (bitmapDataOfForeignPtr width height fmt fptr) cacheMe
bitmapDataOfForeignPtr :: Int -> Int -> BitmapFormat -> ForeignPtr Word8 -> Bool -> BitmapData
bitmapDataOfForeignPtr width height fmt fptr cacheMe
= let len = width * height * 4
in BitmapData len fmt (width,height) cacheMe fptr
-- | O(size). Copy a `ByteString` of RGBA data into a bitmap with the given
-- width and height.
--
-- The boolean flag controls whether Gloss should cache the data
-- between frames for speed. If you are programatically generating
-- the image for each frame then use `False`. If you have loaded it
-- from a file then use `True`.
bitmapOfByteString :: Int -> Int -> BitmapFormat -> ByteString -> Bool -> Picture
bitmapOfByteString width height fmt bs cacheMe =
Bitmap $
bitmapDataOfByteString width height fmt bs cacheMe
bitmapDataOfByteString :: Int -> Int -> BitmapFormat -> ByteString -> Bool -> BitmapData
bitmapDataOfByteString width height fmt bs cacheMe
= unsafePerformIO
$ do let len = width * height * 4
ptr <- mallocBytes len
fptr <- newForeignPtr finalizerFree ptr
BSU.unsafeUseAsCString bs
$ \cstr -> copyBytes ptr (castPtr cstr) len
return $ BitmapData len fmt (width, height) cacheMe fptr
{-# NOINLINE bitmapDataOfByteString #-}
-- | O(size). Copy a `BMP` file into a bitmap.
bitmapOfBMP :: BMP -> Picture
bitmapOfBMP bmp
= Bitmap $ bitmapDataOfBMP bmp
-- | O(size). Copy a `BMP` file into a bitmap.
bitmapDataOfBMP :: BMP -> BitmapData
bitmapDataOfBMP bmp
= unsafePerformIO
$ do let (width, height) = bmpDimensions bmp
let bs = unpackBMPToRGBA32 bmp
let len = width * height * 4
ptr <- mallocBytes len
fptr <- newForeignPtr finalizerFree ptr
BSU.unsafeUseAsCString bs
$ \cstr -> copyBytes ptr (castPtr cstr) len
return $ BitmapData len (BitmapFormat BottomToTop PxRGBA) (width,height) True fptr
{-# NOINLINE bitmapDataOfBMP #-}
-- | Load an uncompressed 24 or 32bit RGBA BMP file as a bitmap.
loadBMP :: FilePath -> IO Picture
loadBMP filePath
= do ebmp <- readBMP filePath
case ebmp of
Left err -> error $ show err
Right bmp -> return $ bitmapOfBMP bmp
-- | Construct a rectangle of the given width and height,
-- with the lower left corner at the origin.
rectAtOrigin :: Int -> Int -> Rectangle
rectAtOrigin w h = Rectangle (0,0) (w,h)
|