[Scummvm-cvs-logs] scummvm master -> 9cec2eea5cdaf2893771f434c45648dcf7da88f2

sev- sev at scummvm.org
Sun Jul 10 16:24:06 CEST 2016


This automated email contains information about 39 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
08727857bc GUI: Use boss's x/y/w/h instead of clippingArea
49caaf77a1 GUI: Add ScrollContainer
9bf2d65dd2 GUI: Cleanup in ScrollContainer
34af71a8ef GUI: Remove _clippingArea from ScrollContainer
d7278cc48b GUI: Prepare button to be clipped
3d2730a0dd GUI: clippingRect propagated deeper
8f2d35b0b8 GUI: drawRoundedSquareClip()
fca0f0ed34 GUI: Make PopUpWidget clip
b946ef8598 GUI: Make ScrollContainerWidget hide children
425d963bd3 GUI: Fix ThemeItemTextData's dirty rectangle
31e528c070 GUI: Make ScrollContainerWidget do full redraw
e04e13de33 GUI: Remove unnecessary debug output
cccf6eed78 GUI: Add drawRoundedSquareShadowClip()
9c1eab6415 GUI: Fix ScrollContainerWidget look a bit
ac25acbccc GUI: Update ScrollContainerWidget
40fa9b4de3 GUI: Fix ScrollContainerWidget's reflowLayout()
421f9826c8 GUI: Hide scrollbar in ScrollContainerWidget when needed
24963ac97d GUI: Fix Dialog's and TabWidget's reflowLayout()
0ae4409138 GUI: Add ThemeLayoutTabWidget
5868d6d471 GUI: Fix TabWidget's padding in layout_lowres.stx
559ca37daf GUI: Add VectorRendererSpec::drawTriangleClip()
f22d11953d GUI: Add drawSquareClip()
2231de040f GUI: Add drawCircle()
05383532b7 GUI: Add drawLineClip()
ee00156d54 GUI: Add drawBeveledSquareClip()
80412a4139 GUI: Add drawTabClip()
0dcd29e998 GUI: Fix drawRoundedSquareClip()
a39a6533c4 GUI: Add drawCrossClip()
e636894b06 GUI: Add fillSurfaceClip()
916c86e689 GUI: Add blitAlphaBitmapClip()
4b87563792 GUI: Add blipClip()
6fd6043391 GUI: Fix blitAlphaBitmapClip()
dc9b32e620 GUI: Fix PopUpDialog
3d636617d0 GUI: Use clipping everywhere
bc2c7689dc GUI: Update scummmodern.zip
cea58cc61c JANITORIAL: Remove trailing spaces
6de5324742 JANITORIAL: Fix a few warnings
846619fd42 GUI: Add checks in Widget::getBossClipRect()
9cec2eea5c Merge pull request #774 from Tkachov/the-container-box-pr2


Commit: 08727857bcea96a5963db4913cc081ed65341678
    https://github.com/scummvm/scummvm/commit/08727857bcea96a5963db4913cc081ed65341678
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:10:26+02:00

Commit Message:
GUI: Use boss's x/y/w/h instead of clippingArea

Changed paths:
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widget.cpp



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 0ed020e..c116712 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -881,6 +881,28 @@ 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);
+
+	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;
@@ -1215,6 +1237,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:
+		queueDD(kDDTextSelectionBackground, r);
+		restore = false;
+		break;
+
+	case kTextInversionFocus:
+		queueDD(kDDTextSelectionFocusBackground, r);
+		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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index a5ef49c..eab9831 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -375,6 +375,8 @@ public:
 
 	void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
 
+	void drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
+
 	void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
 
 	//@}
@@ -586,6 +588,8 @@ protected:
 	void queueDD(DrawData type,  const Common::Rect &r, 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);
 
 	/**
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 73d0555..2e07fa9 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -280,7 +280,13 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) {
 
 
 void StaticTextWidget::drawWidget() {
-	g_gui.theme()->drawText(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font);
+	int px = _boss->getChildX();
+	int py = _boss->getChildY();
+	g_gui.theme()->drawTextClip(
+		Common::Rect(_x, _y, _x+_w, _y+_h),		
+		Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight()),
+		_label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
+	);
 }
 
 #pragma mark -


Commit: 49caaf77a1aa5f2668a1b21cc2722fb536558929
    https://github.com/scummvm/scummvm/commit/49caaf77a1aa5f2668a1b21cc2722fb536558929
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:10:56+02:00

Commit Message:
GUI: Add ScrollContainer

Changed paths:
  A gui/widgets/scrollcontainer.cpp
  A gui/widgets/scrollcontainer.h
    gui/ThemeEngine.cpp
    gui/widget.cpp
    gui/widget.h



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index c116712..b10349e 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1042,8 +1042,8 @@ 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);
 }
 
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 2e07fa9..cc97988 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -280,8 +280,8 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) {
 
 
 void StaticTextWidget::drawWidget() {
-	int px = _boss->getChildX();
-	int py = _boss->getChildY();
+	int px = _boss->getAbsX();
+	int py = _boss->getAbsY();
 	g_gui.theme()->drawTextClip(
 		Common::Rect(_x, _y, _x+_w, _y+_h),		
 		Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight()),
diff --git a/gui/widget.h b/gui/widget.h
index 7f6f0c0..388b348 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -68,7 +68,8 @@ enum {
 	kPopUpWidget		= 'POPU',
 	kTabWidget			= 'TABW',
 	kGraphicsWidget		= 'GFXW',
-	kContainerWidget	= 'CTNR'
+	kContainerWidget	= 'CTNR',
+	kScrollContainerWidget = 'SCTR'
 };
 
 enum {
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
new file mode 100644
index 0000000..c8dae83
--- /dev/null
+++ b/gui/widgets/scrollcontainer.cpp
@@ -0,0 +1,236 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+#include "gui/widgets/scrollcontainer.h"
+#include "gui/gui-manager.h"
+
+#include "gui/ThemeEval.h"
+
+namespace GUI {
+
+ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h)
+	: Widget(boss, x, y, w, h) {
+	init();
+}
+
+ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::String &name)
+	: Widget(boss, name) {
+	init();
+}
+
+void ScrollContainerWidget::init() {
+	setFlags(WIDGET_ENABLED);
+	_type = kScrollContainerWidget;
+	_verticalScroll = nullptr;
+	_verticalScroll = new ScrollBarWidget(this, _w-16, 0, 16, _h);
+	_verticalScroll->setTarget(this);
+	//_navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", 0, kCmdRight);
+	_scrolledX = 0;
+	_scrolledY = 0;
+	_limitH = 140;
+	_clippingArea = Common::Rect(0, 0, _w, _h);
+	recalc();
+}
+
+void ScrollContainerWidget::recalc() {
+	_verticalScroll->_numEntries = _h;
+	_verticalScroll->_currentPos = _scrolledY;
+	_verticalScroll->_entriesPerPage = _limitH;
+	_verticalScroll->setPos(_w - 16, _scrolledY);
+	_verticalScroll->setSize(16, _limitH);
+	debug("%d %d", _boss->getHeight(), _h);
+}
+
+
+ScrollContainerWidget::~ScrollContainerWidget() {
+	_firstWidget = 0;
+	//delete _navRight;
+}
+
+int16 ScrollContainerWidget::getChildX() const {
+	return getAbsX() - _scrolledX;// +_tabHeight;
+}
+
+int16 ScrollContainerWidget::getChildY() const {
+	return getAbsY() - _scrolledY;// +_tabHeight;
+}
+
+uint16 ScrollContainerWidget::getWidth() const {
+	return (_boss ? _boss->getWidth() : _w);
+}
+
+uint16 ScrollContainerWidget::getHeight() const {
+	return _limitH;
+}
+
+void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+	Widget::handleCommand(sender, cmd, data);	
+	switch (cmd) {
+	case kSetPositionCmd:
+		_scrolledY = _verticalScroll->_currentPos;
+		recalc();
+		draw();
+		break;
+		/*
+	case kCmdLeft:
+		if (_firstVisibleTab) {
+			_firstVisibleTab--;
+			draw();
+		}
+		break;
+
+	case kCmdRight:
+		if (_firstVisibleTab + _w / _tabWidth < (int)_tabs.size()) {
+			_firstVisibleTab++;
+			draw();
+		}
+		break;
+		*/
+	}	
+}
+
+void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+	/*
+	assert(y < _tabHeight);
+
+	// Determine which tab was clicked
+	int tabID = -1;
+	if (x >= 0 && (x % _tabWidth) < _tabWidth) {
+		tabID = x / _tabWidth;
+		if (tabID >= (int)_tabs.size())
+			tabID = -1;
+	}
+
+	// If a tab was clicked, switch to that pane
+	if (tabID >= 0 && tabID + _firstVisibleTab < (int)_tabs.size()) {
+		setActiveTab(tabID + _firstVisibleTab);
+	}
+	*/
+}
+
+bool ScrollContainerWidget::handleKeyDown(Common::KeyState state) {
+	/*
+	if (state.hasFlags(Common::KBD_SHIFT) && state.keycode == Common::KEYCODE_TAB)
+		adjustTabs(kTabBackwards);
+	else if (state.keycode == Common::KEYCODE_TAB)
+		adjustTabs(kTabForwards);
+		*/
+	return Widget::handleKeyDown(state);
+}
+
+void ScrollContainerWidget::reflowLayout() {
+	_clippingArea = Common::Rect(0, 0, _w, _h);
+	recalc();
+	Widget::reflowLayout();
+
+	/*
+	for (uint i = 0; i < _tabs.size(); ++i) {
+		Widget *w = _tabs[i].firstWidget;
+		while (w) {
+			w->reflowLayout();
+			w = w->next();
+		}
+	}
+
+	_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
+	_tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
+	_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
+
+	if (_tabWidth == 0) {
+		_tabWidth = 40;
+#ifdef __DS__
+	}
+	if (true) {
+#endif
+		int maxWidth = _w / _tabs.size();
+
+		for (uint i = 0; i < _tabs.size(); ++i) {
+			// Determine the new tab width
+			int newWidth = g_gui.getStringWidth(_tabs[i].title) + 2 * 3;
+			if (_tabWidth < newWidth)
+				_tabWidth = newWidth;
+			if (_tabWidth > maxWidth)
+				_tabWidth = maxWidth;
+		}
+	}
+
+	_butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.PaddingRight", 0);
+	_butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0);
+	_butW = g_gui.xmlEval()->getVar("GlobalsTabWidget.NavButton.Width", 10);
+	_butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10);
+
+	int x = _w - _butRP - _butW * 2 - 2;
+	int y = _butTP - _tabHeight;
+	_navLeft->resize(x, y, _butW, _butH);
+	_navRight->resize(x + _butW + 2, y, _butW, _butH);
+	*/
+}
+
+void ScrollContainerWidget::drawWidget() {
+	/*
+	Common::Array<Common::String> tabs;
+	for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
+		tabs.push_back(_tabs[i].title);
+	}	
+	g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType);
+	*/
+	g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight()), ThemeEngine::kDialogBackgroundDefault);
+	//g_gui.theme()->addDirtyRect(Common::Rect(_x, _y, _x + _w, _y + getHeight()));
+	/*
+	g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
+	*/
+}
+
+void ScrollContainerWidget::draw() {
+	Widget::draw();
+	/*
+	if (_tabWidth * _tabs.size() > _w) {
+		_navLeft->draw();
+		_navRight->draw();
+	}
+	*/
+}
+
+Widget *ScrollContainerWidget::findWidget(int x, int y) {
+	/*
+	if (y < _tabHeight) {
+		if (_tabWidth * _tabs.size() > _w) {
+			if (y >= _butTP && y < _butTP + _butH) {
+				if (x >= _w - _butRP - _butW * 2 - 2 && x < _w - _butRP - _butW - 2)
+					return _navLeft;
+				if (x >= _w - _butRP - _butW &&  x < _w - _butRP)
+					return _navRight;
+			}
+		}
+
+		// Click was in the tab area
+		return this;
+	} else {	
+		// Iterate over all child widgets and find the one which was clicked
+		return Widget::findWidgetInChain(_firstWidget, x, y - _tabHeight);
+	}
+	*/
+	return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
+}
+
+} // End of namespace GUI
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
new file mode 100644
index 0000000..2aeecb7
--- /dev/null
+++ b/gui/widgets/scrollcontainer.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_WIDGETS_SCROLLCONTAINER_H
+#define GUI_WIDGETS_SCROLLCONTAINER_H
+
+#include "gui/widget.h"
+#include "common/str.h"
+#include "common/array.h"
+#include "scrollbar.h"
+
+namespace GUI {
+
+class ScrollContainerWidget: public Widget {
+	//ButtonWidget *_navLeft, *_navRight; //TODO: add scrollbars similarly
+	ScrollBarWidget *_verticalScroll;
+	int16 _scrolledX, _scrolledY;
+	uint16 _limitH;
+
+	void recalc();
+
+public:
+	ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h);
+	ScrollContainerWidget(GuiObject *boss, const Common::String &name);
+	~ScrollContainerWidget();
+
+	void init();
+
+	virtual void handleMouseDown(int x, int y, int button, int clickCount);
+	virtual bool handleKeyDown(Common::KeyState state);
+	virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+	virtual void reflowLayout();
+
+	virtual void draw();
+
+protected:
+	// We overload getChildY to make sure child widgets are positioned correctly.
+	// Essentially this compensates for the space taken up by the tab title header.
+	virtual int16	getChildX() const;
+	virtual int16	getChildY() const;
+	virtual uint16	getWidth() const;
+	virtual uint16	getHeight() const;
+
+	virtual void drawWidget();
+
+	virtual Widget *findWidget(int x, int y);
+};
+
+} // End of namespace GUI
+
+#endif


Commit: 9bf2d65dd24f217a7462da823ff30c43a7110e29
    https://github.com/scummvm/scummvm/commit/9bf2d65dd24f217a7462da823ff30c43a7110e29
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:13:57+02:00

Commit Message:
GUI: Cleanup in ScrollContainer

Changed paths:
    gui/module.mk
    gui/widgets/scrollcontainer.cpp
    gui/widgets/scrollcontainer.h



diff --git a/gui/module.mk b/gui/module.mk
index 9e821e7..6cbc63d 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -30,6 +30,7 @@ MODULE_OBJS := \
 	widgets/list.o \
 	widgets/popup.o \
 	widgets/scrollbar.o \
+	widgets/scrollcontainer.o \
 	widgets/tab.o
 
 # HACK: create_project's XCode generator relies on the following ifdef
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index c8dae83..7fde9a6 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -41,10 +41,8 @@ ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::Stri
 void ScrollContainerWidget::init() {
 	setFlags(WIDGET_ENABLED);
 	_type = kScrollContainerWidget;
-	_verticalScroll = nullptr;
 	_verticalScroll = new ScrollBarWidget(this, _w-16, 0, 16, _h);
 	_verticalScroll->setTarget(this);
-	//_navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", 0, kCmdRight);
 	_scrolledX = 0;
 	_scrolledY = 0;
 	_limitH = 140;
@@ -58,21 +56,17 @@ void ScrollContainerWidget::recalc() {
 	_verticalScroll->_entriesPerPage = _limitH;
 	_verticalScroll->setPos(_w - 16, _scrolledY);
 	_verticalScroll->setSize(16, _limitH);
-	debug("%d %d", _boss->getHeight(), _h);
 }
 
 
-ScrollContainerWidget::~ScrollContainerWidget() {
-	_firstWidget = 0;
-	//delete _navRight;
-}
+ScrollContainerWidget::~ScrollContainerWidget() {}
 
 int16 ScrollContainerWidget::getChildX() const {
-	return getAbsX() - _scrolledX;// +_tabHeight;
+	return getAbsX() - _scrolledX;
 }
 
 int16 ScrollContainerWidget::getChildY() const {
-	return getAbsY() - _scrolledY;// +_tabHeight;
+	return getAbsY() - _scrolledY;
 }
 
 uint16 ScrollContainerWidget::getWidth() const {
@@ -91,145 +85,20 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 		recalc();
 		draw();
 		break;
-		/*
-	case kCmdLeft:
-		if (_firstVisibleTab) {
-			_firstVisibleTab--;
-			draw();
-		}
-		break;
-
-	case kCmdRight:
-		if (_firstVisibleTab + _w / _tabWidth < (int)_tabs.size()) {
-			_firstVisibleTab++;
-			draw();
-		}
-		break;
-		*/
 	}	
 }
 
-void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
-	/*
-	assert(y < _tabHeight);
-
-	// Determine which tab was clicked
-	int tabID = -1;
-	if (x >= 0 && (x % _tabWidth) < _tabWidth) {
-		tabID = x / _tabWidth;
-		if (tabID >= (int)_tabs.size())
-			tabID = -1;
-	}
-
-	// If a tab was clicked, switch to that pane
-	if (tabID >= 0 && tabID + _firstVisibleTab < (int)_tabs.size()) {
-		setActiveTab(tabID + _firstVisibleTab);
-	}
-	*/
-}
-
-bool ScrollContainerWidget::handleKeyDown(Common::KeyState state) {
-	/*
-	if (state.hasFlags(Common::KBD_SHIFT) && state.keycode == Common::KEYCODE_TAB)
-		adjustTabs(kTabBackwards);
-	else if (state.keycode == Common::KEYCODE_TAB)
-		adjustTabs(kTabForwards);
-		*/
-	return Widget::handleKeyDown(state);
-}
-
 void ScrollContainerWidget::reflowLayout() {
 	_clippingArea = Common::Rect(0, 0, _w, _h);
 	recalc();
 	Widget::reflowLayout();
-
-	/*
-	for (uint i = 0; i < _tabs.size(); ++i) {
-		Widget *w = _tabs[i].firstWidget;
-		while (w) {
-			w->reflowLayout();
-			w = w->next();
-		}
-	}
-
-	_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
-	_tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
-	_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
-
-	if (_tabWidth == 0) {
-		_tabWidth = 40;
-#ifdef __DS__
-	}
-	if (true) {
-#endif
-		int maxWidth = _w / _tabs.size();
-
-		for (uint i = 0; i < _tabs.size(); ++i) {
-			// Determine the new tab width
-			int newWidth = g_gui.getStringWidth(_tabs[i].title) + 2 * 3;
-			if (_tabWidth < newWidth)
-				_tabWidth = newWidth;
-			if (_tabWidth > maxWidth)
-				_tabWidth = maxWidth;
-		}
-	}
-
-	_butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.PaddingRight", 0);
-	_butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0);
-	_butW = g_gui.xmlEval()->getVar("GlobalsTabWidget.NavButton.Width", 10);
-	_butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10);
-
-	int x = _w - _butRP - _butW * 2 - 2;
-	int y = _butTP - _tabHeight;
-	_navLeft->resize(x, y, _butW, _butH);
-	_navRight->resize(x + _butW + 2, y, _butW, _butH);
-	*/
 }
 
 void ScrollContainerWidget::drawWidget() {
-	/*
-	Common::Array<Common::String> tabs;
-	for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
-		tabs.push_back(_tabs[i].title);
-	}	
-	g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType);
-	*/
 	g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight()), ThemeEngine::kDialogBackgroundDefault);
-	//g_gui.theme()->addDirtyRect(Common::Rect(_x, _y, _x + _w, _y + getHeight()));
-	/*
-	g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
-	*/
-}
-
-void ScrollContainerWidget::draw() {
-	Widget::draw();
-	/*
-	if (_tabWidth * _tabs.size() > _w) {
-		_navLeft->draw();
-		_navRight->draw();
-	}
-	*/
 }
 
 Widget *ScrollContainerWidget::findWidget(int x, int y) {
-	/*
-	if (y < _tabHeight) {
-		if (_tabWidth * _tabs.size() > _w) {
-			if (y >= _butTP && y < _butTP + _butH) {
-				if (x >= _w - _butRP - _butW * 2 - 2 && x < _w - _butRP - _butW - 2)
-					return _navLeft;
-				if (x >= _w - _butRP - _butW &&  x < _w - _butRP)
-					return _navRight;
-			}
-		}
-
-		// Click was in the tab area
-		return this;
-	} else {	
-		// Iterate over all child widgets and find the one which was clicked
-		return Widget::findWidgetInChain(_firstWidget, x, y - _tabHeight);
-	}
-	*/
 	return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
 }
 
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
index 2aeecb7..692c7e3 100644
--- a/gui/widgets/scrollcontainer.h
+++ b/gui/widgets/scrollcontainer.h
@@ -25,13 +25,11 @@
 
 #include "gui/widget.h"
 #include "common/str.h"
