SDL  2.0
SDL_shape.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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_video.h"
25 #include "SDL_sysvideo.h"
26 #include "SDL_pixels.h"
27 #include "SDL_surface.h"
28 #include "SDL_shape.h"
29 #include "SDL_shape_internals.h"
30 
32 SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags)
33 {
35  result = SDL_CreateWindow(title,-1000,-1000,w,h,(flags | SDL_WINDOW_BORDERLESS) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE) /* & (~SDL_WINDOW_SHOWN) */);
36  if(result != NULL) {
37  if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) {
39  return NULL;
40  }
42  if(result->shaper != NULL) {
43  result->shaper->userx = x;
44  result->shaper->usery = y;
45  result->shaper->mode.mode = ShapeModeDefault;
46  result->shaper->mode.parameters.binarizationCutoff = 1;
47  result->shaper->hasshape = SDL_FALSE;
48  return result;
49  }
50  else {
52  return NULL;
53  }
54  }
55  else
56  return NULL;
57 }
58 
61 {
62  if(window == NULL)
63  return SDL_FALSE;
64  else
65  return (SDL_bool)(window->shaper != NULL);
66 }
67 
68 /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
69 void
71 {
72  int x = 0;
73  int y = 0;
74  Uint8 r = 0,g = 0,b = 0,alpha = 0;
75  Uint8* pixel = NULL;
76  Uint32 pixel_value = 0,mask_value = 0;
77  int bytes_per_scanline = (shape->w + (ppb - 1)) / ppb;
78  Uint8 *bitmap_scanline;
79  SDL_Color key;
80  if(SDL_MUSTLOCK(shape))
81  SDL_LockSurface(shape);
82  for(y = 0;y<shape->h;y++) {
83  bitmap_scanline = bitmap + y * bytes_per_scanline;
84  for(x=0;x<shape->w;x++) {
85  alpha = 0;
86  pixel_value = 0;
87  pixel = (Uint8 *)(shape->pixels) + (y*shape->pitch) + (x*shape->format->BytesPerPixel);
88  switch(shape->format->BytesPerPixel) {
89  case(1):
90  pixel_value = *pixel;
91  break;
92  case(2):
93  pixel_value = *(Uint16*)pixel;
94  break;
95  case(3):
96  pixel_value = *(Uint32*)pixel & (~shape->format->Amask);
97  break;
98  case(4):
99  pixel_value = *(Uint32*)pixel;
100  break;
101  }
102  SDL_GetRGBA(pixel_value,shape->format,&r,&g,&b,&alpha);
103  switch(mode.mode) {
104  case(ShapeModeDefault):
105  mask_value = (alpha >= 1 ? 1 : 0);
106  break;
108  mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
109  break;
111  mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
112  break;
113  case(ShapeModeColorKey):
114  key = mode.parameters.colorKey;
115  mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
116  break;
117  }
118  bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
119  }
120  }
121  if(SDL_MUSTLOCK(shape))
122  SDL_UnlockSurface(shape);
123 }
124 
125 static SDL_ShapeTree*
127  int x = 0,y = 0;
128  Uint8* pixel = NULL;
129  Uint32 pixel_value = 0;
130  Uint8 r = 0,g = 0,b = 0,a = 0;
131  SDL_bool pixel_opaque = SDL_FALSE;
132  int last_opaque = -1;
133  SDL_Color key;
135  SDL_Rect next = {0,0,0,0};
136 
137  for(y=dimensions.y;y<dimensions.y + dimensions.h;y++) {
138  for(x=dimensions.x;x<dimensions.x + dimensions.w;x++) {
139  pixel_value = 0;
140  pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel);
141  switch(mask->format->BytesPerPixel) {
142  case(1):
143  pixel_value = *pixel;
144  break;
145  case(2):
146  pixel_value = *(Uint16*)pixel;
147  break;
148  case(3):
149  pixel_value = *(Uint32*)pixel & (~mask->format->Amask);
150  break;
151  case(4):
152  pixel_value = *(Uint32*)pixel;
153  break;
154  }
155  SDL_GetRGBA(pixel_value,mask->format,&r,&g,&b,&a);
156  switch(mode.mode) {
157  case(ShapeModeDefault):
158  pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE);
159  break;
161  pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
162  break;
164  pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
165  break;
166  case(ShapeModeColorKey):
167  key = mode.parameters.colorKey;
168  pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
169  break;
170  }
171  if(last_opaque == -1)
172  last_opaque = pixel_opaque;
173  if(last_opaque != pixel_opaque) {
174  const int halfwidth = dimensions.w / 2;
175  const int halfheight = dimensions.h / 2;
176 
177  result->kind = QuadShape;
178 
179  next.x = dimensions.x;
180  next.y = dimensions.y;
181  next.w = halfwidth;
182  next.h = halfheight;
183  result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
184 
185  next.x = dimensions.x + halfwidth;
186  next.w = dimensions.w - halfwidth;
187  result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
188 
189  next.x = dimensions.x;
190  next.w = halfwidth;
191  next.y = dimensions.y + halfheight;
192  next.h = dimensions.h - halfheight;
193  result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
194 
195  next.x = dimensions.x + halfwidth;
196  next.w = dimensions.w - halfwidth;
197  result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
198 
199  return result;
200  }
201  }
202  }
203 
204 
205  /* If we never recursed, all the pixels in this quadrant have the same "value". */
206  result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape);
207  result->data.shape = dimensions;
208  return result;
209 }
210 
213 {
214  SDL_Rect dimensions;
216 
217  dimensions.x = 0;
218  dimensions.y = 0;
219  dimensions.w = shape->w;
220  dimensions.h = shape->h;
221 
222  if(SDL_MUSTLOCK(shape))
223  SDL_LockSurface(shape);
224  result = RecursivelyCalculateShapeTree(mode,shape,dimensions);
225  if(SDL_MUSTLOCK(shape))
226  SDL_UnlockSurface(shape);
227  return result;
228 }
229 
230 void
232 {
233  SDL_assert(tree != NULL);
234  if(tree->kind == QuadShape) {
235  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft,function,closure);
236  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright,function,closure);
237  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft,function,closure);
238  SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright,function,closure);
239  }
240  else
241  function(tree,closure);
242 }
243 
244 void
246 {
247  if((*shape_tree)->kind == QuadShape) {
248  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upleft);
249  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upright);
250  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downleft);
251  SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downright);
252  }
253  SDL_free(*shape_tree);
254  *shape_tree = NULL;
255 }
256 
257 int
259 {
260  int result;
262  /* The window given was not a shapeable window. */
264  if(shape == NULL)
265  /* Invalid shape argument. */
267 
268  if(shape_mode != NULL)
269  window->shaper->mode = *shape_mode;
270  result = SDL_GetVideoDevice()->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
271  window->shaper->hasshape = SDL_TRUE;
272  if(window->shaper->userx != 0 && window->shaper->usery != 0) {
273  SDL_SetWindowPosition(window,window->shaper->userx,window->shaper->usery);
274  window->shaper->userx = 0;
275  window->shaper->usery = 0;
276  }
277  return result;
278 }
279 
280 static SDL_bool
282 {
283  if (window == NULL || !SDL_IsShapedWindow(window))
284  return SDL_FALSE;
285  return window->shaper->hasshape;
286 }
287 
288 int
290 {
291  if(window != NULL && SDL_IsShapedWindow(window)) {
292  if(shape_mode == NULL) {
294  /* The window given has a shape. */
295  return 0;
296  else
297  /* The window given is shapeable but lacks a shape. */
298  return SDL_WINDOW_LACKS_SHAPE;
299  }
300  else {
301  *shape_mode = window->shaper->mode;
302  return 0;
303  }
304  }
305  else
306  /* The window given is not a valid shapeable window. */
308 }
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#define SDL_DestroyWindow
#define SDL_CreateWindow
#define SDL_SetWindowPosition
#define SDL_malloc
#define SDL_UnlockSurface
#define SDL_free
#define SDL_LockSurface
#define SDL_GetRGBA
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLboolean GLboolean GLboolean b
GLenum mode
GLuint64EXT * result
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
GLboolean GLboolean GLboolean GLboolean a
GLboolean GLboolean g
GLbitfield flags
GLfloat GLfloat GLfloat alpha
GLenum GLint GLuint mask
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
static SDL_bool SDL_WindowHasAShape(SDL_Window *window)
Definition: SDL_shape.c:281
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:32
int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode)
Get the shape parameters of a shaped window.
Definition: SDL_shape.c:289
void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure)
Definition: SDL_shape.c:231
void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
Definition: SDL_shape.c:70
void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree)
Definition: SDL_shape.c:245
static SDL_ShapeTree * RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions)
Definition: SDL_shape.c:126
SDL_ShapeTree * SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape)
Definition: SDL_shape.c:212
SDL_bool SDL_IsShapedWindow(const SDL_Window *window)
Return whether the given window is a shaped window.
Definition: SDL_shape.c:60
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:258
#define SDL_INVALID_SHAPE_ARGUMENT
Definition: SDL_shape.h:43
#define SDL_NONSHAPEABLE_WINDOW
Definition: SDL_shape.h:42
@ ShapeModeBinarizeAlpha
A binarized alpha cutoff with a given integer value.
Definition: SDL_shape.h:84
@ ShapeModeColorKey
A color key is applied.
Definition: SDL_shape.h:88
@ ShapeModeDefault
The default mode, a binarized alpha cutoff of 1.
Definition: SDL_shape.h:82
@ ShapeModeReverseBinarizeAlpha
A binarized alpha cutoff with a given integer value, but with the opposite comparison.
Definition: SDL_shape.h:86
#define SDL_WINDOW_LACKS_SHAPE
Definition: SDL_shape.h:44
@ QuadShape
@ TransparentShape
@ OpaqueShape
void(* SDL_TraversalFunction)(SDL_ShapeTree *, void *)
uint16_t Uint16
Definition: SDL_stdinc.h:197
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
uint32_t Uint32
Definition: SDL_stdinc.h:209
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:62
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:587
@ SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:104
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:99
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:103
#define NULL
Definition: begin_code.h:163
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
GLuint64 key
Definition: gl2ext.h:2192
Uint8 BytesPerPixel
Definition: SDL_pixels.h:329
struct SDL_ShapeTree * downright
struct SDL_ShapeTree * upleft
struct SDL_ShapeTree * downleft
struct SDL_ShapeTree * upright
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
int(* SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
Definition: SDL_sysvideo.h:62
SDL_WindowShaper *(* CreateShaper)(SDL_Window *window)
Definition: SDL_sysvideo.h:61
SDL_ShapeKind kind
SDL_ShapeUnion data
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
SDL_PixelFormat * format
Definition: SDL_surface.h:73
void * pixels
Definition: SDL_surface.h:76
SDL_ShapeDriver shape_driver
Definition: SDL_sysvideo.h:246
The type used to identify a window.
Definition: SDL_sysvideo.h:75
A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents.
Definition: SDL_shape.h:101
WindowShapeMode mode
The mode of these window-shape parameters.
Definition: SDL_shape.h:103
SDL_QuadTreeChildren children