/
surface.go
422 lines (376 loc) · 14.2 KB
/
surface.go
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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
package sdl
/*
#include "sdl_wrapper.h"
#if !(SDL_VERSION_ATLEAST(2,0,5))
#pragma message("SDL_CreateRGBSurfaceWithFormat is not supported before SDL 2.0.5")
static inline SDL_Surface* SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)
{
return NULL;
}
#pragma message("SDL_CreateRGBSurfaceWithFormatFrom is not supported before SDL 2.0.5")
static inline SDL_Surface* SDL_CreateRGBSurfaceWithFormatFrom(void* pixels, int width, int height, int depth, int pitch, Uint32 format)
{
return NULL;
}
#endif
*/
import "C"
import "unsafe"
import "reflect"
// 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
)
// 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
}
// 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
}
// GetColorKey retruns 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.W*surface.H) * int(surface.Format.BytesPerPixel)
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
}