[Scummvm-cvs-logs] CVS: scummvm/scumm wiz_he.cpp,2.113,2.114

Gregory Montoir cyx at users.sourceforge.net
Mon Jan 30 11:22:01 CET 2006


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8166

Modified Files:
	wiz_he.cpp 
Log Message:
Some cleanup and fixes to the wiz transformation code.

Index: wiz_he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/wiz_he.cpp,v
retrieving revision 2.113
retrieving revision 2.114
diff -u -d -r2.113 -r2.114
--- wiz_he.cpp	29 Jan 2006 08:12:32 -0000	2.113
+++ wiz_he.cpp	30 Jan 2006 19:20:51 -0000	2.114
@@ -1099,8 +1099,7 @@
 }
 
 struct PolygonDrawData {
-	struct InterArea {
-		bool valid;
+	struct PolygonArea {
 		int32 xmin;
 		int32 xmax;
 		int32 x1;
@@ -1108,57 +1107,73 @@
 		int32 x2;
 		int32 y2;
 	};
-	Common::Point pto;
-	InterArea *ia;
-	int areasNum;
+	struct ResultArea {
+		int32 dst_offs;
+		int32 x_step;
+		int32 y_step;
+		int32 x_s;
+		int32 y_s;
+		int32 w;
+	};
+	Common::Point mat[4];
+	PolygonArea *pa;
+	ResultArea *ra;
+	int rAreasNum;
+	int pAreasNum;
 
 	PolygonDrawData(int n) {
-		areasNum = n;
-		ia = new InterArea[areasNum];
-		memset(ia, 0, sizeof(InterArea) * areasNum);
+		memset(mat, 0, sizeof(mat));
+		pa = new PolygonArea[n];
+		for (int i = 0; i < n; ++i) {
+			pa[i].xmin = 12345;
+			pa[i].xmax = -12345;
+		}
+		ra = new ResultArea[n];
+		rAreasNum = 0;
+		pAreasNum = n;
 	}
 
 	~PolygonDrawData() {
-		delete[] ia;
+		delete[] pa;
+		delete[] ra;
 	}
 
-	void calcIntersection(const Common::Point *p1, const Common::Point *p2, const Common::Point *p3, const Common::Point *p4) {
-		int32 x1_acc = p1->x << 0x10;
-		int32 x3_acc = p3->x << 0x10;
-		int32 y3_acc = p3->y << 0x10;
-  		uint16 dy = ABS(p2->y - p1->y) + 1;
-  		int32 x1_step = ((p2->x - p1->x) << 0x10) / dy;
-  		int32 x3_step = ((p4->x - p3->x) << 0x10) / dy;
-  		int32 y3_step = ((p4->y - p3->y) << 0x10) / dy;
+	void transform(const Common::Point *tp1, const Common::Point *tp2, const Common::Point *sp1, const Common::Point *sp2) {
+		int32 tx_acc = tp1->x << 16;
+		int32 sx_acc = sp1->x << 16;
+		int32 sy_acc = sp1->y << 16;
+  		uint16 dy = ABS(tp2->y - tp1->y) + 1;
+  		int32 tx_step = ((tp2->x - tp1->x) << 16) / dy;
+  		int32 sx_step = ((sp2->x - sp1->x) << 16) / dy;
+  		int32 sy_step = ((sp2->y - sp1->y) << 16) / dy;
 
-  		int iaidx = p1->y - pto.y;
+  		int y = tp1->y - mat[0].y;
   		while (dy--) {
-  			assert(iaidx >= 0 && iaidx < areasNum);
-  			InterArea *pia = &ia[iaidx];
-  			int32 tx1 = x1_acc >> 0x10;
-  			int32 tx3 = x3_acc >> 0x10;
-  			int32 ty3 = y3_acc >> 0x10;
+  			assert(y >= 0 && y < pAreasNum);
+  			PolygonArea *ppa = &pa[y];
+  			int32 ttx = tx_acc >> 16;
+  			int32 tsx = sx_acc >> 16;
+  			int32 tsy = sy_acc >> 16;
 
-  			if (!pia->valid || pia->xmin > tx1) {
-  				pia->xmin = tx1;
-  				pia->x1 = tx3;
-  				pia->y1 = ty3;
+  			if (ppa->xmin > ttx) {
+  				ppa->xmin = ttx;
+  				ppa->x1 = tsx;
+  				ppa->y1 = tsy;
 			}
-  			if (!pia->valid || pia->xmax < tx1) {
-  				pia->xmax = tx1;
-  				pia->x2 = tx3;
-  				pia->y2 = ty3;
+  			if (ppa->xmax < ttx) {
+  				ppa->xmax = ttx;
+  				ppa->x2 = tsx;
+  				ppa->y2 = tsy;
 			}
-  			pia->valid = true;
 
-  			x1_acc += x1_step;
-  			x3_acc += x3_step;
-  			y3_acc += y3_step;
+  			tx_acc += tx_step;
+  			sx_acc += sx_step;
+  			sy_acc += sy_step;
 
-  			if (p2->y <= p1->y) {
-  				--iaidx;
+  			if (tp2->y <= tp1->y) {
+  				--y;
   			} else {
-  				++iaidx;
+  				++y;
   			}
   		}
 	}
@@ -1212,7 +1227,7 @@
 }
 
 void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette) {
-	debug(0, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d palette %d)", resNum, flags, shadow, palette);
+	debug(1, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d dstResNum %d palette %d)", resNum, flags, shadow, dstResNum, palette);
 	int i;
 
 	if (flags & 0x800000) {
@@ -1224,7 +1239,7 @@
 	uint8 *srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, palette);
 	if (srcWizBuf) {
 		uint8 *dst;
-		int32 wizW, wizH;
+		int32 dstw, dsth, wizW, wizH;
 		VirtScreen *pvs = &_vm->virtscr[kMainVirtScreen];
 		int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
 
@@ -1233,18 +1248,19 @@
 			assert(dstPtr);
 			dst = _vm->findWrappedBlock(MKID('WIZD'), dstPtr, 0, 0);
 			assert(dst);
-
-			getWizImageDim(dstResNum, 0, wizW, wizH);
+			getWizImageDim(dstResNum, 0, dstw, dsth);
 		} else {
 			if (flags & kWIFMarkBufferDirty) {
 				dst = pvs->getPixels(0, 0);
 			} else {
 				dst = pvs->getBackPixels(0, 0);
 			}
-
-			getWizImageDim(resNum, state, wizW, wizH);
+			dstw = pvs->w;
+			dsth = pvs->h;
 		}
 
+		getWizImageDim(resNum, state, wizW, wizH);
+
 		Common::Point bbox[4];
 		bbox[0].x = 0;
 		bbox[0].y = 0;
@@ -1256,8 +1272,8 @@
 		bbox[3].y = wizH - 1;
 
   		int16 xmin_p, xmax_p, ymin_p, ymax_p;
-  		xmin_p = ymin_p = 12345;
-  		xmax_p = ymax_p = -12345;
+  		xmin_p = ymin_p = 0x7FFF;
+  		xmax_p = ymax_p = 0x8000;
 
   		for (i = 0; i < 4; ++i) {
   			xmin_p = MIN(wp[i].x, xmin_p);
@@ -1266,38 +1282,87 @@
   			ymax_p = MAX(wp[i].y, ymax_p);
   		}
 
-		if (xmin_p < 0 || ymin_p < 0 || xmax_p >= pvs->w || ymax_p >= pvs->h) {
-			printf("Invalid coords polygon x %d y %d x2 %d y2 %d\n", xmin_p, ymax_p, xmax_p, ymax_p);
+  		int16 xmin_b, xmax_b, ymin_b, ymax_b;
+  		xmin_b = ymin_b = 0x7FFF;
+  		xmax_b = ymax_b = 0x8000;
+		
+		for (i = 0; i < 4; ++i) {
+  			xmin_b = MIN(bbox[i].x, xmin_b);
+  			xmax_b = MAX(bbox[i].x, xmax_b);
+  			ymin_b = MIN(bbox[i].y, ymin_b);
+  			ymax_b = MAX(bbox[i].y, ymax_b);			
 		}
 
 		PolygonDrawData pdd(ymax_p - ymin_p + 1);
-		pdd.pto.x = xmin_p;
-		pdd.pto.y = ymin_p;
+		pdd.mat[0].x = xmin_p;
+		pdd.mat[0].y = ymin_p;
+		pdd.mat[1].x = xmax_p;
+		pdd.mat[1].y = ymax_p;
+		pdd.mat[2].x = xmin_b;
+		pdd.mat[2].y = ymin_b;
+		pdd.mat[3].x = xmax_b;
+		pdd.mat[3].y = ymax_b;
 
+		// precompute the transformation which remaps 'bbox' pixels to 'wp'
 		for (i = 0; i < 3; ++i) {
-			pdd.calcIntersection(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]);
+			pdd.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]);
 		}
-		pdd.calcIntersection(&wp[3], &wp[0], &bbox[3], &bbox[0]);
+		pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]);
 
-		uint yoff = pdd.pto.y * pvs->w;
-		for (i = 0; i < pdd.areasNum; ++i) {
-			PolygonDrawData::InterArea *pia = &pdd.ia[i];
-			uint16 dx = pia->xmax - pia->xmin + 1;
-			uint8 *dstPtr = dst + pia->xmin + yoff;
-			int32 x_acc = pia->x1 << 0x10;
-			int32 y_acc = pia->y1 << 0x10;
-			int32 x_step = ((pia->x2 - pia->x1) << 0x10) / dx;
-			int32 y_step = ((pia->y2 - pia->y1) << 0x10) / dx;
-			while (dx--) {
-				uint srcWizOff = (y_acc >> 0x10) * wizW + (x_acc >> 0x10);
-				assert(srcWizOff < (uint32)(wizW * wizH));
-				x_acc += x_step;
-				y_acc += y_step;
-				if (transColor == -1 || transColor != srcWizBuf[srcWizOff])
-					*dstPtr = srcWizBuf[srcWizOff];
+		pdd.rAreasNum = 0;
+		PolygonDrawData::ResultArea *pra = &pdd.ra[0];
+		int32 yoff = pdd.mat[0].y * dstw;
+		int16 y_start = pdd.mat[0].y;
+		for (i = 0; i < pdd.pAreasNum; ++i) {
+			PolygonDrawData::PolygonArea *ppa = &pdd.pa[i];
+			if (y_start >= 0 && y_start < dsth) {
+				int16 x1 = ppa->xmin;
+				if (x1 < 0) {
+					x1 = 0;
+				}
+				int16 x2 = ppa->xmax;
+				if (x2 >= dstw) {
+					x2 = dstw - 1;
+				}
+				int16 w = x2 - x1 + 1;
+				if (w > 0) {
+					int16 width = ppa->xmax - ppa->xmin + 1;
+					pra->x_step = ((ppa->x2 - ppa->x1) << 16) / width;
+					pra->y_step = ((ppa->y2 - ppa->y1) << 16) / width;
+					pra->dst_offs = yoff + x1;
+					pra->w = w;
+					pra->x_s = ppa->x1 << 16;
+					pra->y_s = ppa->y1 << 16;
+					int16 tmp = x1 - ppa->xmin;
+					if (tmp != 0) {
+						pra->x_s += pra->x_step * tmp;
+						pra->y_s += pra->y_step * tmp;
+					}
+					++pra;
+					++pdd.rAreasNum;
+				}
+			}
+			++ppa;
+			yoff += dstw;
+			++y_start;
+		}
+
+		pra = &pdd.ra[0];
+		for (i = 0; i < pdd.rAreasNum; ++i, ++pra) {
+			uint8 *dstPtr = dst + pra->dst_offs;
+			int32 w = pra->w;
+			int32 x_acc = pra->x_s;
+			int32 y_acc = pra->y_s;
+			while (--w) {
+				int32 src_offs = (y_acc >> 16) * wizW + (x_acc >> 16);
+				assert(src_offs < wizW * wizH);
+				x_acc += pra->x_step;
+				y_acc += pra->y_step;
+				if (transColor == -1 || transColor != srcWizBuf[src_offs]) {
+					*dstPtr = srcWizBuf[src_offs];
+				}
 				dstPtr++;
 			}
-			yoff += pvs->pitch;
 		}
 
 		Common::Rect bound(xmin_p, ymin_p, xmax_p + 1, ymax_p + 1);





More information about the Scummvm-git-logs mailing list