Mercurial > sdl-ios-xcode
diff src/video/win32/SDL_win32shape.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 | 329708ffe2a7 |
children | 93402b9dd20c |
line wrap: on
line diff
--- a/src/video/win32/SDL_win32shape.c Mon Jul 26 21:49:32 2010 -0400 +++ b/src/video/win32/SDL_win32shape.c Wed Jul 28 23:35:24 2010 -0400 @@ -23,10 +23,6 @@ #include <windows.h> #include "SDL_win32shape.h" -SDL_Window* Win32_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) { - return SDL_CreateWindow(title,x,y,w,h,flags); -} - SDL_WindowShaper* Win32_CreateShaper(SDL_Window * window) { SDL_WindowShaper* result = malloc(sizeof(SDL_WindowShaper)); result->window = window; @@ -35,315 +31,48 @@ result->usershownflag = 0; //Put some driver-data here. window->shaper = result; - int resized_properly = X11ResizeWindowShape(window); + int resized_properly = Win32_ResizeWindowShape(window); assert(resized_properly == 0); return result; } +void CombineRectRegions(SDL_ShapeTree* node,HRGN* mask_region) { + if(node->kind == OpaqueShape) { + HRGN temp_region = CreateRectRgn(node->data.shape.x,node->data.shape.y,node->data.shape.w,node->data.shape.h); + CombineRgn(*mask_region,*mask_region,temp_region, RGN_OR); + DeleteObject(temp_region); + } +} + int Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { assert(shaper != NULL && shape != NULL); - if(!SDL_ISPIXELFORMAT_ALPHA(SDL_MasksToPixelFormatEnum(shape->format->BitsPerPixel,shape->format->Rmask,shape->format->Gmask,shape->format->Bmask,shape->format->Amask))) - return -2; - if(shape->w != shaper->window->w || shape->h != shaper->window->h) - return -3; + if(!SDL_ISPIXELFORMAT_ALPHA(SDL_MasksToPixelFormatEnum(shape->format->BitsPerPixel,shape->format->Rmask,shape->format->Gmask,shape->format->Bmask,shape->format->Amask)) && shapeMode->mode != ShapeModeColorKey || shape->w != shaper->window->w || shape->h != shaper->window->h) + return SDL_INVALID_SHAPE_ARGUMENT; + + SDL_ShapeData *data = (SDL_ShapeData*)shaper->driverdata; + data->mask_tree = SDL_CalculateShapeTree(shapeMode,shape,SDL_FALSE); /* * Start with empty region */ - HRGN MaskRegion = CreateRectRgn(0, 0, 0, 0); - - unsigned int pitch = shape->pitch; - unsigned int width = shape->width; - unsigned int height = shape->height; - unsigned int dy = pitch - width; - - SDL_ShapeData *data = (SDL_ShapeData*)shaper->driverdata; - /* - * Transfer binarized mask image into workbuffer - */ - SDL_CalculateShapeBitmap(shaper->mode,shape,data->shapebuffer,1,0xff); + HRGN mask_region = CreateRectRgn(0, 0, 0, 0); - //Move code over to here from AW_windowShape.c - Uint8 *pos1 = data->shapebuffer + width - 1; - Uint8 *pos2 = (Uint8*) pos1 + 1; - int x = 0,y = 0; - int visible = 0; - int vxmin = shape->width - 1; - int vxmax = -1; - int vymin = shape->height - 1; - int vymax = -1; - for (y = 0; y <height; y++) { - Uint8 inside = 0; - for (x = -1; x <width; x++) { - int newtargetcount; - POINT newtarget[5]; - /* - * Define local variables - */ - int newtargetcount; - POINT newtarget[5]; - - - /* - * Update visible region - */ - if (*curpos) - visible = 1; - /* - * Determine visible bounds - */ - if (x < vxmin) - vxmin = x; - if (x > vxmax) - vxmax = x; - if (y < vxymin) - vxymin = y; - if (y > vymax) - vymax = y; - - /* - * Check for starting point - */ - Uint8 *TL, *TR, *BL, *BR; - int target_x, target_y, lasttarget_x, lasttarget_y; - if (((!*curpos) && (*curpos2 == 0xFF)) || ((!*curpos2) && (*curpos == 0xFF))) { - if (!*curpos) { - BR = curpos2; - BL = (Uint8 *) (BR - 1); - TR = (Uint8 *) (BR - width); - TL = (Uint8 *) (TR - 1); - target_x = x; - target_y = y; - } - else { - BR = curpos2 + 1; - BL = (Uint8 *) (BR - 1); - TR = (Uint8 *) (BR - width); - TL = (Uint8 *) (TR - 1); - target_x = x + 1; - target_y = y; - } - - lasttarget_x = 0; - lasttarget_y = 0; - int firsttime = 1; - pos_array_pos = 0; - - while ((target_x != x) || (target_y != y) || firsttime) { - /* - * New array index - */ - firsttime = 0; - pos_array_pos++; - /* - * Check array index - */ - if (pos_array_pos >= 4096) { - SDL_SetError("Exceeded maximum number of polygon points."); - pos_array_pos--; - } - - /* - * Store point in array - */ - pos_array[pos_array_pos].x = target_x + 1; - pos_array[pos_array_pos].y = target_y; - - /* - * Mark the four poles as visited - */ - if (*TL) - *TL = 0x99; - if (*BL) - *BL = 0x99; - if (*TR) - *TR = 0x99; - if (*BR) - *BR = 0x99; - - newtargetcount = 0; - if ((*TL || *TR) && (*TL != *TR)) { - newtargetcount++; - newtarget[newtargetcount].x = 0; - newtarget[newtargetcount].y = -1; - } - - if ((*TR || *BR) && (*TR != *BR)) { - newtargetcount++; - newtarget[newtargetcount].x = 1; - newtarget[newtargetcount].y = 0; - } - - if ((*BL || *BR) && (*BL != *BR)) { - newtargetcount++; - newtarget[newtargetcount].x = 0; - newtarget[newtargetcount].y = 1; - } - - if ((*TL || *BL) && (*TL != *BL)) { - newtargetcount++; - newtarget[newtargetcount].x = -1; - newtarget[newtargetcount].y = 0; - } - - switch (newtargetcount) { - case 1: - SDL_SetError("Cropping error - Newtargetcount=1."); - return (-1); - break; - - case 2: - if ((target_x + newtarget[1].x != lasttarget_x) || (target_y + newtarget[1].y != lasttarget_y)) { - lasttarget_x = target_x; - lasttarget_y = target_y; - target_x = target_x + newtarget[1].x; - target_y = target_y + newtarget[1].y; - } - else { - lasttarget_x = target_x; - lasttarget_y = target_y; - target_x = target_x + newtarget[2].x; - target_y = target_y + newtarget[2].y; - } - break; - - case 3: - SDL_SetError("Cropping error - Newtargetcount=3."); - return (-1); - break; - - case 4: - if (lasttarget_x > target_x) { - lasttarget_x = target_x; - lasttarget_y = target_y; - if (*TR != 0x00) - target_y--; - else - target_y++; - } - else if (lasttarget_y > target_y) { - lasttarget_x = target_x; - lasttarget_y = target_y; - if (*BL != 0x00) - target_x--; - else - target_x++; - } - else if (lasttarget_x < target_x) { - lasttarget_x = target_x; - lasttarget_y = target_y; - if (*TL != 0x00) - target_y--; - else - target_y++; - } - else if (lasttarget_y < target_y) { - lasttarget_x = target_x; - lasttarget_y = target_y; - if (*TL != 0x00) - target_x--; - else - target_x++; - } - else { - SDL_SetError("Cropping error - no possible targets on newtargetcount=4."); - return (-1); - } - break; - - default: - SDL_SetError("Cropping error - Newtargetcount invalid."); - return (-1); - break; - } - - if (target_x > lasttarget_x) - TL = (Uint8 *) (TL + 1); - else if (target_x < lasttarget_x) - TL = (Uint8 *) (TL - 1); - else if (target_y > lasttarget_y) - TL = (Uint8 *) (TL + width); - else if (target_y < lasttarget_y) - TL = (Uint8 *) (TL - width); - else { - SDL_SetError("Cropping error - no new target."); - return (-1); - } - - BL = (Uint8 *) (TL + width); - TR = (Uint8 *) (TL + 1); - BR = (Uint8 *) (BL + 1); - } // End of while loop - - /* - * Apply the mask to the cropping region - */ - if (pos_array_pos >= 4) { - TempRegion = CreatePolygonRgn(&(pos_array[1]), pos_array_pos, WINDING); - if (TempRegion == NULL) { - SDL_SetError("Cropping error - unable to create polygon."); - return (-1); - } - - /* - * Add current region to final mask region - */ - if (inside) - CombineRgn(MaskRegion, MaskRegion, TempRegion, RGN_DIFF); - else - CombineRgn(MaskRegion, MaskRegion, TempRegion, RGN_OR); - - /* - * Remove temporary region - */ - DeleteObject(TempRegion); - } - - /* - * Switch sides - */ - inside = !inside; - } - else if ((*curpos) && (!*curpos2)) - inside = !inside; - else if ((!*curpos) && (*curpos2)) - inside = !inside; - - curpos++; - curpos2++; - } - curpos = (Uint8 *) (curpos + 2 * enlarge_mask - 1); - curpos2 = (Uint8 *) (curpos + 1); - } + SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region); /* * Set the new region mask for the window */ - SetWindowRgn((SDL_WindowData*)(shaper->window->driverdata)->hwnd, MaskRegion, TRUE); - - /* - * Return value - */ - return (0); + SetWindowRgn((SDL_WindowData*)(shaper->window->driverdata)->hwnd, mask_region, TRUE); + + return 0; } int Win32_ResizeWindowShape(SDL_Window *window) { SDL_ShapeData* data = window->shaper->driverdata; assert(data != NULL); - unsigned int buffersize = window->w * window->h; - if(data->buffersize != buffersize || data->shapebuffer == NULL) { - data->buffersize = buffersize; - if(data->shapebuffer != NULL) - free(data->shapebuffer); - data->shapebuffer = malloc(data->buffersize); - if(data->shapebuffer == NULL) { - SDL_SetError("Could not allocate memory for shaped-window bitmap."); - return -1; - } - } - else - memset(data->shapebuffer,0,data->buffersize); + if(data->mask_tree != NULL) + SDL_FreeShapeTree(&data->mask_tree); window->shaper->usershownflag |= window->flags & SDL_WINDOW_SHOWN;