Mercurial > sdl-ios-xcode
comparison src/video/SDL_shape.c @ 4813:5b4c7d7d8953
Wrote out the system for breaking shape-masks into quad-trees of rectangles, and added code to conglomerate those quad-trees of rectangles into regions for setting shapes under Win32.
author | Eli Gottlieb <eligottlieb@gmail.com> |
---|---|
date | Wed, 28 Jul 2010 23:35:24 -0400 |
parents | 7a602fd2121f |
children | 93402b9dd20c |
comparison
equal
deleted
inserted
replaced
4812:06a03d08cefb | 4813:5b4c7d7d8953 |
---|---|
25 #include "SDL_video.h" | 25 #include "SDL_video.h" |
26 #include "SDL_sysvideo.h" | 26 #include "SDL_sysvideo.h" |
27 #include "SDL_pixels.h" | 27 #include "SDL_pixels.h" |
28 #include "SDL_surface.h" | 28 #include "SDL_surface.h" |
29 #include "SDL_shape.h" | 29 #include "SDL_shape.h" |
30 #include "SDL_shape_internals.h" | |
30 | 31 |
31 SDL_Window* SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) { | 32 SDL_Window* SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) { |
32 SDL_Window *result = SDL_CreateWindow(title,x,y,w,h,SDL_WINDOW_BORDERLESS | flags & !SDL_WINDOW_FULLSCREEN & !SDL_WINDOW_SHOWN); | 33 SDL_Window *result = SDL_CreateWindow(title,x,y,w,h,SDL_WINDOW_BORDERLESS | flags & !SDL_WINDOW_FULLSCREEN & !SDL_WINDOW_SHOWN); |
33 if(result != NULL) { | 34 if(result != NULL) { |
34 result->shaper = result->display->device->shape_driver.CreateShaper(result); | 35 result->shaper = result->display->device->shape_driver.CreateShaper(result); |
53 return SDL_FALSE; | 54 return SDL_FALSE; |
54 else | 55 else |
55 return (SDL_bool)(window->shaper != NULL); | 56 return (SDL_bool)(window->shaper != NULL); |
56 } | 57 } |
57 | 58 |
58 /* REQUIRES that bitmap point to a w-by-h bitmap with 1bpp. */ | 59 /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */ |
59 void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb,Uint8 value) { | 60 void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitmap,Uint8 ppb,Uint8 value) { |
60 int x = 0; | 61 int x = 0; |
61 int y = 0; | 62 int y = 0; |
62 Uint8 r = 0,g = 0,b = 0,alpha = 0; | 63 Uint8 r = 0,g = 0,b = 0,alpha = 0; |
63 Uint8* pixel = NULL; | 64 Uint8* pixel = NULL; |
101 } | 102 } |
102 } | 103 } |
103 } | 104 } |
104 if(SDL_MUSTLOCK(shape)) | 105 if(SDL_MUSTLOCK(shape)) |
105 SDL_UnlockSurface(shape); | 106 SDL_UnlockSurface(shape); |
107 } | |
108 | |
109 SDL_ShapeTree* RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_bool invert,SDL_Rect dimensions) { | |
110 int x = 0,y = 0; | |
111 Uint8* pixel = NULL; | |
112 Uint32 pixel_value = 0; | |
113 Uint8 r = 0,g = 0,b = 0,a = 0; | |
114 SDL_bool pixel_transparent = SDL_FALSE; | |
115 int last_transparent = -1; | |
116 SDL_Color key; | |
117 SDL_ShapeTree* result = malloc(sizeof(SDL_ShapeTree)); | |
118 SDL_Rect next = {0,0,0,0}; | |
119 for(y=dimensions.y;y<dimensions.h;y++) | |
120 for(x=dimensions.x;x<dimensions.w;x++) { | |
121 pixel_value = 0; | |
122 pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel); | |
123 switch(mask->format->BytesPerPixel) { | |
124 case(1): | |
125 pixel_value = *(Uint8*)pixel; | |
126 break; | |
127 case(2): | |
128 pixel_value = *(Uint16*)pixel; | |
129 break; | |
130 case(4): | |
131 pixel_value = *(Uint32*)pixel; | |
132 break; | |
133 } | |
134 SDL_GetRGBA(pixel_value,mask->format,&r,&g,&b,&a); | |
135 switch(mode.mode) { | |
136 case(ShapeModeDefault): | |
137 pixel_transparent = (a >= 1 ? !invert : invert); | |
138 break; | |
139 case(ShapeModeBinarizeAlpha): | |
140 pixel_transparent = (a >= mode.parameters.binarizationCutoff ? !invert : invert); | |
141 break; | |
142 case(ShapeModeReverseBinarizeAlpha): | |
143 pixel_transparent = (a <= mode.parameters.binarizationCutoff ? !invert : invert); | |
144 break; | |
145 case(ShapeModeColorKey): | |
146 key = mode.parameters.colorKey; | |
147 pixel_transparent = ((key.r == r && key.g == g && key.b == b) ? !invert : invert); | |
148 break; | |
149 } | |
150 if(last_transparent == -1) { | |
151 last_transparent = pixel_transparent; | |
152 break; | |
153 } | |
154 if(last_transparent != pixel_transparent) { | |
155 result->kind = QuadShape; | |
156 //These will stay the same. | |
157 next.w = dimensions.w / 2; | |
158 next.h = dimensions.h / 2; | |
159 //These will change from recursion to recursion. | |
160 next.x = dimensions.x; | |
161 next.y = dimensions.y; | |
162 result->data.children.upleft = RecursivelyCalculateShapeTree(mode,mask,invert,next); | |
163 next.x = dimensions.w / 2 + 1; | |
164 //Unneeded: next.y = dimensions.y; | |
165 result->data.children.upright = RecursivelyCalculateShapeTree(mode,mask,invert,next); | |
166 next.x = dimensions.x; | |
167 next.y = dimensions.h / 2 + 1; | |
168 result->data.children.downleft = RecursivelyCalculateShapeTree(mode,mask,invert,next); | |
169 next.x = dimensions.w / 2 + 1; | |
170 //Unneeded: next.y = dimensions.h / 2 + 1; | |
171 result->data.children.downright = RecursivelyCalculateShapeTree(mode,mask,invert,next); | |
172 return result; | |
173 } | |
174 } | |
175 //If we never recursed, all the pixels in this quadrant have the same "value". | |
176 result->kind = (last_transparent == SDL_FALSE ? OpaqueShape : TransparentShape); | |
177 result->data.shape = dimensions; | |
178 return result; | |
179 } | |
180 | |
181 SDL_ShapeTree* SDL_CalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* shape,SDL_bool invert) { | |
182 SDL_Rect dimensions = {0,0,shape->w,shape->h}; | |
183 SDL_ShapeTree* result = NULL; | |
184 if(SDL_MUSTLOCK(shape)) | |
185 SDL_LockSurface(shape); | |
186 result = RecursivelyCalculateShapeTree(mode,shape,invert,dimensions); | |
187 if(SDL_MUSTLOCK(shape)) | |
188 SDL_UnlockSurface(shape); | |
189 return result; | |
190 } | |
191 | |
192 void SDL_TraverseShapeTree(SDL_ShapeTree *tree,void(*function)(SDL_ShapeTree*,void*),void* closure) { | |
193 if(tree->kind == QuadShape) { | |
194 SDL_TraverseShapeTree(tree->data.children.upleft,function,closure); | |
195 SDL_TraverseShapeTree(tree->data.children.upright,function,closure); | |
196 SDL_TraverseShapeTree(tree->data.children.downleft,function,closure); | |
197 SDL_TraverseShapeTree(tree->data.children.downright,function,closure); | |
198 } | |
199 else | |
200 function(tree,closure); | |
201 } | |
202 | |
203 void SDL_FreeShapeTree(SDL_ShapeTree** shapeTree) { | |
204 if((*shapeTree)->kind == QuadShape) { | |
205 SDL_FreeShapeTree(&(*shapeTree)->data.children.upleft); | |
206 SDL_FreeShapeTree(&(*shapeTree)->data.children.upright); | |
207 SDL_FreeShapeTree(&(*shapeTree)->data.children.downleft); | |
208 SDL_FreeShapeTree(&(*shapeTree)->data.children.downright); | |
209 } | |
210 free(*shapeTree); | |
211 *shapeTree = NULL; | |
106 } | 212 } |
107 | 213 |
108 int SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { | 214 int SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { |
109 int result; | 215 int result; |
110 if(window == NULL || !SDL_IsShapedWindow(window)) | 216 if(window == NULL || !SDL_IsShapedWindow(window)) |