aboutsummaryrefslogtreecommitdiff
path: root/engines/mads/msurface.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2014-03-05 09:04:53 -0500
committerPaul Gilbert2014-03-05 09:04:53 -0500
commitd98f890029936dfa8139cf8dce4756ec92bc2568 (patch)
tree04bd9c6f8e872f01ffaaf8ab048de751f25541b8 /engines/mads/msurface.cpp
parent23ebeec600f8210601dd45fc42c21a596fa6d127 (diff)
downloadscummvm-rg350-d98f890029936dfa8139cf8dce4756ec92bc2568.tar.gz
scummvm-rg350-d98f890029936dfa8139cf8dce4756ec92bc2568.tar.bz2
scummvm-rg350-d98f890029936dfa8139cf8dce4756ec92bc2568.zip
MADS: Completed implementing drawElements and support methods
Diffstat (limited to 'engines/mads/msurface.cpp')
-rw-r--r--engines/mads/msurface.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index 5f7b37b1cd..aed00f5553 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -244,6 +244,168 @@ void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds,
}
}
+void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
+ MSurface *depthsSurface, int scale, int transparentColor) {
+
+ int destX = destPos.x, destY = destPos.y;
+ if (scale == 100) {
+ // Copy the specified area
+ Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight());
+
+ if (destX < 0) {
+ copyRect.left += -destX;
+ destX = 0;
+ }
+ else if (destX + copyRect.width() > w) {
+ copyRect.right -= destX + copyRect.width() - w;
+ }
+ if (destY < 0) {
+ copyRect.top += -destY;
+ destY = 0;
+ }
+ else if (destY + copyRect.height() > h) {
+ copyRect.bottom -= destY + copyRect.height() - h;
+ }
+
+ if (!copyRect.isValidRect())
+ return;
+
+ byte *data = src->getData();
+ byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
+ byte *depthsData = depthsSurface->getData();
+ byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX;
+ byte *destPtr = (byte *)pixels + (destY * pitch) + destX;
+
+ // 100% scaling variation
+ for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
+ // Copy each byte one at a time checking against the depth
+ for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) {
+ if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColor))
+ destPtr[xCtr] = srcPtr[xCtr];
+ }
+
+ srcPtr += src->getWidth();
+ depthsPtr += depthsSurface->getWidth();
+ destPtr += getWidth();
+ }
+
+ return;
+ }
+
+ // Start of draw logic for scaled sprites
+ const byte *srcPixelsP = src->getData();
+
+ int destRight = this->getWidth() - 1;
+ int destBottom = this->getHeight() - 1;
+ bool normalFrame = true; // TODO: false for negative frame numbers
+ int frameWidth = src->getWidth();
+ int frameHeight = src->getHeight();
+
+ int highestDim = MAX(frameWidth, frameHeight);
+ bool lineDist[MADS_SCREEN_WIDTH];
+ int distIndex = 0;
+ int distXCount = 0, distYCount = 0;
+
+ int distCtr = 0;
+ do {
+ distCtr += scale;
+ if (distCtr < 100) {
+ lineDist[distIndex] = false;
+ }
+ else {
+ lineDist[distIndex] = true;
+ distCtr -= 100;
+
+ if (distIndex < frameWidth)
+ ++distXCount;
+
+ if (distIndex < frameHeight)
+ ++distYCount;
+ }
+ } while (++distIndex < highestDim);
+
+ destX -= distXCount / 2;
+ destY -= distYCount - 1;
+
+ // Check x bounding area
+ int spriteLeft = 0;
+ int spriteWidth = distXCount;
+ int widthAmount = destX + distXCount - 1;
+
+ if (destX < 0) {
+ spriteWidth += destX;
+ spriteLeft -= destX;
+ }
+ widthAmount -= destRight;
+ if (widthAmount > 0)
+ spriteWidth -= widthAmount;
+
+ int spriteRight = spriteLeft + spriteWidth;
+ if (spriteWidth <= 0)
+ return;
+ if (!normalFrame) {
+ destX += distXCount - 1;
+ spriteLeft = -(distXCount - spriteRight);
+ spriteRight = (-spriteLeft + spriteWidth);
+ }
+
+ // Check y bounding area
+ int spriteTop = 0;
+ int spriteHeight = distYCount;
+ int heightAmount = destY + distYCount - 1;
+
+ if (destY < 0) {
+ spriteHeight += destY;
+ spriteTop -= destY;
+ }
+ heightAmount -= destBottom;
+ if (heightAmount > 0)
+ spriteHeight -= heightAmount;
+ int spriteBottom = spriteTop + spriteHeight;
+
+ if (spriteHeight <= 0)
+ return;
+
+ byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop);
+ const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop);
+
+ spriteLeft = (spriteLeft * (normalFrame ? 1 : -1));
+
+ // Loop through the lines of the sprite
+ for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) {
+ if (!lineDist[yp])
+ // Not a display line, so skip it
+ continue;
+ // Check whether the sprite line is in the display range
+ ++sprY;
+ if ((sprY >= spriteBottom) || (sprY < spriteTop))
+ continue;
+
+ // Found a line to display. Loop through the pixels
+ const byte *srcP = srcPixelsP;
+ const byte *depthP = depthPixelsP;
+ byte *destP = destPixelsP;
+ for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) {
+ if (xp < spriteLeft)
+ // Not yet reached start of display area
+ continue;
+ if (!lineDist[sprX++])
+ // Not a display pixel
+ continue;
+
+ if ((*srcP != transparentColor) && (depth <= (*depthP & 0x7f)))
+ *destP = *srcP;
+
+ ++destP;
+ ++depthP;
+ }
+
+ // Move to the next destination line
+ destPixelsP += this->pitch;
+ depthPixelsP += depthsSurface->pitch;
+ }
+}
+
void MSurface::translate(Common::Array<RGB6> &palette) {
for (int y = 0; y < this->h; ++y) {
byte *pDest = getBasePtr(0, y);
@@ -254,4 +416,18 @@ void MSurface::translate(Common::Array<RGB6> &palette) {
}
}
+MSurface *MSurface::flipHorizontal() const {
+ MSurface *dest = new MSurface(this->w, this->h);
+
+ for (int y = 0; y < this->h; ++y) {
+ const byte *srcP = getBasePtr(this->w - 1, y);
+ byte *destP = dest->getData();
+
+ for (int x = 0; x < this->w; ++x)
+ *destP++ = *srcP--;
+ }
+
+ return dest;
+}
+
} // End of namespace MADS