aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/gfx/opengl
diff options
context:
space:
mode:
authorPaul Gilbert2010-09-07 23:13:44 +0000
committerEugene Sandulenko2010-10-12 23:41:36 +0000
commit07a8c87efcc5397ad681ae64c499483ad6b8d754 (patch)
tree890b2c941e9438c34dbd0bf1fba1d6436f14e8ba /engines/sword25/gfx/opengl
parent795a6110cb8e4409036ebde2815068564037188a (diff)
downloadscummvm-rg350-07a8c87efcc5397ad681ae64c499483ad6b8d754.tar.gz
scummvm-rg350-07a8c87efcc5397ad681ae64c499483ad6b8d754.tar.bz2
scummvm-rg350-07a8c87efcc5397ad681ae64c499483ad6b8d754.zip
SWORD25: Added scaling support
svn-id: r53331
Diffstat (limited to 'engines/sword25/gfx/opengl')
-rw-r--r--engines/sword25/gfx/opengl/glimage.cpp156
-rw-r--r--engines/sword25/gfx/opengl/glimage.h4
2 files changed, 119 insertions, 41 deletions
diff --git a/engines/sword25/gfx/opengl/glimage.cpp b/engines/sword25/gfx/opengl/glimage.cpp
index 839bc44506..785829eedb 100644
--- a/engines/sword25/gfx/opengl/glimage.cpp
+++ b/engines/sword25/gfx/opengl/glimage.cpp
@@ -167,26 +167,46 @@ uint GLImage::getPixel(int x, int y) {
// -----------------------------------------------------------------------------
bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) {
- int x1 = 0, y1 = 0;
- int w = _width, h = _height;
+ // Create an encapsulating surface for the data
+ Graphics::Surface srcImage;
+ srcImage.bytesPerPixel = 4;
+ srcImage.pitch = _width * 4;
+ srcImage.w = _width;
+ srcImage.h = _height;
+ srcImage.pixels = _data;
+
if (pPartRect) {
- x1 = pPartRect->left;
- y1 = pPartRect->top;
- w = pPartRect->right - pPartRect->left;
- h = pPartRect->bottom - pPartRect->top;
- }
+ srcImage.pixels = &_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4];
+ srcImage.w = pPartRect->right - pPartRect->left;
+ srcImage.h = pPartRect->bottom - pPartRect->top;
- debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, x1, y1, w, h, color, width, height);
+ debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %d, %d, %d)", posX, posY, flipping,
+ pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height);
+ } else {
- // Skalierungen berechnen
- float scaleX, scaleY;
- if (width == -1)
- width = _width;
- scaleX = (float)width / (float)_width;
+ debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %d, %d, %d)", posX, posY, flipping, 0, 0,
+ srcImage.w, srcImage.h, color, width, height);
+ }
+ if (width == -1)
+ width = srcImage.w;
if (height == -1)
- height = _height;
- scaleY = (float)height / (float)_height;
+ height = srcImage.h;
+
+#ifdef SCALING_TESTING
+ // Hardcode scaling to 66% to test scaling
+ width = width * 2 / 3;
+ height = height * 2 / 3;
+#endif
+
+ Graphics::Surface *img;
+ Graphics::Surface *imgScaled = NULL;
+ if ((width != srcImage.w) || (height != srcImage.h)) {
+ // Scale the image
+ img = imgScaled = scale(srcImage, width, height);
+ } else {
+ img = &srcImage;
+ }
if ((color & 0xff000000) != 0xff000000) {
warning("STUB: Image transparent bg color: %x", color);
@@ -195,54 +215,46 @@ bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, ui
int cg = (color >> 8) & 0xff;
int cb = (color >> 0) & 0xff;
- if (scaleX != 1.0 || scaleY != 1.0) {
- warning("STUB: Sprite scaling (%f x %f)", scaleX, scaleY);
+ // Handle off-screen clipping
+ if (posY < 0) {
+ img->h -= -posY;
+ img->pixels = (byte *)img->pixels + img->pitch * -posY;
+ posY = 0;
}
if (posX < 0) {
- w -= posX;
- x1 = -posX;
+ img->w -= -posX;
+ img->pixels = (byte *)img->pixels + -posX;
posX = 0;
}
- if (posY < 0) {
- h -= posY;
- y1 = -posY;
- posY = 0;
- }
+ img->w = CLIP((int)img->w, 0, (int)MAX((int)_backSurface->w - posX, 0));
+ img->h = CLIP((int)img->h, 0, (int)MAX((int)_backSurface->h - posY, 0));
- w = CLIP(w, 0, MAX((int)_backSurface->w - posX - 1, 0));
- h = CLIP(h, 0, MAX((int)_backSurface->h - posY - 1, 0));
-
- if (w == 0 || h == 0)
+ if (img->w == 0 || img->h == 0)
return true;
- // Rendern
- // TODO:
- // Die Bedeutung von FLIP_V und FLIP_H ist vertauscht. Allerdings glaubt der Rest der Engine auch daran, daher war es einfacher diesen Fehler
- // weiterzuführen. Bei Gelegenheit ist dieses aber zu ändern.
-
- // TODO: scaling
+ int xp = 0, yp = 0;
int inStep = 4;
- int inoStep = _width * 4;
+ int inoStep = img->pitch;
if (flipping & Image::FLIP_V) {
inStep = -inStep;
- x1 = x1 + w - 1;
+ xp = img->w - 1;
}
if (flipping & Image::FLIP_H) {
inoStep = -inoStep;
- y1 = y1 + h - 1;
+ yp = img->h - 1;
}
- byte *ino = &_data[y1 * _width * 4 + x1 * 4];
+ byte *ino = (byte *)img->getBasePtr(xp, yp);
byte *outo = (byte *)_backSurface->getBasePtr(posX, posY);
byte *in, *out;
- for (int i = 0; i < h; i++) {
+ for (int i = 0; i < img->h; i++) {
out = outo;
in = ino;
- for (int j = 0; j < w; j++) {
+ for (int j = 0; j < img->w; j++) {
int r = in[0];
int g = in[1];
int b = in[2];
@@ -295,9 +307,71 @@ bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, ui
ino += inoStep;
}
- g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY, w, h);
+ g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
+ img->w, img->h);
+
+ if (imgScaled) {
+ imgScaled->free();
+ delete imgScaled;
+ }
return true;
}
+/**
+ * Scales a passed surface, creating a new surface with the result
+ * @param srcImage Source image to scale
+ * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero)
+ * @remarks Caller is responsible for freeing the returned surface
+ */
+Graphics::Surface *GLImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
+ Graphics::Surface *s = new Graphics::Surface();
+ s->create(xSize, ySize, srcImage.bytesPerPixel);
+
+ int *horizUsage = scaleLine(xSize, srcImage.w);
+ int *vertUsage = scaleLine(ySize, srcImage.h);
+
+ // Loop to create scaled version
+ for (int yp = 0; yp < ySize; ++yp) {
+ byte *srcP = (byte *)srcImage.getBasePtr(0, vertUsage[yp]);
+ byte *destP = (byte *)s->getBasePtr(0, yp);
+
+ for (int xp = 0; xp < xSize; ++xp) {
+ byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.bytesPerPixel);
+ for (int byteCtr = 0; byteCtr < srcImage.bytesPerPixel; ++byteCtr) {
+ *destP++ = *tempSrcP++;
+ }
+ }
+ }
+
+ // Delete arrays and return surface
+ delete[] horizUsage;
+ delete[] vertUsage;
+ return s;
+}
+
+/**
+ * Returns an array indicating which pixels of a source image horizontally or vertically get
+ * included in a scaled image
+ */
+int *GLImage::scaleLine(int size, int srcSize) {
+ int scale = 100 * size / srcSize;
+ assert(scale > 0);
+ int *v = new int[size];
+ Common::set_to(v, &v[size], 0);
+
+ int distCtr = 0;
+ int *destP = v;
+ for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
+ distCtr += scale;
+ while (distCtr >= 100) {
+ assert(destP < &v[size]);
+ *destP++ = distIndex;
+ distCtr -= 100;
+ }
+ }
+
+ return v;
+}
+
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/opengl/glimage.h b/engines/sword25/gfx/opengl/glimage.h
index bcc6bf8e20..2b30cec718 100644
--- a/engines/sword25/gfx/opengl/glimage.h
+++ b/engines/sword25/gfx/opengl/glimage.h
@@ -113,6 +113,8 @@ public:
virtual bool isSetContentAllowed() const {
return true;
}
+
+ static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
private:
byte *_data;
int _width;
@@ -120,6 +122,8 @@ private:
bool _doCleanup;
Graphics::Surface *_backSurface;
+
+ static int *scaleLine(int size, int srcSize);
};
} // End of namespace Sword25