aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Montoir2006-01-30 19:20:51 +0000
committerGregory Montoir2006-01-30 19:20:51 +0000
commit5465d3206cd09ff93413648789e87aeca1c4370f (patch)
tree04022de1620e2292b6f43e17236f1c97c7f9f593
parent4a6f2ab3d36b268d119a65ebbd5bc4c12d5afb75 (diff)
downloadscummvm-rg350-5465d3206cd09ff93413648789e87aeca1c4370f.tar.gz
scummvm-rg350-5465d3206cd09ff93413648789e87aeca1c4370f.tar.bz2
scummvm-rg350-5465d3206cd09ff93413648789e87aeca1c4370f.zip
Some cleanup and fixes to the wiz transformation code.
svn-id: r20315
-rw-r--r--scumm/wiz_he.cpp211
1 files changed, 138 insertions, 73 deletions
diff --git a/scumm/wiz_he.cpp b/scumm/wiz_he.cpp
index 42cbd302ba..92cae1ec1f 100644
--- a/scumm/wiz_he.cpp
+++ b/scumm/wiz_he.cpp
@@ -1099,8 +1099,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
}
struct PolygonDrawData {
- struct InterArea {
- bool valid;
+ struct PolygonArea {
int32 xmin;
int32 xmax;
int32 x1;
@@ -1108,57 +1107,73 @@ struct PolygonDrawData {
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;
-
- if (!pia->valid || pia->xmin > tx1) {
- pia->xmin = tx1;
- pia->x1 = tx3;
- pia->y1 = ty3;
+ 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 (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::drawWizPolygon(int resNum, int state, int id, int flags, int shadow, i
}
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 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
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 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
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 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
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 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
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.calcIntersection(&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.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]);
+ }
+ pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]);
+
+ 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);