SDL  2.0
SDL_shape.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 #include "SDL.h"
24 #include "SDL_assert.h"
25 #include "SDL_video.h"
26 #include "SDL_sysvideo.h"
27 #include "SDL_pixels.h"
28 #include "SDL_surface.h"
29 #include "SDL_shape.h"
30 #include "SDL_shape_internals.h"
31 
33 SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags)
34 {
36  result = SDL_CreateWindow(title,-1000,-1000,w,h,(flags | SDL_WINDOW_BORDERLESS) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE) /* & (~SDL_WINDOW_SHOWN) */);
37  if(result != NULL) {
38  if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) {
40  return NULL;
41  }
43  if(result->shaper != NULL) {
44  result->shaper->userx = x;
45  result->shaper->usery = y;
46  result->shaper->mode.mode = ShapeModeDefault;
47  result->shaper->mode.parameters.binarizationCutoff = 1;
48  result->shaper->hasshape = SDL_FALSE;
49  return result;
50  }
51  else {
53  return NULL;
54  }
55  }
56  else
57  return NULL;
58 }
59 
62 {
63  if(window == NULL)
64  return SDL_FALSE;
65  else
66  return (SDL_bool)(window->shaper != NULL);
67 }
68 
69 /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
70 void
72 {
73  int x = 0;
74  int y = 0;
75  Uint8 r = 0,g = 0,b = 0,alpha = 0;
76  Uint8* pixel = NULL;
77  Uint32 pixel_value = 0,mask_value = 0;
78  int bytes_per_scanline = (shape->w + (ppb - 1)) / ppb;
79  Uint8 *bitmap_scanline;
80  SDL_Color key;
81  if(SDL_MUSTLOCK(shape))
82  SDL_LockSurface(shape);
83  for(y = 0;y<shape->h;y++) {
84  bitmap_scanline = bitmap + y * bytes_per_scanline;
85  for(x=0;x<shape->w;x++) {
86  alpha = 0;
87  pixel_value = 0;
88  pixel = (Uint8 *)(shape->pixels) + (y*shape->pitch) + (x*shape->format->BytesPerPixel);
89  switch(shape->format->BytesPerPixel) {
90  case(1):
91  pixel_value = *(Uint8*)pixel;
92  break;
93  case(2):
94  pixel_value = *(Uint16*)pixel;
95  break;
96  case(3):
97  pixel_value = *(Uint32*)pixel & (~shape->format->Amask);
98  break;
99  case(4):
100  pixel_value = *(Uint32*)pixel;
101  break;
102  }
103  SDL_GetRGBA(pixel_value,shape->format,&r,&g,&b,&alpha);
104  switch(mode.mode) {
105  case(ShapeModeDefault):
106  mask_value = (alpha >= 1 ? 1 : 0);
107  break;
109  mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
110  break;
112  mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
113  break;
114  case(ShapeModeColorKey):
115  key = mode.parameters.colorKey;
116  mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
117  break;
118  }
119  bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
120  }
121  }
122  if(SDL_MUSTLOCK(shape))
123  SDL_UnlockSurface(shape);
124 }
125 
126 static SDL_ShapeTree*
128  int x = 0,y = 0;
129  Uint8* pixel = NULL;
130  Uint32 pixel_value = 0;
131  Uint8 r = 0,g = 0,b = 0,a = 0;
132  SDL_bool pixel_opaque = SDL_FALSE;
133  int last_opaque = -1;
134  SDL_Color key;
136  SDL_Rect next = {0,0,0,0};
137 
138  for(y=dimensions.y;y<dimensions.y + dimensions.h;y++) {
139  for(x=dimensions.x;x<dimensions.x + dimensions.w;x++) {
140  pixel_value = 0;
141  pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel);
142  switch(mask->format->BytesPerPixel) {
143  case(1):
144  pixel_value = *(Uint8*)pixel;
145  break;
146  case(2):
147  pixel_value = *(Uint16*)pixel;
148  break;
149  case(3):
150  pixel_value = *(Uint32*)pixel & (~mask->format->Amask);
151  break;
152  case(4):
153  pixel_value = *(Uint32*)pixel;
154  break;
155  }
156  SDL_GetRGBA(pixel_value,mask->format,&r,&g,&b,&a);
157  switch(mode.mode) {
158  case(ShapeModeDefault):
159  pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE);
160  break;
162  pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
163  break;
165  pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
166  break;
167  case(ShapeModeColorKey):
168  key = mode.parameters.colorKey;
169  pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
170  break;
171  }
172  if(last_opaque == -1)
173  last_opaque = pixel_opaque;
174  if(last_opaque != pixel_opaque) {
175  const int halfwidth = dimensions.w / 2;
176  const int halfheight = dimensions.h / 2;
177 
178  result->kind = QuadShape;
179 
180  next.x = dimensions.x;
181  next.y = dimensions.y;
182  next.w = halfwidth;
183  next.h = halfheight;
184  result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
185 
186  next.x = dimensions.x + halfwidth;
187  next.w = dimensions.w - halfwidth;
188  result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
189 
190  next.x = dimensions.x;
191  next.w = halfwidth;
192  next.y = dimensions.y + halfheight;
193  next.h = dimensions.h - halfheight;
194  result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
195 
196  next.x = dimensions.x + halfwidth;
197  next.w = dimensions.w - halfwidth;
198  result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
199 
200  return result;
201  }
202  }
203  }
204 
205 
206  /* If we never recursed, all the pixels in this quadrant have the same "value". */
207  result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape);
208  result->data.shape = dimensions;
209  return result;
210 }
211 
214 {
215  SDL_Rect dimensions;
217 
218  dimensions.x = 0;
219  dimensions.y = 0;
220  dimensions.w = shape->w;
221  dimensions.h = shape->h;
222 
223  if(SDL_MUSTLOCK(shape))
224  SDL_LockSurface(shape);
225  result = RecursivelyCalculateShapeTree(mode,shape,dimensions);
226  if(SDL_MUSTLOCK(shape))
227  SDL_UnlockSurface(shape);
228  return result;
229 }
230 
231 void
233 {
234  SDL_assert(tree != NULL);
235  if(tree->kind == QuadShape) {
236  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft,function,closure);
237  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright,function,closure);
238  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft,function,closure);
239  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright,function,closure);
240  }
241  else
242  function(tree,closure);
243 }
244 
245 void
247 {
248  if((*shape_tree)->kind == QuadShape) {
249  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upleft);
250  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upright);
251  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downleft);
252  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downright);
253  }
254  SDL_free(*shape_tree);
255  *shape_tree = NULL;
256 }
257 
258 int
260 {
261  int result;
263  /* The window given was not a shapeable window. */
265  if(shape == NULL)
266  /* Invalid shape argument. */
268 
269  if(shape_mode != NULL)
270  window->shaper->mode = *shape_mode;
271  result = SDL_GetVideoDevice()->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
272  window->shaper->hasshape = SDL_TRUE;
273  if(window->shaper->userx != 0 && window->shaper->usery != 0) {
274  SDL_SetWindowPosition(window,window->shaper->userx,window->shaper->usery);
275  window->shaper->userx = 0;
276  window->shaper->usery = 0;
277  }
278  return result;
279 }
280 
281 static SDL_bool
283 {
284  if (window == NULL || !SDL_IsShapedWindow(window))
285  return SDL_FALSE;
286  return window->shaper->hasshape;
287 }
288 
289 int
291 {
292  if(window != NULL && SDL_IsShapedWindow(window)) {
293  if(shape_mode == NULL) {
295  /* The window given has a shape. */
296  return 0;
297  else
298  /* The window given is shapeable but lacks a shape. */
299  return SDL_WINDOW_LACKS_SHAPE;
300  }
301  else {
302  *shape_mode = window->shaper->mode;
303  return 0;
304  }
305  }
306  else
307  /* The window given is not a valid shapeable window. */
309 }
SDL.h
SDL_SetWindowShape
int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
Set the shape and parameters of a shaped window.
Definition: SDL_shape.c:259
SDL_UnlockSurface
#define SDL_UnlockSurface
Definition: SDL_dynapi_overrides.h:449
SDL_ShapeTree
Definition: SDL_shape_internals.h:49
SDL_CalculateShapeTree
SDL_ShapeTree * SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape)
Definition: SDL_shape.c:213
SDL_PixelFormat::BytesPerPixel
Uint8 BytesPerPixel
Definition: SDL_pixels.h:320
mask
GLenum GLint GLuint mask
Definition: SDL_opengl_glext.h:657
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:70
SDL_pixels.h
SDL_FreeShapeTree
void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree)
Definition: SDL_shape.c:246
SDL_QuadTreeChildren::upright
struct SDL_ShapeTree * upright
Definition: SDL_shape_internals.h:39
SDL_WindowShaper::userx
Uint32 userx
Definition: SDL_sysvideo.h:46
SDL_TraversalFunction
void(* SDL_TraversalFunction)(SDL_ShapeTree *, void *)
Definition: SDL_shape_internals.h:54
NULL
#define NULL
Definition: begin_code.h:167
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:76
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
SDL_IsShapedWindow
SDL_bool SDL_IsShapedWindow(const SDL_Window *window)
Return whether the given window is a shaped window.
Definition: SDL_shape.c:61
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
SDL_ShapeTree::kind
SDL_ShapeKind kind
Definition: SDL_shape_internals.h:50
SDL_GetShapedWindowMode
int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode)
Get the shape parameters of a shaped window.
Definition: SDL_shape.c:290
SDL_Surface::w
int w
Definition: SDL_surface.h:74
SDL_surface.h
SDL_shape_internals.h
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2078
SDL_WindowHasAShape
static SDL_bool SDL_WindowHasAShape(SDL_Window *window)
Definition: SDL_shape.c:282
SDL_MUSTLOCK
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
TransparentShape
Definition: SDL_shape_internals.h:47
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
SDL_CreateWindow
#define SDL_CreateWindow
Definition: SDL_dynapi_overrides.h:514
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_Rect::x
int x
Definition: SDL_rect.h:79
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:105
SDL_Rect::w
int w
Definition: SDL_rect.h:80
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_INVALID_SHAPE_ARGUMENT
#define SDL_INVALID_SHAPE_ARGUMENT
Definition: SDL_shape.h:43
ShapeModeBinarizeAlpha
A binarized alpha cutoff with a given integer value.
Definition: SDL_shape.h:84
alpha
GLfloat GLfloat GLfloat alpha
Definition: SDL_opengl_glext.h:412
SDL_WindowShapeMode
A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents.
Definition: SDL_shape.h:101
ShapeModeReverseBinarizeAlpha
A binarized alpha cutoff with a given integer value, but with the opposite comparison.
Definition: SDL_shape.h:86
OpaqueShape
Definition: SDL_shape_internals.h:47
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:75
SDL_WindowShapeMode::mode
WindowShapeMode mode
The mode of these window-shape parameters.
Definition: SDL_shape.h:103
SDL_ShapeDriver::SetWindowShape
int(* SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
Definition: SDL_sysvideo.h:61
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1573
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_Rect::y
int y
Definition: SDL_rect.h:79
SDL_Rect::h
int h
Definition: SDL_rect.h:80
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_WINDOW_LACKS_SHAPE
#define SDL_WINDOW_LACKS_SHAPE
Definition: SDL_shape.h:44
SDL_NONSHAPEABLE_WINDOW
#define SDL_NONSHAPEABLE_WINDOW
Definition: SDL_shape.h:42
SDL_CreateShapedWindow
SDL_Window * SDL_CreateShapedWindow(const char *title, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Uint32 flags)
Create a window that can be shaped with the specified position, dimensions, and flags.
Definition: SDL_shape.c:33
SDL_assert.h
key
GLuint64 key
Definition: gl2ext.h:2192
SDL_PixelFormat::Amask
Uint32 Amask
Definition: SDL_pixels.h:325
SDL_GetRGBA
#define SDL_GetRGBA
Definition: SDL_dynapi_overrides.h:289
ShapeModeColorKey
A color key is applied.
Definition: SDL_shape.h:88
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_VideoDevice::shape_driver
SDL_ShapeDriver shape_driver
Definition: SDL_sysvideo.h:245
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1573
SDL_shape.h
SDL_LockSurface
#define SDL_LockSurface
Definition: SDL_dynapi_overrides.h:448
SDL_Surface::h
int h
Definition: SDL_surface.h:74
bitmap
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
Definition: SDL_opengl_glext.h:4534
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_ShapeTree::data
SDL_ShapeUnion data
Definition: SDL_shape_internals.h:51
SDL_Rect
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:77
SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_Color
Definition: SDL_pixels.h:295
SDL_TraverseShapeTree
void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure)
Definition: SDL_shape.c:232
SDL_QuadTreeChildren::downright
struct SDL_ShapeTree * downright
Definition: SDL_shape_internals.h:39
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
QuadShape
Definition: SDL_shape_internals.h:47
SDL_ShapeUnion::children
SDL_QuadTreeChildren children
Definition: SDL_shape_internals.h:43
SDL_video.h
SDL_GetVideoDevice
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
SDL_sysvideo.h
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
RecursivelyCalculateShapeTree
static SDL_ShapeTree * RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions)
Definition: SDL_shape.c:127
ShapeModeDefault
The default mode, a binarized alpha cutoff of 1.
Definition: SDL_shape.h:82
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_CalculateShapeBitmap
void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
Definition: SDL_shape.c:71
SDL_SetWindowPosition
#define SDL_SetWindowPosition
Definition: SDL_dynapi_overrides.h:524
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:73
SDL_QuadTreeChildren::upleft
struct SDL_ShapeTree * upleft
Definition: SDL_shape_internals.h:39
SDL_DestroyWindow
#define SDL_DestroyWindow
Definition: SDL_dynapi_overrides.h:549
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_ShapeDriver::CreateShaper
SDL_WindowShaper *(* CreateShaper)(SDL_Window *window)
Definition: SDL_sysvideo.h:60
SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:104
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
SDL_QuadTreeChildren::downleft
struct SDL_ShapeTree * downleft
Definition: SDL_shape_internals.h:39