-#include "common/array.h"
 #include "scrollbar.h"
 
 namespace GUI {
 
 class ScrollContainerWidget: public Widget {
-	//ButtonWidget *_navLeft, *_navRight; //TODO: add scrollbars similarly
 	ScrollBarWidget *_verticalScroll;
 	int16 _scrolledX, _scrolledY;
 	uint16 _limitH;
@@ -44,15 +42,9 @@ public:
 	~ScrollContainerWidget();
 
 	void init();
-
-	virtual void handleMouseDown(int x, int y, int button, int clickCount);
-	virtual bool handleKeyDown(Common::KeyState state);
 	virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
-
 	virtual void reflowLayout();
 
-	virtual void draw();
-
 protected:
 	// We overload getChildY to make sure child widgets are positioned correctly.
 	// Essentially this compensates for the space taken up by the tab title header.


Commit: 34af71a8ef81db5fb4ee6d502df77a8c15540266
    https://github.com/scummvm/scummvm/commit/34af71a8ef81db5fb4ee6d502df77a8c15540266
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:14:23+02:00

Commit Message:
GUI: Remove _clippingArea from ScrollContainer

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 7fde9a6..8b9341f 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -46,7 +46,6 @@ void ScrollContainerWidget::init() {
 	_scrolledX = 0;
 	_scrolledY = 0;
 	_limitH = 140;
-	_clippingArea = Common::Rect(0, 0, _w, _h);
 	recalc();
 }
 
@@ -89,7 +88,6 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 }
 
 void ScrollContainerWidget::reflowLayout() {
-	_clippingArea = Common::Rect(0, 0, _w, _h);
 	recalc();
 	Widget::reflowLayout();
 }


Commit: d7278cc48b7fd9c1848da6402316663af2d0c7bd
    https://github.com/scummvm/scummvm/commit/d7278cc48b7fd9c1848da6402316663af2d0c7bd
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:14:45+02:00

Commit Message:
GUI: Prepare button to be clipped

Changed paths:
    graphics/VectorRenderer.cpp
    graphics/VectorRenderer.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widget.cpp



diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
index f426dd8..73dc630 100644
--- a/graphics/VectorRenderer.cpp
+++ b/graphics/VectorRenderer.cpp
@@ -55,7 +55,34 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui
 
 	_dynamicData = extra;
 
-	(this->*(step.drawingCall))(area, step);
+	Common::Rect noClip = Common::Rect(0, 0, 0, 0);
+	(this->*(step.drawingCall))(area, step, noClip);
+}
+
+void VectorRenderer::drawStepClip(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step, uint32 extra) {
+
+	if (step.bgColor.set)
+		setBgColor(step.bgColor.r, step.bgColor.g, step.bgColor.b);
+
+	if (step.fgColor.set)
+		setFgColor(step.fgColor.r, step.fgColor.g, step.fgColor.b);
+
+	if (step.bevelColor.set)
+		setBevelColor(step.bevelColor.r, step.bevelColor.g, step.bevelColor.b);
+
+	if (step.gradColor1.set && step.gradColor2.set)
+		setGradientColors(step.gradColor1.r, step.gradColor1.g, step.gradColor1.b,
+			step.gradColor2.r, step.gradColor2.g, step.gradColor2.b);
+
+	setShadowOffset(_disableShadows ? 0 : step.shadow);
+	setBevel(step.bevel);
+	setGradientFactor(step.factor);
+	setStrokeWidth(step.stroke);
+	setFillMode((FillMode)step.fillMode);
+
+	_dynamicData = extra;
+
+	(this->*(step.drawingCall))(area, step, clip);
 }
 
 int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) {
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 6b657f7..e98dbc2 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -38,7 +38,7 @@ class VectorRenderer;
 struct DrawStep;
 
 
-typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &);
+typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &, const Common::Rect &);
 
 
 struct DrawStep {
@@ -355,7 +355,7 @@ public:
 	/**
 	 * DrawStep callback functions for each drawing feature
 	 */
-	void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h, radius;
 
 		radius = stepGetRadius(step, area);
@@ -364,59 +364,59 @@ public:
 		drawCircle(x + radius, y + radius, radius);
 	}
 
-	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawSquare(x, y, w, h);
 	}
 
-	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawLine(x, y, x + w, y + w);
 	}
 
-	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawRoundedSquare(x, y, stepGetRadius(step, area), w, h);
 	}
 
-	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		fillSurface();
 	}
 
-	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawTriangle(x, y, w, h, (TriangleOrientation)step.extraData);
 	}
 
-	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawBeveledSquare(x, y, w, h, _bevel);
 	}
 
-	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawTab(x, y, stepGetRadius(step, area), w, h);
 	}
 
-	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, x + w, y + h));
 	}
 
-	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step) {
+	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawCross(x, y, w, h);
 	}
 
-	void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {}
+	void drawCallback_VOID(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {}
 
 	/**
 	 * Draws the specified draw step on the screen.
@@ -426,6 +426,7 @@ public:
 	 * @param step Pointer to a DrawStep struct.
 	 */
 	virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0);
+	virtual void drawStepClip(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step, uint32 extra = 0);
 
 	/**
 	 * Copies the part of the current frame to the system overlay.
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index b10349e..12788c2 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -121,6 +121,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,
@@ -242,6 +255,23 @@ 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()->drawStep(_area, *step, _dynamicData);
+	}
+
+	_engine->addDirtyRect(extendedRect);
+}
+
 void ThemeItemTextData::drawSelf(bool draw, bool restore) {
 	if (_restoreBg || restore)
 		_engine->restoreBackground(_area);
@@ -862,6 +892,31 @@ 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);
+	area.clip(clippingRect);
+
+	ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, 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) {
 
@@ -942,6 +997,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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index eab9831..76581fa 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -344,6 +344,9 @@ public:
 	void drawButton(const Common::Rect &r, const Common::String &str,
 	                WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
 
+	void drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+		WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
+
 	void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
 	                 WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false);
 
@@ -586,6 +589,7 @@ protected:
 	 * This function is 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,
diff --git a/gui/widget.cpp b/gui/widget.cpp
index cc97988..d17fabe 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -324,8 +324,14 @@ void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 	setPressedState();
 }
 
-void ButtonWidget::drawWidget() {
-	g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, getFlags());
+void ButtonWidget::drawWidget() {	
+	int px = _boss->getAbsX();
+	int py = _boss->getAbsY();
+	g_gui.theme()->drawButtonClip(
+		Common::Rect(_x, _y, _x + _w, _y + _h),
+		Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight()),
+		_label, _state, getFlags()
+	);
 }
 
 void ButtonWidget::setLabel(const Common::String &label) {


Commit: 3d2730a0ddd1e1e33e6639775727beb954d7bfc0
    https://github.com/scummvm/scummvm/commit/3d2730a0ddd1e1e33e6639775727beb954d7bfc0
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:15:51+02:00

Commit Message:
GUI: clippingRect propagated deeper

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index e98dbc2..2af91d3 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -173,6 +173,7 @@ public:
 	 * @param r Radius of the corners.
 	 */
 	virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0;
+	virtual void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch) = 0;
 
 	/**
 	 * Draws a triangle starting at (x,y) with the given base and height.
@@ -379,7 +380,7 @@ public:
 	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawRoundedSquare(x, y, stepGetRadius(step, area), w, h);
+		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip.left, clip.top, clip.right-clip.left, clip.bottom-clip.top);
 	}
 
 	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 258d935..6c559e0 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -920,6 +920,29 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+		w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
+		return;
+
+	if ((r * 2) > w || (r * 2) > h)
+		r = MIN(w / 2, h / 2);
+
+	if (r <= 0)
+		return;
+
+	if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+		&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
+		&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
+		&& h > (Base::_shadowOffset + 1) * 2) {
+		drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
+	}
+
+	drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 drawTab(int x, int y, int r, int w, int h) {
 	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
 		w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 3e54608..13377d8 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -54,6 +54,7 @@ public:
 	void drawCircle(int x, int y, int r);
 	void drawSquare(int x, int y, int w, int h);
 	void drawRoundedSquare(int x, int y, int r, int w, int h);
+	void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
 	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
 	void drawTab(int x, int y, int r, int w, int h);
 	void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 12788c2..3c6f595 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -898,9 +898,8 @@ void ThemeEngine::queueDDClip(DrawData type, const Common::Rect &r, const Common
 
 	Common::Rect area = r;
 	area.clip(_screen.w, _screen.h);
-	area.clip(clippingRect);
 
-	ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, dynamic);
+	ThemeItemDrawDataClip *q = new ThemeItemDrawDataClip(this, _widgets[type], area, clippingRect, dynamic);
 
 	if (_buffering) {
 		if (_widgets[type]->_buffer) {


Commit: 8f2d35b0b89c4b8912df96ec3c403e00c85c5875
    https://github.com/scummvm/scummvm/commit/8f2d35b0b89c4b8912df96ec3c403e00c85c5875
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:16:26+02:00

Commit Message:
GUI: drawRoundedSquareClip()

Changed paths:
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp
    gui/object.cpp
    gui/widgets/scrollcontainer.cpp



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 6c559e0..8a471d5 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -108,6 +108,33 @@ inline frac_t fp_sqroot(uint32 x) {
 	BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py); \
 } while (0)
 
+#define BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
+	if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+		*(ptr1 + (y) - (px)) = color; \
+	if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+		*(ptr1 + (x) - (py)) = color; \
+	if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+		*(ptr2 - (x) - (py)) = color; \
+	if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+		*(ptr2 - (y) - (px)) = color; \
+} while (0)
+
+#define BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
+	if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+		*(ptr3 - (y) + (px)) = color; \
+	if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+		*(ptr3 - (x) + (py)) = color; \
+	if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+		*(ptr4 + (x) + (py)) = color; \
+	if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+		*(ptr4 + (y) + (px)) = color; \
+} while (0)
+
+#define BE_DRAWCIRCLE_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+	BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
+	BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
+} while (0)
+
 #define BE_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \
 	*(ptr1 + (y) - (px)) = color1; \
 	*(ptr1 + (x) - (py)) = color1; \
@@ -119,6 +146,25 @@ inline frac_t fp_sqroot(uint32 x) {
 	*(ptr4 + (y) + (px)) = color2; \
 } while (0)
 
+#define BE_DRAWCIRCLE_BCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+	if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+		*(ptr1 + (y) - (px)) = color1; \
+	if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+		*(ptr1 + (x) - (py)) = color1; \
+	if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+		*(ptr2 - (x) - (py)) = color1; \
+	if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+		*(ptr2 - (y) - (px)) = color1; \
+	if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+		*(ptr3 - (y) + (px)) = color1; \
+	if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+		*(ptr3 - (x) + (py)) = color1; \
+	if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+		*(ptr4 + (x) + (py)) = color2; \
+	if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+		*(ptr4 + (y) + (px)) = color2; \
+} while (0)
+
 #define BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
 	this->blendPixelPtr(ptr + (y) - (px), color, a); \
 } while (0)
@@ -127,6 +173,16 @@ inline frac_t fp_sqroot(uint32 x) {
 	this->blendPixelPtr(ptr + (x) - (py), color, a); \
 } while (0)
 
+#define BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) + (y), (realY) - (x))) \
+		this->blendPixelPtr(ptr + (y) - (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) + (x), (realY) - (y))) \
+		this->blendPixelPtr(ptr + (x) - (py), color, a); \
+} while (0)
+
 #define BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
 	this->blendPixelPtr(ptr - (x) - (py), color, a); \
 } while (0)
@@ -135,6 +191,16 @@ inline frac_t fp_sqroot(uint32 x) {
 	this->blendPixelPtr(ptr - (y) - (px), color, a); \
 } while (0)
 
+#define BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) - (x), (realY) - (y))) \
+		this->blendPixelPtr(ptr - (x) - (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) - (y), (realY) - (x))) \
+		this->blendPixelPtr(ptr - (y) - (px), color, a); \
+} while (0)
+
 #define BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
 	this->blendPixelPtr(ptr - (y) + (px), color, a); \
 } while (0)
@@ -143,6 +209,16 @@ inline frac_t fp_sqroot(uint32 x) {
 	this->blendPixelPtr(ptr - (x) + (py), color, a); \
 } while (0)
 
+#define BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) - (y), (realY) + (x))) \
+		this->blendPixelPtr(ptr - (y) + (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) - (x), (realY) + (y))) \
+		this->blendPixelPtr(ptr - (x) + (py), color, a); \
+} while (0)
+
 #define BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
 	this->blendPixelPtr(ptr + (x) + (py), color, a); \
 } while (0)
@@ -151,6 +227,16 @@ inline frac_t fp_sqroot(uint32 x) {
 	this->blendPixelPtr(ptr + (y) + (px), color, a); \
 } while (0)
 
+#define BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) + (x), (realY) + (y))) \
+		this->blendPixelPtr(ptr + (x) + (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+	if (IS_IN_CLIP((realX) + (y), (realY) + (x))) \
+		this->blendPixelPtr(ptr + (y) + (px), color, a); \
+} while (0)
+
 #define BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py) do { \
 	*(ptr1 + (y) - (px)) = color1; \
 	*(ptr1 + (x) - (py)) = color2; \
@@ -170,6 +256,42 @@ inline frac_t fp_sqroot(uint32 x) {
 	BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py); \
 } while (0)
 
+#define IS_IN_CLIP(x,y) (_clippingArea.left <= (x) && (x) < _clippingArea.right \
+	&& _clippingArea.top <= (y) && (y) < _clippingArea.bottom)
+
+#define BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
+	if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+		*(ptr1 + (y) - (px)) = color1; \
+\
+	if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+		*(ptr1 + (x) - (py)) = color2; \
+\
+	if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+		*(ptr2 - (x) - (py)) = color2; \
+\
+	if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+		*(ptr2 - (y) - (px)) = color1; \
+} while (0)
+
+#define BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
+	if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+		*(ptr3 - (y) + (px)) = color3; \
+\
+	if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+		*(ptr3 - (x) + (py)) = color4; \
+\
+	if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+		*(ptr4 + (x) + (py)) = color4; \
+\
+	if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+		*(ptr4 + (y) + (px)) = color3; \
+} while (0)
+
+#define BE_DRAWCIRCLE_XCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+	BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
+	BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
+} while (0)
+
 
 #define BE_RESET() do { \
 	f = 1 - r; \
@@ -337,6 +459,45 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) {
 	}
 }
 
+template<typename PixelType>
+void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX, int realY, Common::Rect &clippingArea) {
+	if (realY < clippingArea.top || realY >= clippingArea.bottom)
+		return;	
+
+	register int count = (last - first);
+
+	if (realX > clippingArea.right || realX + count < clippingArea.left)
+		return;
+
+	if (realX < clippingArea.left) {
+		register int diff = (clippingArea.left - realX);
+		realX += diff;
+		count -= diff;
+	}
+
+	if (clippingArea.right <= realX + count) {
+		register int diff = (realX + count - clippingArea.right);		
+		count -= diff;
+	}
+
+	if (!count)
+		return;
+
+	register int n = (count + 7) >> 3;
+	switch (count % 8) {
+	case 0: do {
+		*first++ = color;
+	case 7:		*first++ = color;
+	case 6:		*first++ = color;
+	case 5:		*first++ = color;
+	case 4:		*first++ = color;
+	case 3:		*first++ = color;
+	case 2:		*first++ = color;
+	case 1:		*first++ = color;
+	} while (--n > 0);
+	}
+}
+
 
 VectorRenderer *createRenderer(int mode) {
 #ifdef DISABLE_FANCY_THEMES
@@ -376,6 +537,7 @@ VectorRendererSpec(PixelFormat format) :
 	_alphaMask((0xFF >> format.aLoss) << format.aShift) {
 
 	_bitmapAlphaColor = _format.RGBToColor(255, 0, 255);
+	_clippingArea = Common::Rect(0, 0, 64 * 1024, 64 * 1024);
 }
 
 /****************************
@@ -480,6 +642,49 @@ gradientFill(PixelType *ptr, int width, int x, int y) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+gradientFillClip(PixelType *ptr, int width, int x, int y, int realX, int realY) {
+	if (realY < _clippingArea.top || realY >= _clippingArea.bottom) return;
+	bool ox = ((y & 1) == 1);
+	int curGrad = 0;
+
+	while (_gradIndexes[curGrad + 1] <= y)
+		curGrad++;
+
+	// precalcGradient assures that _gradIndexes entries always differ in
+	// their value. This assures stripSize is always different from zero.
+	int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
+
+	int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
+
+	// Dithering:
+	//   +--+ +--+ +--+ +--+
+	//   |  | |  | | *| | *|
+	//   |  | | *| |* | |**|
+	//   +--+ +--+ +--+ +--+
+	//     0    1    2    3
+	if (grad == 0 ||
+		_gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
+		stripSize < 2) { // the stip is small
+		colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
+	} else if (grad == 3 && ox) {
+		colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
+	} else {
+		for (int j = x; j < x + width; j++, ptr++) {
+			if (realX + j - x < _clippingArea.left || realX + j - x >= _clippingArea.right) continue;
+			bool oy = ((j & 1) == 1);
+
+			if ((ox && oy) ||
+				((grad == 2 || grad == 3) && ox && !oy) ||
+				(grad == 3 && oy))
+				*ptr = _gradCache[curGrad + 1];
+			else
+				*ptr = _gradCache[curGrad];
+		}
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 fillSurface() {
 	byte *ptr = (byte *)_activeSurface->getPixels();
 
@@ -931,14 +1136,25 @@ drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw,
 	if (r <= 0)
 		return;
 
+	Common::Rect backup = _clippingArea;
+	_clippingArea = Common::Rect(cx, cy, cx + cw, cy + ch);	
+
 	if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
 		&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
 		&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
 		&& h > (Base::_shadowOffset + 1) * 2) {
+		debug("shadow");
 		drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
 	}
 
-	drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
+	if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
+		drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
+	} else {
+		debug("clipclipclip %d..%d %d..%d", cx, cw + cx, cy, cy + ch);
+		drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
+	}
+
+	_clippingArea = backup;
 }
 
 template<typename PixelType>
@@ -1688,6 +1904,7 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
 	PixelType color1 = color;
 	PixelType color2 = color;
 
+	debug("from %d to %d (drawing from %d to %d or something)", _clippingArea.left, _clippingArea.right, x1, x1+w);
 	while (sw++ < Base::_strokeWidth) {
 		blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top
 		blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom
@@ -1705,6 +1922,9 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
 		while (x++ < (y - 2)) {
 			BE_ALGORITHM();
 
+			if (x < _clippingArea.left || x > _clippingArea.right) continue;
+			if (y < _clippingArea.top || y > _clippingArea.bottom) continue;
+
 			BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
 			BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
 			BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
@@ -1732,6 +1952,74 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+drawBorderRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
+	int f, ddF_x, ddF_y;
+	int x, y, px, py;
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int sw = 0, sp = 0, hp = h * pitch;
+
+	PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+	PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+	PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+	PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+	PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+
+	int real_radius = r;
+	int short_h = h - (2 * r) + 2;
+
+	PixelType color1 = color;
+	PixelType color2 = color;
+	
+	while (sw++ < Base::_strokeWidth) {
+		blendFillClip(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t,
+			x1 + r, y1 + sp/pitch); // top
+		blendFillClip(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b,
+			x1 + r, y1 + (hp - sp)/ pitch); // bottom
+		sp += pitch;
+
+		BE_RESET();
+		r--;
+
+		int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
+		int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
+		int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
+		int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
+
+		// Avoid blending the last pixels twice, since we have an alpha
+		while (x++ < (y - 2)) {
+			BE_ALGORITHM();
+
+			BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)), x1 + w - r, y1 + r);
+			BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)), x1 + w - r, y1 + h - r);
+			BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)), x1 + r, y1 + h - r);
+			BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)), x1 + r, y1 + r);
+
+			BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)), x1 + w - r, y1 + r);
+			BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)), x1 + w - r, y1 + h - r);
+			BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)), x1 + r, y1 + h - r);
+			BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)), x1 + r, y1 + r);
+
+			if (Base::_strokeWidth > 1) {
+				BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py,
+					x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+				BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py,
+					x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+			}
+		}
+	}
+
+	ptr_fill += pitch * real_radius;
+	while (short_h--) {
+		blendFillClip(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l,
+			x1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // left
+		blendFillClip(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r,
+			x1 + w - Base::_strokeWidth + 1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // right
+		ptr_fill += pitch;
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
 	// Do not draw empty space rounded squares.
 	if (w <= 0 || h <= 0) {
@@ -1763,6 +2051,8 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
 		while (x++ < y) {
 			BE_ALGORITHM();
 
+			if (y1 + r + y < _clippingArea.top || y1 + r + y > _clippingArea.bottom) continue;
+
 			color1 = calcGradient(real_radius - x, long_h);
 			color2 = calcGradient(real_radius - y, long_h);
 			color3 = calcGradient(long_h - r + x, long_h);
@@ -1804,6 +2094,91 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+	// Do not draw empty space rounded squares.
+	if (w <= 0 || h <= 0) {
+		return;
+	}
+
+	int f, ddF_x, ddF_y;
+	int x, y, px, py;
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+	PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+	PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+	PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
+	PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
+	PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+
+	int real_radius = r;
+	int short_h = h - (2 * r) + 2;
+	int long_h = h;
+
+	BE_RESET();
+
+	PixelType color1 = color;
+
+	if (fill_m == kFillGradient) {
+		PixelType color2, color3, color4;
+		precalcGradient(long_h);
+
+		while (x++ < y) {
+			BE_ALGORITHM();
+
+			color1 = calcGradient(real_radius - x, long_h);
+			color2 = calcGradient(real_radius - y, long_h);
+			color3 = calcGradient(long_h - r + x, long_h);
+			color4 = calcGradient(long_h - r + y, long_h);
+
+			//TL = (x1 + r, y1 + r)			
+			gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y,
+				x1 + r - x, y1 + r - y);
+			gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x,
+				x1 + r - y, y1 + r - x);
+
+			//BL = (x1 + r, y1 + h - r)	
+			gradientFillClip(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y,
+				x1 + r - x, y1 + h - r + y);
+			gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x,
+				x1 + r - y, y1 + h - r + x);
+			
+			BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
+				x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+		}
+	} else {
+		while (x++ < y) {
+			BE_ALGORITHM();
+
+			colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1,
+				x1 + r - x, y1 + r - y, _clippingArea);
+			colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1,
+				x1 + r - y, y1 + r - x, _clippingArea);
+
+			colorFillClip<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1,
+				x1 + r - x, y1 + h - r + y, _clippingArea);
+			colorFillClip<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1,
+				x1 + r - y, y1 + h - r + x, _clippingArea);
+
+			// do not remove - messes up the drawing at lower resolutions
+			BE_DRAWCIRCLE_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
+				x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+		}
+	}
+
+	ptr_fill += pitch * r;
+	int short_h_orig = short_h;
+	while (short_h--) {
+		if (fill_m == kFillGradient) {
+			gradientFillClip(ptr_fill, w + 1, x1, real_radius++, x1, y1 + r + short_h_orig - short_h -1);
+		} else {			
+			colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color1, x1, y1 + r + short_h_orig - short_h - 1, _clippingArea);
+		}
+		ptr_fill += pitch;
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
 	const uint8 borderAlpha_t = 0;
 	const uint8 borderAlpha_r = 127;
@@ -1817,6 +2192,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
 
 	// If only border is visible
 	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
+		debug("interior");
 		if (fill_m == Base::kFillBackground)
 			drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m);
 		else
@@ -1824,6 +2200,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
 	}
 
 	if (Base::_strokeWidth) {
+		debug("stroke");
 		if (r != 0 && _bevel > 0) {
 			drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
 			drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
@@ -1833,6 +2210,40 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+	const uint8 borderAlpha_t = 0;
+	const uint8 borderAlpha_r = 127;
+	const uint8 borderAlpha_b = 255;
+	const uint8 borderAlpha_l = 63;
+
+	const uint8 bevelAlpha_t = 255;
+	const uint8 bevelAlpha_r = 31;
+	const uint8 bevelAlpha_b = 0;
+	const uint8 bevelAlpha_l = 127;
+
+	debug("clip version");
+
+	// If only border is visible	
+	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {		
+		if (fill_m == Base::kFillBackground)
+			drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, _bgColor, fill_m);
+		else
+			drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m);
+	}	
+
+	//I expect these to work fine with clipping:
+	if (Base::_strokeWidth) {
+		if (r != 0 && _bevel > 0) {
+			drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
+			drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
+		} else {
+			drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
+		}
+	}
+}
+
 /** CIRCLE ALGORITHM **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -1941,6 +2352,8 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 	int width = w + offset + 2;
 	int height = h + offset + 1;
 
+	debug("from %d to %d (drawing from %d to %d or something)", _clippingArea.left, _clippingArea.right, xstart, xstart + width);
+
 	for (int i = offset; i >= 0; i--) {
 		int f, ddF_x, ddF_y;
 		int x, y, px, py;
@@ -1965,28 +2378,33 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 		while (x++ < y) {
 			BE_ALGORITHM();
 
+			if (x + xstart < _clippingArea.left || x + xstart > _clippingArea.right) continue;
+			if (y + ystart  < _clippingArea.top || y + ystart  > _clippingArea.bottom) continue;
 
 			if (((1 << x) & hb) == 0) {
-				blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
+				blendFillClip(xstart + r + x, ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
 
 				// Will create a dark line of pixles if left out
 				if (hb > 0) {
-					blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
+					blendFillClip(x, ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
 				}
 				hb |= (1 << x);
 			}
 
 			if (((1 << y) & hb) == 0) {
-				blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
-				blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
+				blendFillClip(x, ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
+				blendFillClip(x, ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
 				hb |= (1 << y);
 			}
 		}
 
 		ptr_fill += pitch * r;
-		while (short_h--) {
-			blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+		int realy = ystart;
+		while (short_h--) {			
+			if (realy >= _clippingArea.top && realy <= _clippingArea.bottom)
+				blendFillClip(xstart+x, ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
 			ptr_fill += pitch;
+			++realy;
 		}
 
 		// Make shadow smaller each iteration, and move it one pixel inward
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 13377d8..8a101b8 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -81,6 +81,8 @@ public:
 
 protected:
 
+	Common::Rect _clippingArea;
+
 	/**
 	 * Draws a single pixel on the surface with the given coordinates and
 	 * the given color.
@@ -159,12 +161,21 @@ protected:
 	virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h,
 	    PixelType color, FillMode fill_m);
 
+	virtual void drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h,
+		PixelType color, FillMode fill_m);
+
 	virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h,
 	    PixelType color, FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l);
 
+	virtual void drawBorderRoundedSquareAlgClip(int x1, int y1, int r, int w, int h,
+		PixelType color, FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l);
+
 	virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h,
 	    PixelType color, FillMode fill_m);
 
+	virtual void drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h,
+		PixelType color, FillMode fill_m);
+
 	virtual void drawSquareAlg(int x, int y, int w, int h,
 	    PixelType color, FillMode fill_m);
 
@@ -213,6 +224,7 @@ protected:
 
 	void precalcGradient(int h);
 	void gradientFill(PixelType *first, int width, int x, int y);
+	void gradientFillClip(PixelType *first, int width, int x, int y, int realX, int realY);
 
 	/**
 	 * Fills several pixels in a row with a given color and the specified alpha blending.
@@ -228,6 +240,28 @@ protected:
 		while (first != last) blendPixelPtr(first++, color, alpha);
 	}
 
+	inline void blendFillClip(PixelType *first, PixelType *last, PixelType color, uint8 alpha, int realX, int realY) {
+		if (_clippingArea.top <= realY && realY < _clippingArea.bottom) {
+			while (first != last) {
+				if (_clippingArea.left <= realX && realX < _clippingArea.right)
+					blendPixelPtr(first++, color, alpha);
+				else
+					++first;
+				++realX;
+			}
+		}
+	}
+
+	inline void blendFillClip(int x, PixelType *first, PixelType *last, PixelType color, uint8 alpha) {
+		while (first != last) {
+			if (x >= _clippingArea.left && x <= _clippingArea.right)
+				blendPixelPtr(first++, color, alpha);
+			else
+				++first;
+			++x;
+		}
+	}
+
 	void darkenFill(PixelType *first, PixelType *last);
 
 	const PixelFormat _format;
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 3c6f595..1204f00 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -265,8 +265,9 @@ void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) {
 
 	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);
+		for (step = _data->_steps.begin(); step != _data->_steps.end(); ++step) {
+			_engine->renderer()->drawStepClip(_area, _clip, *step, _dynamicData);
+		}
 	}
 
 	_engine->addDirtyRect(extendedRect);
diff --git a/gui/object.cpp b/gui/object.cpp
index ef2cc9d..2d9e959 100644
--- a/gui/object.cpp
+++ b/gui/object.cpp
@@ -45,6 +45,7 @@ void GuiObject::reflowLayout() {
 			error("Could not load widget position for '%s'", _name.c_str());
 		}
 
+		/*
 		if (_x < 0)
 			error("Widget <%s> has x < 0 (%d)", _name.c_str(), _x);
 		if (_x >= g_gui.getWidth())
@@ -57,6 +58,7 @@ void GuiObject::reflowLayout() {
 			error("Widget <%s> has y > %d (%d)", _name.c_str(), g_gui.getHeight(), _y);
 		if (_y + _h > g_gui.getHeight())
 			error("Widget <%s> has y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), _y + _h);
+			*/
 	}
 }
 
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 8b9341f..5e112b4 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -50,7 +50,7 @@ void ScrollContainerWidget::init() {
 }
 
 void ScrollContainerWidget::recalc() {
-	_verticalScroll->_numEntries = _h;
+	_verticalScroll->_numEntries = _h + 40;
 	_verticalScroll->_currentPos = _scrolledY;
 	_verticalScroll->_entriesPerPage = _limitH;
 	_verticalScroll->setPos(_w - 16, _scrolledY);


Commit: fca0f0ed3496530fc0d63efdde9f32fb995cd671
    https://github.com/scummvm/scummvm/commit/fca0f0ed3496530fc0d63efdde9f32fb995cd671
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:16:43+02:00

Commit Message:
GUI: Make PopUpWidget clip

Changed paths:
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widget.cpp
    gui/widget.h
    gui/widgets/popup.cpp



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 1204f00..037940d 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -270,6 +270,8 @@ void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) {
 		}
 	}
 
