[Scummvm-git-logs] scummvm master -> f06f470685fae195d4922cc9efecdbaaeee13330

lephilousophe noreply at scummvm.org
Sat Jun 3 16:27:56 UTC 2023


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

Summary:
f06f470685 GRAPHICS: Properly take stroke width into account when drawing lines


Commit: f06f470685fae195d4922cc9efecdbaaeee13330
    https://github.com/scummvm/scummvm/commit/f06f470685fae195d4922cc9efecdbaaeee13330
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-06-03T18:27:17+02:00

Commit Message:
GRAPHICS: Properly take stroke width into account when drawing lines

Old code:
- didn't handle well strokes with an odd width
- didn't handle strokes widths above 1 in generic lines handler

Changed paths:
    graphics/VectorRendererSpec.cpp


diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index b7014f4a66a..a0fc9f32198 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1081,39 +1081,33 @@ drawLine(int x1, int y1, int x2, int y2) {
 
 	PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
 	int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
-	int st = Base::_strokeWidth >> 1;
+	// Stroke widths before and after the coordinate
+	// Before is favoured in case of even stroke width
+	int stb = Base::_strokeWidth >> 1;
+	int sta = stb + (Base::_strokeWidth & 1);
 
 	bool useClippingVersions = !_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2);
 
-	int ptr_x = x1, ptr_y = y1;
-
 	if (dy == 0) { // horizontal lines
-		if (useClippingVersions) {
-			colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
-		} else {
-			colorFill<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor);
-		}
-
-		for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
 			if (useClippingVersions) {
-				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);
+				colorFillClip<PixelType>(ptr + p, ptr + p + dx + 1, (PixelType)_fgColor, x1, y1 + i, _clippingArea);
 			} else {
-				colorFill<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor);
-				colorFill<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor);
+				colorFill<PixelType>(ptr + p, ptr + p + dx + 1, (PixelType)_fgColor);
 			}
 		}
 
 	} else if (dx == 0) { // vertical lines
 						  // these ones use a static pitch increase.
-		while (y1++ <= y2) {
+		while (y1 <= y2) {
 			if (useClippingVersions) {
-				colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
+				colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, x1 - stb, y1, _clippingArea);
 			} else {
-				colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
+				colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor);
 			}
 			ptr += pitch;
-			++ptr_y;
+			y1++;
 		}
 
 	} else if (dx == dy) { // diagonal lines
@@ -1122,13 +1116,13 @@ drawLine(int x1, int y1, int x2, int y2) {
 
 		while (dy--) {
 			if (useClippingVersions) {
-				colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
+				colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, x1 - stb, y1, _clippingArea);
 			} else {
-				colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
+				colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor);
 			}
 			ptr += pitch;
-			++ptr_y;
-			if (x2 > x1) ++ptr_x; else --ptr_x;
+			y1++;
+			if (x2 > x1) ++x1; else --x1;
 		}
 
 	} else { // generic lines, use the standard algorithm...
@@ -2089,9 +2083,26 @@ void VectorRendererSpec<PixelType>::
 drawLineAlg(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 strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
+	// Stroke widths before and after the coordinate
+	// Before is favoured in case of even stroke width
+	int stb = Base::_strokeWidth >> 1;
+	int sta = stb + (Base::_strokeWidth & 1);
 	int xdir = (x2 > x1) ? 1 : -1;
 
-	*ptr = (PixelType)color;
+	if (strokeState == 0) {
+		// No stroke width
+		*ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			*(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
+	}
 
 	if (dx > dy) {
 		int ddy = dy * 2;
@@ -2107,7 +2118,15 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 			}
 
 			ptr += xdir;
-			*ptr = (PixelType)color;
+
+			if (strokeState) {
+				intptr p = -stb * pitch;
+				for (int i = -stb; i < sta; i++, p += pitch) {
+					*(ptr + p) = (PixelType)color;
+				}
+			} else {
+				*ptr = (PixelType)color;
+			}
 		}
 	} else {
 		int ddx = dx * 2;
@@ -2123,12 +2142,28 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 			}
 
 			ptr += pitch;
-			*ptr = (PixelType)color;
+			if (strokeState) {
+				colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
+			} else {
+				*ptr = (PixelType)color;
+			}
 		}
 	}
 
 	ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
-	*ptr = (PixelType)color;
+	if (strokeState == 0) {
+		// No stroke width
+		*ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			*(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
+	}
 }
 
 template<typename PixelType>
