[Scummvm-cvs-logs] SF.net SVN: scummvm: [32169] scummvm/branches/gsoc2008-gui/graphics

Tanoku at users.sourceforge.net Tanoku at users.sourceforge.net
Sun May 18 15:09:37 CEST 2008


Revision: 32169
          http://scummvm.svn.sourceforge.net/scummvm/?rev=32169&view=rev
Author:   Tanoku
Date:     2008-05-18 06:09:37 -0700 (Sun, 18 May 2008)

Log Message:
-----------
- Massive cleanup
- Documentation update
- Boundaries check

Modified Paths:
--------------
    scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.cpp
    scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.h

Modified: scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.cpp	2008-05-18 13:03:03 UTC (rev 32168)
+++ scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.cpp	2008-05-18 13:09:37 UTC (rev 32169)
@@ -25,38 +25,19 @@
 
 #include "common/util.h"
 #include "graphics/surface.h"
-#include "graphics/VectorRenderer.h"
 #include "graphics/colormasks.h"
 #include "common/system.h"
 #include "common/events.h"
 
-inline uint32 fp_sqroot(uint32 x) {
-	register uint32 root, remHI, remLO, testDIV, count;
+#include "graphics/VectorRenderer.h"
 
-	root = 0;
-	remHI = 0;
-	remLO = x;
-	count = 23;
-
-	do {
-		remHI = (remHI << 2) | (remLO >> 30);
-		remLO <<= 2;
-		root <<= 1;
-		testDIV = (root << 1) + 1;
-
-		if (remHI >= testDIV) {
-			remHI -= testDIV;
-			root++;
-		}
-	} while (count--);
-
-	return root;
-}
-
 namespace Graphics {
 
+/********************************************************************
+ * DEBUG FUNCTIONS
+ ********************************************************************/
 VectorRenderer *createRenderer() {
-	return new VectorRendererAA<uint16, ColorMasks<565> >;
+	return new VectorRendererSpec<uint16, ColorMasks<565> >;
 }
 
 
@@ -114,10 +95,153 @@
 	_system->hideOverlay();
 }
 