+	extendedRect.clip(_clip);
+
 	_engine->addDirtyRect(extendedRect);
 }
 
@@ -1180,6 +1182,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;
@@ -1210,6 +1233,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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 76581fa..af8c293 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -341,6 +341,9 @@ public:
 	void drawWidgetBackground(const Common::Rect &r, uint16 hints,
 	                          WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
 
+	void drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clippingArea, uint16 hints,
+								WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
+
 	void drawButton(const Common::Rect &r, const Common::String &str,
 	                WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
 
@@ -368,6 +371,8 @@ public:
 
 	void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
 	                     int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+	void drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &sel,
+							int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
 
 	void drawCaret(const Common::Rect &r, bool erase,
 	               WidgetStateInfo state = kStateEnabled);
diff --git a/gui/widget.cpp b/gui/widget.cpp
index d17fabe..ed7cf93 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -280,11 +280,8 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) {
 
 
 void StaticTextWidget::drawWidget() {
-	int px = _boss->getAbsX();
-	int py = _boss->getAbsY();
 	g_gui.theme()->drawTextClip(
-		Common::Rect(_x, _y, _x+_w, _y+_h),		
-		Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight()),
+		Common::Rect(_x, _y, _x+_w, _y+_h),	getBossClipRect(),
 		_label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
 	);
 }
@@ -324,12 +321,9 @@ void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 	setPressedState();
 }
 
-void ButtonWidget::drawWidget() {	
-	int px = _boss->getAbsX();
-	int py = _boss->getAbsY();
+void ButtonWidget::drawWidget() {
 	g_gui.theme()->drawButtonClip(
-		Common::Rect(_x, _y, _x + _w, _y + _h),
-		Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight()),
+		Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
 		_label, _state, getFlags()
 	);
 }
diff --git a/gui/widget.h b/gui/widget.h
index 388b348..db801fa 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -112,6 +112,11 @@ public:
 
 	virtual int16	getAbsX() const	{ return _x + _boss->getChildX(); }
 	virtual int16	getAbsY() const	{ return _y + _boss->getChildY(); }
+	virtual Common::Rect getBossClipRect() const {
+		int px = _boss->getAbsX();
+		int py = _boss->getAbsY();
+		return Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight());
+	}
 
 	virtual void setPos(int x, int y) { _x = x; _y = y; }
 	virtual void setSize(int w, int h) { _w = w; _h = h; }
diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp
index 0a1010f..e157f29 100644
--- a/gui/widgets/popup.cpp
+++ b/gui/widgets/popup.cpp
@@ -150,7 +150,7 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
 
 void PopUpDialog::drawDialog() {
 	// Draw the menu border
-	g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0);
+	g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), _popUpBoss->getBossClipRect(), 0);
 
 	/*if (_twoColumns)
 		g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/
@@ -364,8 +364,11 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
 		// Draw a separator
 		g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
 	} else {
-		g_gui.theme()->drawText(Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), name,	hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
-								Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding);
+		g_gui.theme()->drawTextClip(
+			Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), _popUpBoss->getBossClipRect(),
+			name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
+			Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding
+		);
 	}
 }
 
@@ -470,7 +473,10 @@ void PopUpWidget::drawWidget() {
 	Common::String sel;
 	if (_selectedItem >= 0)
 		sel = _entries[_selectedItem].name;
-	g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, _leftPadding, _state, Graphics::kTextAlignLeft);
+	g_gui.theme()->drawPopUpWidgetClip(
+		Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
+		sel, _leftPadding, _state, Graphics::kTextAlignLeft
+	);
 }
 
 } // End of namespace GUI


Commit: b946ef8598b96631057beffddbf35b627fa25b8d
    https://github.com/scummvm/scummvm/commit/b946ef8598b96631057beffddbf35b627fa25b8d
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:17:01+02:00

Commit Message:
GUI: Make ScrollContainerWidget hide children

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 5e112b4..f2fb213 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -81,7 +81,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 	switch (cmd) {
 	case kSetPositionCmd:
 		_scrolledY = _verticalScroll->_currentPos;
-		recalc();
+		reflowLayout();
 		draw();
 		break;
 	}	
@@ -90,6 +90,16 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 void ScrollContainerWidget::reflowLayout() {
 	recalc();
 	Widget::reflowLayout();
+	Widget *ptr = _firstWidget;
+	while (ptr) {
+		int y = ptr->getAbsY() - getChildY();
+		int h = ptr->getHeight();
+		bool visible = true;
+		if (y + h - _scrolledY < 0) visible = false;
+		if (y - _scrolledY > _limitH) visible = false;
+		ptr->setVisible(visible);
+		ptr = ptr->next();
+	}
 }
 
 void ScrollContainerWidget::drawWidget() {


Commit: 425d963bd3c927e529efdfed817960dec8de4552
    https://github.com/scummvm/scummvm/commit/425d963bd3c927e529efdfed817960dec8de4552
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:17:26+02:00

Commit Message:
GUI: Fix ThemeItemTextData's dirty rectangle

Changed paths:
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 8a471d5..6281de7 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -2382,18 +2382,18 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 			if (y + ystart  < _clippingArea.top || y + ystart  > _clippingArea.bottom) continue;
 
 			if (((1 << x) & hb) == 0) {
-				blendFillClip(xstart + r + x, ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
+				blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
 
 				// Will create a dark line of pixles if left out
 				if (hb > 0) {
-					blendFillClip(x, ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
+					blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
 				}
 				hb |= (1 << x);
 			}
 
 			if (((1 << y) & hb) == 0) {
-				blendFillClip(x, ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
-				blendFillClip(x, ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
+				blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
+				blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
 				hb |= (1 << y);
 			}
 		}
@@ -2402,7 +2402,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 		int realy = ystart;
 		while (short_h--) {			
 			if (realy >= _clippingArea.top && realy <= _clippingArea.bottom)
-				blendFillClip(xstart+x, ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+				blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
 			ptr_fill += pitch;
 			++realy;
 		}
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 8a101b8..8a7ce78 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -252,16 +252,6 @@ protected:
 		}
 	}
 
-	inline void blendFillClip(int x, PixelType *first, PixelType *last, PixelType color, uint8 alpha) {
-		while (first != last) {
-			if (x >= _clippingArea.left && x <= _clippingArea.right)
-				blendPixelPtr(first++, color, alpha);
-			else
-				++first;
-			++x;
-		}
-	}
-
 	void darkenFill(PixelType *first, PixelType *last);
 
 	const PixelFormat _format;
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 037940d..a38e565 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -276,15 +276,19 @@ void ThemeItemDrawDataClip::drawSelf(bool draw, bool restore) {
 }
 
 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) {
@@ -1414,12 +1418,12 @@ void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippi
 
 	switch (inverted) {
 	case kTextInversion:
-		queueDD(kDDTextSelectionBackground, r);
+		queueDDClip(kDDTextSelectionBackground, r, clippingArea);
 		restore = false;
 		break;
 
 	case kTextInversionFocus:
-		queueDD(kDDTextSelectionFocusBackground, r);
+		queueDDClip(kDDTextSelectionFocusBackground, r, clippingArea);
 		restore = false;
 		break;
 


Commit: 31e528c070d14baf62dc1e8570075425a2efbb42
    https://github.com/scummvm/scummvm/commit/31e528c070d14baf62dc1e8570075425a2efbb42
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:17:43+02:00

Commit Message:
GUI: Make ScrollContainerWidget do full redraw

Changed paths:
    gui/gui-manager.cpp
    gui/gui-manager.h
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 3ce8bee..9acd943 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -564,6 +564,12 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi
 	}
 }
 
+void GuiManager::doFullRedraw() {
+	_redrawStatus = kRedrawFull;
+	redraw();
+	_system->updateScreen();
+}
+
 void GuiManager::giveFocusToDialog(Dialog *dialog) {
 	int16 dialogX = _globalMousePosition.x - dialog->_x;
 	int16 dialogY = _globalMousePosition.y - dialog->_y;
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 3577921..4dc9af9 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -73,6 +73,7 @@ public:
 	void runLoop();
 
 	void processEvent(const Common::Event &event, Dialog *const activeDialog);
+	void doFullRedraw();
 
 	bool isActive() const	{ return ! _dialogStack.empty(); }
 
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index f2fb213..fffa451 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -83,6 +83,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 		_scrolledY = _verticalScroll->_currentPos;
 		reflowLayout();
 		draw();
+		g_gui.doFullRedraw();
 		break;
 	}	
 }


Commit: e04e13de33cd0440abd194db81062c00536adbd9
    https://github.com/scummvm/scummvm/commit/e04e13de33cd0440abd194db81062c00536adbd9
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:18:00+02:00

Commit Message:
GUI: Remove unnecessary debug output

Changed paths:
    graphics/VectorRendererSpec.cpp



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 6281de7..42f0223 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1143,14 +1143,12 @@ drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw,
 		&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
 		&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
 		&& h > (Base::_shadowOffset + 1) * 2) {
-		debug("shadow");
 		drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
 	}
 
 	if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
 		drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
 	} else {
-		debug("clipclipclip %d..%d %d..%d", cx, cw + cx, cy, cy + ch);
 		drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
 	}
 
@@ -1904,7 +1902,6 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
 	PixelType color1 = color;
 	PixelType color2 = color;
 
-	debug("from %d to %d (drawing from %d to %d or something)", _clippingArea.left, _clippingArea.right, x1, x1+w);
 	while (sw++ < Base::_strokeWidth) {
 		blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top
 		blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom
@@ -2192,7 +2189,6 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
 
 	// If only border is visible
 	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
-		debug("interior");
 		if (fill_m == Base::kFillBackground)
 			drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m);
 		else
@@ -2200,7 +2196,6 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
 	}
 
 	if (Base::_strokeWidth) {
-		debug("stroke");
 		if (r != 0 && _bevel > 0) {
 			drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
 			drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
@@ -2223,8 +2218,6 @@ drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, V
 	const uint8 bevelAlpha_b = 0;
 	const uint8 bevelAlpha_l = 127;
 
-	debug("clip version");
-
 	// If only border is visible	
 	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {		
 		if (fill_m == Base::kFillBackground)
@@ -2352,8 +2345,6 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 	int width = w + offset + 2;
 	int height = h + offset + 1;
 
-	debug("from %d to %d (drawing from %d to %d or something)", _clippingArea.left, _clippingArea.right, xstart, xstart + width);
-
 	for (int i = offset; i >= 0; i--) {
 		int f, ddF_x, ddF_y;
 		int x, y, px, py;


Commit: cccf6eed785c232b430b722e1025be3a8e5f4784
    https://github.com/scummvm/scummvm/commit/cccf6eed785c232b430b722e1025be3a8e5f4784
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:18:18+02:00

Commit Message:
GUI: Add drawRoundedSquareShadowClip()

Changed paths:
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 42f0223..9339c8e 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1143,7 +1143,11 @@ drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw,
 		&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
 		&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
 		&& h > (Base::_shadowOffset + 1) * 2) {
-		drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
+		if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
+			drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
+		} else {
+			drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset);
+		}
 	}
 
 	if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
@@ -2369,9 +2373,6 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 		while (x++ < y) {
 			BE_ALGORITHM();
 
-			if (x + xstart < _clippingArea.left || x + xstart > _clippingArea.right) continue;
-			if (y + ystart  < _clippingArea.top || y + ystart  > _clippingArea.bottom) continue;
-
 			if (((1 << x) & hb) == 0) {
 				blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
 
@@ -2390,12 +2391,9 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 		}
 
 		ptr_fill += pitch * r;
-		int realy = ystart;
 		while (short_h--) {			
-			if (realy >= _clippingArea.top && realy <= _clippingArea.bottom)
-				blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
-			ptr_fill += pitch;
-			++realy;
+			blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+			ptr_fill += pitch;			
 		}
 
 		// Make shadow smaller each iteration, and move it one pixel inward
@@ -2410,6 +2408,83 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+	// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+	uint8 expFactor = 3;
+	uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
+
+	// These constants ensure a border of 2px on the left and of each rounded square
+	int xstart = (x1 > 2) ? x1 - 2 : x1;
+	int ystart = y1;
+	int width = w + offset + 2;
+	int height = h + offset + 1;
+
+	for (int i = offset; i >= 0; i--) {
+		int f, ddF_x, ddF_y;
+		int x, y, px, py;
+
+		PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
+		PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
+		PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
+		PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
+		PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+		int short_h = height - (2 * r) + 2;
+		PixelType color = _format.RGBToColor(0, 0, 0);
+
+		BE_RESET();
+
+		// HACK: As we are drawing circles exploting 8-axis symmetry,
+		// there are 4 pixels on each circle which are drawn twice.
+		// this is ok on filled circles, but when blending on surfaces,
+		// we cannot let it blend twice. awful.
+		uint32 hb = 0;
+
+		while (x++ < y) {
+			BE_ALGORITHM();
+
+			if (((1 << x) & hb) == 0) {
+				blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
+					xstart + r - y, ystart + r - x);
+
+				// Will create a dark line of pixles if left out
+				if (hb > 0) {
+					blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
+						xstart + r - y, ystart + height - r + x);
+				}
+				hb |= (1 << x);
+			}
+
+			if (((1 << y) & hb) == 0) {
+				blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, xstart + r - x, ystart + r - y);
+				blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha, xstart + r - x, ystart + height - r + y);
+				hb |= (1 << y);
+			}
+		}
+
+		ptr_fill += pitch * r;
+		int orig_short_h = short_h;
+		while (short_h--) {			
+			blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha,
+				xstart, ystart + r + orig_short_h - short_h - 1);
+			ptr_fill += pitch;
+		}
+
+		// Make shadow smaller each iteration, and move it one pixel inward
+		xstart += 1;
+		ystart += 1;
+		width -= 2;
+		height -= 2;
+
+		if (_shadowFillMode == kShadowExponential)
+			// Multiply with expfactor
+			alpha = (alpha * (expFactor << 8)) >> 9;
+	}
+}
 
 /******************************************************************************/
 
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 8a7ce78..7a1fe36 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -210,6 +210,7 @@ protected:
 	 */
 	virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
 	virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset);
