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