Esempio n. 1
0
reg_t GfxCompare::kernelCantBeHere32(const reg_t curObject, const reg_t listReference) const {
	// Most of SCI32 graphics code converts rects from the VM to exclusive
	// rects before operating on them, but this call leverages SCI16 engine
	// code that operates on inclusive rects, so the rect's bottom-right
	// point is not modified like in other SCI32 kernel calls
	Common::Rect checkRect;

	// At least LSL6 hires passes invalid rectangles which trigger the
	// isValidRect assertion in the Rect constructor; this is avoided by
	// assigning the properties after construction and then testing the
	// rect for validity ourselves here. SSCI does not care about whether
	// or not the rects are valid
	checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
	checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
	checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
	checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
	if (!checkRect.isValidRect()) {
		return make_reg(0, 0);
	}

	uint16 result = 0;
	uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
	const uint16 signalFlags = kSignalIgnoreActor | kSignalHidden;

	if ((signal & signalFlags) == 0) {
		List *list = _segMan->lookupList(listReference);
		if (!list) {
			error("kCantBeHere called with non-list as parameter");
		}
		result = !canBeHereCheckRectList(curObject, checkRect, list, signalFlags).isNull();
	}

	return make_reg(0, result);
}
Esempio n. 2
0
void Scalpel3DOScreen::SHblitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
	if (!_vm->_isScreenDoubled) {
		ScalpelScreen::SHblitFrom(src, pt, srcBounds);
		return;
	}

	Common::Rect srcRect = srcBounds;
	Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());

	if (!srcRect.isValidRect() || !clip(srcRect, destRect))
		return;

	// Add dirty area remapped to the 640x200 surface
	addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));

	// Transfer the area, doubling each pixel
	for (int yp = 0; yp < srcRect.height(); ++yp) {
		const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
		uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);

		for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
			*destP = *srcP;
			*(destP + 1) = *srcP;
			*(destP + 640) = *srcP;
			*(destP + 640 + 1) = *srcP;
		}
	}
}
Esempio n. 3
0
void Surface::fillRect(Common::Rect r, uint32 color) {
	r.clip(w, h);

	if (!r.isValidRect())
		return;

	int width = r.width();
	int height = r.height();
//	int i;

	if (bytesPerPixel == 1) {
		byte *ptr = (byte *)getBasePtr(r.left, r.top);
		while (height--) {
			memset(ptr, (byte)color, width);
			ptr += pitch;
		}
	} else if (bytesPerPixel == 2) {
		uint16 *ptr = (uint16 *)getBasePtr(r.left, r.top);
		while (height--) {
			Common::set_to(ptr, ptr + width, (uint16)color);
			ptr += pitch/2;
		}
	} else {
		error("Surface::fillRect: bytesPerPixel must be 1 or 2");
	}
}
Esempio n. 4
0
void Screen::slamRect(const Common::Rect &r) {
	if (r.width() && r.height() > 0) {
		Common::Rect srcRect = r, destRect = r;

		destRect.translate(-_currentScroll.x, -_currentScroll.y);

		if (destRect.left < 0) {
			srcRect.left += -destRect.left;
			destRect.left = 0;
		}
		if (destRect.top < 0) {
			srcRect.top += -destRect.top;
			destRect.top = 0;
		}
		if (destRect.right > SHERLOCK_SCREEN_WIDTH) {
			srcRect.right -= (destRect.left - SHERLOCK_SCREEN_WIDTH);
			destRect.right = SHERLOCK_SCREEN_WIDTH;
		}
		if (destRect.bottom > SHERLOCK_SCREEN_HEIGHT) {
			srcRect.bottom -= (destRect.bottom - SHERLOCK_SCREEN_HEIGHT);
			destRect.bottom = SHERLOCK_SCREEN_HEIGHT;
		}

		if (srcRect.isValidRect())
			SHblitFrom(_backBuffer, Common::Point(destRect.left, destRect.top), srcRect);
	}
}
Esempio n. 5
0
reg_t GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
	Common::Rect checkRect;
	uint16 result;

	checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
	checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
	checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
	checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
	uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));

	if (!checkRect.isValidRect()) {	// can occur in Iceman and Mother Goose - HACK? TODO: is this really occuring in sierra sci? check this
		warning("kCan(t)BeHere - invalid rect %d, %d -> %d, %d", checkRect.left, checkRect.top, checkRect.right, checkRect.bottom);
		return NULL_REG; // this means "can be here"
	}

	Common::Rect adjustedRect = _coordAdjuster->onControl(checkRect);
	uint16 controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
	result = isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask;
	if ((!result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
		List *list = _segMan->lookupList(listReference);
		if (!list)
			error("kCanBeHere called with non-list as parameter");

		return canBeHereCheckRectList(curObject, checkRect, list, kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate);
	}

	return make_reg(0, result);
}
Esempio n. 6
0
/**
 * Check if the two rectangles are next to each other.
 * @param pSrc1			a source rectangle
 * @param pSrc2			a source rectangle
 */
