コード例 #1
0
ファイル: picture.cpp プロジェクト: AdamRi/scummvm-pink
void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX) {
	byte *celBitmap = NULL;
	byte *ptr = NULL;
	byte *headerPtr = inbuffer + headerPos;
	byte *rlePtr = inbuffer + rlePos;
	int16 displaceX, displaceY;
	byte priority = _addToFlag ? _priority : 0;
	byte clearColor;
	bool compression = true;
	byte curByte;
	int16 y, lastY, x, leftX, rightX;
	int pixelCount;
	uint16 width, height;

#ifdef ENABLE_SCI32
	if (_resourceType != SCI_PICTURE_TYPE_SCI32) {
#endif
		// Width/height here are always LE, even in Mac versions
		width = READ_LE_UINT16(headerPtr + 0);
		height = READ_LE_UINT16(headerPtr + 2);
		displaceX = (signed char)headerPtr[4];
		displaceY = (unsigned char)headerPtr[5];
		if (_resourceType == SCI_PICTURE_TYPE_SCI11)
			// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
			clearColor = _screen->getColorWhite();
		else
			clearColor = headerPtr[6];
#ifdef ENABLE_SCI32
	} else {
		width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
		height = READ_SCI11ENDIAN_UINT16(headerPtr + 2);
		displaceX = READ_SCI11ENDIAN_UINT16(headerPtr + 4); // probably signed?!?
		displaceY = READ_SCI11ENDIAN_UINT16(headerPtr + 6); // probably signed?!?
		clearColor = headerPtr[8];
		if (headerPtr[9] == 0)
			compression = false;
	}
#endif

	if (displaceX || displaceY)
		error("unsupported embedded cel-data in picture");

	// We will unpack cel-data into a temporary buffer and then plot it to screen
	//  That needs to be done cause a mirrored picture may be requested
	pixelCount = width * height;
	celBitmap = new byte[pixelCount];
	if (!celBitmap)
		error("Unable to allocate temporary memory for picture drawing");

	if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
		// See GfxView::unpackCel() for why this black/white swap is done
		// This picture swap is only needed in SCI32, not SCI1.1
		if (clearColor == 0)
			clearColor = 0xff;
		else if (clearColor == 0xff)
			clearColor = 0;
	}

	if (compression)
		unpackCelData(inbuffer, celBitmap, clearColor, pixelCount, rlePos, literalPos, _resMan->getViewType(), width, false);
	else
		// No compression (some SCI32 pictures)
		memcpy(celBitmap, rlePtr, pixelCount);

	if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
		// See GfxView::unpackCel() for why this black/white swap is done
		// This picture swap is only needed in SCI32, not SCI1.1
		for (int i = 0; i < pixelCount; i++) {
			if (celBitmap[i] == 0)
				celBitmap[i] = 0xff;
			else if (celBitmap[i] == 0xff)
				celBitmap[i] = 0;
		}
	}

	Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();

	uint16 skipCelBitmapPixels = 0;
	int16 displayWidth = width;
	if (pictureX) {
		// scroll position for picture active, we need to adjust drawX accordingly
		drawX -= pictureX;
		if (drawX < 0) {
			skipCelBitmapPixels = -drawX;
			displayWidth -= skipCelBitmapPixels;
			drawX = 0;
		}
	}

	if (displayWidth > 0) {
		y = displayArea.top + drawY;
		lastY = MIN<int16>(height + y, displayArea.bottom);
		leftX = displayArea.left + drawX;
		rightX = MIN<int16>(displayWidth + leftX, displayArea.right);

		uint16 sourcePixelSkipPerRow = 0;
		if (width > rightX - leftX)
			sourcePixelSkipPerRow = width - (rightX - leftX);

		// Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
		// but white and that won't matter because the screen is supposed to be already white. It seems that most (if not all)
		// SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
		// the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra.
		// SCI32 doesn't use _addToFlag at all.
		if (!_addToFlag && _resourceType != SCI_PICTURE_TYPE_SCI32)
			clearColor = _screen->getColorWhite();

		byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;

		ptr = celBitmap;
		ptr += skipCelBitmapPixels;
		if (!_mirroredFlag) {
			// Draw bitmap to screen
			x = leftX;
			while (y < lastY) {
				curByte = *ptr++;
				if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
					_screen->putPixel(x, y, drawMask, curByte, priority, 0);

				x++;

				if (x >= rightX) {
					ptr += sourcePixelSkipPerRow;
					x = leftX;
					y++;
				}
			}
		} else {
			// Draw bitmap to screen (mirrored)
			x = rightX - 1;
			while (y < lastY) {
				curByte = *ptr++;
				if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
					_screen->putPixel(x, y, drawMask, curByte, priority, 0);

				if (x == leftX) {
					ptr += sourcePixelSkipPerRow;
					x = rightX;
					y++;
				}

				x--;
			}
		}
	}

	delete[] celBitmap;
}
コード例 #2
0
ファイル: picture.cpp プロジェクト: DrItanium/scummvm
void GfxPicture::drawCelData(const SciSpan<const byte> &inbuffer, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY, bool isEGA) {
	const SciSpan<const byte> headerPtr = inbuffer.subspan(headerPos);
	const SciSpan<const byte> rlePtr = inbuffer.subspan(rlePos);
	// displaceX, displaceY fields are ignored, and may contain garbage
	// (e.g. pic 261 in Dr. Brain 1 Spanish - bug #3614914)
	//int16 displaceX, displaceY;
	byte priority = _priority;
	byte clearColor;
	bool compression = true;
	byte curByte;
	int16 y, lastY, x, leftX, rightX;
	int pixelCount;
	uint16 width, height;

	// if the picture is not an overlay and we are also not in EGA mode, use priority 0
	if (!isEGA && !_addToFlag)
		priority = 0;

	// Width/height here are always LE, even in Mac versions
	width = headerPtr.getUint16LEAt(0);
	height = headerPtr.getUint16LEAt(2);
	//displaceX = (signed char)headerPtr[4];
	//displaceY = (unsigned char)headerPtr[5];
	if (_resourceType == SCI_PICTURE_TYPE_SCI11)
		// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
		clearColor = _screen->getColorWhite();
	else
		clearColor = headerPtr[6];

	//if (displaceX || displaceY)
	//	error("unsupported embedded cel-data in picture");

	// We will unpack cel-data into a temporary buffer and then plot it to screen
	//  That needs to be done cause a mirrored picture may be requested
	pixelCount = width * height;
	Common::SpanOwner<SciSpan<byte> > celBitmap;
	celBitmap->allocate(pixelCount, _resource->name());

	if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
		// See GfxView::unpackCel() for why this black/white swap is done
		// This picture swap is only needed in SCI32, not SCI1.1
		if (clearColor == 0)
			clearColor = 0xff;
		else if (clearColor == 0xff)
			clearColor = 0;
	}

	if (compression) {
		unpackCelData(inbuffer, *celBitmap, clearColor, rlePos, literalPos, _resMan->getViewType(), width, false);
	} else
		// No compression (some SCI32 pictures)
		memcpy(celBitmap->getUnsafeDataAt(0, pixelCount), rlePtr.getUnsafeDataAt(0, pixelCount), pixelCount);

	Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();

	// Horizontal clipping
	uint16 skipCelBitmapPixels = 0;
	int16 displayWidth = width;
	if (pictureX) {
		// horizontal scroll position for picture active, we need to adjust drawX accordingly
		drawX -= pictureX;
		if (drawX < 0) {
			skipCelBitmapPixels = -drawX;
			displayWidth -= skipCelBitmapPixels;
			drawX = 0;
		}
	}

	// Vertical clipping
	uint16 skipCelBitmapLines = 0;
	int16 displayHeight = height;
	if (pictureY) {
		// vertical scroll position for picture active, we need to adjust drawY accordingly
		// TODO: Finish this
		/*drawY -= pictureY;
		if (drawY < 0) {
			skipCelBitmapLines = -drawY;
			displayHeight -= skipCelBitmapLines;
			drawY = 0;
		}*/
	}

	if (displayWidth > 0 && displayHeight > 0) {
		y = displayArea.top + drawY;
		lastY = MIN<int16>(height + y, displayArea.bottom);
		leftX = displayArea.left + drawX;
		rightX = MIN<int16>(displayWidth + leftX, displayArea.right);

		uint16 sourcePixelSkipPerRow = 0;
		if (width > rightX - leftX)
			sourcePixelSkipPerRow = width - (rightX - leftX);

		// Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
		// but white and that won't matter because the screen is supposed to be already white. It seems that most (if not all)
		// SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
		// the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra.
		if (!_addToFlag)
			clearColor = _screen->getColorWhite();

		byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;

		SciSpan<const byte> ptr = *celBitmap;
		ptr += skipCelBitmapPixels;
		ptr += skipCelBitmapLines * width;

		if ((!isEGA) || (priority < 16)) {
			// VGA + EGA, EGA only checks priority, when given priority is below 16
			if (!_mirroredFlag) {
				// Draw bitmap to screen
				x = leftX;
				while (y < lastY) {
					curByte = *ptr++;
					if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
						_screen->putPixel(x, y, drawMask, curByte, priority, 0);

					x++;

					if (x >= rightX) {
						ptr += sourcePixelSkipPerRow;
						x = leftX;
						y++;
					}
				}
			} else {
				// Draw bitmap to screen (mirrored)
				x = rightX - 1;
				while (y < lastY) {
					curByte = *ptr++;
					if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
						_screen->putPixel(x, y, drawMask, curByte, priority, 0);

					if (x == leftX) {
						ptr += sourcePixelSkipPerRow;
						x = rightX;
						y++;
					}

					x--;
				}
			}
		} else {
			// EGA, when priority is above 15
			//  we don't check priority and also won't set priority at all
			//  fixes picture 48 of kq5 (island overview). Bug #5182
			if (!_mirroredFlag) {
				// EGA+priority>15: Draw bitmap to screen
				x = leftX;
				while (y < lastY) {
					curByte = *ptr++;
					if (curByte != clearColor)
						_screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, curByte, 0, 0);

					x++;

					if (x >= rightX) {
						ptr += sourcePixelSkipPerRow;
						x = leftX;
						y++;
					}
				}
			} else {
				// EGA+priority>15: Draw bitmap to screen (mirrored)
				x = rightX - 1;
				while (y < lastY) {
					curByte = *ptr++;
					if (curByte != clearColor)
						_screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, curByte, 0, 0);

					if (x == leftX) {
						ptr += sourcePixelSkipPerRow;
						x = rightX;
						y++;
					}

					x--;
				}
			}
		}
	}
}