diff options
| -rw-r--r-- | graphics/VectorRenderer.h | 3 | ||||
| -rw-r--r-- | graphics/VectorRendererSpec.cpp | 293 | ||||
| -rw-r--r-- | graphics/VectorRendererSpec.h | 17 | ||||
| -rw-r--r-- | gui/ThemeEngine.cpp | 25 | ||||
| -rw-r--r-- | gui/ThemeEngine.h | 2 | ||||
| -rw-r--r-- | gui/widgets/scrollbar.cpp | 7 | 
6 files changed, 338 insertions, 9 deletions
| diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 2af91d3587..a84062c358 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 9339c8e49a..f2a69d3fca 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 7a1fe369f0..42d906c639 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 a38e565f6c..6d9f7d8a7d 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 af8c293a36..c854b0025d 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 f1306b9c4a..d8bcb18336 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 | 