static bool LooseIntersectRectangle(const Common::Rect &pSrc1, const Common::Rect &pSrc2) {
	Common::Rect pDest;

	pDest.left   = MAX(pSrc1.left, pSrc2.left);
	pDest.top    = MAX(pSrc1.top, pSrc2.top);
	pDest.right  = MIN(pSrc1.right, pSrc2.right);
	pDest.bottom = MIN(pSrc1.bottom, pSrc2.bottom);

	return pDest.isValidRect();
}
Esempio n. 7
0
void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
	Common::Rect srcRect = srcBounds;
	Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());

	if (srcRect.isValidRect() && clip(srcRect, destRect)) {
		// Surface is at least partially or completely on-screen
		addDirtyRect(destRect);
		_surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
	}
}
Esempio n. 8
0
void CSTimeGraphics::drawRect(Common::Rect rect, byte color) {
	rect.clip(Common::Rect(640, 480));

	// Useful with debugging. Shows where hotspots are on the screen and whether or not they're active.
	if (!rect.isValidRect() || rect.width() == 0 || rect.height() == 0)
		return;

	Graphics::Surface *screen = _vm->_system->lockScreen();

	screen->frameRect(rect, color);

	_vm->_system->unlockScreen();
}
Esempio n. 9
0
Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) {
	Common::Rect dst = rect;
	dst.clip(_backgroundWidth, _backgroundHeight);

	if (dst.isEmpty() || !dst.isValidRect())
		return NULL;

	Graphics::Surface *srf = new Graphics::Surface;
	srf->create(dst.width(), dst.height(), _currentBackgroundImage.format);

	srf->copyRectToSurface(_currentBackgroundImage, 0, 0, Common::Rect(dst));

	return srf;
}
Esempio n. 10
0
void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) {
	Common::Rect srcRect = _srcRect;
	if (srcRect.isEmpty())
		srcRect = Common::Rect(src.w, src.h);
	srcRect.clip(src.w, src.h);
	Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
	srcRect.clip(dstRect);

	if (srcRect.isEmpty() || !srcRect.isValidRect())
		return;

	Graphics::Surface *srcAdapted = src.convertTo(dst.format);

	// Copy srcRect from src surface to dst surface
	const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top);

	int xx = _x;
	int yy = _y;

	if (xx < 0)
		xx = 0;
	if (yy < 0)
		yy = 0;

	if (_x >= dst.w || _y >= dst.h) {
		srcAdapted->free();
		delete srcAdapted;
		return;
	}

	byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);

	int32 w = srcRect.width();
	int32 h = srcRect.height();

	for (int32 y = 0; y < h; y++) {
		memcpy(dstBuffer, srcBuffer, w * srcAdapted->format.bytesPerPixel);
		srcBuffer += srcAdapted->pitch;
		dstBuffer += dst.pitch;
	}

	srcAdapted->free();
	delete srcAdapted;
}
Esempio n. 11
0
void Surface::fillRect(Common::Rect r, uint32 color) {
	r.clip(w, h);

	if (!r.isValidRect())
		return;

	int width = r.width();
	int lineLen = width;
	int height = r.height();
	bool useMemset = true;

	if (format.bytesPerPixel == 2) {
		lineLen *= 2;
		if ((uint16)color != ((color & 0xff) | (color & 0xff) << 8))
			useMemset = false;
	} else if (format.bytesPerPixel == 4) {
		useMemset = false;
	} else if (format.bytesPerPixel != 1) {
		error("Surface::fillRect: bytesPerPixel must be 1, 2, or 4");
	}

	if (useMemset) {
		byte *ptr = (byte *)getBasePtr(r.left, r.top);
		while (height--) {
			memset(ptr, (byte)color, lineLen);
			ptr += pitch;
		}
	} else {
		if (format.bytesPerPixel == 2) {
			uint16 *ptr = (uint16 *)getBasePtr(r.left, r.top);
			while (height--) {
				Common::set_to(ptr, ptr + width, (uint16)color);
				ptr += pitch / 2;
			}
		} else {
			uint32 *ptr = (uint32 *)getBasePtr(r.left, r.top);
			while (height--) {
				Common::set_to(ptr, ptr + width, color);
				ptr += pitch / 4;
			}
		}
	}
}
Esempio n. 12
0
void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
	const Common::Point &destPos, int transparencyIndex) {
	// Validation of the rectangle and position
	int destX = destPos.x, destY = destPos.y;
	if ((destX >= w) || (destY >= h))
		return;

	Common::Rect copyRect = srcBounds;
	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;

	// Copy the specified area

	byte *data = src->getData();
	byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
	byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX;

	for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
		// Process each line of the area
		for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) {
			// Check for the range used for the user interface background,
			// which are the only pixels that can be replaced
			if ((destPtr[xCtr] >= 8 && destPtr[xCtr] <= 15) && (int)srcPtr[xCtr] != transparencyIndex)
				destPtr[xCtr] = srcPtr[xCtr];
		}

		srcPtr += src->getWidth();
		destPtr += getWidth();
	}
}
Esempio n. 13
0
/**
 * Copies a section of the game frame in a circle bounded by the specified rectangle
 */