+/********************************************************************
+ * MISCELANEOUS functions
+ ********************************************************************/
+/** Fixed point SQUARE ROOT **/
+inline uint32 fp_sqroot(uint32 x) {
+	register uint32 root, remHI, remLO, testDIV, count;
+
+	root = 0;
+	remHI = 0;
+	remLO = x;
+	count = 23;
+
+	do {
+		remHI = (remHI << 2) | (remLO >> 30);
+		remLO <<= 2;
+		root <<= 1;
+		testDIV = (root << 1) + 1;
+
+		if (remHI >= testDIV) {
+			remHI -= testDIV;
+			root++;
+		}
+	} while (count--);
+
+	return root;
+}
+
+/** HELPER MACROS for BESENHALM's circle drawing algorithm **/
+#define __BE_ALGORITHM() { \
+	if (f >= 0) { \
+		y--; \
+		ddF_y += 2; \
+		f += ddF_y; \
+		py -= pitch; \
+	} \
+	px += pitch; \
+	ddF_x += 2; \
+	f += ddF_x + 1; \
+}
+
+#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \
+	*(ptr1 + (y) - (px)) = color; \
+	*(ptr1 + (x) - (py)) = color; \
+	*(ptr2 - (x) - (py)) = color; \
+	*(ptr2 - (y) - (px)) = color; \
+	*(ptr3 - (y) + (px)) = color; \
+	*(ptr3 - (x) + (py)) = color; \
+	*(ptr4 + (x) + (py)) = color; \
+	*(ptr4 + (y) + (px)) = color; \
+}
+
+#define __BE_RESET() { \
+	f = 1 - r; \
+	ddF_x = 0; ddF_y = -2 * r; \
+	x = 0; y = r; px = 0; py = pitch * r; \
+}
+
+/** HELPER MACROS for WU's circle drawing algorithm **/
+#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \
+	blendPixelPtr(ptr1 + (y) - (px), color, a); \
+	blendPixelPtr(ptr1 + (x) - (py), color, a); \
+	blendPixelPtr(ptr2 - (x) - (py), color, a); \
+	blendPixelPtr(ptr2 - (y) - (px), color, a); \
+	blendPixelPtr(ptr3 - (y) + (px), color, a); \
+	blendPixelPtr(ptr3 - (x) + (py), color, a); \
+	blendPixelPtr(ptr4 + (x) + (py), color, a); \
+	blendPixelPtr(ptr4 + (y) + (px), color, a); \
+}
+
+#define __WU_ALGORITHM() { \
+	oldT = T; \
+	T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \
+	py += p; \
+	if (T < oldT) { \
+		x--; px -= p; \
+	} \
+	a2 = (T >> 8); \
+	a1 = ~a2; \
+}
+
+/********************************************************************
+ * Primitive shapes drawing - Public API calls - VectorRendererSpec
+ ********************************************************************/
+/** LINES **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
+drawLine(int x1, int y1, int x2, int y2) {
+	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);
+	}
+
+	int dx = ABS(x2 - x1);
+	int 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 = Base::surfacePitch();
+
+	if (dy == 0) { // horizontal lines
+		// these can be filled really fast with a single memset.
+		// TODO: Platform specific ASM in set_to, would make this thing fly 
+		Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor);
+
+	} else if (dx == 0) { // vertical lines
+		// these ones use a static pitch increase.
+		while (y1++ <= y2) {
+			*ptr = (PixelType)_fgColor;
+			ptr += pitch;
+		}
+
+	} else if (ABS(dx) == ABS(dy)) { // diagonal lines
+		// these ones also use a fixed pitch increase
+		pitch += (x2 > x1) ? 1 : -1;
+
+		while (dy--) {
+			*ptr = (PixelType)_fgColor;
+			ptr += pitch;
+		}
+
+	} else { // generic lines, use the standard algorithm...
+		drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
+	}
+}
+
+/** CIRCLES **/
+template<typename PixelType, typename PixelFormat>
+void VectorRendererSpec<PixelType, PixelFormat>::
 drawCircle(int x, int y, int r) {
-	if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+	if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h)
+		return;
+
+	if (Base::_fillMode != kNoFill && Base::_shadowOffset 
+		&& x + r + Base::_shadowOffset < Base::_activeSurface->w
+		&& y + r + Base::_shadowOffset < Base::_activeSurface->h) {
 		drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kForegroundFill);
 	}
 
@@ -146,10 +270,16 @@
 	}
 }
 
+/** SQUARES **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
 drawSquare(int x, int y, int w, int h) {
-	if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
+		return;
+
+	if (Base::_fillMode != kNoFill && Base::_shadowOffset
+		&& x + w + Base::_shadowOffset < Base::_activeSurface->w
+		&& y + h + Base::_shadowOffset < Base::_activeSurface->h) {
 		drawSquareShadow(x, y, w, h, Base::_shadowOffset);
 	}
 
@@ -176,10 +306,16 @@
 	}
 }
 
+/** ROUNDED SQUARES **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
 drawRoundedSquare(int x, int y, int r, int w, int h) {
-	if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+	if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
+		return;
+
+	if (Base::_fillMode != kNoFill && Base::_shadowOffset
+		&& x + w + Base::_shadowOffset < Base::_activeSurface->w
+		&& y + h + Base::_shadowOffset < Base::_activeSurface->h) {
 		drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
 	}
 
@@ -212,6 +348,10 @@
 	}
 }
 
+/********************************************************************
+ * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec
+ ********************************************************************/
+/** SQUARE ALGORITHM **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
 drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) {
@@ -244,43 +384,8 @@
 	}
 }
 
+/** GENERIC LINE ALGORITHM **/
 template<typename PixelType, typename PixelFormat>
-void VectorRendererSpec<PixelType, PixelFormat>::
-drawSquareShadow(int x, int y, int w, int h, int blur) {
-	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
-	int pitch = Base::surfacePitch();
-	int i, j;
-
-	i = h - blur;
-
-	while (i--) {
-		j = blur;
-		while (j--)
-			blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur);
-		ptr += pitch;
-	}
-
-	ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1);
-
-	while (i++ < blur) {
-		j = w - blur;
-		while (j--)
-			blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur);
-		ptr += pitch;
-	}
-
-	ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
-
-	i = 0;
-	while (i++ < blur) {
-		j = blur - 1;
-		while (j--)
-			blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur));
-		ptr += pitch;
-	}
-}
-
-template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType,PixelFormat>::
 drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
 	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
