NinePatchBitmap::NinePatchBitmap(Graphics::TransparentSurface *bmp, bool owns_bitmap) { int i; uint8 r, g, b, a; _bmp = bmp; _destroy_bmp = owns_bitmap; _h._m.clear(); _v._m.clear(); _cached_dw = 0; _cached_dh = 0; _width = bmp->w - 2; _height = bmp->h - 2; if (_width <= 0 || _height <= 0) goto bad_bitmap; /* make sure all four corners are transparent */ #define _check_pixel(x, y) \ bmp->format.colorToARGB(*(uint32 *)bmp->getBasePtr(x, y), a, r, g, b); \ if (a != 0 && r + g + b + a != 4) goto bad_bitmap; _check_pixel(0,0); _check_pixel(bmp->w - 1, 0); _check_pixel(0, bmp->h - 1); _check_pixel(bmp->w - 1, bmp->h - 1); #undef _check_pixel _padding.top = _padding.right = _padding.bottom = _padding.left = -1; i = 1; while (i < bmp->w) { bmp->format.colorToARGB(*(uint32 *)bmp->getBasePtr(i, bmp->h - 1), a, r, g, b); if (r + g + b == 0 && a == 1) { if (_padding.left == -1) _padding.left = i - 1; else if (_padding.right != -1) goto bad_bitmap; } else if (a == 0 || r + g + b + a == 4) { if (_padding.left != -1 && _padding.right == -1) _padding.right = bmp->w - i - 1; } ++i; } i = 1; while (i < bmp->h) { bmp->format.colorToARGB(*(uint32 *)bmp->getBasePtr(bmp->w - 1, i), a, r, g, b); if (r + g + b == 0 && a == 1) { if (_padding.top == -1) _padding.top = i - 1; else if (_padding.bottom != -1) goto bad_bitmap; } else if (a == 0 || r + g + b + a == 4) { if (_padding.top != -1 && _padding.bottom == -1) _padding.bottom = bmp->h - i - 1; } ++i; } if (!_h.init(bmp, false) || !_v.init(bmp, true)) { bad_bitmap: _h._m.clear(); _v._m.clear(); } }
NINE_PATCH_BITMAP *create_nine_patch_bitmap(ALLEGRO_BITMAP *bmp, bool owns_bitmap) { int i; NINE_PATCH_BITMAP *p9; ALLEGRO_COLOR c; p9 = al_malloc(sizeof(*p9)); p9->bmp = bmp; p9->destroy_bmp = owns_bitmap; p9->h.m = NULL; p9->v.m = NULL; p9->cached_dw = 0; p9->cached_dh = 0; p9->mutex = al_create_mutex(); p9->width = al_get_bitmap_width(bmp) - 2; p9->height = al_get_bitmap_height(bmp) - 2; al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY); if (p9->width <= 0 || p9->height <= 0) goto bad_bitmap; /* make sure all four corners are transparent */ #define _check_pixel(x, y) \ c = al_get_pixel(bmp, x, y); \ if (c.a != 0 && c.r + c.g + c.b + c.a != 4) goto bad_bitmap; _check_pixel(0,0); _check_pixel(al_get_bitmap_width(bmp) - 1, 0); _check_pixel(0, al_get_bitmap_height(bmp) - 1); _check_pixel(al_get_bitmap_width(bmp) - 1, al_get_bitmap_height(bmp) - 1); #undef _check_pixel p9->padding.top = p9->padding.right = p9->padding.bottom = p9->padding.left = -1; i = 1; while (i < al_get_bitmap_width(bmp)) { c = al_get_pixel(bmp, i, al_get_bitmap_height(bmp) - 1); if (c.r + c.g + c.b == 0 && c.a == 1) { if (p9->padding.left == -1) p9->padding.left = i - 1; else if (p9->padding.right != -1) goto bad_bitmap; } else if (c.a == 0 || c.r + c.g + c.b + c.a == 4) { if (p9->padding.left != -1 && p9->padding.right == -1) p9->padding.right = al_get_bitmap_width(bmp) - i - 1; } ++i; } i = 1; while (i < al_get_bitmap_height(bmp)) { c = al_get_pixel(bmp, al_get_bitmap_width(bmp) - 1, i); if (c.r + c.g + c.b == 0 && c.a == 1) { if (p9->padding.top == -1) p9->padding.top = i - 1; else if (p9->padding.bottom != -1) goto bad_bitmap; } else if (c.a == 0 || c.r + c.g + c.b + c.a == 4) { if (p9->padding.top != -1 && p9->padding.bottom == -1) p9->padding.bottom = al_get_bitmap_height(bmp) - i - 1; } ++i; } if (!init_nine_patch_side(&p9->h, bmp, 0) || !init_nine_patch_side(&p9->v, bmp, 1)) { bad_bitmap: al_destroy_mutex(p9->mutex); if (p9->h.m) al_free(p9->h.m); if (p9->v.m) al_free(p9->v.m); al_free(p9); p9 = NULL; } al_unlock_bitmap(bmp); return p9; }