+	virtual void drawRoundedSquareShadowClip(int x, int y, int r, int w, int h, int offset);
 
 	/**
 	 * Calculates the color gradient on a given point.


Commit: 9c1eab6415729b1c5edf362f0792cde250a382ab
    https://github.com/scummvm/scummvm/commit/9c1eab6415729b1c5edf362f0792cde250a382ab
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:18:34+02:00

Commit Message:
GUI: Fix ScrollContainerWidget look a bit

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index fffa451..d27c9df 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -53,8 +53,8 @@ void ScrollContainerWidget::recalc() {
 	_verticalScroll->_numEntries = _h + 40;
 	_verticalScroll->_currentPos = _scrolledY;
 	_verticalScroll->_entriesPerPage = _limitH;
-	_verticalScroll->setPos(_w - 16, _scrolledY);
-	_verticalScroll->setSize(16, _limitH);
+	_verticalScroll->setPos(_w - 16, _scrolledY+1);
+	_verticalScroll->setSize(16, _limitH -2);
 }
 
 
@@ -104,7 +104,7 @@ void ScrollContainerWidget::reflowLayout() {
 }
 
 void ScrollContainerWidget::drawWidget() {
-	g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight()), ThemeEngine::kDialogBackgroundDefault);
+	g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1), ThemeEngine::kDialogBackgroundDefault);
 }
 
 Widget *ScrollContainerWidget::findWidget(int x, int y) {


Commit: ac25acbccc384eaf1a4e5169da1da3e475b97c83
    https://github.com/scummvm/scummvm/commit/ac25acbccc384eaf1a4e5169da1da3e475b97c83
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:18:52+02:00

Commit Message:
GUI: Update ScrollContainerWidget

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index d27c9df..b975c42 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -50,11 +50,32 @@ void ScrollContainerWidget::init() {
 }
 
 void ScrollContainerWidget::recalc() {
-	_verticalScroll->_numEntries = _h + 40;
+	int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
+
+	//calculate _limitH - available height (boss's height - boss's "offset")
+	int d = _boss->getChildY() - _boss->getAbsY();	
+	_limitH = _boss->getHeight() - d;
+	
+	//calculate virtual height
+	const int spacing = g_gui.xmlEval()->getVar("Global.Font.Height", 16); //on the bottom
+	int h = 0;
+	int min = spacing, max = 0;
+	Widget *ptr = _firstWidget;
+	while (ptr) {
+		if (ptr != _verticalScroll) {
+			int y = ptr->getAbsY() - getChildY();
+			min = MIN(min, y - spacing);
+			max = MAX(max, y + ptr->getHeight() + spacing);
+		}
+		ptr = ptr->next();
+	}
+	h = max - min;
+
+	_verticalScroll->_numEntries = h;
 	_verticalScroll->_currentPos = _scrolledY;
 	_verticalScroll->_entriesPerPage = _limitH;
-	_verticalScroll->setPos(_w - 16, _scrolledY+1);
-	_verticalScroll->setSize(16, _limitH -2);
+	_verticalScroll->setPos(_w - scrollbarWidth, _scrolledY+1);
+	_verticalScroll->setSize(scrollbarWidth, _limitH -2);
 }
 
 
@@ -69,7 +90,7 @@ int16 ScrollContainerWidget::getChildY() const {
 }
 
 uint16 ScrollContainerWidget::getWidth() const {
-	return (_boss ? _boss->getWidth() : _w);
+	return _w - _verticalScroll->getWidth();
 }
 
 uint16 ScrollContainerWidget::getHeight() const {
@@ -89,8 +110,8 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 }
 
 void ScrollContainerWidget::reflowLayout() {
-	recalc();
 	Widget::reflowLayout();
+	recalc();
 	Widget *ptr = _firstWidget;
 	while (ptr) {
 		int y = ptr->getAbsY() - getChildY();
@@ -108,6 +129,8 @@ void ScrollContainerWidget::drawWidget() {
 }
 
 Widget *ScrollContainerWidget::findWidget(int x, int y) {
+	if (x >= _w - _verticalScroll->getWidth())
+		return _verticalScroll;
 	return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
 }
 


Commit: 40fa9b4de3f719ad11ceb665a724712ccbcb7376
    https://github.com/scummvm/scummvm/commit/40fa9b4de3f719ad11ceb665a724712ccbcb7376
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:19:15+02:00

Commit Message:
GUI: Fix ScrollContainerWidget's reflowLayout()

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index b975c42..fdb02f8 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -111,9 +111,20 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 
 void ScrollContainerWidget::reflowLayout() {
 	Widget::reflowLayout();
-	recalc();
+
+	//reflow layout of inner widgets
 	Widget *ptr = _firstWidget;
 	while (ptr) {
+		ptr->reflowLayout();
+		ptr = ptr->next();
+	}
+	
+	//recalculate height
+	recalc();
+
+	//hide those widgets which are out of visible area
+	ptr = _firstWidget;
+	while (ptr) {
 		int y = ptr->getAbsY() - getChildY();
 		int h = ptr->getHeight();
 		bool visible = true;


Commit: 421f9826c8ad403d76b6f40bf1aa4c7c0ec7e676
    https://github.com/scummvm/scummvm/commit/421f9826c8ad403d76b6f40bf1aa4c7c0ec7e676
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:19:31+02:00

Commit Message:
GUI: Hide scrollbar in ScrollContainerWidget when needed

Changed paths:
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index fdb02f8..1173b08 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -90,7 +90,7 @@ int16 ScrollContainerWidget::getChildY() const {
 }
 
 uint16 ScrollContainerWidget::getWidth() const {
-	return _w - _verticalScroll->getWidth();
+	return _w - (_verticalScroll->isVisible() ? _verticalScroll->getWidth() : 0);
 }
 
 uint16 ScrollContainerWidget::getHeight() const {
@@ -133,6 +133,8 @@ void ScrollContainerWidget::reflowLayout() {
 		ptr->setVisible(visible);
 		ptr = ptr->next();
 	}
+
+	_verticalScroll->setVisible(_verticalScroll->_numEntries > _limitH); //show when there is something to scroll
 }
 
 void ScrollContainerWidget::drawWidget() {
@@ -140,7 +142,7 @@ void ScrollContainerWidget::drawWidget() {
 }
 
 Widget *ScrollContainerWidget::findWidget(int x, int y) {
-	if (x >= _w - _verticalScroll->getWidth())
+	if (_verticalScroll->isVisible() && x >= _w - _verticalScroll->getWidth())
 		return _verticalScroll;
 	return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
 }


Commit: 24963ac97d85a3d78d5b36d63be6cea6f63d178d
    https://github.com/scummvm/scummvm/commit/24963ac97d85a3d78d5b36d63be6cea6f63d178d
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:19:48+02:00

Commit Message:
GUI: Fix Dialog's and TabWidget's reflowLayout()

Changed paths:
    gui/dialog.cpp
    gui/widgets/tab.cpp



diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 50b7755..523227a 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -113,13 +113,13 @@ void Dialog::reflowLayout() {
 	// changed, so any cached image may be invalid. The subsequent redraw
 	// should be treated as the very first draw.
 
+	GuiObject::reflowLayout();
+
 	Widget *w = _firstWidget;
 	while (w) {
 		w->reflowLayout();
 		w = w->_next;
 	}
-
-	GuiObject::reflowLayout();
 }
 
 void Dialog::lostFocus() {
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index 756781a..689bf37 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -258,6 +258,10 @@ void TabWidget::adjustTabs(int value) {
 void TabWidget::reflowLayout() {
 	Widget::reflowLayout();
 
+	_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
+	_tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
+	_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
+
 	for (uint i = 0; i < _tabs.size(); ++i) {
 		Widget *w = _tabs[i].firstWidget;
 		while (w) {
@@ -266,10 +270,6 @@ void TabWidget::reflowLayout() {
 		}
 	}
 
-	_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
-	_tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
-	_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
-
 	if (_tabWidth == 0) {
 		_tabWidth = 40;
 #ifdef __DS__


Commit: 0ae4409138f828ee7eb0241db44f43d68cec85d8
    https://github.com/scummvm/scummvm/commit/0ae4409138f828ee7eb0241db44f43d68cec85d8
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:20:03+02:00

Commit Message:
GUI: Add ThemeLayoutTabWidget

Changed paths:
    gui/ThemeEval.cpp
    gui/ThemeLayout.h
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/widgets/scrollcontainer.cpp
    gui/widgets/tab.cpp



diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp
index 9d57d24..9b7b57c 100644
--- a/gui/ThemeEval.cpp
+++ b/gui/ThemeEval.cpp
@@ -89,12 +89,20 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common
 		typeW = getVar("Globals." + type + ".Width", -1);
 		typeH = getVar("Globals." + type + ".Height", -1);
 		typeAlign = (Graphics::TextAlign)getVar("Globals." + type + ".Align", Graphics::kTextAlignInvalid);
-	}
-
-	ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name,
-								typeW == -1 ? w : typeW,
-								typeH == -1 ? h : typeH,
-								typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign);
+	}	
+
+	ThemeLayoutWidget *widget;
+	if (type == "TabWidget")
+		widget = new ThemeLayoutTabWidget(_curLayout.top(), name,
+									typeW == -1 ? w : typeW,
+									typeH == -1 ? h : typeH,
+									typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
+									getVar("Globals.TabWidget.Tab.Height", 0));
+	else
+		widget = new ThemeLayoutWidget(_curLayout.top(), name,
+									typeW == -1 ? w : typeW,
+									typeH == -1 ? h : typeH,
+									typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign);
 
 	_curLayout.top()->addChild(widget);
 	setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0);
diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h
index c4d7e67..00e55ce 100644
--- a/gui/ThemeLayout.h
+++ b/gui/ThemeLayout.h
@@ -45,7 +45,8 @@ public:
 		kLayoutMain,
 		kLayoutVertical,
 		kLayoutHorizontal,
-		kLayoutWidget
+		kLayoutWidget,
+		kLayoutTabWidget
 	};
 
 	ThemeLayout(ThemeLayout *p) :
@@ -223,6 +224,41 @@ protected:
 	Common::String _name;
 };
 
+class ThemeLayoutTabWidget : public ThemeLayoutWidget {
+	int _tabHeight;
+
+public:
+	ThemeLayoutTabWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h, Graphics::TextAlign align, int tabHeight):
+		ThemeLayoutWidget(p, name, w, h, align) {
+		_tabHeight = tabHeight;
+	}
+
+	void reflowLayout() {		
+		for (uint i = 0; i < _children.size(); ++i) {
+			_children[i]->resetLayout();
+			_children[i]->reflowLayout();
+		}
+	}
+
+	virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) {
+		if (ThemeLayoutWidget::getWidgetData(name, x, y, w, h)) {
+			h -= _tabHeight;
+			return true;
+		}
+
+		return false;
+	}
+
+protected:
+	LayoutType getLayoutType() { return kLayoutTabWidget; }
+
+	ThemeLayout *makeClone(ThemeLayout *newParent) {
+		ThemeLayoutTabWidget *n = new ThemeLayoutTabWidget(*this);
+		n->_parent = newParent;
+		return n;
+	}
+};
+
 class ThemeLayoutSpacing : public ThemeLayout {
 public:
 	ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p) {
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index c73ffa1..56a54f8 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -236,7 +236,7 @@
 
 	<dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
-			<widget name = 'TabWidget'/>
+			<widget name = 'TabWidget' type = 'TabWidget'/>
 			<layout type = 'horizontal' padding = '16, 16, 16, 16'>
 				<space/>
 				<widget name = 'Cancel'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 43ec0cd..1c87e85 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -554,7 +554,7 @@
 
 	<dialog name = 'GameOptions' overlays = 'screen' inset = '16' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
-			<widget name = 'TabWidget'/>
+			<widget name = 'TabWidget' type = 'TabWidget'/>
 			<layout type = 'horizontal' padding = '8, 8, 8, 8'>
 				<space/>
 				<widget name = 'Cancel'
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 1173b08..eca0279 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -51,10 +51,7 @@ void ScrollContainerWidget::init() {
 
 void ScrollContainerWidget::recalc() {
 	int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
-
-	//calculate _limitH - available height (boss's height - boss's "offset")
-	int d = _boss->getChildY() - _boss->getAbsY();	
-	_limitH = _boss->getHeight() - d;
+	_limitH = _h;
 	
 	//calculate virtual height
 	const int spacing = g_gui.xmlEval()->getVar("Global.Font.Height", 16); //on the bottom
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index 689bf37..393f63a 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -80,6 +80,8 @@ TabWidget::~TabWidget() {
 }
 
 int16 TabWidget::getChildY() const {
+	// NOTE: if you change that, make sure to do the same
+	// changes in the ThemeLayoutTabWidget (gui/ThemeLayout.cpp)
 	return getAbsY() + _tabHeight;
 }
 
@@ -258,6 +260,8 @@ void TabWidget::adjustTabs(int value) {
 void TabWidget::reflowLayout() {
 	Widget::reflowLayout();
 
+	// NOTE: if you change that, make sure to do the same
+	// changes in the ThemeLayoutTabWidget (gui/ThemeLayout.cpp)
 	_tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height");
 	_tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width");
 	_titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top");
@@ -304,7 +308,7 @@ void TabWidget::drawWidget() {
 	for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
 		tabs.push_back(_tabs[i].title);
 	}
-	g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType);
+	g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), _bodyBackgroundType);
 
 	g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
 }


Commit: 5868d6d47150f3595a499936566eafc717e63802
    https://github.com/scummvm/scummvm/commit/5868d6d47150f3595a499936566eafc717e63802
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:20:21+02:00

Commit Message:
GUI: Fix TabWidget's padding in layout_lowres.stx

Changed paths:
    gui/themes/scummmodern/scummmodern_layout_lowres.stx



diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 1c87e85..a3f06bd 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -95,7 +95,7 @@
 				padding = '0, 0, 2, 0'
 		/>
 		<widget name = 'TabWidget.Body'
-				padding = '0, 0, 0, -8'
+				padding = '0, 0, 0, 0'
 		/>
 		<widget name = 'TabWidget.NavButton'
 				size = '32, 18'


Commit: 559ca37dafea7fa07f2453ee9221df072c501b22
    https://github.com/scummvm/scummvm/commit/559ca37dafea7fa07f2453ee9221df072c501b22
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:20:37+02:00

Commit Message:
GUI: Add VectorRendererSpec::drawTriangleClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widgets/scrollbar.cpp



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 2af91d3..a84062c 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -187,6 +187,7 @@ public:
 	 * @param orient Orientation of the triangle.
 	 */
 	virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0;
+	virtual void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a beveled square like the ones in the Classic GUI themes.
@@ -390,7 +391,7 @@ public:
 	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawTriangle(x, y, w, h, (TriangleOrientation)step.extraData);
+		drawTriangleClip(x, y, w, h, (TriangleOrientation)step.extraData, clip);
 	}
 
 	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 9339c8e..f2a69d3 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -872,6 +872,13 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
 
 template<typename PixelType>
 inline void VectorRendererSpec<PixelType>::
+blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y) {
+	if (IS_IN_CLIP(x, y))
+		blendPixelPtr(ptr, color, alpha);
+}
+
+template<typename PixelType>
+inline void VectorRendererSpec<PixelType>::
 blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) {
 	int idst = *ptr;
 	// This function is only used for corner pixels in rounded rectangles, so
@@ -1263,8 +1270,88 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTriangleClip(int x, int y, int w, int h, TriangleOrientation orient, Common::Rect clipping) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
+		return;
+
+	PixelType color = 0;
+
+	if (Base::_strokeWidth <= 1) {
+		if (Base::_fillMode == kFillForeground)
+			color = _fgColor;
+		else if (Base::_fillMode == kFillBackground)
+			color = _bgColor;
+	} else {
+		if (Base::_fillMode == kFillDisabled)
+			return;
+		color = _fgColor;
+	}
+
+	if (Base::_dynamicData != 0)
+		orient = (TriangleOrientation)Base::_dynamicData;
+
+	Common::Rect backup = _clippingArea;
+	_clippingArea = clipping;
+	bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+	if (w == h) {
+		int newW = w;
+
+		switch (orient) {
+		case kTriangleUp:
+		case kTriangleDown:
+			if (useClippingVersions)
+				drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+			else
+				drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+			break;
 
+		case kTriangleLeft:
+		case kTriangleRight:
+		case kTriangleAuto:
+			break;
+		}
 
+		if (Base::_strokeWidth > 0)
+			if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
+				if (useClippingVersions)
+					drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+				else
+					drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+			}
+	} else {
+		int newW = w;
+		int newH = h;
+
+		switch (orient) {
+		case kTriangleUp:
+		case kTriangleDown:
+			if (useClippingVersions)
+				drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
+			else
+				drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
+			break;
+
+		case kTriangleLeft:
+		case kTriangleRight:
+		case kTriangleAuto:
+			break;
+		}
+
+		if (Base::_strokeWidth > 0) {
+			if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
+				if (useClippingVersions)
+					drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
+				else
+					drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
+			}
+		}
+	}
+
+	_clippingArea = backup;
+}
 
 
 /********************************************************************
@@ -1821,6 +1908,212 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
 
 }
 
+/////////////
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+	// Don't draw anything for empty rects. This assures dy is always different
+	// from zero.
+	if (w <= 0 || h <= 0) {
+		return;
+	}
+
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int gradient_h = 0;
+	int y_pitch_sign = 1;
+	if (!inverted) {
+		pitch = -pitch;
+		y1 += h;
+		y_pitch_sign = -1;
+	}
+
+	PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+	PixelType *floor = ptr_right - 1;
+	PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
+
+	int x2 = x1 + w / 2;
+	int y2 = y1 + h;
+	int x_right = x1;
+	int y_right = y1;
+	int x_left = x1 + w;
+	int y_left = y1;
+	int x_floor = x_right - 1;
+	int y_floor = y_right;
+
+#if FIXED_POINT
+	int dx = (x2 - x1) << 8;
+	int dy = (y2 - y1) << 8;
+
+	if (abs(dx) > abs(dy)) {
+#else
+	double dx = (double)x2 - (double)x1;
+	double dy = (double)y2 - (double)y1;
+
+	if (fabs(dx) > fabs(dy)) {
+#endif
+		while (floor++ != ptr_left)
+			blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+		// In this branch dx is always different from zero. This is because
+		// abs(dx) is strictly greater than abs(dy), and abs returns zero
+		// as minimal value.
+		int gradient = (dy << 8) / dx;
+		int intery = (y1 << 8) + gradient;
+#else
+		double gradient = dy / dx;
+		double intery = y1 + gradient;
+#endif
+
+		for (int x = x1 + 1; x < x2; x++) {
+#if FIXED_POINT
+			if (intery + gradient > ipart(intery) + 0x100) {
+#else
+			if (intery + gradient > ipart(intery) + 1) {
+#endif
+				ptr_right++;
+				ptr_left--;
+				++x_right;
+				--x_left;
+			}
+
+			ptr_left += pitch;
+			ptr_right += pitch;
+			y_right += y_pitch_sign;
+			y_left += y_pitch_sign;
+
+			intery += gradient;
+
+			switch (fill_m) {
+			case kFillDisabled:
+				if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+				if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+				break;
+			case kFillForeground:
+			case kFillBackground:
+				colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+				blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
+				blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
+				break;
+			case kFillGradient:
+				colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+				blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
+				blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
+				break;
+			}
+			}
+
+		return;
+		}
+
+#if FIXED_POINT
+	if (abs(dx) < abs(dy)) {
+#else
+	if (fabs(dx) < fabs(dy)) {
+#endif
+		ptr_left--;
+		--x_left;
+		while (floor++ != ptr_left)
+			blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+		int gradient = (dx << 8) / (dy + 0x100);
+		int interx = (x1 << 8) + gradient;
+#else
+		double gradient = dx / (dy + 1);
+		double interx = x1 + gradient;
+#endif
+
+		for (int y = y1 + 1; y < y2; y++) {
+#if FIXED_POINT
+			if (interx + gradient > ipart(interx) + 0x100) {
+#else
+			if (interx + gradient > ipart(interx) + 1) {
+#endif
+				ptr_right++;
+				ptr_left--;
+				++x_right;
+				--x_left;
+			}
+
+			ptr_left += pitch;
+			ptr_right += pitch;
+			y_right += y_pitch_sign;
+			y_left += y_pitch_sign;
+
+			interx += gradient;
+
+			switch (fill_m) {
+			case kFillDisabled:
+				if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+				if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+				break;
+			case kFillForeground:
+			case kFillBackground:
+				colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+				blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+				blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+				break;
+			case kFillGradient:
+				colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+				blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+				blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+				break;
+			}
+			}
+
+		return;
+		}
+
+	ptr_left--;
+	--x_left;
+	while (floor++ != ptr_left)
+		blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+	int gradient = (dx / dy) << 8;
+	int interx = (x1 << 8) + gradient;
+#else
+	double gradient = dx / dy;
+	double interx = x1 + gradient;
+#endif
+
+	for (int y = y1 + 1; y < y2; y++) {
+		ptr_right++;
+		ptr_left--;
+		++x_right;
+		--x_left;
+
+		ptr_left += pitch;
+		ptr_right += pitch;
+		y_right += y_pitch_sign;
+		y_left += y_pitch_sign;
+
+		interx += gradient;
+
+		switch (fill_m) {
+		case kFillDisabled:			
+			if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+			if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+			break;
+		case kFillForeground:
+		case kFillBackground:
+			colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+			blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+			blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+			break;
+		case kFillGradient:
+			colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+			blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+			blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+			break;
+		}
+	}
+}
+
+/////////////
+
 /** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 7a1fe36..42d906c 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -50,14 +50,15 @@ class VectorRendererSpec : public VectorRenderer {
 public:
 	VectorRendererSpec(PixelFormat format);
 
-	void drawLine(int x1, int y1, int x2, int y2);
-	void drawCircle(int x, int y, int r);
-	void drawSquare(int x, int y, int w, int h);
+	void drawLine(int x1, int y1, int x2, int y2); //TODO
+	void drawCircle(int x, int y, int r); //TODO
+	void drawSquare(int x, int y, int w, int h); //TODO
 	void drawRoundedSquare(int x, int y, int r, int w, int h);
 	void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
-	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
-	void drawTab(int x, int y, int r, int w, int h);
-	void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
+	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); //TODO
+	void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
+	void drawTab(int x, int y, int r, int w, int h); //TODO
+	void drawBeveledSquare(int x, int y, int w, int h, int bevel) { //TODO
 		drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
 	}
 	void drawString(const Graphics::Font *font, const Common::String &text,
@@ -122,6 +123,7 @@ protected:
 	 * @param alpha Alpha intensity of the pixel (0-255)
 	 */
 	inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha);
+	inline void blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y);
 
 	/**
 	 * Blends a single pixel on the surface in the given pixel pointer, using supplied color
@@ -182,6 +184,9 @@ protected:
 	virtual void drawTriangleVertAlg(int x, int y, int w, int h,
 	    bool inverted, PixelType color, FillMode fill_m);
 
+	virtual void drawTriangleVertAlgClip(int x, int y, int w, int h,
+		bool inverted, PixelType color, FillMode fill_m);
+
 	virtual void drawTriangleFast(int x, int y, int size,
 	    bool inverted, PixelType color, FillMode fill_m);
 
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index a38e565..6d9f7d8 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1127,6 +1127,29 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe
 	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;
@@ -1199,7 +1222,7 @@ void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect
 	else if (state == kStateDisabled)
 		dd = kDDPopUpDisabled;
 
-	queueDDClip(dd, r, clip);
+	queueDDClip(dd, r, clip);	
 
 	if (!sel.empty()) {
 		Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index af8c293..c854b00 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -368,6 +368,8 @@ public:
 
 	void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
 	                   ScrollbarState, WidgetStateInfo state = kStateEnabled);
+	void drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight,
+					   ScrollbarState scrollState, WidgetStateInfo state = kStateEnabled);
 
 	void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
 	                     int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
diff --git a/gui/widgets/scrollbar.cpp b/gui/widgets/scrollbar.cpp
index f1306b9..d8bcb18 100644
--- a/gui/widgets/scrollbar.cpp
+++ b/gui/widgets/scrollbar.cpp
@@ -26,6 +26,7 @@
 #include "gui/widgets/scrollbar.h"
 #include "gui/gui-manager.h"
 #include "gui/ThemeEngine.h"
+#include "gui/widgets/scrollcontainer.h"
 
 namespace GUI {
 
@@ -202,7 +203,11 @@ void ScrollBarWidget::drawWidget() {
 		state = ThemeEngine::kScrollbarStateSlider;
 	}
 
-	g_gui.theme()->drawScrollbar(Common::Rect(_x, _y, _x+_w, _y+_h), _sliderPos, _sliderHeight, state, _state);
+	Common::Rect clipRect = getBossClipRect();
+	//scrollbar is not a usual child of ScrollContainerWidget, so it gets this special treatment
+	if (dynamic_cast<ScrollContainerWidget *>(_boss))
+		clipRect.right += _w;
+	g_gui.theme()->drawScrollbarClip(Common::Rect(_x, _y, _x+_w, _y+_h), clipRect, _sliderPos, _sliderHeight, state, _state);
 }
 
 } // End of namespace GUI


Commit: f22d11953d355f8b56d504301997eb4643c299bc
    https://github.com/scummvm/scummvm/commit/f22d11953d355f8b56d504301997eb4643c299bc
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:21:09+02:00

Commit Message:
GUI: Add drawSquareClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widgets/editable.cpp



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index a84062c..5afdd54 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -161,6 +161,7 @@ public:
 	 * @param h Height of the square
 	 */
 	virtual void drawSquare(int x, int y, int w, int h) = 0;
+	virtual void drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a rounded square starting at (x,y) with the given width and height.
@@ -369,7 +370,7 @@ public:
 	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawSquare(x, y, w, h);
+		drawSquareClip(x, y, w, h, clip);
 	}
 
 	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index f2a69d3..a0091a6 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1106,6 +1106,65 @@ drawSquare(int x, int y, int w, int h) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+		w <= 0 || h <= 0 || x < 0 || y < 0)
+		return;
+
+	Common::Rect backup = _clippingArea;
+	_clippingArea = clipping;
+	bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+	if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+		&& x + w + Base::_shadowOffset < Base::_activeSurface->w
+		&& y + h + Base::_shadowOffset < Base::_activeSurface->h) {
+		if (useClippingVersions)
+			drawSquareShadowClip(x, y, w, h, Base::_shadowOffset);
+		else
+			drawSquareShadow(x, y, w, h, Base::_shadowOffset);
+	}
+
+	switch (Base::_fillMode) {
+	case kFillDisabled:
+		if (Base::_strokeWidth)
+			if (useClippingVersions)
+				drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+			else
+				drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+		break;
+
+	case kFillForeground:
+		if (useClippingVersions)
+			drawSquareAlgClip(x, y, w, h, _fgColor, kFillForeground);
+		else 
+			drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
+		break;
+
+	case kFillBackground:
+		if (useClippingVersions) {
+			drawSquareAlgClip(x, y, w, h, _bgColor, kFillBackground);
+			drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+		} else {
+			drawSquareAlg(x, y, w, h, _bgColor, kFillBackground);
+			drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+		}
+		break;
+
+	case kFillGradient:
+		VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
+		if (Base::_strokeWidth)
+			if (useClippingVersions)
+				drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+			else
+				drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+		break;
+	}
+
+	_clippingArea = backup;
+}
+
 /** ROUNDED SQUARES **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -1606,6 +1665,46 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillM
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawSquareAlgClip(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+	// Do not draw anything for empty rects.
+	if (w <= 0 || h <= 0) {
+		return;
+	}
+
+	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int max_h = h;
+	int ptr_y = y;
+
+	if (fill_m != kFillDisabled) {
+		while (h--) {
+			if (fill_m == kFillGradient)
+				color = calcGradient(max_h - h, max_h);
+
+			colorFillClip<PixelType>(ptr, ptr + w, color, x, ptr_y, _clippingArea);
+			ptr += pitch;
+			++ptr_y;
+		}
+	} else {
+		int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
+
+		while (sw--) {
+			colorFillClip<PixelType>(ptr + sp, ptr + w + sp, color, x, ptr_y + sp/pitch, _clippingArea);
+			colorFillClip<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color, x, ptr_y + h - sp/pitch, _clippingArea);
+			sp += pitch;
+		}
+
+		while (h--) {
+			colorFillClip<PixelType>(ptr, ptr + Base::_strokeWidth, color, x, ptr_y, _clippingArea);
+			colorFillClip<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color, x + w - Base::_strokeWidth, ptr_y, _clippingArea);
+			ptr += pitch;
+			ptr_y += 1;
+		}
+	}
+}
+
 /** SQUARE ALGORITHM **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -2629,6 +2728,54 @@ drawSquareShadow(int x, int y, int w, int h, int offset) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+drawSquareShadowClip(int x, int y, int w, int h, int offset) {
+	// Do nothing for empty rects or no shadow offset.
+	if (w <= 0 || h <= 0 || offset <= 0) {
+		return;
+	}
+
+	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int i, j, ptr_x = x+w-1, ptr_y = y+offset;
+
+	i = h - offset;
+
+	while (i--) {
+		j = offset;
+		while (j--)
+			blendPixelPtrClip(ptr + j, 0, ((offset - j) << 8) / offset, ptr_x + j, ptr_y);
+		ptr += pitch;
+		++ptr_y;
+	}
+
+	ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
+	ptr_x = x + offset;
+	ptr_y = y + h - 1;
+
+	while (i++ < offset) {
+		j = w - offset;
+		while (j--)
+			blendPixelPtrClip(ptr + j, 0, ((offset - i) << 8) / offset, ptr_x + j, ptr_y);
+		ptr += pitch;
+		++ptr_y;
+	}
+
+	ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
+	ptr_x = x + w;
+	ptr_y = y + h;
+
+	i = 0;
+	while (i++ < offset) {
+		j = offset - 1;
+		while (j--)
+			blendPixelPtrClip(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset), ptr_x + j, ptr_y);
+		ptr += pitch;
+		++ptr_y;
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
 
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 42d906c..1961e18 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -52,10 +52,11 @@ public:
 
 	void drawLine(int x1, int y1, int x2, int y2); //TODO
 	void drawCircle(int x, int y, int r); //TODO
-	void drawSquare(int x, int y, int w, int h); //TODO
+	void drawSquare(int x, int y, int w, int h);
+	void drawSquareClip(int x, int y, int w, int h, Common::Rect clipping);
 	void drawRoundedSquare(int x, int y, int r, int w, int h);
 	void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
-	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); //TODO
+	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
 	void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
 	void drawTab(int x, int y, int r, int w, int h); //TODO
 	void drawBeveledSquare(int x, int y, int w, int h, int bevel) { //TODO
@@ -181,6 +182,9 @@ protected:
 	virtual void drawSquareAlg(int x, int y, int w, int h,
 	    PixelType color, FillMode fill_m);
 
+	virtual void drawSquareAlgClip(int x, int y, int w, int h,
+		PixelType color, FillMode fill_m);
+
 	virtual void drawTriangleVertAlg(int x, int y, int w, int h,
 	    bool inverted, PixelType color, FillMode fill_m);
 
@@ -214,6 +218,7 @@ protected:
 	 * @param offset Intensity/size of the shadow.
 	 */
 	virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
+	virtual void drawSquareShadowClip(int x, int y, int w, int h, int offset);
 	virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset);
 	virtual void drawRoundedSquareShadowClip(int x, int y, int r, int w, int h, int offset);
 
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 6d9f7d8..13bf813 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1177,6 +1177,35 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b
 	}
 }
 
+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:
+		break;
+	}
+}
+
 void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) {
 	if (!ready())
 		return;
@@ -1188,6 +1217,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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index c854b00..3c83020 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -379,9 +379,13 @@ public:
 	void drawCaret(const Common::Rect &r, bool erase,
 	               WidgetStateInfo state = kStateEnabled);
 
+	void drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase,
+		WidgetStateInfo state = kStateEnabled);
+
 	void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
 
 	void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
+	void drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground type, WidgetStateInfo state = kStateEnabled);
 
 	void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
 
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 2d92911..83b6a7b 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -274,7 +274,7 @@ void EditableWidget::drawCaret(bool erase) {
 	x += getAbsX();
 	y += getAbsY();
 
-	g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
+	g_gui.theme()->drawCaretClip(Common::Rect(x, y, x + 1, y + editRect.height()), getBossClipRect(), erase);
 
 	if (erase) {
 		GUI::EditableWidget::String character;


Commit: 2231de040f37502031686edf62f501a02ae6d1c4
    https://github.com/scummvm/scummvm/commit/2231de040f37502031686edf62f501a02ae6d1c4
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:21:24+02:00

Commit Message:
GUI: Add drawCircle()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 5afdd54..38185f1 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -151,6 +151,7 @@ public:
 	 * @param r Radius of the circle.
 	 */
 	virtual void drawCircle(int x, int y, int r) = 0;
+	virtual void drawCircleClip(int x, int y, int r, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a square starting at (x,y) with the given width and height.
@@ -358,16 +359,16 @@ public:
 	/**
 	 * DrawStep callback functions for each drawing feature
 	 */
-	void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h, radius;
 
 		radius = stepGetRadius(step, area);
 		stepGetPositions(step, area, x, y, w, h);
 
-		drawCircle(x + radius, y + radius, radius);
+		drawCircleClip(x + radius, y + radius, radius, clip);
 	}
 
-	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawSquareClip(x, y, w, h, clip);
@@ -389,7 +390,7 @@ public:
 		fillSurface();
 	}
 
-	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawTriangleClip(x, y, w, h, (TriangleOrientation)step.extraData, clip);
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index a0091a6..cbabdc7 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1069,6 +1069,69 @@ drawCircle(int x, int y, int r) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawCircleClip(int x, int y, int r, Common::Rect clipping) {
+	if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h ||
+		x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0)
+		return;
+
+	Common::Rect backup = _clippingArea;
+	_clippingArea = clipping;
+	bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x - r, y - r, x + r, y + r)));
+
+	if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+		&& x + r + Base::_shadowOffset < Base::_activeSurface->w
+		&& y + r + Base::_shadowOffset < Base::_activeSurface->h) {
+		if (useClippingVersions)
+			drawCircleAlgClip(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
+		else
+			drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
+	}
+
+	switch (Base::_fillMode) {
+	case kFillDisabled:
+		if (Base::_strokeWidth)
+			if (useClippingVersions)
+				drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
+			else
+				drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
+		break;
+
+	case kFillForeground:
+		if (useClippingVersions)
+			drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
+		else
+			drawCircleAlg(x, y, r, _fgColor, kFillForeground);
+		break;
+
+	case kFillBackground:
+		if (Base::_strokeWidth > 1) {
+			if (useClippingVersions) {
+				drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
+				drawCircleAlgClip(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
+			} else {
+				drawCircleAlg(x, y, r, _fgColor, kFillForeground);
+				drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
+			}
+		} else {
+			if (useClippingVersions) {
+				drawCircleAlgClip(x, y, r, _bgColor, kFillBackground);
+				drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
+			} else {
+				drawCircleAlg(x, y, r, _bgColor, kFillBackground);
+				drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
+			}
+		}
+		break;
+
+	case kFillGradient:
+		break;
+	}
+
+	_clippingArea = backup;
+}
+
 /** SQUARES **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -2677,7 +2740,47 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
 }
 
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawCircleAlgClip(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
+	int f, ddF_x, ddF_y;
+	int x, y, px, py, sw = 0;
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+
+	if (fill_m == kFillDisabled) {
+		while (sw++ < Base::_strokeWidth) {
+			BE_RESET();
+			r--;
+
+			if (IS_IN_CLIP(x1 + y, y1)) *(ptr + y) = color;
+			if (IS_IN_CLIP(x1 - y, y1)) *(ptr - y) = color;
+			if (IS_IN_CLIP(x1, y1 + y)) *(ptr + py) = color;
+			if (IS_IN_CLIP(x1, y1 - y)) *(ptr - py) = color;
+
+			while (x++ < y) {
+				BE_ALGORITHM();
+				BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
+
+				if (Base::_strokeWidth > 1) {
+					BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x - 1, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
+					BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px - pitch, py, x1, y1, x1, y1, x1, y1, x1, y1);
+				}
+			}
+		}
+	} else {
+		colorFillClip<PixelType>(ptr - r, ptr + r, color, x1 - r, y1 + r, _clippingArea);
+		BE_RESET();
 
+		while (x++ < y) {
+			BE_ALGORITHM();
+			colorFillClip<PixelType>(ptr - x + py, ptr + x + py, color, x1 - x, y1 + y, _clippingArea);
+			colorFillClip<PixelType>(ptr - x - py, ptr + x - py, color, x1 - x, y1 - y, _clippingArea);
+			colorFillClip<PixelType>(ptr - y + px, ptr + y + px, color, x1 - y, y1 + x, _clippingArea);
+			colorFillClip<PixelType>(ptr - y - px, ptr + y - px, color, x1 - y, y1 - x, _clippingArea);
+		}
+	}
+}
 
 
 /********************************************************************
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 1961e18..0191000 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -51,7 +51,8 @@ public:
 	VectorRendererSpec(PixelFormat format);
 
 	void drawLine(int x1, int y1, int x2, int y2); //TODO
-	void drawCircle(int x, int y, int r); //TODO
+	void drawCircle(int x, int y, int r);
+	void drawCircleClip(int x, int y, int r, Common::Rect clipping);
 	void drawSquare(int x, int y, int w, int h);
 	void drawSquareClip(int x, int y, int w, int h, Common::Rect clipping);
 	void drawRoundedSquare(int x, int y, int r, int w, int h);
@@ -161,6 +162,9 @@ protected:
 	virtual void drawCircleAlg(int x, int y, int r,
 	    PixelType color, FillMode fill_m);
 
+	virtual void drawCircleAlgClip(int x, int y, int r,
+		PixelType color, FillMode fill_m);
+
 	virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h,
 	    PixelType color, FillMode fill_m);
 


Commit: 05383532b7da1a2ed669d03ee9ca8aa9e6bdcdf1
    https://github.com/scummvm/scummvm/commit/05383532b7da1a2ed669d03ee9ca8aa9e6bdcdf1
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:21:40+02:00

Commit Message:
GUI: Add drawLineClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 38185f1..d180d87 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -142,6 +142,7 @@ public:
 	 * @param y2 Vertical (Y) coordinate for the line end
 	 */
 	virtual void drawLine(int x1, int y1, int x2, int y2) = 0;
+	virtual void drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a circle centered at (x,y) with radius r.
@@ -374,10 +375,10 @@ public:
 		drawSquareClip(x, y, w, h, clip);
 	}
 
