Atlas - SDL_shape.c
Home / ext / SDL2 / src / video Lines: 1 | Size: 11349 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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 32SDL_Window* 33SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) 34{ 35 SDL_Window *result = NULL; 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 } 42 result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result); 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 { 52 SDL_DestroyWindow(result); 53 return NULL; 54 } 55 } 56 else 57 return NULL; 58} 59 60SDL_bool 61SDL_IsShapedWindow(const SDL_Window *window) 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. */ 70void 71SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb) 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; 108 case(ShapeModeBinarizeAlpha): 109 mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0); 110 break; 111 case(ShapeModeReverseBinarizeAlpha): 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 126static SDL_ShapeTree* 127RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rect dimensions) { 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; 135 SDL_ShapeTree* result = (SDL_ShapeTree*)SDL_malloc(sizeof(SDL_ShapeTree)); 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; 161 case(ShapeModeBinarizeAlpha): 162 pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE); 163 break; 164 case(ShapeModeReverseBinarizeAlpha): 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 212SDL_ShapeTree* 213SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape) 214{ 215 SDL_Rect dimensions; 216 SDL_ShapeTree* result = NULL; 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 231void 232SDL_TraverseShapeTree(SDL_ShapeTree *tree,SDL_TraversalFunction function,void* closure) 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 245void 246SDL_FreeShapeTree(SDL_ShapeTree** shape_tree) 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 258int 259SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) 260{ 261 int result; 262 if(window == NULL || !SDL_IsShapedWindow(window)) 263 /* The window given was not a shapeable window. */ 264 return SDL_NONSHAPEABLE_WINDOW; 265 if(shape == NULL) 266 /* Invalid shape argument. */ 267 return SDL_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 281static SDL_bool 282SDL_WindowHasAShape(SDL_Window *window) 283{ 284 if (window == NULL || !SDL_IsShapedWindow(window)) 285 return SDL_FALSE; 286 return window->shaper->hasshape; 287} 288 289int 290SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode) 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. */ 308 return SDL_NONSHAPEABLE_WINDOW; 309} 310[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.