@@ -327,160 +432,89 @@
 	*ptr = (PixelType)color;
 }
 
-
+/** ROUNDED SQUARE ALGORITHM **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
-blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
-	if (alpha == 255) {
-		*ptr = color;
-		return;
-	}
-
-	register int idst = *ptr;
-	register int isrc = color;
-
-	*ptr = (PixelType)(
-		(PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) +
-		((int)(((int)(isrc & PixelFormat::kRedMask) -
-		(int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) |
-		(PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) +
-		((int)(((int)(isrc & PixelFormat::kGreenMask) -
-		(int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) |
-		(PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) +
-		((int)(((int)(isrc & PixelFormat::kBlueMask) -
-		(int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) );
-}
-
-
-template<typename PixelType, typename PixelFormat>
-void VectorRendererAA<PixelType, PixelFormat>::
-drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
-
-	PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) {
+	int f, ddF_x, ddF_y;
+	int x, y, px, py;
 	int pitch = Base::surfacePitch();
-	int xdir = (x2 > x1) ? 1 : -1;
-	uint16 error_tmp, error_acc, gradient;
-	uint8 alpha;
+	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);
 
-	*ptr = (PixelType)color;
+	int real_radius = r;
+	int short_h = h - (2 * r) + 2;
+	int long_h = h;
 
-	if (dx > dy) {
-		gradient = (uint32)(dy << 16) / (uint32)dx;
-		error_acc = 0;
+	if (fill_m == kNoFill) {
+		while (sw++ < Base::_strokeWidth) {
+			Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
+			Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
+			sp += pitch;
 
-		while (--dx) {
-			error_tmp = error_acc;
-			error_acc += gradient;
+			__BE_RESET();
+			r--;
+			
+			while (x++ < y) {
+				__BE_ALGORITHM();
+				__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
 
-			if (error_acc <= error_tmp)
-				ptr += pitch;
+				if (Base::_strokeWidth > 1) {
+					__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
+					__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
+				}
+			} 
+		}
 
-			ptr += xdir;
-			alpha = (error_acc >> 8);
-
-			blendPixelPtr(ptr, color, ~alpha);
-			blendPixelPtr(ptr + pitch, color, alpha);
+		ptr_fill += pitch * real_radius;
+		while (short_h--) {
+			Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color);
+			Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
+			ptr_fill += pitch;
 		}
 	} else {
-		gradient = (uint32)(dx << 16) / (uint32)dy;
-		error_acc = 0;
+		__BE_RESET();
 
-		while (--dy) {
-			error_tmp = error_acc;
-			error_acc += gradient;
+		if (fill_m == kGradientFill) {
+			while (x++ < y) {
+				__BE_ALGORITHM();
+				Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h));
+				Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h));
 
-			if (error_acc <= error_tmp)
-				ptr += xdir;
+				Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h));
+				Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h));
+			}
+		} else {
+			while (x++ < y) {
+				__BE_ALGORITHM();			
 
-			ptr += pitch;
-			alpha = (error_acc >> 8);
+				Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color);
+				Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color);
 
-			blendPixelPtr(ptr, color, ~alpha);
-			blendPixelPtr(ptr + xdir, color, alpha);
-		}
-	}
+				Common::set_to(ptr_bl - x + py, ptr_br + x + py, color);
+				Common::set_to(ptr_bl - y + px, ptr_br + y + px, color);
 
-	Base::putPixel(x2, y2, color);
-}
-
-template<typename PixelType, typename PixelFormat>
-void VectorRendererSpec<PixelType, PixelFormat>::
-drawLine(int x1, int y1, int x2, int y2) {
-	// we draw from top to bottom
-	if (y2 < y1) {
-		SWAP(x1, x2);
-		SWAP(y1, y2);
-	}
-
-	int dx = ABS(x2 - x1);
-	int 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 = Base::surfacePitch();
-
-	if (dy == 0) { // horizontal lines
-		// these can be filled really fast with a single memset.
-		// TODO: Platform specific ASM in set_to, would make this thing fly 
-		Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor);
-
-	} else if (dx == 0) { // vertical lines
-		// these ones use a static pitch increase.
-		while (y1++ <= y2) {
-			*ptr = (PixelType)_fgColor;
-			ptr += pitch;
+				// FIXME: maybe not needed at all?
+				__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+			}
 		}
 
-	} else if (ABS(dx) == ABS(dy)) { // diagonal lines
-		// these ones also use a fixed pitch increase
-		pitch += (x2 > x1) ? 1 : -1;
-
-		while (dy--) {
-			*ptr = (PixelType)_fgColor;
-			ptr += pitch;
+		ptr_fill += pitch * r;
+		while (short_h--) {
+			if (fill_m == kGradientFill)
+				color = calcGradient(real_radius++, long_h);
+			Common::set_to(ptr_fill, ptr_fill + w + 1, color);
+			ptr_fill += pitch;
 		}
-
-	} else { // generic lines, use the standard algorithm...
-		drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
 	}
 }
 
-#define __BE_ALGORITHM() { \
-	if (f >= 0) { \
-		y--; \
-		ddF_y += 2; \
-		f += ddF_y; \
-		py -= pitch; \
-	} \
-	px += pitch; \
-	ddF_x += 2; \
-	f += ddF_x + 1; \
-}
-
-#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \
-	*(ptr1 + (y) - (px)) = color; \
-	*(ptr1 + (x) - (py)) = color; \
-	*(ptr2 - (x) - (py)) = color; \
-	*(ptr2 - (y) - (px)) = color; \
-	*(ptr3 - (y) + (px)) = color; \
-	*(ptr3 - (x) + (py)) = color; \
-	*(ptr4 + (x) + (py)) = color; \
-	*(ptr4 + (y) + (px)) = color; \
-}
-
-#define __BE_RESET() { \
-	f = 1 - r; \
-	ddF_x = 0; ddF_y = -2 * r; \
-	x = 0; y = r; px = 0; py = pitch * r; \
-}
-
-
+/** CIRCLE ALGORITHM **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
 drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) {
@@ -523,8 +557,48 @@
 	}
 }
 
+
+/********************************************************************
+ * SHADOW drawing algorithms - VectorRendererSpec
+ ********************************************************************/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererSpec<PixelType, PixelFormat>::
+drawSquareShadow(int x, int y, int w, int h, int blur) {
+	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
+	int pitch = Base::surfacePitch();
+	int i, j;
+
+	i = h - blur;
+
+	while (i--) {
+		j = blur;
+		while (j--)
+			blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur);
+		ptr += pitch;
+	}
+
+	ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1);
+
+	while (i++ < blur) {
+		j = w - blur;
+		while (j--)
+			blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur);
+		ptr += pitch;
+	}
+
+	ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
+
+	i = 0;
+	while (i++ < blur) {
+		j = blur - 1;
+		while (j--)
+			blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur));
+		ptr += pitch;
+	}
+}
+
+template<typename PixelType, typename PixelFormat>
+void VectorRendererSpec<PixelType, PixelFormat>::
 drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) {
 	int f, ddF_x, ddF_y;
 	int x, y, px, py;
@@ -578,109 +652,63 @@
 	}
 }
 