-	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawLine(x, y, x + w, y + w);
+		drawLineClip(x, y, x + w, y + w, clip);
 	}
 
 	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index cbabdc7..3011601 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1030,6 +1030,77 @@ drawLine(int x1, int y1, int x2, int y2) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) {
+	x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
+	x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
+	y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
+	y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
+
+	// we draw from top to bottom
+	if (y2 < y1) {
+		SWAP(x1, x2);
+		SWAP(y1, y2);
+	}
+
+	uint dx = ABS(x2 - x1);
+	uint dy = ABS(y2 - y1);
+
+	// this is a point, not a line. stoopid.
+	if (dy == 0 && dx == 0)
+		return;
+
+	if (Base::_strokeWidth == 0)
+		return;
+
+	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int st = Base::_strokeWidth >> 1;
+
+	Common::Rect backup = _clippingArea;
+	_clippingArea = clipping;
+	bool needsClipping = !_clippingArea.isEmpty() && (!_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2));
+	if (!needsClipping) {
+		drawLine(x1, y1, x2, y2);
+		_clippingArea = backup;
+		return;
+	}
+
+	int ptr_x = x1, ptr_y = y1;
+
+	if (dy == 0) { // horizontal lines
+		colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
+
+		for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
+			colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
+			colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
+		}
+
+	} else if (dx == 0) { // vertical lines
+						  // these ones use a static pitch increase.
+		while (y1++ <= y2) {
+			colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
+			ptr += pitch;
+			++ptr_y;
+		}
+
+	} else if (dx == dy) { // diagonal lines
+						   // these ones also use a fixed pitch increase
+		pitch += (x2 > x1) ? 1 : -1;
+
+		while (dy--) {
+			colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
+			ptr += pitch;
+			++ptr_y;
+			if (x2 > x1) ++ptr_x; else --ptr_x;
+		}
+
+	} else { // generic lines, use the standard algorithm...
+		drawLineAlgClip(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
+	}
+}
+
 /** CIRCLES **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -1872,6 +1943,59 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 	*ptr = (PixelType)color;
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
+	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int xdir = (x2 > x1) ? 1 : -1;
+	int ptr_x = x1, ptr_y = y1;
+
+	if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+
+	if (dx > dy) {
+		int ddy = dy * 2;
+		int dysub = ddy - (dx * 2);
+		int error_term = ddy - dx;
+
+		while (dx--) {
+			if (error_term >= 0) {
+				ptr += pitch;
+				++ptr_y;
+				error_term += dysub;
+			} else {
+				error_term += ddy;
+			}
+
+			ptr += xdir;
+			ptr_x += xdir;
+			if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+		}
+	} else {
+		int ddx = dx * 2;
+		int dxsub = ddx - (dy * 2);
+		int error_term = ddx - dy;
+
+		while (dy--) {
+			if (error_term >= 0) {
+				ptr += xdir;
+				ptr_x += xdir;
+				error_term += dxsub;
+			} else {
+				error_term += ddx;
+			}
+
+			ptr += pitch;
+			++ptr_y;
+			if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+		}
+	}
+
+	ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
+	ptr_x = x2; ptr_y = y2;
+	if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+}
+
 /** VERTICAL TRIANGLE DRAWING ALGORITHM **/
 /**
 	FIXED POINT ARITHMETIC
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 0191000..dcef88e 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -50,7 +50,8 @@ class VectorRendererSpec : public VectorRenderer {
 public:
 	VectorRendererSpec(PixelFormat format);
 
-	void drawLine(int x1, int y1, int x2, int y2); //TODO
+	void drawLine(int x1, int y1, int x2, int y2);
+	void drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping);
 	void drawCircle(int x, int y, int r);
 	void drawCircleClip(int x, int y, int r, Common::Rect clipping);
 	void drawSquare(int x, int y, int w, int h);
@@ -159,6 +160,9 @@ protected:
 	virtual void drawLineAlg(int x1, int y1, int x2, int y2,
 	    uint dx, uint dy, PixelType color);
 
+	virtual void drawLineAlgClip(int x1, int y1, int x2, int y2,
+		uint dx, uint dy, PixelType color);
+
 	virtual void drawCircleAlg(int x, int y, int r,
 	    PixelType color, FillMode fill_m);
 


Commit: ee00156d5450b01508894013dc446ef3d928d781
    https://github.com/scummvm/scummvm/commit/ee00156d5450b01508894013dc446ef3d928d781
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:21:55+02:00

Commit Message:
GUI: Add drawBeveledSquareClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index d180d87..bedc8a3 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -204,6 +204,7 @@ public:
 	 * @param bevel Amount of bevel. Must be positive.
 	 */
 	virtual void drawBeveledSquare(int x, int y, int w, int h, int bevel) = 0;
+	virtual void drawBeveledSquareClip(int x, int y, int w, int h, int bevel, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a tab-like shape, specially thought for the Tab widget.
@@ -397,10 +398,10 @@ public:
 		drawTriangleClip(x, y, w, h, (TriangleOrientation)step.extraData, clip);
 	}
 
-	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawBeveledSquare(x, y, w, h, _bevel);
+		drawBeveledSquareClip(x, y, w, h, _bevel, clip);
 	}
 
 	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 3011601..607b9a3 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -922,6 +922,36 @@ darkenFill(PixelType *ptr, PixelType *end) {
 	}
 }
 
+template<typename PixelType>
+inline void VectorRendererSpec<PixelType>::
+darkenFillClip(PixelType *ptr, PixelType *end, int x, int y) {
+	PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
+
+	if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
+		// !kFeatureOverlaySupportsAlpha (but might have alpha bits)
+
+		while (ptr != end) {
+			if (IS_IN_CLIP(x, y)) *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
+			++ptr;
+			++x;
+		}
+	} else {
+		// kFeatureOverlaySupportsAlpha
+		// assuming at least 3 alpha bits
+
+		mask |= 3 << _format.aShift;
+		PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
+
+		while (ptr != end) {
+			// Darken the color, and increase the alpha
+			// (0% -> 75%, 100% -> 100%)
+			if (IS_IN_CLIP(x, y)) *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
+			++ptr;
+			++x;
+		}
+	}
+}
+
 /********************************************************************
  ********************************************************************
  * Primitive shapes drawing - Public API calls - VectorRendererSpec *
@@ -1895,6 +1925,72 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawBevelSquareAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) {
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int i, j;
+	PixelType *ptr_left;
+	int ptr_x, ptr_y;
+
+	// Fill Background
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+	ptr_x = x; ptr_y = y;
+	i = h;
+	if (fill) {
+		assert((_bgColor & ~_alphaMask) == 0); // only support black
+		while (i--) {
+			darkenFillClip(ptr_left, ptr_left + w, ptr_x, ptr_y);
+			ptr_left += pitch;
+			++ptr_y;
+		}
+	}
+
+	x = MAX(x - bevel, 0);
+	y = MAX(y - bevel, 0);
+
+	w = MIN(w + (bevel * 2), (int)_activeSurface->w);
+	h = MIN(h + (bevel * 2), (int)_activeSurface->h);
+
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+	ptr_x = x; ptr_y = y;
+	i = bevel;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
+		ptr_left += pitch;
+		++ptr_y;
+	}
+
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
+	ptr_x = x; ptr_y = y + bevel;
+	i = h - bevel;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
+		ptr_left += pitch;
+		++ptr_y;
+	}
+
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
+	ptr_x = x; ptr_y = y + h - bevel;
+	i = bevel;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left + i, ptr_left + w, bottom_color, ptr_x + i, ptr_y, _clippingArea);
+		ptr_left += pitch;
+		++ptr_y;
+	}
+
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
+	ptr_x = x + w - bevel; ptr_y = y;
+	i = h - bevel;
+	j = bevel - 1;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
+		if (j > 0) j--;
+		ptr_left += pitch;
+		++ptr_y;
+	}
+}
+
 /** GENERIC LINE ALGORITHM **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index dcef88e..b69ab87 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -61,9 +61,20 @@ public:
 	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
 	void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
 	void drawTab(int x, int y, int r, int w, int h); //TODO
-	void drawBeveledSquare(int x, int y, int w, int h, int bevel) { //TODO
+	void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
 		drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
 	}
+	void drawBeveledSquareClip(int x, int y, int w, int h, int bevel, Common::Rect clipping) {
+		bool useClippingVersions = !(clipping.isEmpty() || clipping.contains(Common::Rect(x, y, x + w, y + h)));
+		if (useClippingVersions) {
+			Common::Rect backup = _clippingArea;
+			_clippingArea = clipping;
+			drawBevelSquareAlgClip(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
+			_clippingArea = backup;
+		} else {
+			drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
+		}
+	}
 	void drawString(const Graphics::Font *font, const Common::String &text,
 					const Common::Rect &area, Graphics::TextAlign alignH,
 					GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool elipsis, const Common::Rect &textDrawableArea = Common::Rect(0, 0, 0, 0));
@@ -205,6 +216,9 @@ protected:
 	virtual void drawBevelSquareAlg(int x, int y, int w, int h,
 	    int bevel, PixelType top_color, PixelType bottom_color, bool fill);
 
+	virtual void drawBevelSquareAlgClip(int x, int y, int w, int h,
+		int bevel, PixelType top_color, PixelType bottom_color, bool fill);
+
 	virtual void drawTabAlg(int x, int y, int w, int h, int r,
 	    PixelType color, VectorRenderer::FillMode fill_m,
 	    int baseLeft = 0, int baseRight = 0);
@@ -272,6 +286,7 @@ protected:
 	}
 
 	void darkenFill(PixelType *first, PixelType *last);
+	void darkenFillClip(PixelType *first, PixelType *last, int x, int y);
 
 	const PixelFormat _format;
 	const PixelType _redMask, _greenMask, _blueMask, _alphaMask;


Commit: 80412a4139d19024a9ef941004380e6bbb8d4da9
    https://github.com/scummvm/scummvm/commit/80412a4139d19024a9ef941004380e6bbb8d4da9
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:22:10+02:00

Commit Message:
GUI: Add drawTabClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widgets/tab.cpp



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index bedc8a3..af275c5 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -218,6 +218,7 @@ public:
 	 * @param r Radius of the corners of the tab (0 for squared tabs).
 	 */
 	virtual void drawTab(int x, int y, int r, int w, int h) = 0;
+	virtual void drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) = 0;
 
 
 	/**
@@ -404,10 +405,10 @@ public:
 		drawBeveledSquareClip(x, y, w, h, _bevel, clip);
 	}
 
-	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawTab(x, y, stepGetRadius(step, area), w, h);
+		drawTabClip(x, y, stepGetRadius(step, area), w, h, clip);
 	}
 
 	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 607b9a3..672ca34 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1427,6 +1427,66 @@ drawTab(int x, int y, int r, int w, int h) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+		w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
+		return;
+
+	Common::Rect backup = _clippingArea;
+	_clippingArea = clipping;
+	bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+	if (r == 0 && Base::_bevel > 0) {
+		if (useClippingVersions)
+			drawBevelTabAlgClip(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+		else
+			drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+		_clippingArea = backup;
+		return;
+	}
+
+	if (r == 0) {
+		_clippingArea = backup;
+		return;
+	}
+
+	switch (Base::_fillMode) {
+	case kFillDisabled:
+		// FIXME: Implement this
+		_clippingArea = backup;
+		return;
+
+	case kFillGradient:
+	case kFillBackground:
+		// FIXME: This is broken for the AA renderer.
+		// See the rounded rect alg for how to fix it. (The border should
+		// be drawn before the interior, both inside drawTabAlg.)
+		if (useClippingVersions) {
+			drawTabShadowClip(x, y, w - 2, h, r);
+			drawTabAlgClip(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
+			if (Base::_strokeWidth)
+				drawTabAlgClip(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+		} else {
+			drawTabShadow(x, y, w - 2, h, r);
+			drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
+			if (Base::_strokeWidth)
+				drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+		}
+		break;
+
+	case kFillForeground:
+		if (useClippingVersions)
+			drawTabAlgClip(x, y, w, h, r, _fgColor, Base::_fillMode);
+		else
+			drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
+		break;
+	}
+
+	_clippingArea = backup;
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
 
 	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
@@ -1685,6 +1745,120 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTabAlgClip(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
+	// Don't draw anything for empty rects.
+	if (w <= 0 || h <= 0) {
+		return;
+	}
+
+	int f, ddF_x, ddF_y;
+	int x, y, px, py;
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int sw = 0, sp = 0, hp = 0;
+
+	PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
+	PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
+	PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+	int tl_x = x1 + r, tl_y = y1 + r;
+	int tr_x = x1 + w - r, tr_y = y1 + r;
+	int fill_x = x1, fill_y = y1;
+
+	int real_radius = r;
+	int short_h = h - r + 2;
+	int long_h = h;
+
+	if (fill_m == kFillDisabled) {
+		while (sw++ < Base::_strokeWidth) {
+			colorFillClip<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, fill_x + r, fill_y + sp/pitch, _clippingArea);
+			colorFillClip<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, fill_x + r, fill_y + hp / pitch - sp / pitch, _clippingArea);
+			sp += pitch;
+
+			BE_RESET();
+			r--;
+
+			while (x++ < y) {
+				BE_ALGORITHM();
+				BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+
+				if (Base::_strokeWidth > 1)
+					BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px - pitch, py, tr_x, tr_y, tl_x, tl_y);
+			}
+		}
+
+		ptr_fill += pitch * real_radius;
+		fill_y += real_radius;
+		while (short_h--) {
+			colorFillClip<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color, fill_x, fill_y, _clippingArea);
+			colorFillClip<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, fill_x + w - Base::_strokeWidth + 1, fill_y, _clippingArea);
+			ptr_fill += pitch;
+			++fill_y;
+		}
+
+		if (baseLeft) {
+			sw = 0;
+			ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
+			fill_x = x1;
+			fill_y = y1 + h + 1;
+			while (sw++ < Base::_strokeWidth) {
+				colorFillClip<PixelType>(ptr_fill - baseLeft, ptr_fill, color, fill_x - baseLeft, fill_y, _clippingArea);
+				ptr_fill += pitch;
+				++fill_y;
+			}
+		}
+
+		if (baseRight) {
+			sw = 0;
+			ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
+			fill_x = x1 + w;
+			fill_y = y1 + h + 1;
+			while (sw++ < Base::_strokeWidth) {
+				colorFillClip<PixelType>(ptr_fill, ptr_fill + baseRight, color, fill_x, fill_y, _clippingArea);
+				ptr_fill += pitch;
+				++fill_y;
+			}
+		}
+	} else {
+		BE_RESET();
+
+		precalcGradient(long_h);
+
+		PixelType color1, color2;
+		color1 = color2 = color;
+
+		while (x++ < y) {
+			BE_ALGORITHM();
+
+			if (fill_m == kFillGradient) {
+				color1 = calcGradient(real_radius - x, long_h);
+				color2 = calcGradient(real_radius - y, long_h);
+
+				gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y, tl_x - x, tl_y - y);
+				gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x, tl_x - y, tl_y - x);
+
+				BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+			} else {
+				colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color, tl_x - x, tl_y - y, _clippingArea);
+				colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color, tl_x - y, tl_y - x, _clippingArea);
+
+				BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+			}
+		}
+
+		ptr_fill += pitch * r;
+		fill_y += r;
+		while (short_h--) {
+			if (fill_m == kFillGradient) {
+				gradientFillClip(ptr_fill, w + 1, x1, real_radius++, fill_x, fill_y);
+			} else {
+				colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color, fill_x, fill_y, _clippingArea);
+			}
+			ptr_fill += pitch;
+			++fill_y;
+		}
+	}
+}
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -1747,6 +1921,72 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTabShadowClip(int x1, int y1, int w, int h, int r) {
+	int offset = 3;
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+	// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+	uint8 expFactor = 3;
+	uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
+
+	int xstart = x1;
+	int ystart = y1;
+	int width = w;
+	int height = h + offset + 1;
+
+	for (int i = offset; i >= 0; i--) {
+		int f, ddF_x, ddF_y;
+		int x, y, px, py;
+
+		PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
+		PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
+		PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+		int tl_x = xstart + r, tl_y = ystart + r;
+		int fill_x = xstart, fill_y = ystart;
+
+		int short_h = height - (2 * r) + 2;
+		PixelType color = _format.RGBToColor(0, 0, 0);
+
+		BE_RESET();
+
+		// HACK: As we are drawing circles exploting 8-axis symmetry,
+		// there are 4 pixels on each circle which are drawn twice.
+		// this is ok on filled circles, but when blending on surfaces,
+		// we cannot let it blend twice. awful.
+		uint32 hb = 0;
+
+		while (x++ < y) {
+			BE_ALGORITHM();
+
+			if (((1 << x) & hb) == 0) {
+				blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, tl_x - y, tl_y - x);
+				hb |= (1 << x);
+			}
+
+			if (((1 << y) & hb) == 0) {
+				blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, tl_x - x, tl_y - y);
+				hb |= (1 << y);
+			}
+		}
+
+		ptr_fill += pitch * r;
+		fill_y += r;
+		while (short_h--) {
+			blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha, fill_x, fill_y);
+			ptr_fill += pitch;
+			++fill_y;
+		}
+
+		// Move shadow one pixel upward each iteration
+		xstart += 1;
+		// Multiply with expfactor
+		alpha = (alpha * (expFactor << 8)) >> 9;
+	}
+}
+
 /** BEVELED TABS FOR CLASSIC THEME **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
@@ -1791,6 +2031,57 @@ drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, Pixe
 	}
 }
 
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawBevelTabAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
+	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int i, j;
+
+	PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+	int ptr_x = x, ptr_y = y;
+
+	i = bevel;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
+		ptr_left += pitch;
+		++ptr_y;
+	}
+
+	if (baseLeft > 0) {
+		i = h - bevel;
+		ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+		ptr_x = x; ptr_y = y;
+		while (i--) {
+			colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
+			ptr_left += pitch;
+			++ptr_y;
+		}
+	}
+
+	i = h - bevel;
+	j = bevel - 1;
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
+	ptr_x = x + w - bevel; ptr_y = y;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
+		if (j > 0) j--;
+		ptr_left += pitch;
+		++ptr_y;
+	}
+
+	i = bevel;
+	ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
+	ptr_x = x + w - bevel; ptr_y = y + h - bevel;
+	while (i--) {
+		colorFillClip<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color, ptr_x, ptr_y, _clippingArea);
+
+		if (baseLeft)
+			colorFillClip<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color, ptr_x - w - baseLeft + bevel, ptr_y, _clippingArea);
+		ptr_left += pitch;
+		++ptr_y;
+	}
+}
+
 /** SQUARE ALGORITHM **/
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index b69ab87..7b2c273 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -60,7 +60,8 @@ public:
 	void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
 	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
 	void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
