SDL  2.0
SDL_shape.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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) {
39  SDL_DestroyWindow(result);
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;
48  result->shaper->hasshape = SDL_FALSE;
49  return result;
50  }
51  else {
52  SDL_DestroyWindow(result);
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;
262  if(window == NULL || !SDL_IsShapedWindow(window))
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) {
294  if(SDL_WindowHasAShape(window))
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 }
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree)
Definition: SDL_shape.c:246
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
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
#define SDL_UnlockSurface
SDL_ShapeTree * SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape)
Definition: SDL_shape.c:213
GLuint64EXT * result
Uint8 g
Definition: SDL_pixels.h:298
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
Uint8 BytesPerPixel
Definition: SDL_pixels.h:320
struct SDL_ShapeTree * upright
SDL_bool hasshape
Definition: SDL_sysvideo.h:52
GLfloat GLfloat GLfloat GLfloat h
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
A color key is applied.
Definition: SDL_shape.h:88
SDL_bool SDL_IsShapedWindow(const SDL_Window *window)
Return whether the given window is a shaped window.
Definition: SDL_shape.c:61
int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode)
Get the shape parameters of a shaped window.
Definition: SDL_shape.c:290
Uint8 b
Definition: SDL_pixels.h:299
#define SDL_CreateWindow
SDL_ShapeUnion data
uint32_t Uint32
Definition: SDL_stdinc.h:181
static SDL_bool SDL_WindowHasAShape(SDL_Window *window)
Definition: SDL_shape.c:282
GLfloat GLfloat GLfloat alpha
#define SDL_INVALID_SHAPE_ARGUMENT
Definition: SDL_shape.h:43
int(* SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
Definition: SDL_sysvideo.h:61
SDL_WindowShapeMode mode
Definition: SDL_sysvideo.h:49
GLuint64 key
Definition: gl2ext.h:2192
Uint8 r
Definition: SDL_pixels.h:297
void(* SDL_TraversalFunction)(SDL_ShapeTree *, void *)
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
void * pixels
Definition: SDL_surface.h:75
SDL_WindowShaper * shaper
Definition: SDL_sysvideo.h:104
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_NONSHAPEABLE_WINDOW
Definition: SDL_shape.h:42
GLenum GLint GLuint mask
GLenum mode
GLubyte GLubyte GLubyte GLubyte w
#define SDL_WINDOW_LACKS_SHAPE
Definition: SDL_shape.h:44
The default mode, a binarized alpha cutoff of 1.
Definition: SDL_shape.h:82
SDL_WindowShapeParams parameters
Window-shape parameters.
Definition: SDL_shape.h:105
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
int w
Definition: SDL_rect.h:67
#define SDL_GetRGBA
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
A binarized alpha cutoff with a given integer value.
Definition: SDL_shape.h:84
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_LockSurface
GLbitfield flags
SDL_WindowShaper *(* CreateShaper)(SDL_Window *window)
Definition: SDL_sysvideo.h:60
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:61
int h
Definition: SDL_rect.h:67
SDL_Color colorKey
Definition: SDL_shape.h:97
A binarized alpha cutoff with a given integer value, but with the opposite comparison.
Definition: SDL_shape.h:86
The type used to identify a window.
Definition: SDL_sysvideo.h:73
void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure)
Definition: SDL_shape.c:232
struct SDL_ShapeTree * upleft
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:586
SDL_ShapeDriver shape_driver
Definition: SDL_sysvideo.h:244
Uint8 binarizationCutoff
A cutoff alpha value for binarization of the window shape&#39;s alpha channel.
Definition: SDL_shape.h:96
#define SDL_malloc
A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents...
Definition: SDL_shape.h:101
static SDL_ShapeTree * RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions)
Definition: SDL_shape.c:127
SDL_ShapeKind kind
WindowShapeMode mode
The mode of these window-shape parameters.
Definition: SDL_shape.h:103
GLboolean GLboolean GLboolean GLboolean a
#define SDL_DestroyWindow
GLboolean GLboolean g
GLboolean GLboolean GLboolean b
struct SDL_ShapeTree * downright
int y
Definition: SDL_rect.h:66
#define SDL_SetWindowPosition
SDL_QuadTreeChildren children
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
struct SDL_ShapeTree * downleft
void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
Definition: SDL_shape.c:71