/// Simple DirectMedia Layer
/// Copyright (C) 1997-2025 Sam Lantinga
///
/// This software is provided 'as-is', without any express or implied
/// warranty. In no event will the authors be held liable for any damages
/// arising from the use of this software.
///
/// Permission is granted to anyone to use this software for any purpose,
/// including commercial applications, and to alter it and redistribute it
/// freely, subject to the following restrictions:
///
/// 1. The origin of this software must not be misrepresented; you must not
/// claim that you wrote the original software. If you use this software
/// in a product, an acknowledgment in the product documentation would be
/// appreciated but is not required.
/// 2. Altered source versions must be plainly marked as such, and must not be
/// misrepresented as being the original software.
/// 3. This notice may not be removed or altered from any source distribution.
/// # CategorySurface
///
/// SDL surfaces are buffers of pixels in system RAM. These are useful for
/// passing around and manipulating images that are not stored in GPU memory.
///
/// SDL_Surface makes serious efforts to manage images in various formats, and
/// provides a reasonable toolbox for transforming the data, including copying
/// between surfaces, filling rectangles in the image data, etc.
///
/// There is also a simple .bmp loader, SDL_LoadBMP(). SDL itself does not
/// provide loaders for various other file formats, but there are several
/// excellent external libraries that do, including its own satellite library,
/// [SDL_image](https://wiki.libsdl.org/SDL3_image)
/// :
///
/// https://github.com/libsdl-org/SDL_image
///| The flags on an SDL_Surface.
///
/// These are generally considered read-only.
///
/// @since This datatype is available since SDL 3.2.0.
///
/// ```c
/// typedef Uint32 SDL_SurfaceFlags;
/// ```
pub typealias UInt as SDL_SurfaceFlags
///| Surface uses preallocated pixel memory
pub const SDL_SURFACE_PREALLOCATED: UInt = 0x00000001
///| Surface needs to be locked to access pixels
pub const SDL_SURFACE_LOCK_NEEDED: UInt = 0x00000002
///| Surface is currently locked
pub const SDL_SURFACE_LOCKED: UInt = 0x00000004
///| Surface uses pixel memory allocated with SDL_aligned_alloc()
pub const SDL_SURFACE_SIMD_ALIGNED: UInt = 0x00000008
///| The scaling mode.
///
/// @since This enum is available since SDL 3.2.0.
///
/// ```c
/// typedef enum SDL_ScaleMode
/// {
/// SDL_SCALEMODE_INVALID = -1,
/// SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
/// SDL_SCALEMODE_LINEAR, /**< linear filtering */
/// SDL_SCALEMODE_PIXELART /**< nearest pixel sampling with improved scaling for pixel art */
/// } SDL_ScaleMode;
/// ```
pub(all) enum SDL_ScaleMode {
SDL_SCALEMODE_NEAREST
SDL_SCALEMODE_LINEAR
SDL_SCALEMODE_PIXELART
}
///| The flip mode.
///
/// @since This enum is available since SDL 3.2.0.
///
/// ```c
/// typedef enum SDL_FlipMode
/// {
/// SDL_FLIP_NONE, /**< Do not flip */
/// SDL_FLIP_HORIZONTAL, /**< flip horizontally */
/// SDL_FLIP_VERTICAL /**< flip vertically */
/// } SDL_FlipMode;
/// ```
pub(all) enum SDL_FlipMode {
SDL_FLIP_NONE ///< Do not flip
SDL_FLIP_HORIZONTAL ///< flip horizontally
SDL_FLIP_VERTICAL ///< flip vertically
}
#external
pub type SDL_Surface
// SDL_PixelFormat is already defined in pixels.mbt as an enum
// SDL_Colorspace is defined as external type in video/pixels modules
// SDL_PropertiesID is handled as UInt throughout the codebase
///| Allocate a new surface with a specific pixel format.
///
/// The pixels of the new surface are initialized to zero.
///
/// @param width the width of the surface.
/// @param height the height of the surface.
/// @param format the SDL_PixelFormat for the new surface's pixel format.
/// @return the new SDL_Surface structure that is created or NULL on failure;
/// call SDL_GetError() for more information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_CreateSurfaceFrom
/// @see SDL_DestroySurface
///
/// ```c
/// extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurface(int width, int height, SDL_PixelFormat format);
/// ```
pub extern "C" fn sdl_CreateSurface(width: Int, height: Int, format: SDL_PixelFormat) -> SDL_Surface = "SDL_CreateSurface"
///| Allocate a new surface with a specific pixel format and existing pixel
/// data.
///
/// No copy is made of the pixel data. Pixel data is not managed automatically;
/// you must free the surface before you free the pixel data.
///
/// Pitch is the offset in bytes from one row of pixels to the next, e.g.
/// `width*4` for `SDL_PIXELFORMAT_RGBA8888`.
///
/// You may pass NULL for pixels and 0 for pitch to create a surface that you
/// will fill in with valid values later.
///
/// @param width the width of the surface.
/// @param height the height of the surface.
/// @param format the SDL_PixelFormat for the new surface's pixel format.
/// @param pixels a pointer to existing pixel data.
/// @param pitch the number of bytes between each row, including padding.
/// @return the new SDL_Surface structure that is created or NULL on failure;
/// call SDL_GetError() for more information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_CreateSurface
/// @see SDL_DestroySurface
///
/// ```c
/// extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurfaceFrom(int width, int height, SDL_PixelFormat format, void *pixels, int pitch);
/// ```
pub extern "C" fn sdl_CreateSurfaceFrom(width: Int, height: Int, format: SDL_PixelFormat, pixels: VoidPtr, pitch: Int) -> SDL_Surface = "SDL_CreateSurfaceFrom"
///| Free a surface.
///
/// It is safe to pass NULL to this function.
///
/// @param surface the SDL_Surface to free.
///
/// @threadsafety No other thread should be using the surface when it is freed.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_CreateSurface
/// @see SDL_CreateSurfaceFrom
///
/// ```c
/// extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
/// ```
pub extern "C" fn sdl_DestroySurface(surface: SDL_Surface) = "SDL_DestroySurface"
///| Get the properties associated with a surface.
///
/// The following properties are understood by SDL:
///
/// - `SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point
/// surfaces, this defines the value of 100% diffuse white, with higher
/// values being displayed in the High Dynamic Range headroom. This defaults
/// to 203 for HDR10 surfaces and 1.0 for floating point surfaces.
/// - `SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point
/// surfaces, this defines the maximum dynamic range used by the content, in
/// terms of the SDR white point. This defaults to 0.0, which disables tone
/// mapping.
/// - `SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING`: the tone mapping operator
/// used when compressing from a surface with high dynamic range to another
/// with lower dynamic range. Currently this supports "chrome", which uses
/// the same tone mapping that Chrome uses for HDR content, the form "*=N",
/// where N is a floating point scale factor applied in linear space, and
/// "none", which disables tone mapping. This defaults to "chrome".
/// - `SDL_PROP_SURFACE_HOTSPOT_X_NUMBER`: the hotspot pixel offset from the
/// left edge of the image, if this surface is being used as a cursor.
/// - `SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER`: the hotspot pixel offset from the
/// top edge of the image, if this surface is being used as a cursor.
///
/// @param surface the SDL_Surface structure to query.
/// @return a valid property ID on success or 0 on failure; call
/// SDL_GetError() for more information.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
/// ```
pub extern "C" fn sdl_GetSurfaceProperties(surface: SDL_Surface) -> UInt = "SDL_GetSurfaceProperties"
pub const SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT: String = "SDL.surface.SDR_white_point"
pub const SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT: String = "SDL.surface.HDR_headroom"
pub const SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING: String = "SDL.surface.tonemap"
pub const SDL_PROP_SURFACE_HOTSPOT_X_NUMBER: String = "SDL.surface.hotspot.x"
pub const SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER: String = "SDL.surface.hotspot.y"
///| Set the colorspace used by a surface.
///
/// Setting the colorspace doesn't change the pixels, only how they are
/// interpreted in color operations.
///
/// @param surface the SDL_Surface structure to update.
/// @param colorspace an SDL_Colorspace value describing the surface
/// colorspace.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety This function is not thread safe.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_GetSurfaceColorspace
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace colorspace);
/// ```
pub extern "C" fn sdl_SetSurfaceColorspace(surface: SDL_Surface, colorspace: SDL_Colorspace) -> Bool = "SDL_SetSurfaceColorspace"
///| Get the colorspace used by a surface.
///
/// The colorspace defaults to SDL_COLORSPACE_SRGB_LINEAR for floating point
/// formats, SDL_COLORSPACE_HDR10 for 10-bit formats, SDL_COLORSPACE_SRGB for
/// other RGB surfaces and SDL_COLORSPACE_BT709_FULL for YUV textures.
///
/// @param surface the SDL_Surface structure to query.
/// @return the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if
/// the surface is NULL.
///
/// @threadsafety This function is not thread safe.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_SetSurfaceColorspace
///
/// ```c
/// extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface *surface);
/// ```
pub extern "C" fn sdl_GetSurfaceColorspace(surface: SDL_Surface) -> SDL_Colorspace = "SDL_GetSurfaceColorspace"
///| Perform a fast blit from the source surface to the destination surface.
///
/// @param src the SDL_Surface structure to be copied from.
/// @param srcrect the SDL_Rect structure representing the rectangle to be
/// copied, or NULL to copy the entire surface.
/// @param dst the SDL_Surface structure that is the blit target.
/// @param dstrect the SDL_Rect structure representing the target rectangle in
/// the destination surface, or NULL to fill the entire
/// destination surface.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety Only one thread should be using the `src` and `dst` surfaces
/// at any given time.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_BlitSurfaceScaled
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
/// ```
pub extern "C" fn sdl_BlitSurface(src: SDL_Surface, srcrect: FixedArray[SDL_Rect], dst: SDL_Surface, dstrect: FixedArray[SDL_Rect]) -> Bool = "SDL_BlitSurface"
///| Perform a scaled blit to a destination surface, which may be of a different
/// format.
///
/// @param src the SDL_Surface structure to be copied from.
/// @param srcrect the SDL_Rect structure representing the rectangle to be
/// copied, or NULL to copy the entire surface.
/// @param dst the SDL_Surface structure that is the blit target.
/// @param dstrect the SDL_Rect structure representing the target rectangle in
/// the destination surface, or NULL to fill the entire
/// destination surface.
/// @param scaleMode the SDL_ScaleMode to be used.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety Only one thread should be using the `src` and `dst` surfaces
/// at any given time.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_BlitSurface
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
/// ```
pub extern "C" fn sdl_BlitSurfaceScaled(src: SDL_Surface, srcrect: FixedArray[SDL_Rect], dst: SDL_Surface, dstrect: FixedArray[SDL_Rect], scaleMode: SDL_ScaleMode) -> Bool = "SDL_BlitSurfaceScaled"
///| Perform a tiled blit to a destination surface, which may be of a different
/// format.
///
/// The pixels in `srcrect` will be repeated as many times as needed to
/// completely fill `dstrect`.
///
/// @param src the SDL_Surface structure to be copied from.
/// @param srcrect the SDL_Rect structure representing the rectangle to be
/// copied, or NULL to copy the entire surface.
/// @param dst the SDL_Surface structure that is the blit target.
/// @param dstrect the SDL_Rect structure representing the target rectangle in
/// the destination surface, or NULL to fill the entire surface.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety Only one thread should be using the `src` and `dst` surfaces
/// at any given time.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_BlitSurface
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
/// ```
pub extern "C" fn sdl_BlitSurfaceTiled(src: SDL_Surface, srcrect: FixedArray[SDL_Rect], dst: SDL_Surface, dstrect: FixedArray[SDL_Rect]) -> Bool = "SDL_BlitSurfaceTiled"
///| Map an RGB triple to an opaque pixel value for a surface.
///
/// This function maps the RGB color value to the specified pixel format and
/// returns the pixel value best approximating the given RGB color value for
/// the given pixel format.
///
/// If the surface has a palette, the index of the closest matching color in
/// the palette will be returned.
///
/// If the surface pixel format has an alpha component it will be returned as
/// all 1 bits (fully opaque).
///
/// If the pixel format bpp (color depth) is less than 32-bpp then the unused
/// upper bits of the return value can safely be ignored (e.g., with a 16-bpp
/// format the return value can be assigned to a Uint16, and similarly a Uint8
/// for an 8-bpp format).
///
/// @param surface the surface to use for the pixel format and palette.
/// @param r the red component of the pixel in the range 0-255.
/// @param g the green component of the pixel in the range 0-255.
/// @param b the blue component of the pixel in the range 0-255.
/// @return a pixel value.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_MapSurfaceRGBA
///
/// ```c
/// extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b);
/// ```
pub extern "C" fn sdl_MapSurfaceRGB(surface: SDL_Surface, r: Byte, g: Byte, b: Byte) -> UInt = "SDL_MapSurfaceRGB"
///| Map an RGBA quadruple to a pixel value for a surface.
///
/// This function maps the RGBA color value to the specified pixel format and
/// returns the pixel value best approximating the given RGBA color value for
/// the given pixel format.
///
/// If the surface pixel format has no alpha component the alpha value will be
/// ignored (as it will be in formats with a palette).
///
/// If the surface has a palette, the index of the closest matching color in
/// the palette will be returned.
///
/// If the pixel format bpp (color depth) is less than 32-bpp then the unused
/// upper bits of the return value can safely be ignored (e.g., with a 16-bpp
/// format the return value can be assigned to a Uint16, and similarly a Uint8
/// for an 8-bpp format).
///
/// @param surface the surface to use for the pixel format and palette.
/// @param r the red component of the pixel in the range 0-255.
/// @param g the green component of the pixel in the range 0-255.
/// @param b the blue component of the pixel in the range 0-255.
/// @param a the alpha component of the pixel in the range 0-255.
/// @return a pixel value.
///
/// @threadsafety It is safe to call this function from any thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// @see SDL_MapSurfaceRGB
///
/// ```c
/// extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/// ```
pub extern "C" fn sdl_MapSurfaceRGBA(surface: SDL_Surface, r: Byte, g: Byte, b: Byte, a: Byte) -> UInt = "SDL_MapSurfaceRGBA"
///| Retrieves a single pixel from a surface.
///
/// This function prioritizes correctness over speed: it is suitable for unit
/// tests, but is not intended for use in a game engine.
///
/// Like SDL_GetRGBA, this uses the entire 0..255 range when converting color
/// components from pixel formats with less than 8 bits per RGB component.
///
/// @param surface the surface to read.
/// @param x the horizontal coordinate, 0 <= x < width.
/// @param y the vertical coordinate, 0 <= y < height.
/// @param r a pointer filled in with the red channel, 0-255, or NULL to ignore
/// this channel.
/// @param g a pointer filled in with the green channel, 0-255, or NULL to
/// ignore this channel.
/// @param b a pointer filled in with the blue channel, 0-255, or NULL to
/// ignore this channel.
/// @param a a pointer filled in with the alpha channel, 0-255, or NULL to
/// ignore this channel.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety This function is not thread safe.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
/// ```
pub extern "C" fn sdl_ReadSurfacePixel(surface: SDL_Surface, x: Int, y: Int, r: FixedArray[Byte], g: FixedArray[Byte], b: FixedArray[Byte], a: FixedArray[Byte]) -> Bool = "SDL_ReadSurfacePixel"
///| Writes a single pixel to a surface.
///
/// This function prioritizes correctness over speed: it is suitable for unit
/// tests, but is not intended for use in a game engine.
///
/// Like SDL_MapRGBA, this uses the entire 0..255 range when converting color
/// components from pixel formats with less than 8 bits per RGB component.
///
/// @param surface the surface to write.
/// @param x the horizontal coordinate, 0 <= x < width.
/// @param y the vertical coordinate, 0 <= y < height.
/// @param r the red channel value, 0-255.
/// @param g the green channel value, 0-255.
/// @param b the blue channel value, 0-255.
/// @param a the alpha channel value, 0-255.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety This function is not thread safe.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/// ```
pub extern "C" fn sdl_WriteSurfacePixel(surface: SDL_Surface, x: Int, y: Int, r: Byte, g: Byte, b: Byte, a: Byte) -> Bool = "SDL_WriteSurfacePixel"
///| Load a BMP image from a file.
///
/// @param file the BMP file to load.
/// @return a new SDL_Surface with the loaded image, or NULL on error.
///
/// @threadsafety This function should only be called on the main thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file);
/// ```
extern "C" fn __sdl_LoadBMP(file: Bytes) -> SDL_Surface = "SDL_LoadBMP"
pub fn sdl_LoadBMP(file: String) -> SDL_Surface {
__sdl_LoadBMP(string_to_cbytes(file))
}
///| Save a BMP image to a file.
///
/// @param surface the surface to save.
/// @param file the BMP file to save to.
/// @return true on success or false on failure; call SDL_GetError() for more
/// information.
///
/// @threadsafety This function should only be called on the main thread.
///
/// @since This function is available since SDL 3.2.0.
///
/// ```c
/// extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file);
/// ```
extern "C" fn __sdl_SaveBMP(surface: SDL_Surface, file: Bytes) -> Bool = "SDL_SaveBMP"
pub fn sdl_SaveBMP(surface: SDL_Surface, file: String) -> Bool {
__sdl_SaveBMP(surface, string_to_cbytes(file))
}