-	void drawTab(int x, int y, int r, int w, int h); //TODO
+	void drawTab(int x, int y, int r, int w, int h);
+	void drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping);
 	void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
 		drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
 	}
@@ -223,12 +224,22 @@ protected:
 	    PixelType color, VectorRenderer::FillMode fill_m,
 	    int baseLeft = 0, int baseRight = 0);
 
+	virtual void drawTabAlgClip(int x, int y, int w, int h, int r,
+		PixelType color, VectorRenderer::FillMode fill_m,
+		int baseLeft = 0, int baseRight = 0);
+
 	virtual void drawTabShadow(int x, int y, int w, int h, int r);
 
+	virtual void drawTabShadowClip(int x, int y, int w, int h, int r);
+
 	virtual void drawBevelTabAlg(int x, int y, int w, int h,
 	    int bevel, PixelType topColor, PixelType bottomColor,
 	    int baseLeft = 0, int baseRight = 0);
 
+	virtual void drawBevelTabAlgClip(int x, int y, int w, int h,
+		int bevel, PixelType topColor, PixelType bottomColor,
+		int baseLeft = 0, int baseRight = 0);
+
 	/**
 	 * SHADOW DRAWING ALGORITHMS
 	 *
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 13bf813..0824538 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1351,6 +1351,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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 3c83020..d88890d 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -365,6 +365,9 @@ public:
 	void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
 	             const Common::Array<Common::String> &tabs, int active, uint16 hints,
 	             int titleVPad, WidgetStateInfo state = kStateEnabled);
+	void drawTabClip(const Common::Rect &r, const Common::Rect &clippingRect, int tabHeight, int tabWidth,
+				 const Common::Array<Common::String> &tabs, int active, uint16 hints,
+				 int titleVPad, WidgetStateInfo state = kStateEnabled);
 
 	void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
 	                   ScrollbarState, WidgetStateInfo state = kStateEnabled);
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index 393f63a..784e438 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -308,9 +308,9 @@ void TabWidget::drawWidget() {
 	for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
 		tabs.push_back(_tabs[i].title);
 	}
-	g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), _bodyBackgroundType);
+	g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), getBossClipRect(), _bodyBackgroundType);
 
-	g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
+	g_gui.theme()->drawTabClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
 }
 
 void TabWidget::draw() {


Commit: 0dcd29e998e29b8a056493bf95adf98b9de5aecf
    https://github.com/scummvm/scummvm/commit/0dcd29e998e29b8a056493bf95adf98b9de5aecf
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:22:26+02:00

Commit Message:
GUI: Fix drawRoundedSquareClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index af275c5..9346ce6 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -176,7 +176,7 @@ public:
 	 * @param r Radius of the corners.
 	 */
 	virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0;
-	virtual void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch) = 0;
+	virtual void drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping) = 0;
 
 	/**
 	 * Draws a triangle starting at (x,y) with the given base and height.
@@ -386,7 +386,7 @@ public:
 	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip.left, clip.top, clip.right-clip.left, clip.bottom-clip.top);
+		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip);
 	}
 
 	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 672ca34..9260728 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1355,7 +1355,7 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
-drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch) {
+drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
 	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
 		w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
 		return;
@@ -1367,20 +1367,21 @@ drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw,
 		return;
 
 	Common::Rect backup = _clippingArea;
-	_clippingArea = Common::Rect(cx, cy, cx + cw, cy + ch);	
+	_clippingArea = clipping;
+	bool useOriginal = (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
 
 	if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
 		&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
 		&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
 		&& h > (Base::_shadowOffset + 1) * 2) {
-		if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
+		if (useOriginal) {
 			drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
 		} else {
 			drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset);
 		}
 	}
 
-	if (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h))) {
+	if (useOriginal) {
 		drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
 	} else {
 		drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 7b2c273..f084816 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -57,7 +57,7 @@ public:
 	void drawSquare(int x, int y, int w, int h);
 	void drawSquareClip(int x, int y, int w, int h, Common::Rect clipping);
 	void drawRoundedSquare(int x, int y, int r, int w, int h);
-	void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
+	void drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping);
 	void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
 	void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
 	void drawTab(int x, int y, int r, int w, int h);


Commit: a39a6533c466e8de48eb367ffe78a162b069de54
    https://github.com/scummvm/scummvm/commit/a39a6533c466e8de48eb367ffe78a162b069de54
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:22:41+02:00

Commit Message:
GUI: Add drawCrossClip()

Changed paths:
    graphics/VectorRenderer.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 9346ce6..1ec28d7 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -229,6 +229,11 @@ public:
 		drawLine(x + w, y, x, y + h);
 	}
 
+	virtual void drawCrossClip(int x, int y, int w, int h, Common::Rect clipping) {
+		drawLineClip(x, y, x + w, y + w, clipping);
+		drawLineClip(x + w, y, x, y + h, clipping);
+	}
+
 	/**
 	 * Set the active foreground painting color for the renderer.
 	 * All the foreground drawing from then on will be done with that color, unless
@@ -383,7 +388,7 @@ public:
 		drawLineClip(x, y, x + w, y + w, clip);
 	}
 
-	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
 		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip);
@@ -417,10 +422,10 @@ public:
 		blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, x + w, y + h));
 	}
 
-	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		drawCross(x, y, w, h);
+		drawCrossClip(x, y, w, h, clip);
 	}
 
 	void drawCallback_VOID(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {}


Commit: e636894b0653f9bf546bdec8768cabbf2606d2e5
    https://github.com/scummvm/scummvm/commit/e636894b0653f9bf546bdec8768cabbf2606d2e5
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:23:12+02:00

Commit Message:
GUI: Add fillSurfaceClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 1ec28d7..5f1ff98 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -290,6 +290,7 @@ public:
 	 * Defaults to using the active Foreground color for filling.
 	 */
 	virtual void fillSurface() = 0;
+	virtual void fillSurfaceClip(Common::Rect clipping) = 0;
 
 	/**
 	 * Clears the active surface.
@@ -394,8 +395,8 @@ public:
 		drawRoundedSquareClip(x, y, stepGetRadius(step, area), w, h, clip);
 	}
 
-	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
-		fillSurface();
+	void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
+		fillSurfaceClip(clip);
 	}
 
 	void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 9260728..fd1f587 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -708,6 +708,44 @@ fillSurface() {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+fillSurfaceClip(Common::Rect clipping) {
+	int w = _activeSurface->w;
+	int h = _activeSurface->h;
+	if (clipping.isEmpty() || (clipping.left == 0 && clipping.top == 0 && clipping.right == w && clipping.bottom == h)) {
+		fillSurface();
+		return;
+	}
+
+	byte *ptr = (byte *)_activeSurface->getPixels();
+	int pitch = _activeSurface->pitch;
+
+	if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {		
+		PixelType color = (Base::_fillMode == kFillBackground ? _bgColor : _fgColor);
+		byte *ptrLeft = (ptr + _clippingArea.left), *ptrRight = ptr + _clippingArea.right;
+		for (int i = 0; i < h; i++) {			
+			if (_clippingArea.top <= i && i < _clippingArea.bottom) {
+				colorFill<PixelType>((PixelType *)ptrLeft, (PixelType *)ptrRight, color);
+			}
+
+			ptrLeft += pitch;
+			ptrRight += pitch;
+		}
+
+	} else if (Base::_fillMode == kFillGradient) {
+		precalcGradient(h);
+
+		for (int i = 0; i < h; i++) {
+			if (_clippingArea.top <= i && i < _clippingArea.bottom) {
+				gradientFill((PixelType *)ptr + _clippingArea.left, _clippingArea.width(), 0, i);
+			}
+
+			ptr += pitch;
+		}
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 copyFrame(OSystem *sys, const Common::Rect &r) {
 
 	sys->copyRectToOverlay(
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index f084816..61d58b3 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -89,6 +89,7 @@ public:
 	void copyWholeFrame(OSystem *sys) { copyFrame(sys, Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); }
 
 	void fillSurface();
+	void fillSurfaceClip(Common::Rect clipping);
 	void blitSurface(const Graphics::Surface *source, const Common::Rect &r);
 	void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r);
 	void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r);


Commit: 916c86e68941cb1a752566ac9c0346263970b366
    https://github.com/scummvm/scummvm/commit/916c86e68941cb1a752566ac9c0346263970b366
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:23:41+02:00

Commit Message:
GUI: Add blitAlphaBitmapClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 5f1ff98..78133b0 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -417,10 +417,10 @@ public:
 		drawTabClip(x, y, stepGetRadius(step, area), w, h, clip);
 	}
 
-	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
+	void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
 		uint16 x, y, w, h;
 		stepGetPositions(step, area, x, y, w, h);
-		blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, x + w, y + h));
+		blitAlphaBitmapClip(step.blitSrc, Common::Rect(x, y, x + w, y + h), clip);
 	}
 
 	void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
@@ -482,6 +482,7 @@ public:
 	virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) = 0;
 
 	virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) = 0;
+	virtual void blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) = 0;
 
 	/**
 	 * Draws a string into the screen. Wrapper for the Graphics::Font string drawing
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index fd1f587..32c2f06 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -833,6 +833,65 @@ blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
+	if (clipping.isEmpty() || clipping.contains(r)) {
+		blitAlphaBitmap(source, r);
+		return;
+	}
+
+	int16 x = r.left;
+	int16 y = r.top;
+
+	if (r.width() > source->w)
+		x = x + (r.width() >> 1) - (source->w >> 1);
+
+	if (r.height() > source->h)
+		y = y + (r.height() >> 1) - (source->h >> 1);
+
+	int w = source->w, h = source->h;
+	int usedW = w, usedH = h;
+	int offsetX = 0, offsetY = 0;
+
+	if (x > clipping.right || x + w < clipping.left) return;
+	if (y > clipping.bottom || y + h < clipping.top) return;
+	if (x < clipping.left) {
+		offsetX = clipping.left - x;
+		usedW -= offsetX;
+		x = clipping.left;
+	}
+	if (y < clipping.top) {
+		offsetY = clipping.top - y;
+		usedH -= offsetY;
+		y = clipping.top;
+	}
+	if (usedW > clipping.width()) usedW = clipping.width();
+	if (usedH > clipping.width()) usedH = clipping.height();
+
+	PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
+	const PixelType *src_ptr = (const PixelType *)source->getBasePtr(offsetX, offsetY);
+
+	int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+	int src_pitch = source->pitch / source->format.bytesPerPixel;
+
+	h = usedH;
+	while (h--) {
+		w = usedW;
+
+		while (w--) {
+			if (*src_ptr != _bitmapAlphaColor)
+				*dst_ptr = *src_ptr;
+
+			dst_ptr++;
+			src_ptr++;
+		}
+
+		dst_ptr = dst_ptr - usedW + dst_pitch;
+		src_ptr = src_ptr - usedH + src_pitch;
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
 	int pixels = _activeSurface->w * _activeSurface->h;
 	PixelType *ptr = (PixelType *)_activeSurface->getPixels();
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 61d58b3..5517555 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -93,6 +93,7 @@ public:
 	void blitSurface(const Graphics::Surface *source, const Common::Rect &r);
 	void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r);
 	void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r);
+	void blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping);
 
 	void applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle);
 


Commit: 4b87563792163d5fd538092b340500bccd20aa7b
    https://github.com/scummvm/scummvm/commit/4b87563792163d5fd538092b340500bccd20aa7b
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:23:57+02:00

Commit Message:
GUI: Add blipClip()

Changed paths:
    graphics/nine_patch.cpp
    graphics/nine_patch.h
    graphics/transparent_surface.cpp
    graphics/transparent_surface.h
    gui/ThemeEngine.cpp



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


Commit: 6fd6043391d7faef569612797fb1c181c45a91dc
    https://github.com/scummvm/scummvm/commit/6fd6043391d7faef569612797fb1c181c45a91dc
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:11+02:00

Commit Message:
GUI: Fix blitAlphaBitmapClip()

Changed paths:
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widget.cpp



diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 78133b0..0352808 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -480,6 +480,7 @@ public:
 	 * blitted into the active surface, at the position specified by "r".
 	 */
 	virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) = 0;
+	virtual void blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) = 0;
 
 	virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) = 0;
 	virtual void blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) = 0;
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 32c2f06..43ca2c4 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -797,6 +797,58 @@ blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) {
 
 template<typename PixelType>
 void VectorRendererSpec<PixelType>::
+blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
+	if (clipping.isEmpty() || clipping.contains(r)) {
+		blitSubSurface(source, r);
+		return;
+	}
+
+	int16 x = r.left;
+	int16 y = r.top;
+
+	if (r.width() > source->w)
+		x = x + (r.width() >> 1) - (source->w >> 1);
+
+	if (r.height() > source->h)
+		y = y + (r.height() >> 1) - (source->h >> 1);
+
+	int w = source->w, h = source->h;
+	int usedW = w, usedH = h;
+	int offsetX = 0, offsetY = 0;
+
+	if (x > clipping.right || x + w < clipping.left) return;
+	if (y > clipping.bottom || y + h < clipping.top) return;
+	if (x < clipping.left) {
+		offsetX = clipping.left - x;
+		usedW -= offsetX;
+		x = clipping.left;
+	}
+	if (y < clipping.top) {
+		offsetY = clipping.top - y;
+		usedH -= offsetY;
+		y = clipping.top;
+	}
+	if (usedW > clipping.width()) usedW = clipping.width();
+	if (usedH > clipping.width()) usedH = clipping.height();
+
+	byte *dst_ptr = (byte *)_activeSurface->getBasePtr(x, y);
+	const byte *src_ptr = (const byte *)source->getBasePtr(offsetX, offsetY);
+
+	const int dst_pitch = _activeSurface->pitch;
+	const int src_pitch = source->pitch;
+
+	int lines = usedH;
+	const int sz = usedW * sizeof(PixelType);
+
+	while (lines--) {
+		memcpy(dst_ptr, src_ptr, sz);
+		dst_ptr += dst_pitch;
+		src_ptr += src_pitch;
+	}
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
 blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) {
 	int16 x = r.left;
 	int16 y = r.top;
@@ -886,7 +938,7 @@ blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, cons
 		}
 
 		dst_ptr = dst_ptr - usedW + dst_pitch;
-		src_ptr = src_ptr - usedH + src_pitch;
+		src_ptr = src_ptr - usedW + src_pitch;
 	}
 }
 
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 5517555..bee6d4c 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -92,6 +92,7 @@ public:
 	void fillSurfaceClip(Common::Rect clipping);
 	void blitSurface(const Graphics::Surface *source, const Common::Rect &r);
 	void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r);
+	void blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping);
 	void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r);
 	void blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping);
 
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index b16a428..6174d41 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -168,6 +168,19 @@ protected:
 	bool _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
  *********************************************************/
@@ -303,6 +316,21 @@ void ThemeItemBitmap::drawSelf(bool draw, bool restore) {
 	_engine->addDirtyRect(_area);
 }
 
+void ThemeItemBitmapClip::drawSelf(bool draw, bool restore) {
+	if (restore)
+		_engine->restoreBackground(_area);
+
+	if (draw) {
+		if (_alpha)
+			_engine->renderer()->blitAlphaBitmapClip(_bitmap, _area, _clip);
+		else
+			_engine->renderer()->blitSubSurfaceClip(_bitmap, _area, _clip);
+	}
+
+	Common::Rect dirtyRect = _area;
+	dirtyRect.clip(_clip);
+	_engine->addDirtyRect(dirtyRect);
+}
 
 /**********************************************************
  * ThemeEngine class
@@ -976,6 +1004,21 @@ void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rec
 	}
 }
 
+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
  *********************************************************/
@@ -1270,6 +1313,13 @@ void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &su
 	queueBitmap(&surface, r, themeTrans);
 }
 
+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;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index d88890d..b8ceeda 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -351,7 +351,10 @@ public:
 		WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
 
 	void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