+
+/********************************************************************
+ * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA
+ ********************************************************************/
+/** LINES **/
 template<typename PixelType, typename PixelFormat>
-void VectorRendererSpec<PixelType, PixelFormat>::
-drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) {
-	int f, ddF_x, ddF_y;
-	int x, y, px, py;
+void VectorRendererAA<PixelType, PixelFormat>::
+drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
+
+	PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
 	int pitch = Base::surfacePitch();
-	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 xdir = (x2 > x1) ? 1 : -1;
+	uint16 error_tmp, error_acc, gradient;
+	uint8 alpha;
 
-	int real_radius = r;
-	int short_h = h - (2 * r) + 2;
-	int long_h = h;
+	*ptr = (PixelType)color;
 
-	if (fill_m == kNoFill) {
-		while (sw++ < Base::_strokeWidth) {
-			Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
-			Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
-			sp += pitch;
+	if (dx > dy) {
+		gradient = (uint32)(dy << 16) / (uint32)dx;
+		error_acc = 0;
 
-			__BE_RESET();
-			r--;
-			
-			while (x++ < y) {
-				__BE_ALGORITHM();
-				__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+		while (--dx) {
+			error_tmp = error_acc;
+			error_acc += gradient;
 
-				if (Base::_strokeWidth > 1) {
-					__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
-					__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
-				}
-			} 
-		}
+			if (error_acc <= error_tmp)
+				ptr += pitch;
 
-		ptr_fill += pitch * real_radius;
-		while (short_h--) {
-			Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color);
-			Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
-			ptr_fill += pitch;
+			ptr += xdir;
+			alpha = (error_acc >> 8);
+
+			blendPixelPtr(ptr, color, ~alpha);
+			blendPixelPtr(ptr + pitch, color, alpha);
 		}
 	} else {
-		__BE_RESET();
+		gradient = (uint32)(dx << 16) / (uint32)dy;
+		error_acc = 0;
 
-		if (fill_m == kGradientFill) {
-			while (x++ < y) {
-				__BE_ALGORITHM();
-				Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h));
-				Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h));
+		while (--dy) {
+			error_tmp = error_acc;
+			error_acc += gradient;
 
-				Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h));
-				Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h));
-			}
-		} else {
-			while (x++ < y) {
-				__BE_ALGORITHM();			
+			if (error_acc <= error_tmp)
+				ptr += xdir;
 
-				Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color);
-				Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color);
+			ptr += pitch;
+			alpha = (error_acc >> 8);
 
