SDL_shape.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
#include "SDL.h"
#include "SDL_assert.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels.h"
#include "SDL_surface.h"
#include "SDL_shape.h"
#include "SDL_shape_internals.h"
SDL_Window*
SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags)
{
SDL_Window *result = NULL;
result = SDL_CreateWindow(title,-1000,-1000,w,h,(flags | SDL_WINDOW_BORDERLESS) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE) /* & (~SDL_WINDOW_SHOWN) */);
if(result != NULL) {
if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) {
SDL_DestroyWindow(result);
return NULL;
}
result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result);
if(result->shaper != NULL) {
result->shaper->userx = x;
result->shaper->usery = y;
result->shaper->mode.mode = ShapeModeDefault;
result->shaper->mode.parameters.binarizationCutoff = 1;
result->shaper->hasshape = SDL_FALSE;
return result;
}
else {
SDL_DestroyWindow(result);
return NULL;
}
}
else
return NULL;
}
SDL_bool
SDL_IsShapedWindow(const SDL_Window *window)
{
if(window == NULL)
return SDL_FALSE;
else
return (SDL_bool)(window->shaper != NULL);
}
/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
void
SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb)
{
int x = 0;
int y = 0;
Uint8 r = 0,g = 0,b = 0,alpha = 0;
Uint8* pixel = NULL;
Uint32 pixel_value = 0,mask_value = 0;
int bytes_per_scanline = (shape->w + (ppb - 1)) / ppb;
Uint8 *bitmap_scanline;
SDL_Color key;
if(SDL_MUSTLOCK(shape))
SDL_LockSurface(shape);
for(y = 0;y<shape->h;y++) {
bitmap_scanline = bitmap + y * bytes_per_scanline;
for(x=0;x<shape->w;x++) {
alpha = 0;
pixel_value = 0;
pixel = (Uint8 *)(shape->pixels) + (y*shape->pitch) + (x*shape->format->BytesPerPixel);
switch(shape->format->BytesPerPixel) {
case(1):
pixel_value = *(Uint8*)pixel;
break;
case(2):
pixel_value = *(Uint16*)pixel;
break;
case(3):
pixel_value = *(Uint32*)pixel & (~shape->format->Amask);
break;
case(4):
pixel_value = *(Uint32*)pixel;
break;
}
SDL_GetRGBA(pixel_value,shape->format,&r,&g,&b,&alpha);
switch(mode.mode) {
case(ShapeModeDefault):
mask_value = (alpha >= 1 ? 1 : 0);
break;
case(ShapeModeBinarizeAlpha):
mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
break;
case(ShapeModeReverseBinarizeAlpha):
mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
break;
case(ShapeModeColorKey):
key = mode.parameters.colorKey;
mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
break;
}
bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
}
}
if(SDL_MUSTLOCK(shape))
SDL_UnlockSurface(shape);
}
static SDL_ShapeTree*
RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rect dimensions) {
int x = 0,y = 0;
Uint8* pixel = NULL;
Uint32 pixel_value = 0;
Uint8 r = 0,g = 0,b = 0,a = 0;
SDL_bool pixel_opaque = SDL_FALSE;
int last_opaque = -1;
SDL_Color key;
SDL_ShapeTree* result = (SDL_ShapeTree*)SDL_malloc(sizeof(SDL_ShapeTree));
SDL_Rect next = {0,0,0,0};
for(y=dimensions.y;y<dimensions.y + dimensions.h;y++) {
for(x=dimensions.x;x<dimensions.x + dimensions.w;x++) {
pixel_value = 0;
pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel);
switch(mask->format->BytesPerPixel) {
case(1):
pixel_value = *(Uint8*)pixel;
break;
case(2):
pixel_value = *(Uint16*)pixel;
break;
case(3):
pixel_value = *(Uint32*)pixel & (~mask->format->Amask);
break;
case(4):
pixel_value = *(Uint32*)pixel;
break;
}
SDL_GetRGBA(pixel_value,mask->format,&r,&g,&b,&a);
switch(mode.mode) {
case(ShapeModeDefault):
pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE);
break;
case(ShapeModeBinarizeAlpha):
pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
break;
case(ShapeModeReverseBinarizeAlpha):
pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
break;
case(ShapeModeColorKey):
key = mode.parameters.colorKey;
pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
break;
}
if(last_opaque == -1)
last_opaque = pixel_opaque;
if(last_opaque != pixel_opaque) {
const int halfwidth = dimensions.w / 2;
const int halfheight = dimensions.h / 2;
result->kind = QuadShape;
next.x = dimensions.x;
next.y = dimensions.y;
next.w = halfwidth;
next.h = halfheight;
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x + halfwidth;
next.w = dimensions.w - halfwidth;
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x;
next.w = halfwidth;
next.y = dimensions.y + halfheight;
next.h = dimensions.h - halfheight;
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x + halfwidth;
next.w = dimensions.w - halfwidth;
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
return result;
}
}
}
/* If we never recursed, all the pixels in this quadrant have the same "value". */
result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape);
result->data.shape = dimensions;
return result;
}
SDL_ShapeTree*
SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape)
{
SDL_Rect dimensions;
SDL_ShapeTree* result = NULL;
dimensions.x = 0;
dimensions.y = 0;
dimensions.w = shape->w;
dimensions.h = shape->h;
if(SDL_MUSTLOCK(shape))
SDL_LockSurface(shape);
result = RecursivelyCalculateShapeTree(mode,shape,dimensions);
if(SDL_MUSTLOCK(shape))
SDL_UnlockSurface(shape);
return result;
}
void
SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* closure)
{
SDL_assert(tree != NULL);
if(tree->kind == QuadShape) {
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft,function,closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright,function,closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft,function,closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright,function,closure);
}
else
function(tree,closure);
}
void
SDL_FreeShapeTree(SDL_ShapeTree** shape_tree)
{
if((*shape_tree)->kind == QuadShape) {
SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upleft);
SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.upright);
SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downleft);
SDL_FreeShapeTree((SDL_ShapeTree **)(char*)&(*shape_tree)->data.children.downright);
}
SDL_free(*shape_tree);
*shape_tree = NULL;
}
int
SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode)
{
int result;
if(window == NULL || !SDL_IsShapedWindow(window))
/* The window given was not a shapeable window. */
return SDL_NONSHAPEABLE_WINDOW;
if(shape == NULL)
/* Invalid shape argument. */
return SDL_INVALID_SHAPE_ARGUMENT;
if(shape_mode != NULL)
window->shaper->mode = *shape_mode;
result = SDL_GetVideoDevice()->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
window->shaper->hasshape = SDL_TRUE;
if(window->shaper->userx != 0 && window->shaper->usery != 0) {
SDL_SetWindowPosition(window,window->shaper->userx,window->shaper->usery);
window->shaper->userx = 0;
window->shaper->usery = 0;
}
return result;
}
static SDL_bool
SDL_WindowHasAShape(SDL_Window *window)
{
if (window == NULL || !SDL_IsShapedWindow(window))
return SDL_FALSE;
return window->shaper->hasshape;
}
int
SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode)
{
if(window != NULL && SDL_IsShapedWindow(window)) {
if(shape_mode == NULL) {
if(SDL_WindowHasAShape(window))
/* The window given has a shape. */
return 0;
else
/* The window given is shapeable but lacks a shape. */
return SDL_WINDOW_LACKS_SHAPE;
}
else {
*shape_mode = window->shaper->mode;
return 0;
}
}
else
/* The window given is not a valid shapeable window. */
return SDL_NONSHAPEABLE_WINDOW;
}
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
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
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
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
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
@ 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
@ 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
@ 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
@ ShapeModeReverseBinarizeAlpha
A binarized alpha cutoff with a given integer value, but with the opposite comparison.
Definition: SDL_shape.h:86
OpaqueShape
@ 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
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
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_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
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
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
@ 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:1574
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_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
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_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
QuadShape
@ 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
@ 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
SDL_ShapeDriver::CreateShaper
SDL_WindowShaper *(* CreateShaper)(SDL_Window *window)
Definition: SDL_sysvideo.h:60
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_WINDOW_BORDERLESS
@ 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
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179