void RMWindow::getNewFrameWipe(byte *lpBuf, Common::Rect &rcBoundEllipse) {
	// Clear the screen
	g_system->fillScreen(0);

	if (!rcBoundEllipse.isValidRect())
		return;

	Common::Point center(rcBoundEllipse.left + rcBoundEllipse.width() / 2,
	                     rcBoundEllipse.top + rcBoundEllipse.height() / 2);

	// The rectangle technically defines the area inside the ellipse, with the corners touching
	// the ellipse boundary. Since we're currently simulating the ellipse using a plain circle,
	// we need to calculate a necessary width using the hypotenuse of X/2 & Y/2
	int x2y2 = (rcBoundEllipse.width() / 2) * (rcBoundEllipse.width() / 2) +
	           (rcBoundEllipse.height() / 2) * (rcBoundEllipse.height() / 2);
	int radius = 0;
	while ((radius * radius) < x2y2)
		++radius;

	// Proceed copying a circular area of the frame with the calculated radius onto the screen
	int error = -radius;
	int x = radius;
	int y = 0;

	while (x >= y) {
		plotSplices(lpBuf, center, x, y);

		error += y;
		++y;
		error += y;

		if (error >= 0) {
			error -= x;
			--x;
			error -= x;
		}
	}
}
Esempio n. 14
0
void Sprite::blit(const Sprite &from, const Common::Rect &area, int32 x, int32 y, bool transp) {
	// Sanity checks
	assert((x >= 0) && (y >= 0) && (x <= 0x7FFF) && (y <= 0x7FFF));

	if (!exists() || !from.exists())
		return;

	Common::Rect toArea = getArea(true);

	toArea.left = x;
	toArea.top  = y;
	if (toArea.isEmpty())
		return;

	Common::Rect fromArea = from.getArea();

	fromArea.clip(area);
	fromArea.setWidth (MIN(fromArea.width() , toArea.width()));
	fromArea.setHeight(MIN(fromArea.height(), toArea.height()));
	if (fromArea.isEmpty() || !fromArea.isValidRect())
		return;

	int32 w = fromArea.width();
	int32 h = fromArea.height();

	const int32 fromTop   = fracToInt(fromArea.top  * from._scaleInverse);
	const int32 fromLeft  = fracToInt(fromArea.left * from._scaleInverse);

	const byte *src = (const byte *) from._surfaceTrueColor.getBasePtr(fromLeft, fromTop);
	      byte *dst = (      byte *)      _surfaceTrueColor.getBasePtr(x, y);

	const uint8 *srcT = from._transparencyMap + fromTop * from._surfaceTrueColor.w + fromLeft;
	      uint8 *dstT =      _transparencyMap +       y *      _surfaceTrueColor.w + x;

	frac_t posW = 0, posH = 0;
	while (h-- > 0) {
		posW = 0;

		const byte *srcRow = src;
		      byte *dstRow = dst;

		const uint8 *srcRowT = srcT;
		      uint8 *dstRowT = dstT;

		for (int32 j = 0; j < w; j++, dstRow += _surfaceTrueColor.bytesPerPixel, dstRowT++) {
			if (!transp || (*srcRowT == 0)) {
				// Ignore transparency or source is solid => copy
				memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel);
				*dstRowT = *srcRowT;
			} else if (*srcRowT == 2) {
				// Half-transparent
				if (*dstRowT == 1)
					// But destination is transparent => propagate
					memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel);
				else
					// Destination is solid => mix
					ImgConv.mixTrueColor(dstRow, srcRow);

				*dstRowT = *srcRowT;
			}

			// Advance source data
			posW += from._scaleInverse;
			while (posW >= ((frac_t) FRAC_ONE)) {
				srcRow += from._surfaceTrueColor.bytesPerPixel;
				srcRowT++;
				posW -= FRAC_ONE;
			}

		}

		dst  += _surfaceTrueColor.pitch;
		dstT += _surfaceTrueColor.w;

		// Advance source data
		posH += from._scaleInverse;
		while (posH >= ((frac_t) FRAC_ONE)) {
			src  += from._surfaceTrueColor.pitch;
			srcT += from._surfaceTrueColor.w;
			posH -= FRAC_ONE;
		}

	}
}
Esempio n. 15
0
void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor) {
	if (scale == 100) {
		// use optimized path
		bltMaskNoScale(r, data, surf, z, transparentColor);
		return;
	}

	// unscaled rectangle size
	uint width = r.width();
	uint height = r.height();

	// scaled rectangle size
	uint scaledWidth = r.width() * scale / 100;
	uint scaledHeight = r.height() * scale / 100;

	// scaled rectangle origin
	uint scaledLeft = r.left + (width - scaledWidth) / 2;
	uint scaledTop = r.top + (height - scaledHeight);

	// clipped scaled destination rectangle
	Common::Rect dstRect(scaledWidth, scaledHeight);
	dstRect.moveTo(scaledLeft, scaledTop);

	Common::Rect clipper(surf->w, surf->h);
	dstRect.clip(clipper);
	if (!dstRect.isValidRect()) return;

	// clipped source rectangle
	Common::Rect srcRect;
	srcRect.left = (dstRect.left - scaledLeft)  * 100 / scale;
	srcRect.top = (dstRect.top - scaledTop) * 100 / scale;
	srcRect.setWidth(dstRect.width() * 100 / scale);
	srcRect.setHeight(dstRect.height() * 100 / scale);
	if (!srcRect.isValidRect()) return;

	Common::Point dp;
	dp.x = dstRect.left;
	dp.y = dstRect.top;

	byte *s = data + srcRect.left + srcRect.top * width;
	byte *d = (byte *)surf->getBasePtr(dp.x, dp.y);

	uint line = 0, col = 0;

	uint xAccum = 0, yAccum = 0;
	uint inc = width * (100 - scale);
	uint thr = width * 100;

	for (uint16 i = 0; i < srcRect.height(); i++) {
		yAccum += inc;

		if (yAccum >= thr) {
			yAccum -= thr;
			s += width;
			continue;
		}

		xAccum = 0;
		byte *d2 = d;
		col = 0;

		for (uint16 j = 0; j < srcRect.width(); j++) {
			xAccum += inc;

			if (xAccum >= thr) {
				xAccum -= thr;
				s++;
				continue;
			}

			if (*s != transparentColor) {
				if (_backgroundInfo->hasMask()) {
					byte v = _backgroundInfo->_mask->getValue(dp.x + col, dp.y + line);
					if (z >= v) *d2 = *s;
				} else {
					*d2 = *s;
				}
			}

			s++;
			d2++;
			col++;
		}

		s += width - srcRect.width();
		d += surf->w;
		line++;
	}

}
Esempio n. 16
0
void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) {
	Common::Rect srcRect = _srcRect;
	if (srcRect.isEmpty())
		srcRect = Common::Rect(src.w, src.h);
	srcRect.clip(src.w, src.h);
	Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
	srcRect.clip(dstRect);

	if (srcRect.isEmpty() || !srcRect.isValidRect())
		return;

	Graphics::Surface *srcAdapted = src.convertTo(dst.format);
	uint32 keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1);

	// Copy srcRect from src surface to dst surface
	const byte *srcBuffer = (const byte *)srcAdapted->getBasePtr(srcRect.left, srcRect.top);

	int xx = _x;
	int yy = _y;

	if (xx < 0)
		xx = 0;
	if (yy < 0)
		yy = 0;

	if (_x >= dst.w || _y >= dst.h) {
		srcAdapted->free();
		delete srcAdapted;
		return;
	}

	byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);

	int32 w = srcRect.width();
	int32 h = srcRect.height();

	for (int32 y = 0; y < h; y++) {
		switch (srcAdapted->format.bytesPerPixel) {
		case 1: {
			const uint *srcTemp = (const uint *)srcBuffer;
			uint *dstTemp = (uint *)dstBuffer;
			for (int32 x = 0; x < w; x++) {
				if (*srcTemp != keycolor)
					*dstTemp = *srcTemp;
				srcTemp++;
				dstTemp++;
			}
		}
		break;

		case 2: {
			const uint16 *srcTemp = (const uint16 *)srcBuffer;
			uint16 *dstTemp = (uint16 *)dstBuffer;
			for (int32 x = 0; x < w; x++) {
				if (*srcTemp != keycolor)
					*dstTemp = *srcTemp;
				srcTemp++;
				dstTemp++;
			}
		}
		break;

		case 4: {
			const uint32 *srcTemp = (const uint32 *)srcBuffer;
			uint32 *dstTemp = (uint32 *)dstBuffer;
			for (int32 x = 0; x < w; x++) {
				if (*srcTemp != keycolor)
					*dstTemp = *srcTemp;
				srcTemp++;
				dstTemp++;
			}
		}
		break;

		default:
			break;
		}
		srcBuffer += srcAdapted->pitch;
		dstBuffer += dst.pitch;
	}

	srcAdapted->free();
	delete srcAdapted;
}
Esempio n. 17
0
bool RenderObject::getObjectIntersection(RenderObjectPtr<RenderObject> pObject, Common::Rect &result) {
	result = pObject->getBbox();
	result.clip(_bbox);
	return result.isValidRect();
}