-				Common::set_to(ptr_bl - x + py, ptr_br + x + py, color);
-				Common::set_to(ptr_bl - y + px, ptr_br + y + px, color);
-
-				// FIXME: maybe not needed at all?
-				__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
-			}
+			blendPixelPtr(ptr, color, ~alpha);
+			blendPixelPtr(ptr + xdir, color, alpha);
 		}
-
-		ptr_fill += pitch * r;
-		while (short_h--) {
-			if (fill_m == kGradientFill)
-				color = calcGradient(real_radius++, long_h);
-			Common::set_to(ptr_fill, ptr_fill + w + 1, color);
-			ptr_fill += pitch;
-		}
 	}
-}
 
-#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \
-	blendPixelPtr(ptr1 + (y) - (px), color, a); \
-	blendPixelPtr(ptr1 + (x) - (py), color, a); \
-	blendPixelPtr(ptr2 - (x) - (py), color, a); \
-	blendPixelPtr(ptr2 - (y) - (px), color, a); \
-	blendPixelPtr(ptr3 - (y) + (px), color, a); \
-	blendPixelPtr(ptr3 - (x) + (py), color, a); \
-	blendPixelPtr(ptr4 + (x) + (py), color, a); \
-	blendPixelPtr(ptr4 + (y) + (px), color, a); \
+	Base::putPixel(x2, y2, color);
 }
 
