diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/EventRecorder.cpp | 12 | ||||
-rw-r--r-- | gui/ThemeEngine.cpp | 687 | ||||
-rw-r--r-- | gui/ThemeEngine.h | 120 | ||||
-rw-r--r-- | gui/Tooltip.cpp | 4 | ||||
-rw-r--r-- | gui/Tooltip.h | 2 | ||||
-rw-r--r-- | gui/about.cpp | 6 | ||||
-rw-r--r-- | gui/about.h | 2 | ||||
-rw-r--r-- | gui/console.cpp | 14 | ||||
-rw-r--r-- | gui/console.h | 2 | ||||
-rw-r--r-- | gui/dialog.cpp | 3 | ||||
-rw-r--r-- | gui/dialog.h | 2 | ||||
-rw-r--r-- | gui/gui-manager.cpp | 32 | ||||
-rw-r--r-- | gui/massadd.cpp | 2 | ||||
-rw-r--r-- | gui/widgets/popup.cpp | 9 |
14 files changed, 365 insertions, 532 deletions
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp index 39811513e3..849405410a 100644 --- a/gui/EventRecorder.cpp +++ b/gui/EventRecorder.cpp @@ -557,17 +557,19 @@ Common::SaveFileManager *EventRecorder::getSaveManager(Common::SaveFileManager * } void EventRecorder::preDrawOverlayGui() { - if ((_initialized) || (_needRedraw)) { + if ((_initialized) || (_needRedraw)) { RecordMode oldMode = _recordMode; _recordMode = kPassthrough; g_system->showOverlay(); g_gui.theme()->clearAll(); - g_gui.theme()->openDialog(true, GUI::ThemeEngine::kShadingNone); - _controlPanel->drawDialog(); - g_gui.theme()->finishBuffering(); + g_gui.theme()->drawToBackbuffer(); + _controlPanel->drawDialog(kDrawLayerBackground); + g_gui.theme()->drawToScreen(); + g_gui.theme()->copyBackBufferToScreen(); + _controlPanel->drawDialog(kDrawLayerForeground); g_gui.theme()->updateScreen(); _recordMode = oldMode; - } + } } void EventRecorder::postDrawOverlayGui() { diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index cff0947775..b16a6cfe4f 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -89,7 +89,7 @@ struct WidgetDrawData { uint16 _backgroundOffset; uint16 _shadowOffset; - bool _buffer; + DrawLayer _layer; /** @@ -102,111 +102,13 @@ struct WidgetDrawData { void calcBackgroundOffset(); }; -class ThemeItem { - -public: - ThemeItem(ThemeEngine *engine, const Common::Rect &area) : - _engine(engine), _area(area) {} - virtual ~ThemeItem() {} - - virtual void drawSelf(bool doDraw, bool doRestore) = 0; - -protected: - ThemeEngine *_engine; - Common::Rect _area; -}; - -class ThemeItemDrawData : public ThemeItem { -public: - ThemeItemDrawData(ThemeEngine *engine, const WidgetDrawData *data, const Common::Rect &area, uint32 dynData) : - ThemeItem(engine, area), _dynamicData(dynData), _data(data) {} - - void drawSelf(bool draw, bool restore); - -protected: - uint32 _dynamicData; - 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, - const Common::String &text, Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, - bool ellipsis, bool restoreBg, int deltaX) : - ThemeItem(engine, area), _data(data), _color(color), _text(text), _alignH(alignH), _alignV(alignV), - _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX), _textDrawableArea(textDrawableArea) {} - - void drawSelf(bool draw, bool restore); - -protected: - Common::Rect _textDrawableArea; - const TextDrawData *_data; - const TextColorData *_color; - Common::String _text; - Graphics::TextAlign _alignH; - GUI::ThemeEngine::TextAlignVertical _alignV; - bool _ellipsis; - bool _restoreBg; - int _deltax; -}; - -class ThemeItemBitmap : public ThemeItem { -public: - ThemeItemBitmap(ThemeEngine *engine, const Common::Rect &area, const Graphics::Surface *bitmap, bool alpha) : - ThemeItem(engine, area), _bitmap(bitmap), _alpha(alpha) {} - - void drawSelf(bool draw, bool restore); - -protected: - const Graphics::Surface *_bitmap; - 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 *********************************************************/ 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. + DrawLayer layer; ///< Sets whether this item is part of the foreground or background layer of its dialog DrawData parent; ///< Parent DrawData item, for items that overlay. E.g. kDDButtonIdle -> kDDButtonHover }; @@ -214,167 +116,62 @@ struct DrawDataInfo { * Default values for each DrawData item. */ static const DrawDataInfo kDrawDataDefaults[] = { - {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, - {kDDSpecialColorBackground, "special_bg", true, kDDNone}, - {kDDPlainColorBackground, "plain_bg", true, kDDNone}, - {kDDTooltipBackground, "tooltip_bg", true, kDDNone}, - {kDDDefaultBackground, "default_bg", true, kDDNone}, - {kDDTextSelectionBackground, "text_selection", false, kDDNone}, - {kDDTextSelectionFocusBackground, "text_selection_focus", false, kDDNone}, - - {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, - {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, - {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, - {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, - - {kDDButtonIdle, "button_idle", true, kDDNone}, - {kDDButtonHover, "button_hover", false, kDDButtonIdle}, - {kDDButtonDisabled, "button_disabled", true, kDDNone}, - {kDDButtonPressed, "button_pressed", false, kDDButtonIdle}, - - {kDDSliderFull, "slider_full", false, kDDNone}, - {kDDSliderHover, "slider_hover", false, kDDNone}, - {kDDSliderDisabled, "slider_disabled", false, kDDNone}, - - {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, - {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, - {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, - - {kDDRadiobuttonDefault, "radiobutton_default", true, kDDNone}, - {kDDRadiobuttonDisabled, "radiobutton_disabled", true, kDDNone}, - {kDDRadiobuttonSelected, "radiobutton_selected", false, kDDRadiobuttonDefault}, - - {kDDTabActive, "tab_active", false, kDDTabInactive}, - {kDDTabInactive, "tab_inactive", true, kDDNone}, - {kDDTabBackground, "tab_background", true, kDDNone}, - - {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, - - {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone}, - {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle}, - - {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone}, - {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase}, - - {kDDPopUpIdle, "popup_idle", true, kDDNone}, - {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, - {kDDPopUpDisabled, "popup_disabled", true, kDDNone}, - - {kDDCaret, "caret", false, kDDNone}, - {kDDSeparator, "separator", true, kDDNone}, + {kDDMainDialogBackground, "mainmenu_bg", kDrawLayerBackground, kDDNone}, + {kDDSpecialColorBackground, "special_bg", kDrawLayerBackground, kDDNone}, + {kDDPlainColorBackground, "plain_bg", kDrawLayerBackground, kDDNone}, + {kDDTooltipBackground, "tooltip_bg", kDrawLayerBackground, kDDNone}, + {kDDDefaultBackground, "default_bg", kDrawLayerBackground, kDDNone}, + {kDDTextSelectionBackground, "text_selection", kDrawLayerForeground, kDDNone}, + {kDDTextSelectionFocusBackground, "text_selection_focus", kDrawLayerForeground, kDDNone}, + + {kDDWidgetBackgroundDefault, "widget_default", kDrawLayerBackground, kDDNone}, + {kDDWidgetBackgroundSmall, "widget_small", kDrawLayerBackground, kDDNone}, + {kDDWidgetBackgroundEditText, "widget_textedit", kDrawLayerBackground, kDDNone}, + {kDDWidgetBackgroundSlider, "widget_slider", kDrawLayerBackground, kDDNone}, + + {kDDButtonIdle, "button_idle", kDrawLayerBackground, kDDNone}, + {kDDButtonHover, "button_hover", kDrawLayerForeground, kDDButtonIdle}, + {kDDButtonDisabled, "button_disabled", kDrawLayerBackground, kDDNone}, + {kDDButtonPressed, "button_pressed", kDrawLayerForeground, kDDButtonIdle}, + + {kDDSliderFull, "slider_full", kDrawLayerForeground, kDDNone}, + {kDDSliderHover, "slider_hover", kDrawLayerForeground, kDDNone}, + {kDDSliderDisabled, "slider_disabled", kDrawLayerForeground, kDDNone}, + + {kDDCheckboxDefault, "checkbox_default", kDrawLayerBackground, kDDNone}, + {kDDCheckboxDisabled, "checkbox_disabled", kDrawLayerBackground, kDDNone}, + {kDDCheckboxSelected, "checkbox_selected", kDrawLayerForeground, kDDCheckboxDefault}, + + {kDDRadiobuttonDefault, "radiobutton_default", kDrawLayerBackground, kDDNone}, + {kDDRadiobuttonDisabled, "radiobutton_disabled", kDrawLayerBackground, kDDNone}, + {kDDRadiobuttonSelected, "radiobutton_selected", kDrawLayerForeground, kDDRadiobuttonDefault}, + + {kDDTabActive, "tab_active", kDrawLayerForeground, kDDTabInactive}, + {kDDTabInactive, "tab_inactive", kDrawLayerBackground, kDDNone}, + {kDDTabBackground, "tab_background", kDrawLayerBackground, kDDNone}, + + {kDDScrollbarBase, "scrollbar_base", kDrawLayerBackground, kDDNone}, + + {kDDScrollbarButtonIdle, "scrollbar_button_idle", kDrawLayerBackground, kDDNone}, + {kDDScrollbarButtonHover, "scrollbar_button_hover", kDrawLayerForeground, kDDScrollbarButtonIdle}, + + {kDDScrollbarHandleIdle, "scrollbar_handle_idle", kDrawLayerForeground, kDDNone}, + {kDDScrollbarHandleHover, "scrollbar_handle_hover", kDrawLayerForeground, kDDScrollbarBase}, + + {kDDPopUpIdle, "popup_idle", kDrawLayerBackground, kDDNone}, + {kDDPopUpHover, "popup_hover", kDrawLayerForeground, kDDPopUpIdle}, + {kDDPopUpDisabled, "popup_disabled", kDrawLayerBackground, kDDNone}, + + {kDDCaret, "caret", kDrawLayerForeground, kDDNone}, + {kDDSeparator, "separator", kDrawLayerBackground, kDDNone}, }; - -/********************************************************** - * ThemeItem functions for drawing queues. - *********************************************************/ -void ThemeItemDrawData::drawSelf(bool draw, bool restore) { - - Common::Rect extendedRect = _area; - extendedRect.grow(_engine->kDirtyRectangleThreshold + _data->_backgroundOffset); - if (_data->_shadowOffset > _data->_backgroundOffset) { - extendedRect.right += _data->_shadowOffset - _data->_backgroundOffset; - extendedRect.bottom += _data->_shadowOffset - _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()->drawStep(_area, *step, _dynamicData); - } - - _engine->addDirtyRect(extendedRect); -} - -void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) { - - Common::Rect extendedRect = _area; - extendedRect.grow(_engine->kDirtyRectangleThreshold + _data->_backgroundOffset); - if (_data->_shadowOffset > _data->_backgroundOffset) { - extendedRect.right += _data->_shadowOffset - _data->_backgroundOffset; - extendedRect.bottom += _data->_shadowOffset - _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(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(dirty); -} - -void ThemeItemBitmap::drawSelf(bool draw, bool restore) { - if (restore) - _engine->restoreBackground(_area); - - if (draw) { - if (_alpha) - _engine->renderer()->blitKeyBitmap(_bitmap, _area); - else - _engine->renderer()->blitSubSurface(_bitmap, _area); - } - - _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 *********************************************************/ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) : _system(0), _vectorRenderer(0), - _buffering(false), _bytesPerPixel(0), _graphicsMode(kGfxDisabled), + _layerToDraw(kDrawLayerBackground), _bytesPerPixel(0), _graphicsMode(kGfxDisabled), _font(0), _initOk(false), _themeOk(false), _enabled(false), _themeFiles(), _cursor(0) { @@ -555,7 +352,7 @@ bool ThemeEngine::init() { void ThemeEngine::clearAll() { if (_initOk) { _system->clearOverlay(); - _system->grabOverlay(_screen.getPixels(), _screen.pitch); + _system->grabOverlay(_backBuffer.getPixels(), _backBuffer.pitch); } } @@ -671,8 +468,15 @@ void WidgetDrawData::calcBackgroundOffset() { } void ThemeEngine::restoreBackground(Common::Rect r) { + if (_vectorRenderer->getActiveSurface() == &_backBuffer) { + // Only restore the background when drawing to the screen surface + return; + } + r.clip(_screen.w, _screen.h); _vectorRenderer->blitSurface(&_backBuffer, r); + + addDirtyRect(r); } @@ -871,7 +675,7 @@ bool ThemeEngine::addDrawData(const Common::String &data, bool cached) { delete _widgets[id]; _widgets[id] = new WidgetDrawData; - _widgets[id]->_buffer = kDrawDataDefaults[id].buffer; + _widgets[id]->_layer = kDrawDataDefaults[id].layer; _widgets[id]->_textDataId = kTextDataNone; return true; @@ -1028,143 +832,167 @@ bool ThemeEngine::loadThemeXML(const Common::String &themeId) { /********************************************************** - * Drawing Queue management + * Draw Date descriptors drawing functions *********************************************************/ -void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic, bool restore) { - if (_widgets[type] == 0) +void ThemeEngine::drawDD(DrawData type, const Common::Rect &r, uint32 dynamic, bool forceRestore) { + WidgetDrawData *drawData = _widgets[type]; + + if (!drawData) return; + if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) + drawDD(kDrawDataDefaults[type].parent, r); + Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, dynamic); + Common::Rect extendedRect = area; + extendedRect.grow(kDirtyRectangleThreshold + drawData->_backgroundOffset); + if (drawData->_shadowOffset > drawData->_backgroundOffset) { + extendedRect.right += drawData->_shadowOffset - drawData->_backgroundOffset; + extendedRect.bottom += drawData->_shadowOffset - drawData->_backgroundOffset; + } - if (_buffering) { - if (_widgets[type]->_buffer) { - _bufferQueue.push_back(q); - } else { - if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) - queueDD(kDrawDataDefaults[type].parent, r); + if (forceRestore || drawData->_layer == kDrawLayerBackground) + restoreBackground(extendedRect); - _screenQueue.push_back(q); - } - } else { - q->drawSelf(!_widgets[type]->_buffer, restore || _widgets[type]->_buffer); - delete q; + if (drawData->_layer == _layerToDraw) { + Common::List<Graphics::DrawStep>::const_iterator step; + for (step = drawData->_steps.begin(); step != drawData->_steps.end(); ++step) + _vectorRenderer->drawStep(area, *step, dynamic); + + addDirtyRect(extendedRect); } } -void ThemeEngine::queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic, bool restore) { - if (_widgets[type] == 0) +void ThemeEngine::drawDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic, + bool forceRestore) { + WidgetDrawData *drawData = _widgets[type]; + + if (!drawData) return; + if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) + drawDDClip(kDrawDataDefaults[type].parent, r, clippingRect); + Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemDrawDataClip *q = new ThemeItemDrawDataClip(this, _widgets[type], area, clippingRect, dynamic); + Common::Rect extendedRect = area; + extendedRect.grow(kDirtyRectangleThreshold + drawData->_backgroundOffset); + if (drawData->_shadowOffset > drawData->_backgroundOffset) { + extendedRect.right += drawData->_shadowOffset - drawData->_backgroundOffset; + extendedRect.bottom += drawData->_shadowOffset - drawData->_backgroundOffset; + } + extendedRect.clip(clippingRect); - 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); + if (forceRestore || drawData->_layer == kDrawLayerBackground) + restoreBackground(extendedRect); - _screenQueue.push_back(q); + if (drawData->_layer == _layerToDraw) { + Common::List<Graphics::DrawStep>::const_iterator step; + for (step = drawData->_steps.begin(); step != drawData->_steps.end(); ++step) { + _vectorRenderer->drawStepClip(area, clippingRect, *step, dynamic); } - } else { - q->drawSelf(!_widgets[type]->_buffer, restore || _widgets[type]->_buffer); - delete q; + + addDirtyRect(extendedRect); } } -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) { +void ThemeEngine::drawDDText(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 (type == kTextDataNone || _texts[type] == 0) + if (type == kTextDataNone || !_texts[type] || _layerToDraw == kDrawLayerBackground) return; Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, drawableTextArea, text, alignH, alignV, ellipsis, restoreBg, deltax); + Common::Rect dirty = drawableTextArea; + if (dirty.isEmpty()) dirty = area; + else dirty.clip(area); - if (_buffering) { - _screenQueue.push_back(q); - } else { - q->drawSelf(true, false); - delete q; - } + if (restoreBg) + restoreBackground(dirty); + + _vectorRenderer->setFgColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b); + _vectorRenderer->drawString(_texts[type]->_fontPtr, text, area, alignH, alignV, deltax, ellipsis, drawableTextArea); + + addDirtyRect(dirty); } -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) { +void ThemeEngine::drawDDTextClip(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) + if (type == kTextDataNone || !_texts[type] || _layerToDraw == kDrawLayerBackground) 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); + Common::Rect dirty = drawableTextArea; + if (dirty.isEmpty()) dirty = area; + else dirty.clip(area); - if (_buffering) { - _screenQueue.push_back(q); - } else { - q->drawSelf(true, false); - delete q; - } + dirty.clip(clippingArea); + + // HACK: One small pixel should be invisible enough + if (dirty.isEmpty()) dirty = Common::Rect(0, 0, 1, 1); + + if (restoreBg) + restoreBackground(dirty); + + _vectorRenderer->setFgColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b); + _vectorRenderer->drawString(_texts[type]->_fontPtr, text, area, alignH, alignV, deltax, ellipsis, dirty); + + addDirtyRect(dirty); } -void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) { +void ThemeEngine::drawBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) { + if (_layerToDraw == kDrawLayerBackground) + return; Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemBitmap *q = new ThemeItemBitmap(this, area, bitmap, alpha); + if (alpha) + _vectorRenderer->blitKeyBitmap(bitmap, r); + else + _vectorRenderer->blitSubSurface(bitmap, r); - if (_buffering) { - _screenQueue.push_back(q); - } else { - q->drawSelf(true, false); - delete q; - } + addDirtyRect(r); } -void ThemeEngine::queueABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha) { +void ThemeEngine::drawABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha) { + if (_layerToDraw == kDrawLayerBackground) + return; Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemABitmap *q = new ThemeItemABitmap(this, area, bitmap, autoscale, alpha); + _vectorRenderer->blitAlphaBitmap(bitmap, area, autoscale, Graphics::DrawStep::kVectorAlignManual, Graphics::DrawStep::kVectorAlignManual, alpha); - if (_buffering) { - _screenQueue.push_back(q); - } else { - q->drawSelf(true, false); - delete q; - } + addDirtyRect(area); } -void ThemeEngine::queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &r, const Common::Rect &clip, bool alpha) { +void ThemeEngine::drawBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &r, const Common::Rect &clip, bool alpha) { + if (_layerToDraw == kDrawLayerBackground) + return; Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemBitmapClip *q = new ThemeItemBitmapClip(this, area, clip, bitmap, alpha); + if (alpha) + _vectorRenderer->blitKeyBitmapClip(bitmap, area, clip); + else + _vectorRenderer->blitSubSurfaceClip(bitmap, area, clip); - if (_buffering) { - _screenQueue.push_back(q); - } else { - q->drawSelf(true, false); - delete q; - } + Common::Rect dirtyRect = area; + dirtyRect.clip(clip); + addDirtyRect(dirtyRect); } /********************************************************** @@ -1185,8 +1013,8 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W else if (state == kStatePressed) dd = kDDButtonPressed; - queueDD(dd, r, 0, hints & WIDGET_CLEARBG); - queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + drawDD(dd, r, 0, hints & WIDGET_CLEARBG); + drawDDText(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) { @@ -1204,22 +1032,22 @@ void ThemeEngine::drawButtonClip(const Common::Rect &r, const Common::Rect &clip 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); + drawDDClip(dd, r, clippingRect, 0, hints & WIDGET_CLEARBG); + drawDDTextClip(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; - queueDD(kDDSeparator, r); + drawDD(kDDSeparator, r); } void ThemeEngine::drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingRect, WidgetStateInfo state) { if (!ready()) return; - queueDDClip(kDDSeparator, r, clippingRect); + drawDDClip(kDDSeparator, r, clippingRect); } void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { @@ -1240,12 +1068,12 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - queueDD(dd, r2); + drawDD(dd, r2); r2.left = r2.right + checkBoxSize; r2.right = r.right; - queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); + drawDDText(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) { @@ -1266,12 +1094,12 @@ void ThemeEngine::drawCheckboxClip(const Common::Rect &r, const Common::Rect &cl r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - queueDDClip(dd, r2, clip); + drawDDClip(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); + drawDDTextClip(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) { @@ -1292,12 +1120,12 @@ void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &s r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - queueDD(dd, r2); + drawDD(dd, r2); r2.left = r2.right + checkBoxSize; r2.right = r.right; - queueDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV); + drawDDText(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) { @@ -1318,12 +1146,12 @@ void ThemeEngine::drawRadiobuttonClip(const Common::Rect &r, const Common::Rect r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - queueDDClip(dd, r2, clippingRect); + drawDDClip(dd, r2, clippingRect); r2.left = r2.right + checkBoxSize; r2.right = MAX(r2.left, r.right); - queueDDTextClip(getTextData(dd), getTextColor(dd), r2, clippingRect, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV); + drawDDTextClip(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) { @@ -1343,7 +1171,7 @@ void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo s drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); - queueDD(dd, r2); + drawDD(dd, r2); } void ThemeEngine::drawSliderClip(const Common::Rect &r, const Common::Rect &clip, int width, WidgetStateInfo state) { @@ -1363,23 +1191,23 @@ void ThemeEngine::drawSliderClip(const Common::Rect &r, const Common::Rect &clip drawWidgetBackgroundClip(r, clip, 0, kWidgetBackgroundSlider, kStateEnabled); - queueDDClip(dd, r2, clip); + drawDDClip(dd, r2, clip); } void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { if (!ready()) return; - queueDD(kDDScrollbarBase, r); + drawDD(kDDScrollbarBase, r); Common::Rect r2 = r; const int buttonExtra = (r.width() * 120) / 100; r2.bottom = r2.top + buttonExtra; - queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); + drawDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); r2.translate(0, r.height() - r2.height()); - queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); + drawDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); r2 = r; r2.left += 1; @@ -1389,30 +1217,30 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe //r2.top += r.width() / 5; //r2.bottom -= r.width() / 5; - queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); + drawDD(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); + drawDDClip(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); + drawDDClip(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); + drawDDClip(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); + drawDDClip(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2, clippingRect); } void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) { @@ -1421,23 +1249,23 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b switch (bgtype) { case kDialogBackgroundMain: - queueDD(kDDMainDialogBackground, r); + drawDD(kDDMainDialogBackground, r); break; case kDialogBackgroundSpecial: - queueDD(kDDSpecialColorBackground, r); + drawDD(kDDSpecialColorBackground, r); break; case kDialogBackgroundPlain: - queueDD(kDDPlainColorBackground, r); + drawDD(kDDPlainColorBackground, r); break; case kDialogBackgroundTooltip: - queueDD(kDDTooltipBackground, r); + drawDD(kDDTooltipBackground, r); break; case kDialogBackgroundDefault: - queueDD(kDDDefaultBackground, r); + drawDD(kDDDefaultBackground, r); break; case kDialogBackgroundNone: break; @@ -1450,23 +1278,23 @@ void ThemeEngine::drawDialogBackgroundClip(const Common::Rect &r, const Common:: switch (bgtype) { case kDialogBackgroundMain: - queueDDClip(kDDMainDialogBackground, r, clip); + drawDDClip(kDDMainDialogBackground, r, clip); break; case kDialogBackgroundSpecial: - queueDDClip(kDDSpecialColorBackground, r, clip); + drawDDClip(kDDSpecialColorBackground, r, clip); break; case kDialogBackgroundPlain: - queueDDClip(kDDPlainColorBackground, r, clip); + drawDDClip(kDDPlainColorBackground, r, clip); break; case kDialogBackgroundTooltip: - queueDDClip(kDDTooltipBackground, r, clip); + drawDDClip(kDDTooltipBackground, r, clip); break; case kDialogBackgroundDefault: - queueDDClip(kDDDefaultBackground, r, clip); + drawDDClip(kDDDefaultBackground, r, clip); break; case kDialogBackgroundNone: // no op @@ -1480,9 +1308,8 @@ void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo s if (erase) { restoreBackground(r); - addDirtyRect(r); } else - queueDD(kDDCaret, r); + drawDD(kDDCaret, r); } void ThemeEngine::drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase, WidgetStateInfo state) { @@ -1491,9 +1318,8 @@ void ThemeEngine::drawCaretClip(const Common::Rect &r, const Common::Rect &clip, if (erase) { restoreBackground(r); - addDirtyRect(r); } else - queueDDClip(kDDCaret, r, clip); + drawDDClip(kDDCaret, r, clip); } void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) { @@ -1509,11 +1335,11 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s else if (state == kStateDisabled) dd = kDDPopUpDisabled; - queueDD(dd, r); + drawDD(dd, r); if (!sel.empty()) { Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom); - queueDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); + drawDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); } } @@ -1530,11 +1356,11 @@ void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect else if (state == kStateDisabled) dd = kDDPopUpDisabled; - queueDDClip(dd, r, clip); + drawDDClip(dd, r, clip); if (!sel.empty() && r.width() >= 13 && r.height() >= 1) { 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); + drawDDTextClip(getTextData(dd), getTextColor(dd), text, clip, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); } } @@ -1542,21 +1368,21 @@ void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &su if (!ready()) return; - queueBitmap(&surface, r, themeTrans); + drawBitmap(&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); + drawABitmap(&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); + drawBitmapClip(&surface, r, clip, themeTrans); } void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { @@ -1565,19 +1391,19 @@ void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, Widg switch (background) { case kWidgetBackgroundBorderSmall: - queueDD(kDDWidgetBackgroundSmall, r); + drawDD(kDDWidgetBackgroundSmall, r); break; case kWidgetBackgroundEditText: - queueDD(kDDWidgetBackgroundEditText, r); + drawDD(kDDWidgetBackgroundEditText, r); break; case kWidgetBackgroundSlider: - queueDD(kDDWidgetBackgroundSlider, r); + drawDD(kDDWidgetBackgroundSlider, r); break; default: - queueDD(kDDWidgetBackgroundDefault, r); + drawDD(kDDWidgetBackgroundDefault, r); break; } } @@ -1588,19 +1414,19 @@ void ThemeEngine::drawWidgetBackgroundClip(const Common::Rect &r, const Common:: switch (background) { case kWidgetBackgroundBorderSmall: - queueDDClip(kDDWidgetBackgroundSmall, r, clip); + drawDDClip(kDDWidgetBackgroundSmall, r, clip); break; case kWidgetBackgroundEditText: - queueDDClip(kDDWidgetBackgroundEditText, r, clip); + drawDDClip(kDDWidgetBackgroundEditText, r, clip); break; case kWidgetBackgroundSlider: - queueDDClip(kDDWidgetBackgroundSlider, r, clip); + drawDDClip(kDDWidgetBackgroundSlider, r, clip); break; default: - queueDDClip(kDDWidgetBackgroundDefault, r, clip); + drawDDClip(kDDWidgetBackgroundDefault, r, clip); break; } } @@ -1609,7 +1435,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co if (!ready()) return; - queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); + drawDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); for (int i = 0; i < (int)tabs.size(); ++i) { if (i == active) @@ -1619,8 +1445,8 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co continue; Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight); - queueDD(kDDTabInactive, tabRect); - queueDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); + drawDD(kDDTabInactive, tabRect); + drawDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); } if (active >= 0 && @@ -1628,8 +1454,8 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co 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); - queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); - queueDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); + drawDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); + drawDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); } } @@ -1639,7 +1465,7 @@ void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, i assert(tabs.size() == tabWidths.size()); - queueDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip); + drawDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip); int width = 0; int activePos = -1; @@ -1654,16 +1480,16 @@ void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, i Common::Rect tabRect(r.left + width, r.top, r.left + width + tabWidths[i], r.top + tabHeight); - queueDDClip(kDDTabInactive, tabRect, clip); - queueDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); + drawDDClip(kDDTabInactive, tabRect, clip); + drawDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); } if (activePos >= 0) { Common::Rect tabRect(r.left + activePos, r.top, r.left + activePos + tabWidths[active], r.top + tabHeight); const uint16 tabLeft = activePos; 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); + drawDDClip(kDDTabActive, tabRect, clip, (tabLeft << 16) | (tabRight & 0xFFFF)); + drawDDTextClip(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, clip, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); } } @@ -1724,12 +1550,12 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid switch (inverted) { case kTextInversion: - queueDD(kDDTextSelectionBackground, r); + drawDD(kDDTextSelectionBackground, r); restore = false; break; case kTextInversionFocus: - queueDD(kDDTextSelectionFocusBackground, r); + drawDD(kDDTextSelectionFocusBackground, r); restore = false; break; @@ -1737,7 +1563,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid break; } - queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea); + drawDDText(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) { @@ -1797,12 +1623,12 @@ void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippi switch (inverted) { case kTextInversion: - queueDDClip(kDDTextSelectionBackground, r, clippingArea); + drawDDClip(kDDTextSelectionBackground, r, clippingArea); restore = false; break; case kTextInversionFocus: - queueDDClip(kDDTextSelectionFocusBackground, r, clippingArea); + drawDDClip(kDDTextSelectionFocusBackground, r, clippingArea); restore = false; break; @@ -1810,7 +1636,7 @@ void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippi break; } - queueDDTextClip(textId, colorId, r, clippingArea, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea); + drawDDTextClip(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) { @@ -1853,40 +1679,18 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { /********************************************************** * Screen/overlay management *********************************************************/ -void ThemeEngine::updateScreen(bool render) { - if (!_bufferQueue.empty()) { - _vectorRenderer->setSurface(&_backBuffer); - - for (Common::List<ThemeItem *>::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) { - (*q)->drawSelf(true, false); - delete *q; - } - - _vectorRenderer->setSurface(&_screen); - memcpy(_screen.getPixels(), _backBuffer.getPixels(), _screen.pitch * _screen.h); - _bufferQueue.clear(); - } - - if (!_screenQueue.empty()) { - _vectorRenderer->disableShadows(); - for (Common::List<ThemeItem *>::iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) { - (*q)->drawSelf(true, false); - delete *q; - } - - _vectorRenderer->enableShadows(); - _screenQueue.clear(); - } +void ThemeEngine::copyBackBufferToScreen() { + memcpy(_screen.getPixels(), _backBuffer.getPixels(), _screen.pitch * _screen.h); +} - if (render) { +void ThemeEngine::updateScreen() { #ifdef LAYOUT_DEBUG_DIALOG - _vectorRenderer->fillSurface(); - _themeEval->debugDraw(&_screen, _font); - _vectorRenderer->copyWholeFrame(_system); + _vectorRenderer->fillSurface(); + _themeEval->debugDraw(&_screen, _font); + _vectorRenderer->copyWholeFrame(_system); #else - renderDirtyScreen(); + updateDirtyScreen(); #endif - } } void ThemeEngine::addDirtyRect(Common::Rect r) { @@ -1917,7 +1721,7 @@ void ThemeEngine::addDirtyRect(Common::Rect r) { _dirtyScreen.push_back(r); } -void ThemeEngine::renderDirtyScreen() { +void ThemeEngine::updateDirtyScreen() { if (_dirtyScreen.empty()) return; @@ -1929,17 +1733,11 @@ void ThemeEngine::renderDirtyScreen() { _dirtyScreen.clear(); } -void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) { - if (doBuffer) - _buffering = true; - +void ThemeEngine::applyScreenShading(ShadingStyle style) { if (style != kShadingNone) { _vectorRenderer->applyScreenShading(style); addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h)); } - - memcpy(_backBuffer.getPixels(), _screen.getPixels(), _screen.pitch * _screen.h); - _vectorRenderer->setSurface(&_screen); } bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY) { @@ -2476,5 +2274,12 @@ void ThemeEngine::hideCursor() { } } +void ThemeEngine::drawToBackbuffer() { + _vectorRenderer->setSurface(&_backBuffer); +} + +void ThemeEngine::drawToScreen() { + _vectorRenderer->setSurface(&_screen); +} } // End of namespace GUI. diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 9d8ed41738..5675f0c5d7 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -54,7 +54,6 @@ struct TextColorData; class Dialog; class GuiObject; class ThemeEval; -class ThemeItem; class ThemeParser; /** @@ -113,6 +112,18 @@ enum DrawData { kDDNone = -1 }; +/** + * Dialog layers. + * The currently active dialog has two layers, background and foreground. + * The background layer is drawn to the backbuffer. The foreground layer + * is drawn to the screen. This allows draw calls to restore the background + * layer before redrawing a widget. + */ +enum DrawLayer { + kDrawLayerBackground, + kDrawLayerForeground +}; + // FIXME: TextData is really a bad name, not conveying what this enum is about. enum TextData { kTextDataNone = -1, @@ -308,22 +319,38 @@ public: const Graphics::PixelFormat getPixelFormat() const { return _overlayFormat; } /** - * Implementation of the GUI::Theme API. Called when a - * new dialog is opened. Note that the boolean parameter - * meaning has been changed. + * Draw full screen shading with the supplied style + * + * This is used to dim the inactive dialogs so the active one stands out. + */ + void applyScreenShading(ShadingStyle shading); + + /** + * Sets the active drawing surface to the back buffer. + * + * All drawing from this point on will be done on that surface. + * The back buffer surface needs to be copied to the screen surface + * in order to become visible. + */ + void drawToBackbuffer(); + + /** + * Sets the active drawing surface to the screen. * - * @param enableBuffering If set to true, buffering is enabled for - * drawing this dialog, and will continue enabled - * until disabled. + * All drawing from this point on will be done on that surface. */ - void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); + void drawToScreen(); /** * The updateScreen() method is called every frame. - * It processes all the drawing queues and then copies dirty rects - * in the current Screen surface to the overlay. + * It copies dirty rectangles in the Screen surface to the overlay. */ - void updateScreen(bool render = true); + void updateScreen(); + + /** + * Copy the entire backbuffer surface to the screen surface + */ + void copyBackBufferToScreen(); /** @name FONT MANAGEMENT METHODS */ @@ -425,8 +452,8 @@ public: /** * Actual implementation of a dirty rect handling. - * Dirty rectangles are queued on a list and are later used for the - * actual drawing. + * Dirty rectangles are queued on a list, merged and optimized + * when possible and are later used for the actual drawing. * * @param r Area of the dirty rect. */ @@ -534,13 +561,6 @@ protected: void setGraphicsMode(GraphicsMode mode); public: - /** - * Finishes buffering: widgets from then on will be drawn straight on the screen - * without drawing queues. - */ - inline void finishBuffering() { _buffering = false; } - inline void startBuffering() { _buffering = true; } - inline ThemeEval *getEvaluator() { return _themeEval; } inline Graphics::VectorRenderer *renderer() { return _vectorRenderer; } @@ -623,33 +643,35 @@ protected: const Graphics::Font *loadFont(const Common::String &filename, const Common::String &scalableFilename, const Common::String &charset, const int pointsize, const bool makeLocalizedFont); /** - * Actual Dirty Screen handling function. - * Handles all the dirty squares in the list, merges and optimizes - * them when possible and draws them to the screen. - * Called from updateScreen() + * Dirty Screen handling function. + * Draws all the dirty rectangles in the list to the overlay. */ - void renderDirtyScreen(); + void updateDirtyScreen(); /** - * Generates a DrawQueue item and enqueues it so it's drawn to the screen - * when the drawing queue is processed. + * Draws a GUI element according to a DrawData descriptor. * - * If Buffering is enabled, the DrawQueue item will be automatically placed - * on its corresponding queue. - * If Buffering is disabled, the DrawQueue item will be processed immediately - * and drawn to the screen. + * Only calls with a DrawData layer attribute matching the active layer + * are actually drawn to the active surface. * - * This function is called from all the Widget Drawing methods. + * These functions are called from all the Widget drawing methods. */ - void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false); - void queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0, bool restore = false); - void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); - void queueDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &text, bool restoreBg, - bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); - void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); - void queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r, bool alpha); - void queueABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha); + void drawDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool forceRestore = false); + void drawDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0, + bool forceRestore = false); + void drawDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg, + bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, + TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, + const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); + void drawDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect, + const Common::String &text, bool restoreBg, + bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, + TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, + const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); + void drawBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); + void drawBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r, + bool alpha); + void drawABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha); /** * DEBUG: Draws a white square and writes some text next to it. @@ -695,9 +717,13 @@ protected: /** Backbuffer surface. Stores previous states of the screen to blit back */ Graphics::TransparentSurface _backBuffer; - /** Sets whether the current drawing is being buffered (stored for later - processing) or drawn directly to the screen. */ - bool _buffering; + /** + * Filter the submitted DrawData descriptors according to their layer attribute + * + * This is used to selectively draw the background or foreground layer + * of the dialogs. + */ + DrawLayer _layerToDraw; /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ int _bytesPerPixel; @@ -731,12 +757,6 @@ protected: /** List of all the dirty screens that must be blitted to the overlay. */ Common::List<Common::Rect> _dirtyScreen; - /** Queue with all the drawing that must be done to the Back Buffer */ - Common::List<ThemeItem *> _bufferQueue; - - /** Queue with all the drawing that must be done to the screen */ - Common::List<ThemeItem *> _screenQueue; - bool _initOk; ///< Class and renderer properly initialized bool _themeOk; ///< Theme data successfully loaded. bool _enabled; ///< Whether the Theme is currently shown on the overlay diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp index 09ad7ce5ca..bcaa8cee2a 100644 --- a/gui/Tooltip.cpp +++ b/gui/Tooltip.cpp @@ -56,11 +56,11 @@ void Tooltip::setup(Dialog *parent, Widget *widget, int x, int y) { _y = MIN<int16>(parent->_y + y + _ydelta, g_gui.getHeight() - _h - 3); } -void Tooltip::drawDialog() { +void Tooltip::drawDialog(DrawLayer layerToDraw) { int num = 0; int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2; - Dialog::drawDialog(); + Dialog::drawDialog(layerToDraw); for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) { g_gui.theme()->drawText( diff --git a/gui/Tooltip.h b/gui/Tooltip.h index 60688412e6..64496fff9d 100644 --- a/gui/Tooltip.h +++ b/gui/Tooltip.h @@ -40,7 +40,7 @@ public: void setup(Dialog *parent, Widget *widget, int x, int y); - void drawDialog(); + void drawDialog(DrawLayer layerToDraw) override; virtual void receivedFocus(int x = -1, int y = -1) {} protected: diff --git a/gui/about.cpp b/gui/about.cpp index a72a4ed09b..0d70f3dd42 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -180,8 +180,8 @@ void AboutDialog::close() { Dialog::close(); } -void AboutDialog::drawDialog() { - Dialog::drawDialog(); +void AboutDialog::drawDialog(DrawLayer layerToDraw) { + Dialog::drawDialog(layerToDraw); setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h)); @@ -268,7 +268,7 @@ void AboutDialog::handleTickle() { _scrollPos = 0; _scrollTime += kScrollStartDelay; } - drawDialog(); + drawDialog(kDrawLayerForeground); } } diff --git a/gui/about.h b/gui/about.h index 9eeb3071f3..b6510772bf 100644 --- a/gui/about.h +++ b/gui/about.h @@ -48,7 +48,7 @@ public: void open(); void close(); - void drawDialog(); + void drawDialog(DrawLayer layerToDraw) override; void handleTickle(); void handleMouseUp(int x, int y, int button, int clickCount); void handleKeyDown(Common::KeyState state); diff --git a/gui/console.cpp b/gui/console.cpp index 942ef615ab..1c7be32286 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -163,18 +163,11 @@ void ConsoleDialog::close() { Dialog::close(); } -void ConsoleDialog::drawDialog() { - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + _h), ThemeEngine::kDialogBackgroundPlain/*_backgroundType*/); - // FIXME: for the old theme the frame around the console vanishes - // when any action is processed if we enable this - // _drawingHints &= ~THEME_HINT_FIRST_DRAW; +void ConsoleDialog::drawDialog(DrawLayer layerToDraw) { + Dialog::drawDialog(layerToDraw); for (int line = 0; line < _linesPerPage; line++) drawLine(line, false); - - // Draw the scrollbar - _scrollBar->markAsDirty(); - _scrollBar->draw(); } void ConsoleDialog::drawLine(int line, bool restoreBg) { @@ -188,7 +181,6 @@ void ConsoleDialog::drawLine(int line, bool restoreBg) { if (restoreBg) { Common::Rect r(_x, y - 2, _x + _pageWidth * kConsoleCharWidth, y+kConsoleLineHeight); g_gui.theme()->restoreBackground(r); - g_gui.theme()->addDirtyRect(r); } for (int column = 0; column < limit; column++) { @@ -201,8 +193,6 @@ void ConsoleDialog::drawLine(int line, bool restoreBg) { g_gui.theme()->drawChar(Common::Rect(x, y, x+kConsoleCharWidth, y+kConsoleLineHeight), c, _font); x += kConsoleCharWidth; } - - g_gui.theme()->updateScreen(); } void ConsoleDialog::reflowLayout() { diff --git a/gui/console.h b/gui/console.h index 430d5b9434..04ad5526a6 100644 --- a/gui/console.h +++ b/gui/console.h @@ -132,7 +132,7 @@ public: void open(); void close(); - void drawDialog(); + void drawDialog(DrawLayer layerToDraw) override; void handleTickle(); void reflowLayout(); diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 408387b662..6f4e8e6b44 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -161,11 +161,12 @@ void Dialog::markWidgetsAsDirty() { } } -void Dialog::drawDialog() { +void Dialog::drawDialog(DrawLayer layerToDraw) { if (!isVisible()) return; + g_gui.theme()->_layerToDraw = layerToDraw; g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); markWidgetsAsDirty(); diff --git a/gui/dialog.h b/gui/dialog.h index 8f3b2343f5..efa6f76e03 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -92,7 +92,7 @@ protected: void markWidgetsAsDirty(); /** Draw the dialog in its entirety (background and widgets) */ - virtual void drawDialog(); + virtual void drawDialog(DrawLayer layerToDraw); /** Draw only the dialog's widgets */ void drawWidgets(); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 7c00c68189..9515d1be8e 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -224,20 +224,33 @@ void GuiManager::redraw() { case kRedrawFull: case kRedrawTopDialog: _theme->clearAll(); - _theme->openDialog(true, ThemeEngine::kShadingNone); + _theme->drawToBackbuffer(); - for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) - _dialogStack[i]->drawDialog(); - - _theme->finishBuffering(); + for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) { + _dialogStack[i]->drawDialog(kDrawLayerBackground); + _dialogStack[i]->drawDialog(kDrawLayerForeground); + } // fall through case kRedrawOpenDialog: - _theme->updateScreen(false); - _theme->openDialog(true, shading); - _dialogStack.top()->drawDialog(); - _theme->finishBuffering(); + // This case is an optimization to avoid redrawing the whole dialog + // stack when opening a new dialog. + + _theme->drawToBackbuffer(); + + if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 1) { + Dialog *previousDialog = _dialogStack[_dialogStack.size() - 2]; + previousDialog->drawDialog(kDrawLayerForeground); + } + + _theme->applyScreenShading(shading); + _dialogStack.top()->drawDialog(kDrawLayerBackground); + + _theme->drawToScreen(); + _theme->copyBackBufferToScreen(); + + _dialogStack.top()->drawDialog(kDrawLayerForeground); break; default: @@ -245,6 +258,7 @@ void GuiManager::redraw() { } // Redraw the widgets that are marked as dirty + _theme->drawToScreen(); _dialogStack.top()->drawWidgets(); _theme->updateScreen(); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 34e1ab466e..db569fac82 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -274,7 +274,7 @@ void MassAddDialog::handleTickle() { _list->scrollToEnd(); } - drawDialog(); + drawDialog(kDrawLayerForeground); } diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp index f59a89e543..40af769a34 100644 --- a/gui/widgets/popup.cpp +++ b/gui/widgets/popup.cpp @@ -37,7 +37,6 @@ class PopUpDialog : public Dialog { protected: PopUpWidget *_popUpBoss; int _clickX, _clickY; - byte *_buffer; int _selection; uint32 _openTime; bool _twoColumns; @@ -49,7 +48,7 @@ protected: public: PopUpDialog(PopUpWidget *boss, int clickX, int clickY); - void drawDialog(); + void drawDialog(DrawLayer layerToDraw) override; void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel @@ -70,9 +69,9 @@ protected: PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) : Dialog(0, 0, 16, 16), _popUpBoss(boss) { + _backgroundType = ThemeEngine::kDialogBackgroundNone; _openTime = 0; - _buffer = nullptr; _entriesPerColumn = 1; // Copy the selection index @@ -148,7 +147,9 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) _clickY = clickY - _y; } -void PopUpDialog::drawDialog() { +void PopUpDialog::drawDialog(DrawLayer layerToDraw) { + Dialog::drawDialog(layerToDraw); + // Draw the menu border g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0); |