From bc798d9ff4d46ba758fa2d225cdd741f4c94ff18 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 29 Jul 2016 10:27:30 +0200 Subject: GRAPHICS: Add custom border measures --- graphics/macgui/macwindow.cpp | 120 +++++++++++++++++++++++++++++------ graphics/macgui/macwindow.h | 15 ++++- graphics/macgui/macwindowborder.cpp | 22 +++++-- graphics/macgui/macwindowborder.h | 4 +- graphics/macgui/macwindowmanager.cpp | 49 +++++++++++++- graphics/macgui/macwindowmanager.h | 13 +++- graphics/nine_patch.cpp | 89 ++++++++++++++++++++++++-- graphics/nine_patch.h | 14 +++- 8 files changed, 285 insertions(+), 41 deletions(-) (limited to 'graphics') diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp index 350878446b..e754f3c593 100644 --- a/graphics/macgui/macwindow.cpp +++ b/graphics/macgui/macwindow.cpp @@ -50,6 +50,7 @@ #include "common/events.h" #include "graphics/macgui/macwindowmanager.h" #include "graphics/macgui/macwindow.h" +#include "image/bmp.h" namespace Graphics { @@ -99,6 +100,8 @@ void MacWindow::setActive(bool active) { _borderIsDirty = true; } +bool MacWindow::isActive() { return _active; } + void MacWindow::resize(int w, int h) { if (_surface.w == w && _surface.h == h) return; @@ -177,13 +180,14 @@ static void drawPixelInverted(int x, int y, int color, void *data) { } void MacWindow::updateInnerDims() { - _innerDims = _dims; if (_macBorder.hasBorder(_active) && _macBorder.hasOffsets()) { - int maxW = _innerDims.width() - _macBorder.getBorderOffset(kBorderOffsetLeft) - _macBorder.getBorderOffset(kBorderOffsetRight); - int maxH = _innerDims.width() - _macBorder.getBorderOffset(kBorderOffsetTop) - _macBorder.getBorderOffset(kBorderOffsetBottom); - _innerDims.clip(maxW, maxH); - _innerDims.translate(_macBorder.getBorderOffset(kBorderOffsetLeft), _macBorder.getBorderOffset(kBorderOffsetTop)); + _innerDims = Common::Rect( + _dims.left + _macBorder.getOffset(kBorderOffsetLeft), + _dims.top + _macBorder.getOffset(kBorderOffsetTop), + _dims.right - _macBorder.getOffset(kBorderOffsetRight), + _dims.bottom - _macBorder.getOffset(kBorderOffsetBottom)); } else { + _innerDims = _dims; _innerDims.grow(-kBorderWidth); } } @@ -192,12 +196,11 @@ void MacWindow::drawBorder() { _borderIsDirty = false; ManagedSurface *g = &_borderSurface; - prepareBorderSurface(g); - - if (_macBorder.hasBorder(_active)) + if (_macBorder.hasBorder(_active)) { drawBorderFromSurface(g); - else + } else { drawSimpleBorder(g); + } } void MacWindow::prepareBorderSurface(ManagedSurface *g) { @@ -211,6 +214,11 @@ void MacWindow::prepareBorderSurface(ManagedSurface *g) { } void MacWindow::drawBorderFromSurface(ManagedSurface *g) { + g->clear(kColorGreen2); + Common::Rect inside = _innerDims; + inside.moveTo(_macBorder.getOffset(kBorderOffsetLeft), _macBorder.getOffset(kBorderOffsetTop)); + g->fillRect(inside, kColorGreen); + _macBorder.blitBorderInto(_borderSurface, _active); } @@ -223,6 +231,8 @@ void MacWindow::drawSimpleBorder(ManagedSurface *g) { int width = _borderSurface.w; int height = _borderSurface.h; + prepareBorderSurface(g); + drawBox(g, x, y, size, size); drawBox(g, x + width - size - 1, y, size, size); drawBox(g, x + width - size - 1, y + height - size - 1, size, size); @@ -304,14 +314,33 @@ void MacWindow::setHighlight(WindowClick highlightedPart) { _borderIsDirty = true; } - void MacWindow::setBorder(TransparentSurface &border, bool active, int lo, int ro, int to, int bo) { + void MacWindow::loadBorder(Common::SeekableReadStream &file, bool active, int lo, int ro, int to, int bo) { + + Image::BitmapDecoder bmpDecoder; + Graphics::Surface source; + Graphics::TransparentSurface *surface = new Graphics::TransparentSurface(); + + bmpDecoder.loadStream(file); + source = *(bmpDecoder.getSurface()); + + source.convertToInPlace(surface->getSupportedPixelFormat(), bmpDecoder.getPalette()); + surface->create(source.w, source.h, source.format); + surface->copyFrom(source); + surface->applyColorKey(255, 0, 255, false); + if (active) - _macBorder.addActiveBorder(border); + _macBorder.addActiveBorder(*surface); else - _macBorder.addInactiveBorder(border); + _macBorder.addInactiveBorder(*surface); if (!_macBorder.hasOffsets()) - _macBorder.setBorderOffsets(lo, ro, to, bo); + _macBorder.setOffsets(lo, ro, to, bo); + + updateInnerDims(); + } + + void MacWindow::setCloseable(bool closeable) { + _closeable = closeable; } void MacWindow::drawBox(ManagedSurface *g, int x, int y, int w, int h) { @@ -331,18 +360,56 @@ WindowClick MacWindow::isInBorder(int x, int y) { if (_innerDims.contains(x, y)) return kBorderInner; - if (x >= _innerDims.left - _borderWidth && x < _innerDims.left && y >= _innerDims.top - _borderWidth && y < _innerDims.top) + if (isInCloseButton(x, y)) return kBorderCloseButton; if (_resizable) - if (x >= _innerDims.right && x < _innerDims.right + _borderWidth && y >= _innerDims.bottom && y < _innerDims.bottom + _borderWidth) + if (isInResizeButton(x, y)) return kBorderResizeButton; - if (_scrollable && x >= _innerDims.right && x < _innerDims.right + _borderWidth) { - if (y < _innerDims.top - _borderWidth) + if (_scrollable) + return isInScroll(x, y); + + return kBorderBorder; +} + +bool MacWindow::isInCloseButton(int x, int y) { + int bLeft = kBorderWidth; + int bTop = kBorderWidth; + if (_macBorder.hasOffsets()) { + bLeft = _macBorder.getOffset(kBorderOffsetLeft); + bTop = _macBorder.getOffset(kBorderOffsetTop); + } + return (x >= _innerDims.left - bLeft && x < _innerDims.left && y >= _innerDims.top - bTop && y < _innerDims.top); +} + +bool MacWindow::isInResizeButton(int x, int y) { + int bRight = kBorderWidth; + int bBottom = kBorderWidth; + if (_macBorder.hasOffsets()) { + bRight = _macBorder.getOffset(kBorderOffsetRight); + bBottom = _macBorder.getOffset(kBorderOffsetBottom); + } + return (x >= _innerDims.right && x < _innerDims.right + bRight && y >= _innerDims.bottom && y < _innerDims.bottom + bBottom); +} + +WindowClick MacWindow::isInScroll(int x, int y) { + int bLeft = kBorderWidth; + int bTop = kBorderWidth; + int bRight = kBorderWidth; + int bBottom = kBorderWidth; + if (_macBorder.hasOffsets()) { + bLeft = _macBorder.getOffset(kBorderOffsetLeft); + bTop = _macBorder.getOffset(kBorderOffsetTop); + bRight = _macBorder.getOffset(kBorderOffsetRight); + bBottom = _macBorder.getOffset(kBorderOffsetBottom); + } + + if (x >= _innerDims.right && x < _innerDims.right + bRight) { + if (y < _innerDims.top - bTop) return kBorderBorder; - if (y >= _innerDims.bottom + _borderWidth) + if (y >= _innerDims.bottom + bBottom) return kBorderBorder; if (y >= _innerDims.top + _innerDims.height() / 2) @@ -351,6 +418,19 @@ WindowClick MacWindow::isInBorder(int x, int y) { return kBorderScrollUp; } + if (y >= _innerDims.bottom && y < _innerDims.bottom + bBottom) { + if (x < _innerDims.left - bTop) + return kBorderBorder; + + if (x >= _innerDims.right + bRight) + return kBorderBorder; + + if (x >= _innerDims.left + _innerDims.width() / 2) + return kBorderScrollRight; + + return kBorderScrollLeft; + } + return kBorderBorder; } @@ -397,6 +477,10 @@ bool MacWindow::processEvent(Common::Event &event) { _draggedY = event.mouse.y; } + if (click == kBorderCloseButton && _closeable) { + _wm->removeWindow(this); + } + break; case Common::EVENT_LBUTTONUP: _beingDragged = false; diff --git a/graphics/macgui/macwindow.h b/graphics/macgui/macwindow.h index ce5cd1a813..763e215c46 100644 --- a/graphics/macgui/macwindow.h +++ b/graphics/macgui/macwindow.h @@ -75,6 +75,8 @@ namespace MacWindowConstants { kBorderNone = 0, kBorderScrollUp, kBorderScrollDown, + kBorderScrollLeft, + kBorderScrollRight, kBorderCloseButton, kBorderInner, kBorderBorder, @@ -132,13 +134,18 @@ public: bool draw(ManagedSurface *g, bool forceRedraw = false); void setActive(bool active); + bool isActive(); + void setTitle(Common::String &title) { _title = title; } void setHighlight(WindowClick highlightedPart); void setScroll(float scrollPos, float scrollSize); bool processEvent(Common::Event &event); bool hasAllFocus() { return _beingDragged || _beingResized; } - void setBorder(TransparentSurface &border, bool active, int lo, int ro, int to, int bo); + void loadBorder(Common::SeekableReadStream &file, bool active, int lo, int ro, int to, int bo); + //void setBorder(TransparentSurface &border, bool active); + + void setCloseable(bool closeable); private: void drawBorder(); @@ -151,6 +158,10 @@ private: void updateInnerDims(); WindowClick isInBorder(int x, int y); + bool isInCloseButton(int x, int y); + bool isInResizeButton(int x, int y); + WindowClick isInScroll(int x, int y); + private: ManagedSurface _borderSurface; ManagedSurface _composeSurface; @@ -177,6 +188,8 @@ private: Common::String _title; }; + + } // End of namespace Graphics #endif diff --git a/graphics/macgui/macwindowborder.cpp b/graphics/macgui/macwindowborder.cpp index b5fdcc33bf..f5458cb976 100644 --- a/graphics/macgui/macwindowborder.cpp +++ b/graphics/macgui/macwindowborder.cpp @@ -1,14 +1,20 @@ #include "macwindowborder.h" +#include "common/system.h" + +#include "graphics/macgui/macwindowmanager.h" + + namespace Graphics { +using namespace Graphics::MacGUIConstants; + MacWindowBorder::MacWindowBorder() : _activeInitialized(false), _inactiveInitialized(false) { _activeBorder = nullptr; _inactiveBorder = nullptr; _hasOffsets = false; } - MacWindowBorder::~MacWindowBorder() { if (_activeBorder) delete _activeBorder; @@ -36,7 +42,7 @@ bool MacWindowBorder::hasOffsets() { return _hasOffsets; } -void MacWindowBorder::setBorderOffsets(int left, int right, int top, int bottom) { +void MacWindowBorder::setOffsets(int left, int right, int top, int bottom) { _borderOffsets[0] = left; _borderOffsets[1] = right; _borderOffsets[2] = top; @@ -44,7 +50,7 @@ void MacWindowBorder::setBorderOffsets(int left, int right, int top, int bottom) _hasOffsets = true; } -int MacWindowBorder::getBorderOffset(MacBorderOffset offset) { +int MacWindowBorder::getOffset(MacBorderOffset offset) { return _borderOffsets[offset]; } @@ -53,10 +59,14 @@ void MacWindowBorder::blitBorderInto(ManagedSurface &destination, bool active) { TransparentSurface srf; NinePatchBitmap *src = active ? _activeBorder : _inactiveBorder; - srf.create(destination.w, destination.h, src->getSource()->format); + srf.create(destination.w, destination.h, destination.format); + srf.fillRect(Common::Rect(0, 0, srf.w, srf.h), kColorGreen2); + + byte palette[kColorCount]; + g_system->getPaletteManager()->grabPalette(palette, 0, kColorCount); - src->blit(srf, 0, 0, srf.w, srf.h); - destination.transBlitFrom(srf, destination.format.ARGBToColor(0, 255, 255, 255)); + src->blit(srf, 0, 0, srf.w, srf.h, palette, kColorCount); + destination.transBlitFrom(srf, kColorGreen2); } } // End of namespace Graphics diff --git a/graphics/macgui/macwindowborder.h b/graphics/macgui/macwindowborder.h index f1d0d2c81a..3c41ef2819 100644 --- a/graphics/macgui/macwindowborder.h +++ b/graphics/macgui/macwindowborder.h @@ -74,8 +74,8 @@ public: void addInactiveBorder(TransparentSurface &source); bool hasOffsets(); - void setBorderOffsets(int left, int right, int top, int bottom); - int getBorderOffset(MacBorderOffset offset); + void setOffsets(int left, int right, int top, int bottom); + int getOffset(MacBorderOffset offset); void blitBorderInto(ManagedSurface &destination, bool active); diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp index da573e6025..de94acf33a 100644 --- a/graphics/macgui/macwindowmanager.cpp +++ b/graphics/macgui/macwindowmanager.cpp @@ -184,6 +184,11 @@ void MacWindowManager::setActive(int id) { _fullRefresh = true; } +void MacWindowManager::removeWindow(MacWindow *target) { + _windowsToRemove.push_back(target); + _needsRemoval = true; +} + struct PlotData { Graphics::ManagedSurface *surface; MacPatterns *patterns; @@ -242,6 +247,8 @@ void MacWindowManager::drawDesktop() { void MacWindowManager::draw() { assert(_screen); + removeMarked(); + if (_fullRefresh) drawDesktop(); @@ -269,9 +276,9 @@ bool MacWindowManager::processEvent(Common::Event &event) { if (_menu && _menu->processEvent(event)) return true; - if (event.type != Common::EVENT_MOUSEMOVE && event.type != Common::EVENT_LBUTTONDOWN && - event.type != Common::EVENT_LBUTTONUP) - return false; + if (event.type != Common::EVENT_MOUSEMOVE && event.type != Common::EVENT_LBUTTONDOWN && + event.type != Common::EVENT_LBUTTONUP) + return false; if (_windows[_activeWindow]->isEditable() && _windows[_activeWindow]->getType() == kWindowWindow && ((MacWindow *)_windows[_activeWindow])->getInnerDimensions().contains(event.mouse.x, event.mouse.y)) { @@ -302,6 +309,42 @@ bool MacWindowManager::processEvent(Common::Event &event) { return false; } +void MacWindowManager::removeMarked() { + if (!_needsRemoval) return; + + Common::List::const_iterator it; + for (it = _windowsToRemove.begin(); it != _windowsToRemove.end(); it++) { + removeFromStack(*it); + removeFromWindowList(*it); + delete *it; + _activeWindow = 0; + _fullRefresh = true; + } + _windowsToRemove.clear(); + _needsRemoval = false; +} + +void MacWindowManager::removeFromStack(BaseMacWindow *target) { + Common::List::iterator stackIt; + for (stackIt = _windowStack.begin(); stackIt != _windowStack.end(); stackIt++) { + if (*stackIt == target) { + stackIt = _windowStack.erase(stackIt); + stackIt--; + } + } +} + +void MacWindowManager::removeFromWindowList(BaseMacWindow *target) { + int size = _windows.size(); + int ndx = 0; + for (int i = 0; i < size; i++) { + if (_windows[i] == target) { + ndx = i; + } + } + _windows.remove_at(ndx); +} + ////////////////////// // Font stuff ////////////////////// diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h index 21bc3815db..c208089c24 100644 --- a/graphics/macgui/macwindowmanager.h +++ b/graphics/macgui/macwindowmanager.h @@ -56,7 +56,7 @@ #include "graphics/fontman.h" #include "graphics/macgui/macwindow.h" -namespace Graphics { +namespace Graphics { namespace MacGUIConstants { enum { @@ -68,7 +68,8 @@ namespace MacGUIConstants { kColorGray = 1, kColorWhite = 2, kColorGreen = 3, - kColorGreen2 = 4 + kColorGreen2 = 4, + kColorCount }; enum { @@ -98,6 +99,7 @@ public: MacWindow *addWindow(bool scrollable, bool resizable, bool editable); Menu *addMenu(); void setActive(int id); + void removeWindow(MacWindow *target); void setFullRefresh(bool redraw) { _fullRefresh = true; } @@ -117,12 +119,19 @@ private: void drawDesktop(); void loadFonts(); + void removeMarked(); + void removeFromStack(BaseMacWindow *target); + void removeFromWindowList(BaseMacWindow *target); + private: ManagedSurface *_screen; Common::List _windowStack; Common::Array _windows; + Common::List _windowsToRemove; + bool _needsRemoval; + int _lastId; int _activeWindow; diff --git a/graphics/nine_patch.cpp b/graphics/nine_patch.cpp index 8ac6977eed..89c534f1ac 100644 --- a/graphics/nine_patch.cpp +++ b/graphics/nine_patch.cpp @@ -48,6 +48,8 @@ #include "graphics/transparent_surface.h" #include "graphics/nine_patch.h" +#include "graphics/managed_surface.h" + namespace Graphics { NinePatchSide::~NinePatchSide() { @@ -201,7 +203,7 @@ bad_bitmap: } } -void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, int dh) { +void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, int dh, byte *palette, byte numColors) { /* don't draw bitmaps that are smaller than the fixed area */ if (dw < _h._fix || dh < _v._fix) return; @@ -223,15 +225,50 @@ void NinePatchBitmap::blit(Graphics::Surface &target, int dx, int dy, int dw, in _cached_dh = dh; } + /* Handle CLUT8 */ + if (target.format.bytesPerPixel == 1) { + if (!palette) + warning("Trying to blit into a surface with 1bpp, you need the palette."); + + Surface srf; + srf.create(target.w, target.h, _bmp->format); + + drawRegions(srf, dx, dy, dw, dh); + + byte black = getColorIndex(TS_RGB(0, 0, 0), palette); + byte white = getColorIndex(TS_RGB(255, 255, 255), palette); + + for (uint i = 0; i < srf.w; ++i) { + for (uint j = 0; j < srf.h; ++j) { + uint32 color = *(uint32*)srf.getBasePtr(i, j); + if (color > 0) { + *((byte *)target.getBasePtr(i, j)) = closestGrayscale(color, palette, numColors); + } + } + } + + return; + } + + /* Else, draw regions normally */ + drawRegions(target, dx, dy, dw, dh); +} + +NinePatchBitmap::~NinePatchBitmap() { + if (_destroy_bmp) + delete _bmp; +} + +void NinePatchBitmap::drawRegions(Graphics::Surface &target, int dx, int dy, int dw, int 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); + _h._m[j]->offset + _h._m[j]->length, _v._m[i]->offset + _v._m[i]->length); _bmp->blit(target, 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); + Graphics::FLIP_NONE, &r, TS_ARGB(255, 255, 255, 255), + _h._m[j]->dest_length, _v._m[i]->dest_length); } } } @@ -271,9 +308,47 @@ void NinePatchBitmap::blitClip(Graphics::Surface &target, Common::Rect clip, int } } -NinePatchBitmap::~NinePatchBitmap() { - if (_destroy_bmp) - delete _bmp; +byte NinePatchBitmap::getColorIndex(uint32 target, byte* palette) { + byte *pal = palette; + uint i = 0; + uint32 color = TS_RGB(pal[0], pal[1], pal[2]); + while (color != target) { + i += 3; + color = TS_RGB(pal[i], pal[i + 1], pal[i + 2]); + } + return (i / 3); +} + +uint32 NinePatchBitmap::grayscale(uint32 color) { + byte r, g, b; + _bmp->format.colorToRGB(color, r, g, b); + return grayscale(r, g, b); +} + +uint32 NinePatchBitmap::grayscale(byte r, byte g, byte b) { + return (0.29 * r + 0.58 * g + 0.11 * b) / 3; +} + +static inline uint32 dist(uint32 a, uint32 b) { + if (a > b) + return (a - b); + + return b - a; +} + +byte NinePatchBitmap::closestGrayscale(uint32 color, byte* palette, byte paletteLength) { + byte target = grayscale(color); + byte bestNdx = 0; + byte bestColor = grayscale(palette[0], palette[1], palette[2]); + for (byte i = 1; i < paletteLength; ++i) { + byte current = grayscale(palette[i * 3], palette[(i * 3) + 1], palette[(i * 3) + 2]); + if (dist(target, bestColor) >= dist(target, current)) { + bestColor = current; + bestNdx = i; + } + } + + return bestNdx; } } // end of namespace Graphics diff --git a/graphics/nine_patch.h b/graphics/nine_patch.h index eaebac3e7b..d0fc1af05a 100644 --- a/graphics/nine_patch.h +++ b/graphics/nine_patch.h @@ -86,15 +86,25 @@ public: NinePatchBitmap(Graphics::TransparentSurface *bmp, bool owns_bitmap); ~NinePatchBitmap(); - void blit(Graphics::Surface &target, int dx, int dy, int dw, int dh); + void blit(Graphics::Surface &target, int dx, int dy, int dw, int dh, byte *palette = NULL, byte numColours = 0); void blitClip(Graphics::Surface &target, Common::Rect clip, int dx, int dy, int dw, int dh); - + int getWidth() { return _width; } int getHeight() { return _height; } int getMinWidth() { return _h._fix; } int getMinHeight() { return _v._fix; } Graphics::TransparentSurface *getSource() { return _bmp; } Common::Rect &getPadding() { return _padding; } + +private: + + void drawRegions(Graphics::Surface &target, int dx, int dy, int dw, int dh); + + // Assumes color is in the palette + byte getColorIndex(uint32 target, byte *palette); + uint32 grayscale(uint32 color); + uint32 grayscale(byte r, byte g, byte b); + byte closestGrayscale(uint32 color, byte* palette, byte paletteLength); }; } // end of namespace Graphics -- cgit v1.2.3