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; }
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) { 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); next.x += next.w; /* Unneeded: next.y = dimensions.y; */ result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); next.x = dimensions.x; next.y += next.h; result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode,mask,next); next.x += next.w; /* Unneeded: next.y = dimensions.y + dimensions.h /2; */ 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; }