Files
radiantwave/archive/vendor/github.com/veandco/go-sdl2/sdl/surface.go
T
2026-08-07 14:51:41 -05:00

807 lines
25 KiB
Go

package sdl
/*
#include "sdl_wrapper.h"
#if !(SDL_VERSION_ATLEAST(2,0,9))
#if defined(WARN_OUTDATED)
#pragma message("SDL_HasColorKey is not supported before SDL 2.0.9")
#endif
static SDL_bool SDL_HasColorKey(SDL_Surface * surface)
{
return SDL_FALSE;
}
#endif
#if !(SDL_VERSION_ATLEAST(2,0,8))
typedef enum {
SDL_YUV_CONVERSION_JPEG,
SDL_YUV_CONVERSION_BT601,
SDL_YUV_CONVERSION_BT709,
SDL_YUV_CONVERSION_AUTOMATIC
} SDL_YUV_CONVERSION_MODE;
#if defined(WARN_OUTDATED)
#pragma message("SDL_SetYUVConversionMode is not supported before SDL 2.0.8")
#endif
void SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode)
{
}
#if defined(WARN_OUTDATED)
#pragma message("SDL_GetYUVConversionMode is not supported before SDL 2.0.8")
#endif
SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionMode(void)
{
return -1;
}
#if defined(WARN_OUTDATED)
#pragma message("SDL_GetYUVConversionModeForResolution is not supported before SDL 2.0.8")
#endif
SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionModeForResolution(int width, int height)
{
return -1;
}
#endif
#if !(SDL_VERSION_ATLEAST(2,0,6))
#if defined(WARN_OUTDATED)
#pragma message("SDL_DuplicateSurface is not supported before SDL 2.0.6")
#endif
static inline SDL_Surface* SDL_DuplicateSurface(SDL_Surface *surface)
{
return NULL;
}
#endif
#if !(SDL_VERSION_ATLEAST(2,0,5))
#if defined(WARN_OUTDATED)
#pragma message("SDL_CreateRGBSurfaceWithFormat is not supported before SDL 2.0.5")
#endif
static inline SDL_Surface* SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)
{
return NULL;
}
#if defined(WARN_OUTDATED)
#pragma message("SDL_CreateRGBSurfaceWithFormatFrom is not supported before SDL 2.0.5")
#endif
static inline SDL_Surface* SDL_CreateRGBSurfaceWithFormatFrom(void* pixels, int width, int height, int depth, int pitch, Uint32 format)
{
return NULL;
}
#endif
#if !(SDL_VERSION_ATLEAST(2,0,16))
#if defined(WARN_OUTDATED)
#pragma message("SDL_SoftStretchLinear is not supported before SDL 2.0.16")
#endif
static int SDL_SoftStretchLinear(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, const SDL_Rect * dstrect)
{
return -1;
}
#endif
#if !(SDL_VERSION_ATLEAST(2,0,18))
#if defined(WARN_OUTDATED)
#pragma message("SDL_PremultiplyAlpha is not supported before SDL 2.0.18")
#endif
static int SDL_PremultiplyAlpha(int width, int height, Uint32 src_format, const void * src, int src_pitch, Uint32 dst_format, void * dst, int dst_pitch)
{
return -1;
}
#endif
*/
import "C"
import (
"image"
"image/color"
"reflect"
"unsafe"
)
// Surface flags (internal use)
const (
SWSURFACE = C.SDL_SWSURFACE // just here for compatibility
PREALLOC = C.SDL_PREALLOC // surface uses preallocated memory
RLEACCEL = C.SDL_RLEACCEL // surface is RLE encoded
DONTFREE = C.SDL_DONTFREE // surface is referenced internally
)
type YUV_CONVERSION_MODE C.SDL_YUV_CONVERSION_MODE
// YUV Conversion Modes
const (
YUV_CONVERSION_JPEG YUV_CONVERSION_MODE = C.SDL_YUV_CONVERSION_JPEG // Full range JPEG
YUV_CONVERSION_BT601 = C.SDL_YUV_CONVERSION_BT601 // BT.601 (the default)
YUV_CONVERSION_BT709 = C.SDL_YUV_CONVERSION_BT709 // BT.709
YUV_CONVERSION_AUTOMATIC = C.SDL_YUV_CONVERSION_AUTOMATIC // BT.601 for SD content, BT.709 for HD content
)
// Surface contains a collection of pixels used in software blitting.
// (https://wiki.libsdl.org/SDL_Surface)
type Surface struct {
flags uint32 // (internal use)
Format *PixelFormat // the format of the pixels stored in the surface (read-only) (https://wiki.libsdl.org/SDL_PixelFormat)
W int32 // the width in pixels (read-only)
H int32 // the height in pixels (read-only)
Pitch int32 // the length of a row of pixels in bytes (read-only)
pixels unsafe.Pointer // the pointer to the actual pixel data; use Pixels() for access
UserData unsafe.Pointer // an arbitrary pointer you can set
locked int32 // used for surfaces that require locking (internal use)
lockData unsafe.Pointer // used for surfaces that require locking (internal use)
ClipRect Rect // a Rect structure used to clip blits to the surface which can be set by SetClipRect() (read-only)
_ unsafe.Pointer // map; info for fast blit mapping to other surfaces (internal use)
RefCount int32 // reference count that can be incremented by the application
}
type cSurface C.SDL_Surface
func (surface *Surface) cptr() *C.SDL_Surface {
return (*C.SDL_Surface)(unsafe.Pointer(surface))
}
// MustLock reports whether the surface must be locked for access.
// (https://wiki.libsdl.org/SDL_MUSTLOCK)
func (surface *Surface) MustLock() bool {
return (surface.flags & RLEACCEL) != 0
}
// CreateRGBSurface allocates a new RGB surface.
// (https://wiki.libsdl.org/SDL_CreateRGBSurface)
func CreateRGBSurface(flags uint32, width, height, depth int32, Rmask, Gmask, Bmask, Amask uint32) (*Surface, error) {
surface := (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurface(
C.Uint32(flags),
C.int(width),
C.int(height),
C.int(depth),
C.Uint32(Rmask),
C.Uint32(Gmask),
C.Uint32(Bmask),
C.Uint32(Amask))))
if surface == nil {
return nil, GetError()
}
return surface, nil
}
// CreateRGBSurfaceFrom allocate a new RGB surface with existing pixel data.
// (https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom)
func CreateRGBSurfaceFrom(pixels unsafe.Pointer, width, height int32, depth, pitch int, Rmask, Gmask, Bmask, Amask uint32) (*Surface, error) {
surface := (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurfaceFrom(
pixels,
C.int(width),
C.int(height),
C.int(depth),
C.int(pitch),
C.Uint32(Rmask),
C.Uint32(Gmask),
C.Uint32(Bmask),
C.Uint32(Amask))))
if surface == nil {
return nil, GetError()
}
return surface, nil
}
// CreateRGBSurfaceWithFormat allocates an RGB surface.
// (https://wiki.libsdl.org/SDL_CreateRGBSurfaceWithFormat)
func CreateRGBSurfaceWithFormat(flags uint32, width, height, depth int32, format uint32) (*Surface, error) {
surface := (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurfaceWithFormat(
C.Uint32(flags),
C.int(width),
C.int(height),
C.int(depth),
C.Uint32(format))))
if surface == nil {
return nil, GetError()
}
return surface, nil
}
// CreateRGBSurfaceWithFormatFrom allocates an RGB surface from provided pixel data.
// (https://wiki.libsdl.org/SDL_CreateRGBSurfaceWithFormatFrom)
func CreateRGBSurfaceWithFormatFrom(pixels unsafe.Pointer, width, height, depth, pitch int32, format uint32) (*Surface, error) {
surface := (*Surface)(unsafe.Pointer(C.SDL_CreateRGBSurfaceWithFormatFrom(
pixels,
C.int(width),
C.int(height),
C.int(depth),
C.int(pitch),
C.Uint32(format))))
if surface == nil {
return nil, GetError()
}
return surface, nil
}
// SetYUVConversionMode sets the YUV conversion mode
// TODO: (https://wiki.libsdl.org/SDL_SetYUVConversionMode)
func SetYUVConversionMode(mode YUV_CONVERSION_MODE) {
_mode := C.SDL_YUV_CONVERSION_MODE(mode)
C.SDL_SetYUVConversionMode(_mode)
}
// GetYUVConversionMode gets the YUV conversion mode
// TODO: (https://wiki.libsdl.org/SDL_GetYUVConversionMode)
func GetYUVConversionMode() YUV_CONVERSION_MODE {
return YUV_CONVERSION_MODE(C.SDL_GetYUVConversionMode())
}
// GetYUVConversionModeForResolution gets the YUV conversion mode
// TODO: (https://wiki.libsdl.org/SDL_GetYUVConversionModeForResolution)
func GetYUVConversionModeForResolution(width, height int) YUV_CONVERSION_MODE {
_width := C.int(width)
_height := C.int(height)
return YUV_CONVERSION_MODE(C.SDL_GetYUVConversionModeForResolution(_width, _height))
}
// Free frees the RGB surface.
// (https://wiki.libsdl.org/SDL_FreeSurface)
func (surface *Surface) Free() {
C.SDL_FreeSurface(surface.cptr())
}
// SetPalette sets the palette used by the surface.
// (https://wiki.libsdl.org/SDL_SetSurfacePalette)
func (surface *Surface) SetPalette(palette *Palette) error {
if C.SDL_SetSurfacePalette(surface.cptr(), palette.cptr()) != 0 {
return GetError()
}
return nil
}
// Lock sets up the surface for directly accessing the pixels.
// (https://wiki.libsdl.org/SDL_LockSurface)
func (surface *Surface) Lock() error {
if C.SDL_LockSurface(surface.cptr()) != 0 {
return GetError()
}
return nil
}
// Unlock releases the surface after directly accessing the pixels.
// (https://wiki.libsdl.org/SDL_UnlockSurface)
func (surface *Surface) Unlock() {
C.SDL_UnlockSurface(surface.cptr())
}
// LoadBMPRW loads a BMP image from a seekable SDL data stream (memory or file).
// (https://wiki.libsdl.org/SDL_LoadBMP_RW)
func LoadBMPRW(src *RWops, freeSrc bool) (*Surface, error) {
surface := (*Surface)(unsafe.Pointer(C.SDL_LoadBMP_RW(src.cptr(), C.int(Btoi(freeSrc)))))
if surface == nil {
return nil, GetError()
}
return surface, nil
}
// LoadBMP loads a surface from a BMP file.
// (https://wiki.libsdl.org/SDL_LoadBMP)
func LoadBMP(file string) (*Surface, error) {
return LoadBMPRW(RWFromFile(file, "rb"), true)
}
// SaveBMPRW save the surface to a seekable SDL data stream (memory or file) in BMP format.
// (https://wiki.libsdl.org/SDL_SaveBMP_RW)
func (surface *Surface) SaveBMPRW(dst *RWops, freeDst bool) error {
if C.SDL_SaveBMP_RW(surface.cptr(), dst.cptr(), C.int(Btoi(freeDst))) != 0 {
return GetError()
}
return nil
}
// SaveBMP saves the surface to a BMP file.
// (https://wiki.libsdl.org/SDL_SaveBMP)
func (surface *Surface) SaveBMP(file string) error {
return surface.SaveBMPRW(RWFromFile(file, "wb"), true)
}
// SetRLE sets the RLE acceleration hint for the surface.
// (https://wiki.libsdl.org/SDL_SetSurfaceRLE)
func (surface *Surface) SetRLE(flag bool) error {
if C.SDL_SetSurfaceRLE(surface.cptr(), C.int(Btoi(flag))) != 0 {
return GetError()
}
return nil
}
// SetColorKey sets the color key (transparent pixel) in the surface.
// (https://wiki.libsdl.org/SDL_SetColorKey)
func (surface *Surface) SetColorKey(flag bool, key uint32) error {
if C.SDL_SetColorKey(surface.cptr(), C.int(Btoi(flag)), C.Uint32(key)) != 0 {
return GetError()
}
return nil
}
// HasColorKey returns the color key (transparent pixel) for the surface.
// TODO: (https://wiki.libsdl.org/SDL_HasColorKey)
func (surface *Surface) HasColorKey() bool {
return C.SDL_HasColorKey(surface.cptr()) == C.SDL_TRUE
}
// GetColorKey returns the color key (transparent pixel) for the surface.
// (https://wiki.libsdl.org/SDL_GetColorKey)
func (surface *Surface) GetColorKey() (key uint32, err error) {
_key := (*C.Uint32)(unsafe.Pointer(&key))
if C.SDL_GetColorKey(surface.cptr(), _key) != 0 {
return key, GetError()
}
return key, nil
}
// SetColorMod sets an additional color value multiplied into blit operations.
// (https://wiki.libsdl.org/SDL_SetSurfaceColorMod)
func (surface *Surface) SetColorMod(r, g, b uint8) error {
if C.SDL_SetSurfaceColorMod(surface.cptr(), C.Uint8(r), C.Uint8(g), C.Uint8(b)) != 0 {
return GetError()
}
return nil
}
// GetColorMod returns the additional color value multiplied into blit operations.
// (https://wiki.libsdl.org/SDL_GetSurfaceColorMod)
func (surface *Surface) GetColorMod() (r, g, b uint8, err error) {
_r := (*C.Uint8)(unsafe.Pointer(&r))
_g := (*C.Uint8)(unsafe.Pointer(&g))
_b := (*C.Uint8)(unsafe.Pointer(&b))
if C.SDL_GetSurfaceColorMod(surface.cptr(), _r, _g, _b) != 0 {
return r, g, b, GetError()
}
return r, g, b, nil
}
// SetAlphaMod sets an additional alpha value used in blit operations.
// (https://wiki.libsdl.org/SDL_SetSurfaceAlphaMod)
func (surface *Surface) SetAlphaMod(alpha uint8) error {
if C.SDL_SetSurfaceAlphaMod(surface.cptr(), C.Uint8(alpha)) != 0 {
return GetError()
}
return nil
}
// GetAlphaMod returns the additional alpha value used in blit operations.
// (https://wiki.libsdl.org/SDL_GetSurfaceAlphaMod)
func (surface *Surface) GetAlphaMod() (alpha uint8, err error) {
_alpha := (*C.Uint8)(unsafe.Pointer(&alpha))
if C.SDL_GetSurfaceAlphaMod(surface.cptr(), _alpha) != 0 {
return alpha, GetError()
}
return alpha, nil
}
// SetBlendMode sets the blend mode used for blit operations.
// (https://wiki.libsdl.org/SDL_SetSurfaceBlendMode)
func (surface *Surface) SetBlendMode(bm BlendMode) error {
if C.SDL_SetSurfaceBlendMode(surface.cptr(), bm.c()) != 0 {
return GetError()
}
return nil
}
// GetBlendMode returns the blend mode used for blit operations.
// (https://wiki.libsdl.org/SDL_GetSurfaceBlendMode)
func (surface *Surface) GetBlendMode() (bm BlendMode, err error) {
if C.SDL_GetSurfaceBlendMode(surface.cptr(), bm.cptr()) != 0 {
return bm, GetError()
}
return bm, nil
}
// SetClipRect sets the clipping rectangle for the surface
// (https://wiki.libsdl.org/SDL_SetClipRect)
func (surface *Surface) SetClipRect(rect *Rect) bool {
return C.SDL_SetClipRect(surface.cptr(), rect.cptr()) > 0
}
// GetClipRect returns the clipping rectangle for a surface.
// (https://wiki.libsdl.org/SDL_GetClipRect)
func (surface *Surface) GetClipRect(rect *Rect) {
C.SDL_GetClipRect(surface.cptr(), rect.cptr())
}
// Convert copies the existing surface into a new one that is optimized for blitting to a surface of a specified pixel format.
// (https://wiki.libsdl.org/SDL_ConvertSurface)
func (surface *Surface) Convert(fmt *PixelFormat, flags uint32) (*Surface, error) {
_surface := (*Surface)(unsafe.Pointer(C.SDL_ConvertSurface(surface.cptr(), fmt.cptr(), C.Uint32(flags))))
if _surface == nil {
return nil, GetError()
}
return _surface, nil
}
// ConvertFormat copies the existing surface to a new surface of the specified format.
// (https://wiki.libsdl.org/SDL_ConvertSurfaceFormat)
func (surface *Surface) ConvertFormat(pixelFormat uint32, flags uint32) (*Surface, error) {
_surface := (*Surface)(unsafe.Pointer(C.SDL_ConvertSurfaceFormat(surface.cptr(), C.Uint32(pixelFormat), C.Uint32(flags))))
if _surface == nil {
return nil, GetError()
}
return _surface, nil
}
// ConvertPixels copies a block of pixels of one format to another format.
// (https://wiki.libsdl.org/SDL_ConvertPixels)
func ConvertPixels(width, height int32, srcFormat uint32, src unsafe.Pointer, srcPitch int,
dstFormat uint32, dst unsafe.Pointer, dstPitch int) error {
if C.SDL_ConvertPixels(C.int(width), C.int(height), C.Uint32(srcFormat), src, C.int(srcPitch), C.Uint32(dstFormat), dst, C.int(dstPitch)) != 0 {
return GetError()
}
return nil
}
// FillRect performs a fast fill of a rectangle with a specific color.
// (https://wiki.libsdl.org/SDL_FillRect)
func (surface *Surface) FillRect(rect *Rect, color uint32) error {
if C.SDL_FillRect(surface.cptr(), rect.cptr(), C.Uint32(color)) != 0 {
return GetError()
}
return nil
}
// FillRects performs a fast fill of a set of rectangles with a specific color.
// (https://wiki.libsdl.org/SDL_FillRects)
func (surface *Surface) FillRects(rects []Rect, color uint32) error {
if C.SDL_FillRects(surface.cptr(), rects[0].cptr(), C.int(len(rects)), C.Uint32(color)) != 0 {
return GetError()
}
return nil
}
// Blit performs a fast surface copy to a destination surface.
// (https://wiki.libsdl.org/SDL_BlitSurface)
func (surface *Surface) Blit(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_BlitSurface(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// BlitScaled performs a scaled surface copy to a destination surface.
// (https://wiki.libsdl.org/SDL_BlitScaled)
func (surface *Surface) BlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_BlitScaled(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// UpperBlit has been replaced by Blit().
// (https://wiki.libsdl.org/SDL_UpperBlit)
func (surface *Surface) UpperBlit(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_UpperBlit(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// LowerBlit performs low-level surface blitting only.
// (https://wiki.libsdl.org/SDL_LowerBlit)
func (surface *Surface) LowerBlit(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_LowerBlit(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// SoftStretch has been replaced by BlitScaled().
// (https://wiki.libsdl.org/SDL_SoftStretch)
func (surface *Surface) SoftStretch(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_SoftStretch(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// UpperBlitScaled has been replaced by BlitScaled().
// (https://wiki.libsdl.org/SDL_UpperBlitScaled)
func (surface *Surface) UpperBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_UpperBlitScaled(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// LowerBlitScaled performs low-level surface scaled blitting only.
// (https://wiki.libsdl.org/SDL_LowerBlitScaled)
func (surface *Surface) LowerBlitScaled(srcRect *Rect, dst *Surface, dstRect *Rect) error {
if C.SDL_LowerBlitScaled(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr()) != 0 {
return GetError()
}
return nil
}
// PixelNum returns the number of pixels stored in the surface.
func (surface *Surface) PixelNum() int {
return int(surface.W * surface.H)
}
// BytesPerPixel return the number of significant bits in a pixel values of the surface.
func (surface *Surface) BytesPerPixel() int {
return int(surface.Format.BytesPerPixel)
}
// Pixels returns the actual pixel data of the surface.
func (surface *Surface) Pixels() []byte {
var b []byte
length := int(surface.H) * int(surface.Pitch)
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sliceHeader.Cap = int(length)
sliceHeader.Len = int(length)
sliceHeader.Data = uintptr(surface.pixels)
return b
}
// Data returns the pointer to the actual pixel data of the surface.
func (surface *Surface) Data() unsafe.Pointer {
return surface.pixels
}
// Duplicate creates a new surface identical to the existing surface
func (surface *Surface) Duplicate() (newSurface *Surface, err error) {
_newSurface := C.SDL_DuplicateSurface(surface.cptr())
if _newSurface == nil {
err = GetError()
return
}
newSurface = (*Surface)(unsafe.Pointer(_newSurface))
return
}
// ColorModel returns the color model used by this Surface.
func (surface *Surface) ColorModel() color.Model {
switch surface.Format.Format {
case PIXELFORMAT_ARGB8888, PIXELFORMAT_ABGR8888:
return color.RGBAModel
case PIXELFORMAT_RGB888:
return color.RGBAModel
case PIXELFORMAT_RGB444:
return RGB444Model
case PIXELFORMAT_RGB332:
return RGB332Model
case PIXELFORMAT_RGB555:
return RGB555Model
case PIXELFORMAT_RGB565:
return RGB565Model
case PIXELFORMAT_BGR555:
return BGR555Model
case PIXELFORMAT_BGR565:
return BGR565Model
case PIXELFORMAT_ARGB4444:
return ARGB4444Model
case PIXELFORMAT_ABGR4444:
return ABGR4444Model
case PIXELFORMAT_RGBA4444:
return RGBA4444Model
case PIXELFORMAT_BGRA4444:
return BGRA4444Model
case PIXELFORMAT_ARGB1555:
return ARGB1555Model
case PIXELFORMAT_RGBA5551:
return RGBA5551Model
case PIXELFORMAT_ABGR1555:
return ABGR1555Model
case PIXELFORMAT_BGRA5551:
return BGRA5551Model
case PIXELFORMAT_RGBA8888:
return RGBA8888Model
case PIXELFORMAT_BGRA8888:
return BGRA8888Model
default:
panic("Not implemented yet")
}
}
// Bounds return the bounds of this surface. Currently, it always starts at
// (0,0), but this is not guaranteed in the future so don't rely on it.
func (surface *Surface) Bounds() image.Rectangle {
return image.Rect(0, 0, int(surface.W), int(surface.H))
}
// At returns the pixel color at (x, y)
func (surface *Surface) At(x, y int) color.Color {
pix := surface.Pixels()
i := int32(y)*surface.Pitch + int32(x)*int32(surface.Format.BytesPerPixel)
r, g, b, a := GetRGBA(*((*uint32)(unsafe.Pointer(&pix[i]))), surface.Format)
return color.NRGBA{R: r, G: g, B: b, A: a}
}
// Set the color of the pixel at (x, y) using this surface's color format to
// convert c to the appropriate byte sequence. This method is required for the
// draw.Image interface. The surface may require locking before calling Set.
func (surface *Surface) Set(x, y int, c color.Color) {
// All sdl2 colors are a subset of NRGBA so it is safe precision-wise to
// convert to NRGBA and use the color components from there.
nrgbaColor := color.NRGBAModel.Convert(c).(color.NRGBA)
colR, colG, colB, colA := nrgbaColor.R, nrgbaColor.G, nrgbaColor.B, nrgbaColor.A
pix := surface.Pixels()
i := int32(y)*surface.Pitch + int32(x)*int32(surface.Format.BytesPerPixel)
switch surface.Format.Format {
case PIXELFORMAT_ARGB8888:
pix[i+3] = colA
pix[i+2] = colR
pix[i+1] = colG
pix[i+0] = colB
case PIXELFORMAT_ABGR8888:
pix[i+3] = colA
pix[i+2] = colB
pix[i+1] = colG
pix[i+0] = colR
case PIXELFORMAT_RGB24, PIXELFORMAT_RGB888:
pix[i+2] = colR
pix[i+1] = colG
pix[i+0] = colB
case PIXELFORMAT_BGR24, PIXELFORMAT_BGR888:
pix[i+2] = colB
pix[i+1] = colG
pix[i+0] = colR
case PIXELFORMAT_RGB444:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 4 & 0x0F
g := uint32(colG) >> 4 & 0x0F
b := uint32(colB) >> 4 & 0x0F
*buf = r<<8 | g<<4 | b
case PIXELFORMAT_RGB332:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 5 & 0x0F
g := uint32(colG) >> 5 & 0x0F
b := uint32(colB) >> 6 & 0x0F
*buf = r<<5 | g<<2 | b
case PIXELFORMAT_RGB565:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 2 & 0xFF
b := uint32(colB) >> 3 & 0xFF
*buf = r<<11 | g<<5 | b
case PIXELFORMAT_RGB555:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
*buf = r<<10 | g<<5 | b
case PIXELFORMAT_BGR565:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 2 & 0xFF
b := uint32(colB) >> 3 & 0xFF
*buf = b<<11 | g<<5 | r
case PIXELFORMAT_BGR555:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
*buf = b<<10 | g<<5 | r
case PIXELFORMAT_ARGB4444:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
a := uint32(colA) >> 4 & 0x0F
r := uint32(colR) >> 4 & 0x0F
g := uint32(colG) >> 4 & 0x0F
b := uint32(colB) >> 4 & 0x0F
*buf = a<<12 | r<<8 | g<<4 | b
case PIXELFORMAT_ABGR4444:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
a := uint32(colA) >> 4 & 0x0F
r := uint32(colR) >> 4 & 0x0F
g := uint32(colG) >> 4 & 0x0F
b := uint32(colB) >> 4 & 0x0F
*buf = a<<12 | b<<8 | g<<4 | r
case PIXELFORMAT_RGBA4444:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 4 & 0x0F
g := uint32(colG) >> 4 & 0x0F
b := uint32(colB) >> 4 & 0x0F
a := uint32(colA) >> 4 & 0x0F
*buf = r<<12 | g<<8 | b<<4 | a
case PIXELFORMAT_BGRA4444:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 4 & 0x0F
g := uint32(colG) >> 4 & 0x0F
b := uint32(colB) >> 4 & 0x0F
a := uint32(colA) >> 4 & 0x0F
*buf = b<<12 | g<<8 | r<<4 | a
case PIXELFORMAT_ARGB1555:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
a := uint32(0)
if colA > 0 {
a = 1
}
*buf = a<<15 | r<<10 | g<<5 | b
case PIXELFORMAT_RGBA5551:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
a := uint32(0)
if colA > 0 {
a = 1
}
*buf = r<<11 | g<<6 | b<<1 | a
case PIXELFORMAT_ABGR1555:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
a := uint32(0)
if colA > 0 {
a = 1
}
*buf = a<<15 | b<<10 | g<<5 | r
case PIXELFORMAT_BGRA5551:
buf := (*uint32)(unsafe.Pointer(&pix[i]))
r := uint32(colR) >> 3 & 0xFF
g := uint32(colG) >> 3 & 0xFF
b := uint32(colB) >> 3 & 0xFF
a := uint32(0)
if colA > 0 {
a = 1
}
*buf = b<<11 | g<<6 | r<<1 | a
case PIXELFORMAT_RGBA8888:
pix[i+3] = colR
pix[i+2] = colG
pix[i+1] = colB
pix[i+0] = colA
case PIXELFORMAT_BGRA8888:
pix[i+3] = colB
pix[i+2] = colG
pix[i+1] = colR
pix[i+0] = colA
default:
panic("Unknown pixel format!")
}
}
// SoftStretchLinear performs bilinear scaling between two surfaces of the same format, 32BPP.
// (https://wiki.libsdl.org/SDL_SoftStretchLinear)
func (surface *Surface) SoftStretchLinear(srcRect *Rect, dst *Surface, dstRect *Rect) (err error) {
return errorFromInt(int(C.SDL_SoftStretchLinear(surface.cptr(), srcRect.cptr(), dst.cptr(), dstRect.cptr())))
}
// PremultiplyAlpha premultiplies the alpha on a block of pixels.
//
// This is safe to use with src == dst, but not for other overlapping areas.
//
// This function is currently only implemented for SDL_PIXELFORMAT_ARGB8888.
//
// (https://wiki.libsdl.org/SDL_PremultiplyAlpha)
func PremultiplyAlpha(width, height int, srcFormat uint32, src []byte, srcPitch int, dstFormat uint32, dst []byte, dstPitch int) (err error) {
_width := C.int(width)
_height := C.int(height)
_srcFormat := C.Uint32(srcFormat)
_src := unsafe.Pointer(&src[0])
_srcPitch := C.int(srcPitch)
_dstFormat := C.Uint32(dstFormat)
_dst := unsafe.Pointer(&dst[0])
_dstPitch := C.int(dstPitch)
err = errorFromInt(int(C.SDL_PremultiplyAlpha(_width, _height, _srcFormat, _src, _srcPitch, _dstFormat, _dst, _dstPitch)))
return
}