aboutsummaryrefslogtreecommitdiff
path: root/gui/ThemeEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gui/ThemeEngine.cpp')
-rw-r--r--gui/ThemeEngine.cpp653
1 files changed, 629 insertions, 24 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 1b95a11e03..96108bccce 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -31,11 +31,13 @@
#include "graphics/cursorman.h"
#include "graphics/fontman.h"
#include "graphics/surface.h"
+#include "graphics/transparent_surface.h"
#include "graphics/VectorRenderer.h"
#include "graphics/fonts/bdf.h"
#include "graphics/fonts/ttf.h"
#include "image/bmp.h"
+#include "image/png.h"
#include "gui/widget.h"
#include "gui/ThemeEngine.h"
@@ -59,6 +61,10 @@ const char *const ThemeEngine::kImageStopSmallButton = "stopbtn_small.bmp";
const char *const ThemeEngine::kImageEditSmallButton = "editbtn_small.bmp";
const char *const ThemeEngine::kImageSwitchModeSmallButton = "switchbtn_small.bmp";
const char *const ThemeEngine::kImageFastReplaySmallButton = "fastreplay_small.bmp";
+const char *const ThemeEngine::kImageDropboxLogo = "dropbox.bmp";
+const char *const ThemeEngine::kImageOneDriveLogo = "onedrive.bmp";
+const char *const ThemeEngine::kImageGoogleDriveLogo = "googledrive.bmp";
+const char *const ThemeEngine::kImageBoxLogo = "box.bmp";
struct TextDrawData {
const Graphics::Font *_fontPtr;
@@ -121,6 +127,19 @@ protected:
const WidgetDrawData *_data;
};
+class ThemeItemDrawDataClip: public ThemeItem{
+public:
+ ThemeItemDrawDataClip(ThemeEngine *engine, const WidgetDrawData *data, const Common::Rect &area, const Common::Rect &clip, uint32 dynData) :
+ ThemeItem(engine, area), _dynamicData(dynData), _data(data), _clip(clip) {}
+
+ void drawSelf(bool draw, bool restore);
+
+protected:
+ uint32 _dynamicData;
+ const WidgetDrawData *_data;
+ const Common::Rect _clip;
+};
+
class ThemeItemTextData : public ThemeItem {
public:
ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::Rect &textDrawableArea,
@@ -155,7 +174,30 @@ protected:
bool _alpha;
};
+class ThemeItemABitmap : public ThemeItem {
+public:
+ ThemeItemABitmap(ThemeEngine *engine, const Common::Rect &area, Graphics::TransparentSurface *bitmap, ThemeEngine::AutoScaleMode autoscale, int alpha) :
+ ThemeItem(engine, area), _bitmap(bitmap), _autoscale(autoscale), _alpha(alpha) {}
+ void drawSelf(bool draw, bool restore);
+
+protected:
+ Graphics::TransparentSurface *_bitmap;
+ ThemeEngine::AutoScaleMode _autoscale;
+ int _alpha;
+};
+
+class ThemeItemBitmapClip : public ThemeItem {
+public:
+ ThemeItemBitmapClip(ThemeEngine *engine, const Common::Rect &area, const Common::Rect &clip, const Graphics::Surface *bitmap, bool alpha) :
+ ThemeItem(engine, area), _bitmap(bitmap), _alpha(alpha), _clip(clip) {}
+ void drawSelf(bool draw, bool restore);
+
+protected:
+ const Graphics::Surface *_bitmap;
+ bool _alpha;
+ const Common::Rect _clip;
+};
/**********************************************************
* Data definitions for theme engine elements
@@ -164,7 +206,7 @@ struct DrawDataInfo {
DrawData id; ///< The actual ID of the DrawData item.
const char *name; ///< The name of the DrawData item as it appears in the Theme Description files
bool buffer; ///< Sets whether this item is buffered on the backbuffer or drawn directly to the screen.
- DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover
+ DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kDDButtonIdle -> kDDButtonHover
};
/**
@@ -242,16 +284,40 @@ void ThemeItemDrawData::drawSelf(bool draw, bool restore) {
_engine->addDirtyRect(extendedRect);
}
+void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) {
+
+ Common::Rect extendedRect = _area;
+ extendedRect.grow(_engine->kDirtyRectangleThreshold + _data->_backgroundOffset);
+
+ if (restore)
+ _engine->restoreBackground(extendedRect);
+
+ if (draw) {
+ Common::List<Graphics::DrawStep>::const_iterator step;
+ for (step = _data->_steps.begin(); step != _data->_steps.end(); ++step) {
+ _engine->renderer()->drawStepClip(_area, _clip, *step, _dynamicData);
+ }
+ }
+
+ extendedRect.clip(_clip);
+
+ _engine->addDirtyRect(extendedRect);
+}
+
void ThemeItemTextData::drawSelf(bool draw, bool restore) {
+ Common::Rect dirty = _textDrawableArea;
+ if (dirty.isEmpty()) dirty = _area;
+ else dirty.clip(_area);
+
if (_restoreBg || restore)
- _engine->restoreBackground(_area);
+ _engine->restoreBackground(dirty);
if (draw) {
_engine->renderer()->setFgColor(_color->r, _color->g, _color->b);
_engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis, _textDrawableArea);
}
- _engine->addDirtyRect(_area);
+ _engine->addDirtyRect(dirty);
}
void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
@@ -260,7 +326,7 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
if (draw) {
if (_alpha)
- _engine->renderer()->blitAlphaBitmap(_bitmap, _area);
+ _engine->renderer()->blitKeyBitmap(_bitmap, _area);
else
_engine->renderer()->blitSubSurface(_bitmap, _area);
}
@@ -268,7 +334,31 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
_engine->addDirtyRect(_area);
}
+void ThemeItemABitmap::drawSelf(bool draw, bool restore) {
+ if (restore)
+ _engine->restoreBackground(_area);
+
+ if (draw)
+ _engine->renderer()->blitAlphaBitmap(_bitmap, _area, _autoscale, Graphics::DrawStep::kVectorAlignManual, Graphics::DrawStep::kVectorAlignManual, _alpha);
+
+ _engine->addDirtyRect(_area);
+}
+
+void ThemeItemBitmapClip::drawSelf(bool draw, bool restore) {
+ if (restore)
+ _engine->restoreBackground(_area);
+
+ if (draw) {
+ if (_alpha)
+ _engine->renderer()->blitKeyBitmapClip(_bitmap, _area, _clip);
+ else
+ _engine->renderer()->blitSubSurfaceClip(_bitmap, _area, _clip);
+ }
+ Common::Rect dirtyRect = _area;
+ dirtyRect.clip(_clip);
+ _engine->addDirtyRect(dirtyRect);
+}
/**********************************************************
* ThemeEngine class
@@ -311,6 +401,12 @@ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) :
_themeArchive = 0;
_initOk = false;
+ _cursorHotspotX = _cursorHotspotY = 0;
+ _cursorWidth = _cursorHeight = 0;
+ _cursorPalSize = 0;
+
+ _needPaletteUpdates = false;
+
// We prefer files in archive bundles over the common search paths.
_themeFiles.add("default", &SearchMan, 0, false);
}
@@ -333,6 +429,15 @@ ThemeEngine::~ThemeEngine() {
}
_bitmaps.clear();
+ for (AImagesMap::iterator i = _abitmaps.begin(); i != _abitmaps.end(); ++i) {
+ Graphics::TransparentSurface *surf = i->_value;
+ if (surf) {
+ surf->free();
+ delete surf;
+ }
+ }
+ _abitmaps.clear();
+
delete _parser;
delete _themeEval;
delete[] _cursor;
@@ -457,6 +562,15 @@ void ThemeEngine::refresh() {
}
}
_bitmaps.clear();
+
+ for (AImagesMap::iterator i = _abitmaps.begin(); i != _abitmaps.end(); ++i) {
+ Graphics::TransparentSurface *surf = i->_value;
+ if (surf) {
+ surf->free();
+ delete surf;
+ }
+ }
+ _abitmaps.clear();
}
init();
@@ -558,7 +672,7 @@ void ThemeEngine::restoreBackground(Common::Rect r) {
void ThemeEngine::addDrawStep(const Common::String &drawDataId, const Graphics::DrawStep &step) {
DrawData id = parseDrawDataId(drawDataId);
- assert(_widgets[id] != 0);
+ assert(id != kDDNone && _widgets[id] != 0);
_widgets[id]->_steps.push_back(step);
}
@@ -638,24 +752,51 @@ bool ThemeEngine::addBitmap(const Common::String &filename) {
if (surf)
return true;
- // If not, try to load the bitmap via the BitmapDecoder class.
- Image::BitmapDecoder bitmapDecoder;
const Graphics::Surface *srcSurface = 0;
- Common::ArchiveMemberList members;
- _themeFiles.listMatchingMembers(members, filename);
- for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
- Common::SeekableReadStream *stream = (*i)->createReadStream();
- if (stream) {
- bitmapDecoder.loadStream(*stream);
- srcSurface = bitmapDecoder.getSurface();
- delete stream;
- if (srcSurface)
- break;
+
+ if (filename.hasSuffix(".png")) {
+ // Maybe it is PNG?
+#ifdef USE_PNG
+ Image::PNGDecoder decoder;
+ Common::ArchiveMemberList members;
+ _themeFiles.listMatchingMembers(members, filename);
+ for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
+ Common::SeekableReadStream *stream = (*i)->createReadStream();
+ if (stream) {
+ if (!decoder.loadStream(*stream))
+ error("Error decoding PNG");
+
+ srcSurface = decoder.getSurface();
+ delete stream;
+ if (srcSurface)
+ break;
+ }
+ }
+
+ if (srcSurface && srcSurface->format.bytesPerPixel != 1)
+ surf = srcSurface->convertTo(_overlayFormat);
+#else
+ error("No PNG support compiled in");
+#endif
+ } else {
+ // If not, try to load the bitmap via the BitmapDecoder class.
+ Image::BitmapDecoder bitmapDecoder;
+ Common::ArchiveMemberList members;
+ _themeFiles.listMatchingMembers(members, filename);
+ for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
+ Common::SeekableReadStream *stream = (*i)->createReadStream();
+ if (stream) {
+ bitmapDecoder.loadStream(*stream);
+ srcSurface = bitmapDecoder.getSurface();
+ delete stream;
+ if (srcSurface)
+ break;
+ }
}
- }
- if (srcSurface && srcSurface->format.bytesPerPixel != 1)
- surf = srcSurface->convertTo(_overlayFormat);
+ if (srcSurface && srcSurface->format.bytesPerPixel != 1)
+ surf = srcSurface->convertTo(_overlayFormat);
+ }
// Store the surface into our hashmap (attention, may store NULL entries!)
_bitmaps[filename] = surf;
@@ -663,6 +804,48 @@ bool ThemeEngine::addBitmap(const Common::String &filename) {
return surf != 0;
}
+bool ThemeEngine::addAlphaBitmap(const Common::String &filename) {
+ // Nothing has to be done if the bitmap already has been loaded.
+ Graphics::TransparentSurface *surf = _abitmaps[filename];
+ if (surf)
+ return true;
+
+ const Graphics::TransparentSurface *srcSurface = 0;
+
+ if (filename.hasSuffix(".png")) {
+ // Maybe it is PNG?
+#ifdef USE_PNG
+ Image::PNGDecoder decoder;
+ Common::ArchiveMemberList members;
+ _themeFiles.listMatchingMembers(members, filename);
+ for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
+ Common::SeekableReadStream *stream = (*i)->createReadStream();
+ if (stream) {
+ if (!decoder.loadStream(*stream))
+ error("Error decoding PNG");
+
+ srcSurface = new Graphics::TransparentSurface(*decoder.getSurface(), true);
+ delete stream;
+ if (srcSurface)
+ break;
+ }
+ }
+
+ if (srcSurface && srcSurface->format.bytesPerPixel != 1)
+ surf = srcSurface->convertTo(_overlayFormat);
+#else
+ error("No PNG support compiled in");
+#endif
+ } else {
+ error("Only PNG is supported as alphabitmap");
+ }
+
+ // Store the surface into our hashmap (attention, may store NULL entries!)
+ _abitmaps[filename] = surf;
+
+ return surf != 0;
+}
+
bool ThemeEngine::addDrawData(const Common::String &data, bool cached) {
DrawData id = parseDrawDataId(data);
@@ -856,10 +1039,34 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic,
}
}
+void ThemeEngine::queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic, bool restore) {
+ if (_widgets[type] == 0)
+ return;
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+
+ ThemeItemDrawDataClip *q = new ThemeItemDrawDataClip(this, _widgets[type], area, clippingRect, dynamic);
+
+ if (_buffering) {
+ if (_widgets[type]->_buffer) {
+ _bufferQueue.push_back(q);
+ } else {
+ if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type)
+ queueDDClip(kDrawDataDefaults[type].parent, r, clippingRect);
+
+ _screenQueue.push_back(q);
+ }
+ } else {
+ q->drawSelf(!_widgets[type]->_buffer, restore || _widgets[type]->_buffer);
+ delete q;
+ }
+}
+
void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) {
- if (_texts[type] == 0)
+ if (type == kTextDataNone || _texts[type] == 0)
return;
Common::Rect area = r;
@@ -875,6 +1082,31 @@ void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect
}
}
+void ThemeEngine::queueDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &text, bool restoreBg,
+ bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) {
+
+ if (_texts[type] == 0)
+ return;
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+ Common::Rect textArea = drawableTextArea;
+ if (textArea.isEmpty()) textArea = clippingArea;
+ else {
+ textArea.clip(clippingArea);
+ if (textArea.isEmpty()) textArea = Common::Rect(0, 0, 1, 1); // one small pixel should be invisible enough
+ }
+
+ ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, textArea, text, alignH, alignV, ellipsis, restoreBg, deltax);
+
+ if (_buffering) {
+ _screenQueue.push_back(q);
+ } else {
+ q->drawSelf(true, false);
+ delete q;
+ }
+}
+
void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) {
Common::Rect area = r;
@@ -890,7 +1122,35 @@ void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rec
}
}
+void ThemeEngine::queueABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha) {
+
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+
+ ThemeItemABitmap *q = new ThemeItemABitmap(this, area, bitmap, autoscale, alpha);
+
+ if (_buffering) {
+ _screenQueue.push_back(q);
+ } else {
+ q->drawSelf(true, false);
+ delete q;
+ }
+}
+
+void ThemeEngine::queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &r, const Common::Rect &clip, bool alpha) {
+ Common::Rect area = r;
+ area.clip(_screen.w, _screen.h);
+
+ ThemeItemBitmapClip *q = new ThemeItemBitmapClip(this, area, clip, bitmap, alpha);
+
+ if (_buffering) {
+ _screenQueue.push_back(q);
+ } else {
+ q->drawSelf(true, false);
+ delete q;
+ }
+}
/**********************************************************
* Widget drawing functions
@@ -914,6 +1174,25 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, WidgetStateInfo state, uint16 hints) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDButtonIdle;
+
+ if (state == kStateEnabled)
+ dd = kDDButtonIdle;
+ else if (state == kStateHighlight)
+ dd = kDDButtonHover;
+ else if (state == kStateDisabled)
+ dd = kDDButtonDisabled;
+ else if (state == kStatePressed)
+ dd = kDDButtonPressed;
+
+ queueDDClip(dd, r, clippingRect, 0, hints & WIDGET_CLEARBG);
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r, clippingRect, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
if (!ready())
return;
@@ -921,6 +1200,13 @@ void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state
queueDD(kDDSeparator, r);
}
+void ThemeEngine::drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingRect, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDSeparator, r, clippingRect);
+}
+
void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
if (!ready())
return;
@@ -947,6 +1233,32 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawCheckboxClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &str, bool checked, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ Common::Rect r2 = r;
+ DrawData dd = kDDCheckboxDefault;
+
+ if (checked)
+ dd = kDDCheckboxSelected;
+
+ if (state == kStateDisabled)
+ dd = kDDCheckboxDisabled;
+
+ const int checkBoxSize = MIN((int)r.height(), getFontHeight());
+
+ r2.bottom = r2.top + checkBoxSize;
+ r2.right = r2.left + checkBoxSize;
+
+ queueDDClip(dd, r2, clip);
+
+ r2.left = r2.right + checkBoxSize;
+ r2.right = r.right;
+
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r2, clip, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
if (!ready())
return;
@@ -973,6 +1285,32 @@ void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &s
queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, bool checked, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ Common::Rect r2 = r;
+ DrawData dd = kDDRadiobuttonDefault;
+
+ if (checked)
+ dd = kDDRadiobuttonSelected;
+
+ if (state == kStateDisabled)
+ dd = kDDRadiobuttonDisabled;
+
+ const int checkBoxSize = MIN((int)r.height(), getFontHeight());
+
+ r2.bottom = r2.top + checkBoxSize;
+ r2.right = r2.left + checkBoxSize;
+
+ queueDDClip(dd, r2, clippingRect);
+
+ r2.left = r2.right + checkBoxSize;
+ r2.right = r.right;
+
+ queueDDTextClip(getTextData(dd), getTextColor(dd), r2, clippingRect, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
if (!ready())
return;
@@ -993,6 +1331,26 @@ void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo s
queueDD(dd, r2);
}
+void ThemeEngine::drawSliderClip(const Common::Rect &r, const Common::Rect &clip, int width, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDSliderFull;
+
+ if (state == kStateHighlight)
+ dd = kDDSliderHover;
+ else if (state == kStateDisabled)
+ dd = kDDSliderDisabled;
+
+ Common::Rect r2 = r;
+ r2.setWidth(MIN((int16)width, r.width()));
+ // r2.top++; r2.bottom--; r2.left++; r2.right--;
+
+ drawWidgetBackgroundClip(r, clip, 0, kWidgetBackgroundSlider, kStateEnabled);
+
+ queueDDClip(dd, r2, clip);
+}
+
void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
if (!ready())
return;
@@ -1014,11 +1372,34 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe
r2.top += sliderY;
r2.bottom = r2.top + sliderHeight;
- r2.top += r.width() / 5;
- r2.bottom -= r.width() / 5;
+ //r2.top += r.width() / 5;
+ //r2.bottom -= r.width() / 5;
queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2);
}
+void ThemeEngine::drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDScrollbarBase, r, clippingRect);
+
+ Common::Rect r2 = r;
+ const int buttonExtra = (r.width() * 120) / 100;
+
+ r2.bottom = r2.top + buttonExtra;
+ queueDDClip(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleUp);
+
+ r2.translate(0, r.height() - r2.height());
+ queueDDClip(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleDown);
+
+ r2 = r;
+ r2.left += 1;
+ r2.right -= 1;
+ r2.top += sliderY;
+ r2.bottom = r2.top + sliderHeight;
+ queueDDClip(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2, clippingRect);
+}
+
void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) {
if (!ready())
return;
@@ -1043,6 +1424,38 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b
case kDialogBackgroundDefault:
queueDD(kDDDefaultBackground, r);
break;
+ case kDialogBackgroundNone:
+ break;
+ }
+}
+
+void ThemeEngine::drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground bgtype, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ switch (bgtype) {
+ case kDialogBackgroundMain:
+ queueDDClip(kDDMainDialogBackground, r, clip);
+ break;
+
+ case kDialogBackgroundSpecial:
+ queueDDClip(kDDSpecialColorBackground, r, clip);
+ break;
+
+ case kDialogBackgroundPlain:
+ queueDDClip(kDDPlainColorBackground, r, clip);
+ break;
+
+ case kDialogBackgroundTooltip:
+ queueDDClip(kDDTooltipBackground, r, clip);
+ break;
+
+ case kDialogBackgroundDefault:
+ queueDDClip(kDDDefaultBackground, r, clip);
+ break;
+ case kDialogBackgroundNone:
+ // no op
+ break;
}
}
@@ -1057,6 +1470,17 @@ void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo s
queueDD(kDDCaret, r);
}
+void ThemeEngine::drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ if (erase) {
+ restoreBackground(r);
+ addDirtyRect(r);
+ } else
+ queueDDClip(kDDCaret, r, clip);
+}
+
void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
if (!ready())
return;
@@ -1078,6 +1502,27 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s
}
}
+void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
+ if (!ready())
+ return;
+
+ DrawData dd = kDDPopUpIdle;
+
+ if (state == kStateEnabled)
+ dd = kDDPopUpIdle;
+ else if (state == kStateHighlight)
+ dd = kDDPopUpHover;
+ else if (state == kStateDisabled)
+ dd = kDDPopUpDisabled;
+
+ queueDDClip(dd, r, clip);
+
+ if (!sel.empty()) {
+ Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
+ queueDDTextClip(getTextData(dd), getTextColor(dd), text, clip, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
+ }
+}
+
void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
if (!ready())
return;
@@ -1085,6 +1530,20 @@ void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &su
queueBitmap(&surface, r, themeTrans);
}
+void ThemeEngine::drawASurface(const Common::Rect &r, Graphics::TransparentSurface &surface, AutoScaleMode autoscale, int alpha) {
+ if (!ready())
+ return;
+
+ queueABitmap(&surface, r, autoscale, alpha);
+}
+
+void ThemeEngine::drawSurfaceClip(const Common::Rect &r, const Common::Rect &clip, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
+ if (!ready())
+ return;
+
+ queueBitmapClip(&surface, r, clip, themeTrans);
+}
+
void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
if (!ready())
return;
@@ -1108,6 +1567,29 @@ void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, Widg
}
}
+void ThemeEngine::drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clip, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ switch (background) {
+ case kWidgetBackgroundBorderSmall:
+ queueDDClip(kDDWidgetBackgroundSmall, r, clip);
+ break;
+
+ case kWidgetBackgroundEditText:
+ queueDDClip(kDDWidgetBackgroundEditText, r, clip);
+ break;
+
+ case kWidgetBackgroundSlider:
+ queueDDClip(kDDWidgetBackgroundSlider, r, clip);
+ break;
+
+ default:
+ queueDDClip(kDDWidgetBackgroundDefault, r, clip);
+ break;
+ }
+}
+
void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
if (!ready())
return;
@@ -1136,6 +1618,34 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
}
}
+void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
+ if (!ready())
+ return;
+
+ queueDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip);
+
+ for (int i = 0; i < (int)tabs.size(); ++i) {
+ if (i == active)
+ continue;
+
+ if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
+ continue;
+
+ Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
+ queueDDClip(kDDTabInactive, tabRect, clip);
+ queueDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
+ }
+
+ if (active >= 0 &&
+ (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
+ Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
+ const uint16 tabLeft = active * tabWidth;
+ const uint16 tabRight = MAX(r.right - tabRect.right, 0);
+ queueDDClip(kDDTabActive, tabRect, clip, (tabLeft << 16) | (tabRight & 0xFFFF));
+ queueDDTextClip(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, clip, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
+ }
+}
+
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
if (!ready())
return;
@@ -1209,6 +1719,79 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
}
+void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
+ if (!ready())
+ return;
+
+ TextColor colorId = kTextColorMAX;
+
+ switch (color) {
+ case kFontColorNormal:
+ if (inverted) {
+ colorId = kTextColorNormalInverted;
+ } else {
+ switch (state) {
+ case kStateDisabled:
+ colorId = kTextColorNormalDisabled;
+ break;
+
+ case kStateHighlight:
+ colorId = kTextColorNormalHover;
+ break;
+
+ case kStateEnabled:
+ case kStatePressed:
+ colorId = kTextColorNormal;
+ break;
+ }
+ }
+ break;
+
+ case kFontColorAlternate:
+ if (inverted) {
+ colorId = kTextColorAlternativeInverted;
+ } else {
+ switch (state) {
+ case kStateDisabled:
+ colorId = kTextColorAlternativeDisabled;
+ break;
+
+ case kStateHighlight:
+ colorId = kTextColorAlternativeHover;
+ break;
+
+ case kStateEnabled:
+ case kStatePressed:
+ colorId = kTextColorAlternative;
+ break;
+ }
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ TextData textId = fontStyleToData(font);
+
+ switch (inverted) {
+ case kTextInversion:
+ queueDDClip(kDDTextSelectionBackground, r, clippingArea);
+ restore = false;
+ break;
+
+ case kTextInversionFocus:
+ queueDDClip(kDDTextSelectionFocusBackground, r, clippingArea);
+ restore = false;
+ break;
+
+ default:
+ break;
+ }
+
+ queueDDTextClip(textId, colorId, r, clippingArea, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
+}
+
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
if (!ready())
return;
@@ -1223,6 +1806,21 @@ void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font
addDirtyRect(charArea);
}
+void ThemeEngine::drawCharClip(const Common::Rect &r, const Common::Rect &clip, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
+ if (!ready())
+ return;
+
+ Common::Rect charArea = r;
+ charArea.clip(_screen.w, _screen.h);
+ if (!clip.isEmpty()) charArea.clip(clip);
+
+ uint32 rgbColor = _overlayFormat.RGBToColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
+
+ restoreBackground(charArea);
+ font->drawChar(&_screen, ch, charArea.left, charArea.top, rgbColor);
+ addDirtyRect(charArea);
+}
+
void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
_font->drawString(&_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true);
_screen.hLine(r.left, r.top, r.right, 0xFFFF);
@@ -1259,8 +1857,15 @@ void ThemeEngine::updateScreen(bool render) {
_screenQueue.clear();
}
- if (render)
+ if (render) {
+#ifdef LAYOUT_DEBUG_DIALOG
+ _vectorRenderer->fillSurface();
+ _themeEval->debugDraw(&_screen, _font);
+ _vectorRenderer->copyWholeFrame(_system);
+#else
renderDirtyScreen();
+#endif
+ }
}
void ThemeEngine::addDirtyRect(Common::Rect r) {