-#define __WU_ALGORITHM() { \
-	oldT = T; \
-	T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \
-	py += p; \
-	if (T < oldT) { \
-		x--; px -= p; \
-	} \
-	a2 = (T >> 8); \
-	a1 = ~a2; \
-}
-
+/** ROUNDED SQUARES **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererAA<PixelType, PixelFormat>::
 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
@@ -750,6 +778,7 @@
 	}
 }
 
+/** CIRCLES **/
 template<typename PixelType, typename PixelFormat>
 void VectorRendererAA<PixelType, PixelFormat>::
 drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {

Modified: scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.h
===================================================================
--- scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.h	2008-05-18 13:03:03 UTC (rev 32168)
+++ scummvm/branches/gsoc2008-gui/graphics/VectorRenderer.h	2008-05-18 13:09:37 UTC (rev 32169)
@@ -51,23 +51,18 @@
  * @see VectorRendererAA
  */
 class VectorRenderer {
-
 public:
 	VectorRenderer() : _shadowOffset(0), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {}
 	virtual ~VectorRenderer() {}
 
-	enum FillMode {
+	/** Specified the way in which a shape is filled */
+	static enum FillMode {
 		kNoFill = 0,
 		kForegroundFill = 1,
 		kBackgroundFill = 2,
 		kGradientFill = 3
 	};
 
-/*	enum ColorMode {
-		kForegroundColor,
-		kBackgroundColor
-	}; */
-
 	/**
 	 * Draws a line by considering the special cases for optimization.
 	 *
@@ -157,6 +152,17 @@
 	 */
 	virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0;
 
+	/**
+	 * Set the active gradient color. All shapes drawn using kGradientFill
+	 * as their fill mode will use this VERTICAL gradient as their fill color.
+	 *
+	 * @param r1	value of the red color byte for the start color
+	 * @param g1	value of the green color byte for the start color
+	 * @param b1	value of the blue color byte for the start color
+	 * @param r2	value of the red color byte for the end color
+	 * @param g2	value of the green color byte for the end color
+	 * @param b2	value of the blue color byte for the end color
+	 */
 	virtual void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) = 0;
 
 	/**
@@ -170,10 +176,10 @@
 	}
 
 	/**
-	 * Fills the active surface with the specified fg/bg color.
+	 * Fills the active surface with the specified fg/bg color or the active gradient.
 	 * Defaults to using the active Foreground color for filling.
 	 *
-	 * @param mode Color mode (bg or fg color) used to fill.
+	 * @param mode Fill mode (bg, fg or gradient) used to fill the surface
 	 */
 	virtual void fillSurface(FillMode mode = kForegroundFill) = 0;
 
@@ -197,7 +203,7 @@
 
 	/**
 	 * Sets the stroke width. All shapes drawn with a stroke will
-	 * have that width.
+	 * have that width. Pass 0 to disable shape stroking.
 	 *
 	 * @param width Witdh of the stroke in pixels.
 	 */
@@ -207,11 +213,11 @@
 
 	/**
 	 * Enables adding shadows to all drawn primitives.
-	 * Shadows are drawn automatically under the shapes, at the
-	 * given x/y offsets.
+	 * Shadows are drawn automatically under the shapes. The given offset
+	 * controls their intensity and size (the higher the offset, the
+	 * bigger the shadows).
 	 *
-	 * @param x_offset Horizontal offset for the shadows.
-	 * @param y_offset Vertical offset for the shadows.
+	 * @param offset Shadow offset.
 	 * @see shadowDisable()
 	 */
 	virtual void shadowEnable(int offset) {
@@ -228,6 +234,12 @@
 		_shadowOffset = 0;
 	}
 
+	/**
+	 * Sets the multiplication factor of the active gradient.
+	 *
+	 * @see _gradientFactor
+	 * @param factor Multiplication factor.
+	 */
 	virtual void setGradientFactor(int factor) {
 		if (factor > 0)
 			_gradientFactor = factor;
@@ -241,8 +253,8 @@
 	int _shadowOffset; /** offset for drawn shadows */
 	int _strokeWidth; /** Width of the stroke of all drawn shapes */
 
-	int _gradientFactor;
-	int _gradientBytes[3];
+	int _gradientFactor; /** Multiplication factor of the active gradient */
+	int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */
 };
 
 
@@ -304,6 +316,9 @@
 		this->_bgColor = RGBToColor<PixelFormat>(r, g, b);
 	}
 
+	/**
+	 * @see VectorRenderer::setGradientColors()
+	 */
 	void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) {
 		_gradientEnd = RGBToColor<PixelFormat>(r2, g2, b2);
 		_gradientStart = RGBToColor<PixelFormat>(r1, g1, b1);
@@ -324,9 +339,9 @@
 		int pitch = surfacePitch();
 
 		if (mode == kBackgroundFill)
-			Common::set_to(ptr, ptr + w*h, _bgColor);
+			Common::set_to(ptr, ptr + w * h, _bgColor);
 		else if (mode == kForegroundFill)
-			Common::set_to(ptr, ptr + w*h, _fgColor);
+			Common::set_to(ptr, ptr + w * h, _fgColor);
 		else if (mode == kGradientFill) {
 			int i = h;
 			while (i--) {
@@ -367,22 +382,77 @@
 			blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha);
 	}
 
-	virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha);
+	/**
+	 * Blends a single pixel on the surface in the given pixel pointer, using supplied color
+	 * and Alpha intensity.
+	 * 
+	 * This is implemented to prevent blendPixel() to calculate the surface pointer on each call.
+	 * Optimized drawing algorithms should call this function when possible.
+	 *
+	 * @see blendPixel
+	 * @param ptr Pointer to the pixel to blend on top of
+	 * @param color Color of the pixel
+	 * @param alpha Alpha intensity of the pixel (0-255)
+	 */
+	virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha)	{
+		if (alpha == 255) {
+			*ptr = color;
+			return;
+		}
 
-	/*
-	 * "Bresenham's Line Algorithm", as described in Wikipedia.
-	 * Based on the current implementation in "graphics/primitives.cpp".
+		register int idst = *ptr;
+		register int isrc = color;
+
+		*ptr = (PixelType)(
+			(PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) +
+			((int)(((int)(isrc & PixelFormat::kRedMask) -
+			(int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) |
+			(PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) +
+			((int)(((int)(isrc & PixelFormat::kGreenMask) -
+			(int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) |
+			(PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) +
+			((int)(((int)(isrc & PixelFormat::kBlueMask) -
+			(int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) );
+	}
+
+	/**
+	 * PRIMITIVE DRAWING ALGORITHMS
 	 *
-	 * Generic line drawing algorithm for the aliased renderer. Optimized with no
-	 * floating point operations and direct access to pixel buffer, assumes no special cases.
+	 * Generic algorithms for drawing all kinds of aliased primitive shapes.
+	 * These may be overloaded in inheriting classes to implement platform-specific
+	 * optimizations or improve looks.
+	 *
+	 * @see VectorRendererAA
+	 * @see VectorRendererAA::drawLineAlg
+	 * @see VectorRendererAA::drawCircleAlg
 	 */
 	virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color);
 	virtual void drawCircleAlg(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);
 	virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m);