-	                 WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false);
+	                 WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
+
+	void drawSurfaceClip(const Common::Rect &r, const Common::Rect &clippingRect, const Graphics::Surface &surface,
+		WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
 
 	void drawSlider(const Common::Rect &r, int width,
 	                WidgetStateInfo state = kStateEnabled);
@@ -609,6 +612,7 @@ protected:
 	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);
 
 	/**
 	 * DEBUG: Draws a white square and writes some text next to it.
diff --git a/gui/widget.cpp b/gui/widget.cpp
index ed7cf93..13be22f 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -686,7 +686,7 @@ void GraphicsWidget::drawWidget() {
 		const int x = _x + (_w - _gfx.w) / 2;
 		const int y = _y + (_h - _gfx.h) / 2;
 
-		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), _gfx, _state, _alpha, _transparency);
+		g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);
 	}
 }
 


Commit: dc9b32e62086151c0bac011e6bc4a5d94d8907a3
    https://github.com/scummvm/scummvm/commit/dc9b32e62086151c0bac011e6bc4a5d94d8907a3
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:28+02:00

Commit Message:
GUI: Fix PopUpDialog

Changed paths:
    gui/widgets/popup.cpp



diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp
index e157f29..789064e 100644
--- a/gui/widgets/popup.cpp
+++ b/gui/widgets/popup.cpp
@@ -150,7 +150,7 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
 
 void PopUpDialog::drawDialog() {
 	// Draw the menu border
-	g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), _popUpBoss->getBossClipRect(), 0);
+	g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0);
 
 	/*if (_twoColumns)
 		g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/
@@ -364,8 +364,8 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
 		// Draw a separator
 		g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
 	} else {
-		g_gui.theme()->drawTextClip(
-			Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), _popUpBoss->getBossClipRect(),
+		g_gui.theme()->drawText(
+			Common::Rect(x+1, y+2, x+w, y+2+kLineHeight),
 			name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
 			Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding
 		);


Commit: 3d636617d0781bdd477551a87f6b9fc60e0a4a1f
    https://github.com/scummvm/scummvm/commit/3d636617d0781bdd477551a87f6b9fc60e0a4a1f
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:46+02:00

Commit Message:
GUI: Use clipping everywhere

Changed paths:
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/widget.cpp
    gui/widgets/editable.cpp
    gui/widgets/edittext.cpp
    gui/widgets/list.cpp
    gui/widgets/scrollcontainer.cpp



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 6174d41..b1decb1 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1067,6 +1067,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;
@@ -1093,6 +1100,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;
@@ -1119,6 +1152,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;
@@ -1139,6 +1198,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;
@@ -1582,6 +1661,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);
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index b8ceeda..3c259b4 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -340,30 +340,33 @@ public:
 
 	void drawWidgetBackground(const Common::Rect &r, uint16 hints,
 	                          WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
-
 	void drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clippingArea, uint16 hints,
 								WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
 
 	void drawButton(const Common::Rect &r, const Common::String &str,
 	                WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
-
 	void drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
 		WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
 
 	void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
 	                 WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
-
 	void drawSurfaceClip(const Common::Rect &r, const Common::Rect &clippingRect, const Graphics::Surface &surface,
 		WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
 
 	void drawSlider(const Common::Rect &r, int width,
 	                WidgetStateInfo state = kStateEnabled);
+	void drawSliderClip(const Common::Rect &r, const Common::Rect &clippingRect, int width,
+					WidgetStateInfo state = kStateEnabled);
 
 	void drawCheckbox(const Common::Rect &r, const Common::String &str,
 	                  bool checked, WidgetStateInfo state = kStateEnabled);
+	void drawCheckboxClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+					  bool checked, WidgetStateInfo state = kStateEnabled);
 
 	void drawRadiobutton(const Common::Rect &r, const Common::String &str,
 	                     bool checked, WidgetStateInfo state = kStateEnabled);
+	void drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
+						 bool checked, WidgetStateInfo state = kStateEnabled);
 
 	void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
 	             const Common::Array<Common::String> &tabs, int active, uint16 hints,
@@ -384,20 +387,20 @@ public:
 
 	void drawCaret(const Common::Rect &r, bool erase,
 	               WidgetStateInfo state = kStateEnabled);
-
 	void drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase,
 		WidgetStateInfo state = kStateEnabled);
 
 	void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
+	void drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingArea, WidgetStateInfo state = kStateEnabled);
 
 	void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
 	void drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground type, WidgetStateInfo state = kStateEnabled);
 
 	void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
-
 	void drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
 
 	void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
+	void drawCharClip(const Common::Rect &r, const Common::Rect &clippingArea, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
 
 	//@}
 
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 13be22f..f2a888e 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -99,7 +99,7 @@ void Widget::draw() {
 
 	// Draw border
 	if (_flags & WIDGET_BORDER) {
-		g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundBorder);
+		g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
 		_x += 4;
 		_y += 4;
 		_w -= 8;
@@ -424,7 +424,7 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
 }
 
 void PicButtonWidget::drawWidget() {
-	g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
+	g_gui.theme()->drawButtonClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), "", _state, getFlags());
 
 	if (_gfx.getPixels()) {
 		// Check whether the set up surface needs to be converted to the GUI
@@ -437,7 +437,7 @@ void PicButtonWidget::drawWidget() {
 		const int x = _x + (_w - _gfx.w) / 2;
 		const int y = _y + (_h - _gfx.h) / 2;
 
-		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), _gfx, _state, _alpha, _transparency);
+		g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);		
 	}
 }
 
@@ -472,7 +472,7 @@ void CheckboxWidget::setState(bool state) {
 }
 
 void CheckboxWidget::drawWidget() {
-	g_gui.theme()->drawCheckbox(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state);
+	g_gui.theme()->drawCheckboxClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
 }
 
 #pragma mark -
@@ -541,7 +541,7 @@ void RadiobuttonWidget::setState(bool state, bool setGroup) {
 }
 
 void RadiobuttonWidget::drawWidget() {
-	g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state);
+	g_gui.theme()->drawRadiobuttonClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
 }
 
 #pragma mark -
@@ -609,7 +609,7 @@ void SliderWidget::handleMouseWheel(int x, int y, int direction) {
 }
 
 void SliderWidget::drawWidget() {
-	g_gui.theme()->drawSlider(Common::Rect(_x, _y, _x + _w, _y + _h), valueToBarWidth(_value), _state);
+	g_gui.theme()->drawSliderClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), valueToBarWidth(_value), _state);
 }
 
 int SliderWidget::valueToBarWidth(int value) {
@@ -723,7 +723,7 @@ void ContainerWidget::removeWidget(Widget *widget) {
 }
 
 void ContainerWidget::drawWidget() {
-	g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
+	g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
 }
 
 } // End of namespace GUI
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 83b6a7b..4f7e584 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -303,7 +303,7 @@ void EditableWidget::drawCaret(bool erase) {
 		// possible glitches due to different methods used.
 		width = MIN(editRect.width() - caretOffset, width);
 		if (width > 0) {
-			g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+			g_gui.theme()->drawTextClip(Common::Rect(x, y, x + width, y + editRect.height()), getBossClipRect(), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
 		}
 	}
 
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index bef90d4..0a8725a 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -97,7 +97,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 }
 
 void EditTextWidget::drawWidget() {
-	g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundEditText);
+	g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundEditText);
 
 	// Draw the text
 	adjustOffset();
@@ -105,7 +105,7 @@ void EditTextWidget::drawWidget() {
 	const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
 	setTextDrawableArea(r);
 
-	g_gui.theme()->drawText(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+	g_gui.theme()->drawTextClip(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), getBossClipRect(), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
 }
 
 Common::Rect EditTextWidget::getEditRect() const {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index 4b69202..f6e5c67 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -488,7 +488,7 @@ void ListWidget::drawWidget() {
 	Common::String buffer;
 
 	// Draw a thin frame around the list.
-	g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
+	g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
 	const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0;
 
 	// Draw the list items
@@ -507,7 +507,7 @@ void ListWidget::drawWidget() {
 		// If in numbering mode, we first print a number prefix
 		if (_numberingMode != kListNumberingOff) {
 			buffer = Common::String::format("%2d. ", (pos + _numberingMode));
-			g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2),
+			g_gui.theme()->drawTextClip(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), getBossClipRect(),
 									buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true);
 			pad = 0;
 		}
@@ -528,12 +528,12 @@ void ListWidget::drawWidget() {
 			color = _editColor;
 			adjustOffset();
 			width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW;
-			g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
+			g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state,
 									Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
 		} else {
 			buffer = _list[pos];
 			width = _w - r.left - scrollbarW;
-			g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
+			g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state,
 									Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
 		}
 
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index eca0279..8b68b0f 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -135,7 +135,7 @@ void ScrollContainerWidget::reflowLayout() {
 }
 
 void ScrollContainerWidget::drawWidget() {
-	g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1), ThemeEngine::kDialogBackgroundDefault);
+	g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1), getBossClipRect(), ThemeEngine::kDialogBackgroundDefault);
 }
 
 Widget *ScrollContainerWidget::findWidget(int x, int y) {


Commit: bc2c7689dc6753828f7ac0672eb7b3fea5414293
    https://github.com/scummvm/scummvm/commit/bc2c7689dc6753828f7ac0672eb7b3fea5414293
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:47+02:00

Commit Message:
GUI: Update scummmodern.zip

Changed paths:
    gui/themes/scummmodern.zip



diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 70f7672..d7246fa 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ


Commit: cea58cc61c12206f41b64ba0094655dcd84b57af
    https://github.com/scummvm/scummvm/commit/cea58cc61c12206f41b64ba0094655dcd84b57af
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:53+02:00

Commit Message:
JANITORIAL: Remove trailing spaces

Changed paths:
    graphics/VectorRendererSpec.cpp
    gui/ThemeEngine.cpp
    gui/ThemeEval.cpp
    gui/ThemeLayout.h
    gui/widget.cpp
    gui/widgets/scrollcontainer.cpp



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 43ca2c4..a0cc308 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -462,7 +462,7 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) {
 template<typename PixelType>
 void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX, int realY, Common::Rect &clippingArea) {
 	if (realY < clippingArea.top || realY >= clippingArea.bottom)
-		return;	
+		return;
 
 	register int count = (last - first);
 
@@ -476,7 +476,7 @@ void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX
 	}
 
 	if (clippingArea.right <= realX + count) {
-		register int diff = (realX + count - clippingArea.right);		
+		register int diff = (realX + count - clippingArea.right);
 		count -= diff;
 	}
 
@@ -719,10 +719,10 @@ fillSurfaceClip(Common::Rect clipping) {
 	byte *ptr = (byte *)_activeSurface->getPixels();
 	int pitch = _activeSurface->pitch;
 
-	if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {		
+	if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {
 		PixelType color = (Base::_fillMode == kFillBackground ? _bgColor : _fgColor);
 		byte *ptrLeft = (ptr + _clippingArea.left), *ptrRight = ptr + _clippingArea.right;
-		for (int i = 0; i < h; i++) {			
+		for (int i = 0; i < h; i++) {
 			if (_clippingArea.top <= i && i < _clippingArea.bottom) {
 				colorFill<PixelType>((PixelType *)ptrLeft, (PixelType *)ptrRight, color);
 			}
@@ -1451,7 +1451,7 @@ drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
 	case kFillForeground:
 		if (useClippingVersions)
 			drawSquareAlgClip(x, y, w, h, _fgColor, kFillForeground);
-		else 
+		else
 			drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
 		break;
 
@@ -2916,7 +2916,7 @@ drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType c
 		interx += gradient;
 
 		switch (fill_m) {
-		case kFillDisabled:			
+		case kFillDisabled:
 			if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
 			if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
 			break;
@@ -3247,18 +3247,18 @@ drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType
 			color3 = calcGradient(long_h - r + x, long_h);
 			color4 = calcGradient(long_h - r + y, long_h);
 
-			//TL = (x1 + r, y1 + r)			
+			//TL = (x1 + r, y1 + r)
 			gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y,
 				x1 + r - x, y1 + r - y);
 			gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x,
 				x1 + r - y, y1 + r - x);
 
-			//BL = (x1 + r, y1 + h - r)	
+			//BL = (x1 + r, y1 + h - r)
 			gradientFillClip(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y,
 				x1 + r - x, y1 + h - r + y);
 			gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x,
 				x1 + r - y, y1 + h - r + x);
-			
+	
 			BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
 				x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
 		}
@@ -3287,7 +3287,7 @@ drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType
 	while (short_h--) {
 		if (fill_m == kFillGradient) {
 			gradientFillClip(ptr_fill, w + 1, x1, real_radius++, x1, y1 + r + short_h_orig - short_h -1);
-		} else {			
+		} else {
 			colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color1, x1, y1 + r + short_h_orig - short_h - 1, _clippingArea);
 		}
 		ptr_fill += pitch;
@@ -3338,13 +3338,13 @@ drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, V
 	const uint8 bevelAlpha_b = 0;
 	const uint8 bevelAlpha_l = 127;
 
-	// If only border is visible	
-	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {		
+	// If only border is visible
+	if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
 		if (fill_m == Base::kFillBackground)
 			drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, _bgColor, fill_m);
 		else
 			drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m);
-	}	
+	}
 
 	//I expect these to work fine with clipping:
 	if (Base::_strokeWidth) {
@@ -3595,9 +3595,9 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
 		}
 
 		ptr_fill += pitch * r;
-		while (short_h--) {			
+		while (short_h--) {
 			blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
-			ptr_fill += pitch;			
+			ptr_fill += pitch;
 		}
 
 		// Make shadow smaller each iteration, and move it one pixel inward
@@ -3672,7 +3672,7 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
 
 		ptr_fill += pitch * r;
 		int orig_short_h = short_h;
-		while (short_h--) {			
+		while (short_h--) {
 			blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha,
 				xstart, ystart + r + orig_short_h - short_h - 1);
 			ptr_fill += pitch;
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index b1decb1..c850a6a 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1377,7 +1377,7 @@ void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect
 	else if (state == kStateDisabled)
 		dd = kDDPopUpDisabled;
 
-	queueDDClip(dd, r, clip);	
+	queueDDClip(dd, r, clip);
 
 	if (!sel.empty()) {
 		Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp
index 9b7b57c..5255587 100644
--- a/gui/ThemeEval.cpp
+++ b/gui/ThemeEval.cpp
@@ -89,7 +89,7 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common
 		typeW = getVar("Globals." + type + ".Width", -1);
 		typeH = getVar("Globals." + type + ".Height", -1);
 		typeAlign = (Graphics::TextAlign)getVar("Globals." + type + ".Align", Graphics::kTextAlignInvalid);
-	}	
+	}
 
 	ThemeLayoutWidget *widget;
 	if (type == "TabWidget")
diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h
index 00e55ce..e738002 100644
--- a/gui/ThemeLayout.h
+++ b/gui/ThemeLayout.h
@@ -233,7 +233,7 @@ public:
 		_tabHeight = tabHeight;
 	}
 
-	void reflowLayout() {		
+	void reflowLayout() {
 		for (uint i = 0; i < _children.size(); ++i) {
 			_children[i]->resetLayout();
 			_children[i]->reflowLayout();
diff --git a/gui/widget.cpp b/gui/widget.cpp
index f2a888e..56b7e91 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -437,7 +437,7 @@ void PicButtonWidget::drawWidget() {
 		const int x = _x + (_w - _gfx.w) / 2;
 		const int y = _y + (_h - _gfx.h) / 2;
 
-		g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);		
+		g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);
 	}
 }
 
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index 8b68b0f..1b38478 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -95,7 +95,7 @@ uint16 ScrollContainerWidget::getHeight() const {
 }
 
 void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
-	Widget::handleCommand(sender, cmd, data);	
+	Widget::handleCommand(sender, cmd, data);
 	switch (cmd) {
 	case kSetPositionCmd:
 		_scrolledY = _verticalScroll->_currentPos;
@@ -103,7 +103,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
 		draw();
 		g_gui.doFullRedraw();
 		break;
-	}	
+	}
 }
 
 void ScrollContainerWidget::reflowLayout() {


Commit: 6de5324742fd1ceaa00d9f361638b0c0a9882999
    https://github.com/scummvm/scummvm/commit/6de5324742fd1ceaa00d9f361638b0c0a9882999
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:55+02:00

Commit Message:
JANITORIAL: Fix a few warnings

Changed paths:
    graphics/VectorRendererSpec.cpp



diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index a0cc308..b2314b0 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -537,7 +537,7 @@ VectorRendererSpec(PixelFormat format) :
 	_alphaMask((0xFF >> format.aLoss) << format.aShift) {
 
 	_bitmapAlphaColor = _format.RGBToColor(255, 0, 255);
-	_clippingArea = Common::Rect(0, 0, 64 * 1024, 64 * 1024);
+	_clippingArea = Common::Rect(0, 0, 32767, 32767);
 }
 
 /****************************
@@ -1341,11 +1341,12 @@ drawCircleClip(int x, int y, int r, Common::Rect clipping) {
 
 	switch (Base::_fillMode) {
 	case kFillDisabled:
-		if (Base::_strokeWidth)
+		if (Base::_strokeWidth) {
 			if (useClippingVersions)
 				drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
 			else
 				drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
+		}
 		break;
 
 	case kFillForeground:
@@ -1441,11 +1442,12 @@ drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
 
 	switch (Base::_fillMode) {
 	case kFillDisabled:
-		if (Base::_strokeWidth)
+		if (Base::_strokeWidth) {
 			if (useClippingVersions)
 				drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
 			else
 				drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+		}
 		break;
 
 	case kFillForeground:
@@ -1467,11 +1469,12 @@ drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
 
 	case kFillGradient:
 		VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
-		if (Base::_strokeWidth)
+		if (Base::_strokeWidth) {
 			if (useClippingVersions)
 				drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
 			else
 				drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+		}
 		break;
 	}
 


Commit: 846619fd42ecb11e94958e39bd61ea29a9ff76cd
    https://github.com/scummvm/scummvm/commit/846619fd42ecb11e94958e39bd61ea29a9ff76cd
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-03T12:24:56+02:00

Commit Message:
GUI: Add checks in Widget::getBossClipRect()

Prints a warning if clipping area is invalid and fixes it.

Changed paths:
    gui/object.cpp
    gui/widget.cpp
    gui/widget.h



diff --git a/gui/object.cpp b/gui/object.cpp
index 2d9e959..de66d95 100644
--- a/gui/object.cpp
+++ b/gui/object.cpp
@@ -44,21 +44,6 @@ void GuiObject::reflowLayout() {
 		if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) {
 			error("Could not load widget position for '%s'", _name.c_str());
 		}
-
-		/*
-		if (_x < 0)
-			error("Widget <%s> has x < 0 (%d)", _name.c_str(), _x);
-		if (_x >= g_gui.getWidth())
-			error("Widget <%s> has x > %d (%d)", _name.c_str(), g_gui.getWidth(), _x);
-		if (_x + _w > g_gui.getWidth())
-			error("Widget <%s> has x + w > %d (%d)", _name.c_str(), g_gui.getWidth(), _x + _w);
-		if (_y < 0)
-			error("Widget <%s> has y < 0 (%d)", _name.c_str(), _y);
-		if (_y >= g_gui.getHeight())
-			error("Widget <%s> has y > %d (%d)", _name.c_str(), g_gui.getHeight(), _y);
-		if (_y + _h > g_gui.getHeight())
-			error("Widget <%s> has y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), _y + _h);
-			*/
 	}
 }
 
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 56b7e91..32ca022 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -53,6 +53,31 @@ void Widget::init() {
 	_boss->_firstWidget = this;
 }
 
+Common::Rect Widget::getBossClipRect() const {
+	int bx = _boss->getAbsX();
+	int by = _boss->getAbsY();
+	Common::Rect result = Common::Rect(bx, by, bx + _boss->getWidth(), by + _boss->getHeight());
+	bool needsClipping = false;
+
+	//check whether clipping area is inside the screen
+	if (result.left < 0 && (needsClipping = true))
+		warning("Widget <%s> has clipping area x < 0 (%d)", _name.c_str(), result.left);
+	if (result.left >= g_gui.getWidth() && (needsClipping = true))
+		warning("Widget <%s> has clipping area x > %d (%d)", _name.c_str(), g_gui.getWidth(), result.left);
+	if (result.right > g_gui.getWidth() && (needsClipping = true))
+		warning("Widget <%s> has clipping area x + w > %d (%d)", _name.c_str(), g_gui.getWidth(), result.right);
+	if (result.top < 0 && (needsClipping = true))
+		warning("Widget <%s> has clipping area y < 0 (%d)", _name.c_str(), result.top);
+	if (result.top >= g_gui.getHeight() && (needsClipping = true))
+		warning("Widget <%s> has clipping area y > %d (%d)", _name.c_str(), g_gui.getHeight(), result.top);
+	if (result.bottom > g_gui.getHeight() && (needsClipping = true))
+		warning("Widget <%s> has clipping area y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), result.bottom);
+
+	if (needsClipping)
+		result.clip(g_gui.getWidth(), g_gui.getHeight());
+	return result;
+}
+
 Widget::~Widget() {
 	delete _next;
 	_next = 0;
diff --git a/gui/widget.h b/gui/widget.h
index db801fa..0f4b300 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -112,11 +112,7 @@ public:
 
 	virtual int16	getAbsX() const	{ return _x + _boss->getChildX(); }
 	virtual int16	getAbsY() const	{ return _y + _boss->getChildY(); }
-	virtual Common::Rect getBossClipRect() const {
-		int px = _boss->getAbsX();
-		int py = _boss->getAbsY();
-		return Common::Rect(px, py, px + _boss->getWidth(), py + _boss->getHeight());
-	}
+	virtual Common::Rect getBossClipRect() const;
 
 	virtual void setPos(int x, int y) { _x = x; _y = y; }
 	virtual void setSize(int w, int h) { _w = w; _h = h; }


Commit: 9cec2eea5cdaf2893771f434c45648dcf7da88f2
    https://github.com/scummvm/scummvm/commit/9cec2eea5cdaf2893771f434c45648dcf7da88f2
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-07-10T16:23:34+02:00

Commit Message:
Merge pull request #774 from Tkachov/the-container-box-pr2

GUI: Add ScrollContainerWidget

Changed paths:
  A gui/widgets/scrollcontainer.cpp
  A gui/widgets/scrollcontainer.h
    graphics/VectorRenderer.cpp
    graphics/VectorRenderer.h
    graphics/VectorRendererSpec.cpp
    graphics/VectorRendererSpec.h
    graphics/nine_patch.cpp
    graphics/nine_patch.h
    graphics/transparent_surface.cpp
    graphics/transparent_surface.h
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/ThemeEval.cpp
    gui/ThemeLayout.h
    gui/dialog.cpp
    gui/gui-manager.cpp
    gui/gui-manager.h
    gui/module.mk
    gui/object.cpp
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/widget.cpp
    gui/widget.h
    gui/widgets/editable.cpp
    gui/widgets/edittext.cpp
    gui/widgets/list.cpp
    gui/widgets/popup.cpp
    gui/widgets/scrollbar.cpp
    gui/widgets/tab.cpp









More information about the Scummvm-git-logs mailing list