Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
279 lines (263 loc) · 10.6 KB

SDL_shape.c

File metadata and controls

279 lines (263 loc) · 10.6 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
SDL - Simple DirectMedia Layer
Copyright (C) 2010 Eli Gottlieb
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Eli Gottlieb
eligottlieb@gmail.com
*/
May 27, 2010
May 27, 2010
22
#include "SDL_config.h"
Jun 5, 2010
Jun 5, 2010
23
May 27, 2010
May 27, 2010
24
#include "SDL.h"
Aug 10, 2010
Aug 10, 2010
25
#include "SDL_assert.h"
May 27, 2010
May 27, 2010
26
27
#include "SDL_video.h"
#include "SDL_sysvideo.h"
Jun 30, 2010
Jun 30, 2010
28
29
#include "SDL_pixels.h"
#include "SDL_surface.h"
30
#include "SDL_shape.h"
Aug 10, 2010
Aug 10, 2010
31
#include "SDL_shape_internals.h"
May 21, 2010
May 21, 2010
32
Aug 10, 2010
Aug 10, 2010
33
34
SDL_Window*
SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) {
Aug 16, 2010
Aug 16, 2010
35
SDL_Window *result = NULL;
Aug 17, 2010
Aug 17, 2010
36
result = SDL_CreateWindow(title,-1000,-1000,w,h,(flags | SDL_WINDOW_BORDERLESS) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE) /*& (~SDL_WINDOW_SHOWN)*/);
Aug 10, 2010
Aug 10, 2010
37
38
39
if(result != NULL) {
result->shaper = result->display->device->shape_driver.CreateShaper(result);
if(result->shaper != NULL) {
Aug 15, 2010
Aug 15, 2010
40
41
result->shaper->userx = x;
result->shaper->usery = y;
Aug 10, 2010
Aug 10, 2010
42
43
44
45
46
47
48
49
50
51
52
53
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;
May 21, 2010
May 21, 2010
54
55
}
Aug 10, 2010
Aug 10, 2010
56
57
58
59
60
61
SDL_bool
SDL_IsShapedWindow(const SDL_Window *window) {
if(window == NULL)
return SDL_FALSE;
else
return (SDL_bool)(window->shaper != NULL);
Jun 30, 2010
Jun 30, 2010
62
63
}
Jul 29, 2010
Jul 29, 2010
64
/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
Aug 10, 2010
Aug 10, 2010
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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 bitmap_pixel,pixel_value = 0,mask_value = 0;
SDL_Color key;
if(SDL_MUSTLOCK(shape))
SDL_LockSurface(shape);
pixel = (Uint8*)shape->pixels;
for(y = 0;y<shape->h;y++) {
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);
bitmap_pixel = y*shape->w + x;
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;
Aug 10, 2010
Aug 10, 2010
109
mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
Aug 10, 2010
Aug 10, 2010
110
111
112
113
114
115
116
break;
}
bitmap[bitmap_pixel / ppb] |= mask_value << (7 - ((ppb - 1) - (bitmap_pixel % ppb)));
}
}
if(SDL_MUSTLOCK(shape))
SDL_UnlockSurface(shape);
May 21, 2010
May 21, 2010
117
118
}
Aug 10, 2010
Aug 10, 2010
119
120
121
122
123
124
125
126
127
128
129
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};
Aug 16, 2010
Aug 16, 2010
130
for(y=dimensions.y;y<dimensions.y + dimensions.h;y++) {
Aug 10, 2010
Aug 10, 2010
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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;
Aug 15, 2010
Aug 15, 2010
161
pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
Aug 10, 2010
Aug 10, 2010
162
163
164
165
166
167
168
169
170
171
172
173
174
break;
}
if(last_opaque == -1)
last_opaque = pixel_opaque;
if(last_opaque != pixel_opaque) {
result->kind = QuadShape;
//These will stay the same.
next.w = dimensions.w / 2;
next.h = dimensions.h / 2;
//These will change from recursion to recursion.
next.x = dimensions.x;
next.y = dimensions.y;
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
Aug 15, 2010
Aug 15, 2010
175
next.x += next.w;
Aug 10, 2010
Aug 10, 2010
176
177
178
//Unneeded: next.y = dimensions.y;
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
next.x = dimensions.x;
Aug 15, 2010
Aug 15, 2010
179
next.y += next.h;
Aug 10, 2010
Aug 10, 2010
180
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
Aug 15, 2010
Aug 15, 2010
181
182
next.x += next.w;
//Unneeded: next.y = dimensions.y + dimensions.h /2;
Aug 10, 2010
Aug 10, 2010
183
184
185
186
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next);
return result;
}
}
Aug 16, 2010
Aug 16, 2010
187
}
Aug 10, 2010
Aug 10, 2010
188
189
190
191
//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;
Jul 29, 2010
Jul 29, 2010
192
193
}
Aug 10, 2010
Aug 10, 2010
194
195
196
197
198
199
200
201
202
203
SDL_ShapeTree*
SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape) {
SDL_Rect dimensions = {0,0,shape->w,shape->h};
SDL_ShapeTree* result = NULL;
if(SDL_MUSTLOCK(shape))
SDL_LockSurface(shape);
result = RecursivelyCalculateShapeTree(mode,shape,dimensions);
if(SDL_MUSTLOCK(shape))
SDL_UnlockSurface(shape);
return result;
Jul 29, 2010
Jul 29, 2010
204
205
}
Aug 10, 2010
Aug 10, 2010
206
207
208
209
210
211
212
213
214
215
216
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);
Jul 29, 2010
Jul 29, 2010
217
218
}
Aug 10, 2010
Aug 10, 2010
219
void
Aug 15, 2010
Aug 15, 2010
220
221
222
223
224
225
SDL_FreeShapeTree(SDL_ShapeTree** shape_tree) {
if((*shape_tree)->kind == QuadShape) {
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upleft);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.upright);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downleft);
SDL_FreeShapeTree((SDL_ShapeTree **)&(*shape_tree)->data.children.downright);
Aug 10, 2010
Aug 10, 2010
226
}
Aug 15, 2010
Aug 15, 2010
227
228
SDL_free(*shape_tree);
*shape_tree = NULL;
Jul 29, 2010
Jul 29, 2010
229
230
}
Aug 10, 2010
Aug 10, 2010
231
int
Aug 14, 2010
Aug 14, 2010
232
SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
Aug 10, 2010
Aug 10, 2010
233
234
235
236
237
238
239
240
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;
Aug 14, 2010
Aug 14, 2010
241
242
243
if(shape_mode != NULL)
window->shaper->mode = *shape_mode;
result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
Aug 10, 2010
Aug 10, 2010
244
window->shaper->hasshape = SDL_TRUE;
Aug 16, 2010
Aug 16, 2010
245
if(window->shaper->userx != 0 && window->shaper->usery != 0) {
Aug 15, 2010
Aug 15, 2010
246
247
248
SDL_SetWindowPosition(window,window->shaper->userx,window->shaper->usery);
window->shaper->userx = 0;
window->shaper->usery = 0;
Aug 10, 2010
Aug 10, 2010
249
250
}
return result;
Jun 30, 2010
Jun 30, 2010
251
252
}
Aug 10, 2010
Aug 10, 2010
253
254
255
256
257
SDL_bool
SDL_WindowHasAShape(SDL_Window *window) {
if (window == NULL || !SDL_IsShapedWindow(window))
return SDL_FALSE;
return window->shaper->hasshape;
Jun 10, 2010
Jun 10, 2010
258
259
}
Aug 10, 2010
Aug 10, 2010
260
int
Aug 14, 2010
Aug 14, 2010
261
SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode) {
Aug 10, 2010
Aug 10, 2010
262
if(window != NULL && SDL_IsShapedWindow(window)) {
Aug 14, 2010
Aug 14, 2010
263
if(shape_mode == NULL) {
Aug 10, 2010
Aug 10, 2010
264
265
266
267
268
269
270
271
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 {
Aug 14, 2010
Aug 14, 2010
272
*shape_mode = window->shaper->mode;
Aug 10, 2010
Aug 10, 2010
273
274
275
276
277
278
return 0;
}
}
else
//The window given is not a valid shapeable window.
return SDL_NONSHAPEABLE_WINDOW;
Jun 10, 2010
Jun 10, 2010
279
}