Ejemplo n.º 1
0
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 {