+
+	/**
+	 * SHADOW DRAWING ALGORITHMS
+	 *
+	 * Optimized versions of the primitive drawing algorithms with alpha blending
+	 * for shadow drawing.
+	 * There functions may be overloaded in inheriting classes to improve performance
+	 * in the slowest platforms where pixel alpha blending just doesn't cut it.
+	 *
+	 * @param blur Intensity/size of the shadow.
+	 */
 	virtual void drawSquareShadow(int x, int y, int w, int h, int blur);
 	virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur);
 
+	/**
+	 * Calculates the color gradient on a given point.
+	 * This function assumes that the gradient start/end colors have been set
+	 * beforehand from the API function call.
+	 *
+	 * @param pos Progress of the gradient.
+	 * @param max Maximum amount of the progress.
+	 * @return Composite color of the gradient at the given "progress" amount.
+	 */
 	inline PixelType calcGradient(uint32 pos, uint32 max) {
 		PixelType output = 0;
 		pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max;
@@ -395,6 +465,16 @@
 		return output;
 	}
 
+	/**
+	 * Fills several pixels in a row with a given color and the specifed alpha blending.
+	 *
+	 * @see blendPixelPtr
+	 * @see blendPixel
+	 * @param first Pointer to the first pixel to fill.
+	 * @param last Pointer to the last pixel to fill.
+	 * @param color Color of the pixel
+	 * @param alpha Alpha intensity of the pixel (0-255)
+	 */
 	inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) {
 		while (first != last)
 			blendPixelPtr(first++, color, alpha);
@@ -403,8 +483,8 @@
 	PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */
 	PixelType _bgColor; /** Background color currently being used to draw on the renderer */
 
-	PixelType _gradientStart;
-	PixelType _gradientEnd;
+	PixelType _gradientStart; /** Start color for the fill gradient */
+	PixelType _gradientEnd; /** End color for the fill gradient */
 };
 
 /**
@@ -445,6 +525,13 @@
 	 */
 	virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m);
 
+	/**
+	 * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991,
+	 * modified with corner displacement to allow drawing of squares with rounded
+	 * corners.
+	 *
+	 * @see VectorRenderer::drawRoundedAlg()
+	 */
 	virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
 };
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list