diff options
author | Alexander Tkachev | 2016-06-30 23:34:25 +0600 |
---|---|---|
committer | Eugene Sandulenko | 2016-07-03 12:23:57 +0200 |
commit | 4b87563792163d5fd538092b340500bccd20aa7b (patch) | |
tree | bc64bedf5aef5686c82a1d16cf870b0fc7a1bc35 | |
parent | 916c86e68941cb1a752566ac9c0346263970b366 (diff) | |
download | scummvm-rg350-4b87563792163d5fd538092b340500bccd20aa7b.tar.gz scummvm-rg350-4b87563792163d5fd538092b340500bccd20aa7b.tar.bz2 scummvm-rg350-4b87563792163d5fd538092b340500bccd20aa7b.zip |
GUI: Add blipClip()
-rw-r--r-- | graphics/nine_patch.cpp | 35 | ||||
-rw-r--r-- | graphics/nine_patch.h | 1 | ||||
-rw-r--r-- | graphics/transparent_surface.cpp | 133 | ||||
-rw-r--r-- | graphics/transparent_surface.h | 8 | ||||
-rw-r--r-- | gui/ThemeEngine.cpp | 7 |
5 files changed, 177 insertions, 7 deletions
diff --git a/graphics/nine_patch.cpp b/graphics/nine_patch.cpp index a193200208..8ac6977eed 100644 --- a/graphics/nine_patch.cpp +++ b/graphics/nine_patch.cpp @@ -236,6 +236,41 @@ void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, in } } +void NinePatchBitmap::blitClip(Graphics::Surface &target, Common::Rect clip, int dx, int dy, int dw, int dh) { + /* don't draw bitmaps that are smaller than the fixed area */ + if (dw < _h._fix || dh < _v._fix) + return; + + /* if the bitmap is the same size as the origin, then draw it as-is */ + if (dw == _width && dh == _height) { + Common::Rect r(1, 1, dw, dh); + + _bmp->blitClip(target, clip, dx, dy, Graphics::FLIP_NONE, &r); + return; + } + + /* only recalculate the offsets if they have changed since the last draw */ + if (_cached_dw != dw || _cached_dh != dh) { + _h.calcOffsets(dw); + _v.calcOffsets(dh); + + _cached_dw = dw; + _cached_dh = dh; + } + + /* draw each region */ + for (uint i = 0; i < _v._m.size(); ++i) { + for (uint j = 0; j < _h._m.size(); ++j) { + Common::Rect r(_h._m[j]->offset, _v._m[i]->offset, + _h._m[j]->offset + _h._m[j]->length, _v._m[i]->offset + _v._m[i]->length); + + _bmp->blitClip(target, clip, dx + _h._m[j]->dest_offset, dy + _v._m[i]->dest_offset, + Graphics::FLIP_NONE, &r, TS_ARGB(255, 255, 255, 255), + _h._m[j]->dest_length, _v._m[i]->dest_length); + } + } +} + NinePatchBitmap::~NinePatchBitmap() { if (_destroy_bmp) delete _bmp; diff --git a/graphics/nine_patch.h b/graphics/nine_patch.h index c62de3f6e2..45e4e0918a 100644 --- a/graphics/nine_patch.h +++ b/graphics/nine_patch.h @@ -83,6 +83,7 @@ public: ~NinePatchBitmap(); void blit(Graphics::Surface &target, int dx, int dy, int dw, int dh); + void blitClip(Graphics::Surface &target, Common::Rect clip, int dx, int dy, int dw, int dh); int getWidth() { return _width; } int getHeight() { return _height; } diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp index 19e7655a93..c2903d42c3 100644 --- a/graphics/transparent_surface.cpp +++ b/graphics/transparent_surface.cpp @@ -462,6 +462,139 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p return retSize; } +Common::Rect TransparentSurface::blitClip(Graphics::Surface &target, Common::Rect clippingArea, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) { + Common::Rect retSize; + retSize.top = 0; + retSize.left = 0; + retSize.setWidth(0); + retSize.setHeight(0); + // Check if we need to draw anything at all + int ca = (color >> kAModShift) & 0xff; + + if (ca == 0) { + return retSize; + } + + // Create an encapsulating surface for the data + TransparentSurface srcImage(*this, false); + // TODO: Is the data really in the screen format? + if (format.bytesPerPixel != 4) { + warning("TransparentSurface can only blit 32bpp images, but got %d", format.bytesPerPixel * 8); + return retSize; + } + + if (pPartRect) { + + int xOffset = pPartRect->left; + int yOffset = pPartRect->top; + + if (flipping & FLIP_V) { + yOffset = srcImage.h - pPartRect->bottom; + } + + if (flipping & FLIP_H) { + xOffset = srcImage.w - pPartRect->right; + } + + srcImage.pixels = getBasePtr(xOffset, yOffset); + srcImage.w = pPartRect->width(); + srcImage.h = pPartRect->height(); + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, + pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); + } else { + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, + srcImage.w, srcImage.h, color, width, height); + } + + if (width == -1) { + width = srcImage.w; + } + if (height == -1) { + height = srcImage.h; + } + +#ifdef SCALING_TESTING + // Hardcode scaling to 66% to test scaling + width = width * 2 / 3; + height = height * 2 / 3; +#endif + + Graphics::Surface *img = nullptr; + Graphics::Surface *imgScaled = nullptr; + byte *savedPixels = nullptr; + if ((width != srcImage.w) || (height != srcImage.h)) { + // Scale the image + img = imgScaled = srcImage.scale(width, height); + savedPixels = (byte *)img->getPixels(); + } else { + img = &srcImage; + } + + // Handle off-screen clipping + if (posY < clippingArea.top) { + img->h = MAX(0, (int)img->h - (clippingArea.top - posY)); + img->setPixels((byte *)img->getBasePtr(0, clippingArea.top - posY)); + posY = clippingArea.top; + } + + if (posX < clippingArea.left) { + img->w = MAX(0, (int)img->w - (clippingArea.left - posX)); + img->setPixels((byte *)img->getBasePtr(clippingArea.left - posX, 0)); + posX = clippingArea.left; + } + + img->w = CLIP((int)img->w, 0, (int)MAX((int)clippingArea.right - posX, 0)); + img->h = CLIP((int)img->h, 0, (int)MAX((int)clippingArea.bottom - posY, 0)); + + if ((img->w > 0) && (img->h > 0)) { + int xp = 0, yp = 0; + + int inStep = 4; + int inoStep = img->pitch; + if (flipping & FLIP_H) { + inStep = -inStep; + xp = img->w - 1; + } + + if (flipping & FLIP_V) { + inoStep = -inoStep; + yp = img->h - 1; + } + + byte *ino = (byte *)img->getBasePtr(xp, yp); + byte *outo = (byte *)target.getBasePtr(posX, posY); + + if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) { + doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) { + doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else { + if (blendMode == BLEND_ADDITIVE) { + doBlitAdditiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } else if (blendMode == BLEND_SUBTRACTIVE) { + doBlitSubtractiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } else { + assert(blendMode == BLEND_NORMAL); + doBlitAlphaBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } + } + + } + + retSize.setWidth(img->w); + retSize.setHeight(img->h); + + if (imgScaled) { + imgScaled->setPixels(savedPixels); + imgScaled->free(); + delete imgScaled; + } + + return retSize; +} + /** * Writes a color key to the alpha channel of the surface * @param rKey the red component of the color key diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h index 0cd7d5b2e9..c0d3d26e52 100644 --- a/graphics/transparent_surface.h +++ b/graphics/transparent_surface.h @@ -123,6 +123,14 @@ struct TransparentSurface : public Graphics::Surface { uint color = TS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, TSpriteBlendMode blend = BLEND_NORMAL); + Common::Rect blitClip(Graphics::Surface &target, Common::Rect clippingArea, + int posX = 0, int posY = 0, + int flipping = FLIP_NONE, + Common::Rect *pPartRect = nullptr, + uint color = TS_ARGB(255, 255, 255, 255), + int width = -1, int height = -1, + TSpriteBlendMode blend = BLEND_NORMAL); + void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); /** diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 08245380a8..b16a42806c 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -168,8 +168,6 @@ protected: bool _alpha; }; - - /********************************************************** * Data definitions for theme engine elements *********************************************************/ @@ -306,7 +304,6 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) { } - /********************************************************** * ThemeEngine class *********************************************************/ @@ -979,8 +976,6 @@ void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rec } } - - /********************************************************** * Widget drawing functions *********************************************************/ @@ -1201,8 +1196,6 @@ void ThemeEngine::drawDialogBackgroundClip(const Common::Rect &r, const Common:: case kDialogBackgroundDefault: queueDDClip(kDDDefaultBackground, r, clip); break; - case kDialogBackgroundNone: - break; } } |