bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, RectangleList *updateRects) { int ca = (color >> 24) & 0xff; // Check if we need to draw anything at all if (ca == 0) return true; int cr = (color >> 16) & 0xff; int cg = (color >> 8) & 0xff; int cb = (color >> 0) & 0xff; // Create an encapsulating surface for the data Graphics::Surface srcImage; // TODO: Is the data really in the screen format? srcImage.init(_width, _height, _width * 4, _data, g_system->getScreenFormat()); if (pPartRect) { srcImage.setPixels(&_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, pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); } else { debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, srcImage.w, srcImage.h, color, width, height); } if (width == -1) width = srcImage.w; if (height == -1) 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; byte *savedPixels = NULL; if ((width != srcImage.w) || (height != srcImage.h)) { // Scale the image img = imgScaled = scale(srcImage, width, height); savedPixels = (byte *)img->getPixels(); } else { img = &srcImage; } for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) { const Common::Rect &clipRect = *it; int skipLeft = 0, skipTop = 0; int drawX = posX, drawY = posY; int drawWidth = img->w; int drawHeight = img->h; // Handle clipping if (drawX < clipRect.left) { skipLeft = clipRect.left - drawX; drawWidth -= skipLeft; drawX = clipRect.left; } if (drawY < clipRect.top) { skipTop = clipRect.top - drawY; drawHeight -= skipTop; drawY = clipRect.top; } if (drawX + drawWidth >= clipRect.right) drawWidth = clipRect.right - drawX; if (drawY + drawHeight >= clipRect.bottom) drawHeight = clipRect.bottom - drawY; if ((drawWidth > 0) && (drawHeight > 0)) { int xp = 0, yp = 0; int inStep = 4; int inoStep = img->pitch; if (flipping & Image::FLIP_V) { inStep = -inStep; xp = img->w - 1 - skipLeft; } else { xp = skipLeft; } if (flipping & Image::FLIP_H) { inoStep = -inoStep; yp = img->h - 1 - skipTop; } else { yp = skipTop; } byte *ino = (byte *)img->getBasePtr(xp, yp); byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY); #if defined(SCUMM_LITTLE_ENDIAN) // Simple memcpy if the source bitmap doesn't have transparent pixels and the drawing transparency is 255 // NOTE Only possible with LE-machines at the moment, maybe it would be feasible to convert the bitmap pixels at loading time? if (!_isTransparent && ca == 255) { for (int i = 0; i < drawHeight; i++) { memcpy(outo, ino, drawWidth * 4); outo += _backSurface->pitch; ino += inoStep; } } else #endif { byte *in, *out; for (int i = 0; i < drawHeight; i++) { out = outo; in = ino; for (int j = 0; j < drawWidth; j++) { uint32 pix = *(uint32 *)in; int a = (pix >> 24) & 0xff; in += inStep; if (ca != 255) { a = a * ca >> 8; } if (a == 0) { // Full transparency out += 4; continue; } int b = (pix >> 0) & 0xff; int g = (pix >> 8) & 0xff; int r = (pix >> 16) & 0xff; if (a == 255) { #if defined(SCUMM_LITTLE_ENDIAN) if (cb != 255) b = (b * cb) >> 8; if (cg != 255) g = (g * cg) >> 8; if (cr != 255) r = (r * cr) >> 8; *(uint32 *)out = (255 << 24) | (r << 16) | (g << 8) | b; out += 4; #else *out++ = a; if (cr != 255) *out++ = (r * cr) >> 8; else *out++ = r; if (cg != 255) *out++ = (g * cg) >> 8; else *out++ = g; if (cb != 255) *out++ = (b * cb) >> 8; else *out++ = b; #endif } else {