@@ -2136,10 +2171,27 @@ 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 strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
+	// Stroke widths before and after the coordinate
+	// Before is favoured in case of even stroke width
+	int stb = Base::_strokeWidth >> 1;
+	int sta = stb + (Base::_strokeWidth & 1);
 	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 (strokeState == 0) {
+		// No stroke width
+		if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
+	}
 
 	if (dx > dy) {
 		int ddy = dy * 2;
@@ -2157,7 +2209,15 @@ drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType colo
 
 			ptr += xdir;
 			ptr_x += xdir;
-			if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+
+			if (strokeState) {
+				intptr p = -stb * pitch;
+				for (int i = -stb; i < sta; i++, p += pitch) {
+					if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
+				}
+			} else {
+				if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+			}
 		}
 	} else {
 		int ddx = dx * 2;
@@ -2175,13 +2235,29 @@ drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType colo
 
 			ptr += pitch;
 			++ptr_y;
-			if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+			if (strokeState) {
+				colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
+			} else {
+				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;
+	if (strokeState == 0) {
+		// No stroke width
+		if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
+	}
 }
 
 /** VERTICAL TRIANGLE DRAWING ALGORITHM **/
@@ -3891,11 +3967,28 @@ void VectorRendererAA<PixelType>::
 drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 	PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
 	int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
+	int strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
+	// Stroke widths before and after the coordinate
+	// Before is favoured in case of even stroke width
+	int stb = Base::_strokeWidth >> 1;
+	int sta = stb + (Base::_strokeWidth & 1);
 	int xdir = (x2 > x1) ? 1 : -1;
 	uint16 error_tmp, error_acc, gradient;
 	uint8 alpha;
 
-	*ptr = (PixelType)color;
+	if (strokeState == 0) {
+		// No stroke width
+		*ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			*(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
+	}
 
 	if (dx > dy) {
 		gradient = (dy << 16) / dx;
@@ -3911,8 +4004,18 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 			ptr += xdir;
 			alpha = (error_acc >> 8);
 
-			this->blendPixelPtr(ptr, color, ~alpha);
-			this->blendPixelPtr(ptr + pitch, color, alpha);
+			if (strokeState) {
+				intptr p = -stb * pitch;
+				this->blendPixelPtr(ptr + p, color, ~alpha);
+				p += pitch;
+				for (int i = -stb + 1; i < sta; i++, p += pitch) {
+					*(ptr + p) = (PixelType)color;
+				}
+				this->blendPixelPtr(ptr + p, color, alpha);
+			} else {
+				this->blendPixelPtr(ptr, color, ~alpha);
+				this->blendPixelPtr(ptr + pitch, color, alpha);
+			}
 		}
 	} else if (dy != 0) {
 		gradient = (dx << 16) / dy;
@@ -3928,12 +4031,37 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
 			ptr += pitch;
 			alpha = (error_acc >> 8);
 
-			this->blendPixelPtr(ptr, color, ~alpha);
-			this->blendPixelPtr(ptr + xdir, color, alpha);
+			if (strokeState) {
+				if (xdir > 0) {
+					this->blendPixelPtr(ptr - stb, color, ~alpha);
+					colorFill<PixelType>(ptr - stb + 1, ptr + sta, (PixelType)color);
+					this->blendPixelPtr(ptr + sta, color, alpha);
+				} else {
+					this->blendPixelPtr(ptr - stb, color, alpha);
+					colorFill<PixelType>(ptr - stb + 1, ptr + sta, (PixelType)color);
+					this->blendPixelPtr(ptr + sta, color, ~alpha);
+				}
+			} else {
+				this->blendPixelPtr(ptr, color, ~alpha);
+				this->blendPixelPtr(ptr + xdir, color, alpha);
+			}
 		}
 	}
 
-	Base::putPixel(x2, y2, color);
+	ptr = (PixelType *)Base::_activeSurface->getBasePtr(x2, y2);
+	if (strokeState == 0) {
+		// No stroke width
+		*ptr = (PixelType)color;
+	} else if (strokeState == 1) {
+		// Horizontal line
+		intptr p = -stb * pitch;
+		for (int i = -stb; i < sta; i++, p += pitch) {
+			*(ptr + p) = (PixelType)color;
+		}
+	} else {
+		// Vertical line
+		colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
+	}
 }
 
 /** TAB ALGORITHM */




More information about the Scummvm-git-logs mailing list