void OpenGlTexture::updateLevel(uint32 level, const Graphics::Surface *surface, const byte *palette) {
	if (level == 0) {
		_width = surface->w;
		_height = surface->h;
	}

	if (surface->format.bytesPerPixel != 4) {
		// Convert the surface to texture format
		Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), palette);

		glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, convertedSurface->w, convertedSurface->h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, convertedSurface->getPixels());

		convertedSurface->free();
		delete convertedSurface;
	} else {
		glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, surface->getPixels());
	}
}
Beispiel #2
0
void writeSavegameHeader(Common::OutSaveFile *out, CruiseSavegameHeader &header) {
	// Write out a savegame header
	char saveIdentBuffer[6];
	strcpy(saveIdentBuffer, "SVMCR");
	out->write(saveIdentBuffer, 6);

	out->writeByte(CRUISE_SAVEGAME_VERSION);

	// Write savegame name
	out->write(header.saveName.c_str(), header.saveName.size() + 1);

	// Create a thumbnail and save it
	Graphics::Surface *thumb = new Graphics::Surface();
	::createThumbnail(thumb, globalScreen, 320, 200, workpal);
	Graphics::saveThumbnail(*out, *thumb);
	thumb->free();
	delete thumb;
}
Beispiel #3
0
Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const {
	if (shouldQuit())
		return 0;

	Common::WriteStream *out = 0;
	if (!(out = _saveFileMan->openForSaving(filename))) {
		warning("Can't create file '%s', game not saved", filename);
		return 0;
	}

	// Savegame version
	out->writeUint32BE(MKTAG('W', 'W', 'S', 'V'));
	out->writeByte(_flags.gameID);
	out->writeUint32BE(CURRENT_SAVE_VERSION);
	out->write(saveName, strlen(saveName) + 1);
	if (_flags.isTalkie)
		out->writeUint32BE(GF_TALKIE);
	else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
		out->writeUint32BE(GF_FMTOWNS);
	else
		out->writeUint32BE(GF_FLOPPY);

	if (out->err()) {
		warning("Can't write file '%s'. (Disk full?)", filename);
		delete out;
		return 0;
	}

	Graphics::Surface *genThumbnail = 0;
	if (!thumbnail)
		thumbnail = genThumbnail = generateSaveThumbnail();

	if (thumbnail)
		Graphics::saveThumbnail(*out, *thumbnail);
	else
		Graphics::saveThumbnail(*out);

	if (genThumbnail) {
		genThumbnail->free();
		delete genThumbnail;
	}

	return out;
}
SaveDataWidget::SaveDataWidget(int slot, Gfx::Driver *gfx, SaveLoadMenuScreen *screen) :
		StaticLocationWidget(nullptr, nullptr, nullptr),
		_slot(slot),
		_screen(screen),
		_thumbWidth(StarkUserInterface->kThumbnailWidth),
		_thumbHeight(StarkUserInterface->kThumbnailHeight),
		_texture(gfx->createTexture()),
		_outline(gfx->createTexture()),
		_surfaceRenderer(gfx->createSurfaceRenderer()),
		_textDesc(gfx),
		_textTime(gfx),
		_isMouseHovered(false),
		_hasSave(false),
		_name() {
	// Load from the save data
	loadSaveDataElements();

	_textDesc.setColor(_textColor);
	_textDesc.setFont(FontProvider::kCustomFont, 3);

	_textTime.setColor(_textColor);
	_textTime.setFont(FontProvider::kCustomFont, 3);

	// Create the outline texture
	Graphics::Surface lineSurface;
	lineSurface.create(_thumbWidth, _thumbHeight, Gfx::Driver::getRGBAPixelFormat());
	lineSurface.drawThickLine(0, 0, _thumbWidth - 1, 0, 2, 2, _outlineColor);
	lineSurface.drawThickLine(0, 0, 0, _thumbHeight - 1, 2, 2, _outlineColor);
	lineSurface.drawThickLine(_thumbWidth - 2, 0, _thumbWidth - 2, _thumbHeight - 2, 2, 2, _outlineColor);
	lineSurface.drawThickLine(0, _thumbHeight - 2, _thumbWidth - 2, _thumbHeight - 2, 2, 2, _outlineColor);

	_outline->update(&lineSurface);
	lineSurface.free();

	// Set the position
	_thumbPos.x = 41 + (_slot % SaveLoadMenuScreen::_slotPerRow) * (_thumbWidth + 39);
	_thumbPos.y = 61 + (_slot % SaveLoadMenuScreen::_slotPerPage / SaveLoadMenuScreen::_slotPerColumn) * (_thumbHeight + 38);

	_textDescPos.x = _thumbPos.x;
	_textDescPos.y = _thumbPos.y + _thumbHeight + 2;

	_textTimePos.x = _thumbPos.x;
	_textTimePos.y = _textDescPos.y + 12;
}
Beispiel #5
0
void PlaybackFile::checkRecordedMD5() {
	uint8 currentMD5[16];
	uint8 savedMD5[16];
	Graphics::Surface screen;
	_readStream->read(savedMD5, 16);
	if (!g_eventRec.grabScreenAndComputeMD5(screen, currentMD5)) {
		return;
	}
	uint32 seconds = g_system->getMillis(true) / 1000;
	String screenTime = String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60);
	if (memcmp(savedMD5, currentMD5, 16) != 0) {
		debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = fail", screenTime.c_str());
		warning("Recorded and current screenshots are different");
	} else {
		debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = success", screenTime.c_str());
	}
	Graphics::saveThumbnail(*_screenshotsFile, screen);
	screen.free();
}
Beispiel #6
0
void Menu::goToNode(uint16 node) {
	if (_vm->_state->getMenuSavedAge() == 0 && _vm->_state->getLocationRoom() != 901) {
		// Entering menu, save current location ...
		_vm->_state->setMenuSavedAge(_vm->_state->getLocationAge());
		_vm->_state->setMenuSavedRoom(_vm->_state->getLocationRoom());
		_vm->_state->setMenuSavedNode(_vm->_state->getLocationNode());

		// ... and capture the screen
		Graphics::Surface *big = _vm->_gfx->getScreenshot();
		createThumbnail(big, _saveThumb);
		big->free();
		delete big;
	}

	_vm->_state->setMenuEscapePressed(0);
	_vm->_state->setLocationNextAge(9);
	_vm->_state->setLocationNextRoom(901);
	_vm->goToNode(node, 2);
}
Beispiel #7
0
bool InputControl::process(uint32 deltaTimeInMillis) {
	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
		return false;

	// First see if we need to render the text
	if (_textChanged) {
		// Blit the text using the RenderManager

		Graphics::Surface txt;
		txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_pixelFormat);

		if (!_readOnly || !_focused)
			_txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt);
		else
			_txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringChooserInit, txt);

		_engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top);

		txt.free();
	}

	if (_animation && !_readOnly && _focused) {
		bool needDraw = true;// = _textChanged;
		_frameDelay -= deltaTimeInMillis;
		if (_frameDelay <= 0) {
			_frame = (_frame + 1) % _animation->frameCount();
			_frameDelay = _animation->frameTime();
			needDraw = true;
		}

		if (needDraw) {
			const Graphics::Surface *srf = _animation->getFrameData(_frame);
			uint32 xx = _textRectangle.left + _txtWidth;
			if (xx >= _textRectangle.left + (_textRectangle.width() - _animation->width()))
				xx = _textRectangle.left + _textRectangle.width() - _animation->width();
			_engine->getRenderManager()->blitSurfaceToBkg(*srf, xx, _textRectangle.top);
		}
	}

	_textChanged = false;
	return false;
}
Beispiel #8
0
void RenderManager::processSubs(uint16 deltatime) {
	bool redraw = false;
	for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
		if (it->_value.timer != -1) {
			it->_value.timer -= deltatime;
			if (it->_value.timer <= 0)
				it->_value.todelete = true;
		}
		if (it->_value.todelete) {
			_subsList.erase(it);
			redraw = true;
		} else if (it->_value.redraw) {
			redraw = true;
		}
	}

	if (redraw) {
		_subtitleSurface.fillRect(Common::Rect(_subtitleSurface.w, _subtitleSurface.h), 0);

		for (SubtitleMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
			OneSubtitle *sub = &it->_value;
			if (sub->txt.size()) {
				Graphics::Surface *rndr = new Graphics::Surface();
				rndr->create(sub->r.width(), sub->r.height(), _engine->_resourcePixelFormat);
				_engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr);
				Common::Rect empty;
				blitSurfaceToSurface(*rndr, empty, _subtitleSurface, sub->r.left - _subtitleArea.left + _workingWindow.left, sub->r.top - _subtitleArea.top + _workingWindow.top);
				rndr->free();
				delete rndr;
			}
			sub->redraw = false;
		}

		Common::Rect rect(
			_subtitleArea.left,
			_subtitleArea.top,
			_subtitleArea.left + _subtitleSurface.w,
			_subtitleArea.top + _subtitleSurface.h
		);
		copyToScreen(_subtitleSurface, rect, 0, 0);
	}
}
Beispiel #9
0
bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, Graphics::Surface *dest) {
	assert(dest);
	Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);

	::Image::PNGDecoder png;
	if (!png.loadStream(*fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
		error("Error while reading PNG image");

	const Graphics::Surface *sourceSurface = png.getSurface();
	Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), png.getPalette());

	dest->copyFrom(*pngSurface);

	pngSurface->free();
	delete pngSurface;
	delete fileStr;

	// Signal success
	return true;
}
Beispiel #10
0
void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &desc) {
    Common::String filename = getFilenameForSlot(slot);
    debugC(kWintermuteDebugSaveGame, "Trying to list savegame %s in slot %d", filename.c_str(), slot);
    if (DID_FAIL(readHeader(filename))) {
        debugC(kWintermuteDebugSaveGame, "getSavedDesc(%d) - Failed for %s", slot, filename.c_str());
        return;
    }
    desc.setSaveSlot(slot);
    desc.setDescription(_savedDescription);
    desc.setDeletableFlag(true);
    desc.setWriteProtectedFlag(false);

    int thumbSize = 0;
    byte *thumbData = nullptr;
    if (_scummVMThumbSize > 0) {
        thumbSize = _scummVMThumbSize;
        thumbData = _scummVMThumbnailData;
    } else if (_thumbnailDataSize > 0) {
        thumbSize = _thumbnailDataSize;
        thumbData = _thumbnailData;
    }

    if (thumbSize > 0) {
        Common::MemoryReadStream thumbStream(thumbData, thumbSize, DisposeAfterUse::NO);
        Graphics::BitmapDecoder bmpDecoder;
        if (bmpDecoder.loadStream(thumbStream)) {
            const Graphics::Surface *bmpSurface = bmpDecoder.getSurface();
            TransparentSurface *scaleableSurface = new TransparentSurface(*bmpSurface, false);
            Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2);
            Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat());
            desc.setThumbnail(thumb);
            delete scaleableSurface;
            scaled->free();
            delete scaled;
        }
    }

    desc.setSaveDate(_savedTimestamp.tm_year, _savedTimestamp.tm_mon, _savedTimestamp.tm_mday);
    desc.setSaveTime(_savedTimestamp.tm_hour, _savedTimestamp.tm_min);
    desc.setPlayTime(0);
}
Beispiel #11
0
// TODO: this method will probably go away and be integrated in the main loop
void Animation::play() {
	Common::EventManager *eventMan = g_system->getEventManager();
	while (!hasEnded() && !Engine::shouldQuit()) {
		process();

		if (_changed) {
			// Create a temporary surface to merge the overlay with the background
			Graphics::Surface *s = new Graphics::Surface;
			s->create(640, 480, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));

			draw(s);

			// XXX: Update the screen
			g_system->copyRectToScreen(s->getPixels(), s->pitch, 0, 0, s->w, s->h);

			// Free the temporary surface
			s->free();
			delete s;

			_changed = false;
		}

		g_system->updateScreen();

		//FIXME: implement subtitles
		g_system->delayMillis(20);

		// Handle right-click to interrupt animations
		Common::Event ev = Common::Event();
		while (eventMan->pollEvent(ev)) {
			if (ev.type == Common::EVENT_RBUTTONUP) {
				// Stop audio
				if (_audio)
					_audio->finish();

				// TODO start LNK file sound?
				return;
			}
		}
	}
}
Beispiel #12
0
const Graphics::Surface *JPEGDecoder::decodeImage(Common::SeekableReadStream* stream) {
	if (!_jpeg->read(stream)) {
		warning("Failed to decode JPEG frame");
		return 0;
	}

	if (!_surface) {
		_surface = new Graphics::Surface();
		_surface->create(_jpeg->getWidth(), _jpeg->getHeight(), _pixelFormat.bytesPerPixel);
	}

	Graphics::Surface *frame = _jpeg->getSurface(_pixelFormat);
	assert(frame);

	_surface->copyFrom(*frame);

	frame->free();
	delete frame;

	return _surface;
}
Beispiel #13
0
void Cursor::loadAvailableCursors() {
	assert(_textures.empty());

	// Load available cursors
	for (uint i = 0; i < ARRAYSIZE(availableCursors); i++) {
		// Check if a cursor sharing the same texture has already been loaded
		if (_textures.contains(availableCursors[i].nodeID)) continue;

		// Load the cursor bitmap
		const DirectorySubEntry *cursorDesc = _vm->getFileDescription("GLOB", availableCursors[i].nodeID, 0, DirectorySubEntry::kRawData);
		if (!cursorDesc)
			error("Cursor %d does not exist", availableCursors[i].nodeID);

		Common::MemoryReadStream *bmpStream = cursorDesc->getData();

		Image::BitmapDecoder bitmapDecoder;
		if (!bitmapDecoder.loadStream(*bmpStream))
			error("Could not decode Myst III bitmap");
		const Graphics::Surface *surfaceBGRA = bitmapDecoder.getSurface();
		Graphics::Surface *surfaceRGBA = surfaceBGRA->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));

		delete bmpStream;

		// Apply the colorkey for transparency
		for (uint u = 0; u < surfaceRGBA->w; u++) {
			for (uint v = 0; v < surfaceRGBA->h; v++) {
				uint32 *pixel = (uint32*)(surfaceRGBA->getBasePtr(u, v));
				if (*pixel == 0xFF00FF00)
					*pixel = 0x0000FF00;

			}
		}

		// Create and store the texture
		_textures.setVal(availableCursors[i].nodeID, _vm->_gfx->createTexture(surfaceRGBA));

		surfaceRGBA->free();
		delete surfaceRGBA;
	}
}
Beispiel #14
0
bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) {
	Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);

	::Image::PNGDecoder png;
	if (!png.loadStream(*fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
		error("Error while reading PNG image");

	const Graphics::Surface *sourceSurface = png.getSurface();
	Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), png.getPalette());

	width = pngSurface->w;
	height = pngSurface->h;
	uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h];
	memcpy(uncompressedDataPtr, (byte *)pngSurface->getPixels(), pngSurface->pitch * pngSurface->h);
	pngSurface->free();

	delete pngSurface;
	delete fileStr;

	// Signal success
	return true;
}
Beispiel #15
0
bool Console::dumpFaceMask(uint16 index, int face, DirectorySubEntry::ResourceType type) {
	const DirectorySubEntry *maskDesc = _vm->getFileDescription(0, index, face, type);

	if (!maskDesc)
		return false;

	Common::MemoryReadStream *maskStream = maskDesc->getData();

	Graphics::Surface *mask = Effect::loadMask(maskStream);

	delete maskStream;

	Common::DumpFile outFile;
	outFile.open(Common::String::format("dump/%d-%d.masku_%d", index, face, type));
	outFile.write(mask->getPixels(), mask->pitch * mask->h);
	outFile.close();

	mask->free();
	delete mask;

	return true;
}
Beispiel #16
0
void OSystem_3DS::flushCursor() {
	if (_cursor.getPixels()) {
		Graphics::Surface *converted = _cursor.convertTo(_pfGameTexture, _cursorPaletteEnabled ? _cursorPalette : _palette);
		_cursorTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
		_cursorTexture.markDirty();
		converted->free();
		delete converted;
	
		if (_pfCursor.bytesPerPixel == 1) {
			uint* dest = (uint*) _cursorTexture.getPixels();
			byte* src = (byte*) _cursor.getPixels();
			for (int y = 0; y < _cursor.h; ++y) {
				for (int x = 0; x < _cursor.w; ++x) {
					if (*src++ == _cursorKeyColor)
						*dest++ = 0;
					else
						dest++;
				}
				dest += _cursorTexture.w - _cursorTexture.actualWidth;
			}
		}
	}
}
Beispiel #17
0
ThemeEngine::~ThemeEngine() {
	delete _vectorRenderer;
	_vectorRenderer = 0;
	_screen.free();
	_backBuffer.free();

	unloadTheme();

	// Release all graphics surfaces
	for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) {
		Graphics::Surface *surf = i->_value;
		if (surf) {
			surf->free();
			delete surf;
		}
	}
	_bitmaps.clear();

	delete _parser;
	delete _themeEval;
	delete[] _cursor;
	delete _themeArchive;
}
Beispiel #18
0
Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) {
	Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_targetName, slot);
	if (saveFile == nullptr || saveFile->err()) {
		delete saveFile;
		return Common::kReadingFailed;
	}

	Graphics::Surface thumbnail = generateThumbnail();

	BladeRunner::SaveFileHeader header;
	header._name = desc;

	BladeRunner::SaveFileManager::writeHeader(*saveFile, header);

	saveGame(*saveFile, thumbnail);

	saveFile->finalize();

	thumbnail.free();

	delete saveFile;

	return Common::kNoError;
}
Beispiel #19
0
void AVISurface::copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest) {
	// WORKAROUND: Handle rare cases where frame sizes don't match the video size
	Common::Rect copyRect(0, 0, MIN(src.w, dest.w), MIN(src.h, dest.h));

	if (src.format.bytesPerPixel == 1) {
		// Paletted 8-bit, so convert to 16-bit and copy over
		const byte *palette = _decoder->getPalette();
		if (palette) {
			Graphics::Surface *s = src.convertTo(dest.format, palette);
			dest.blitFrom(*s, copyRect, Common::Point(0, 0));
			s->free();
			delete s;
		}
	} else if (src.format.bytesPerPixel == 2) {
		// Source is already 16-bit, with no alpha, so do a straight copy
		dest.blitFrom(src, copyRect, Common::Point(0, 0));
	} else {
		// Source is 32-bit which may have transparent pixels. Copy over each
		// pixel, replacing transparent pixels with the special transparency color
		byte a, r, g, b;
		assert(src.format.bytesPerPixel == 4 && dest.format.bytesPerPixel == 2);
		uint16 transPixel = _videoSurface->getTransparencyColor();

		for (uint y = 0; y < MIN(src.h, dest.h); ++y) {
			const uint32 *pSrc = (const uint32 *)src.getBasePtr(0, y);
			uint16 *pDest = (uint16 *)dest.getBasePtr(0, y);

			for (uint x = 0; x < MIN(src.w, dest.w); ++x, ++pSrc, ++pDest) {
				src.format.colorToARGB(*pSrc, a, r, g, b);
				assert(a == 0 || a == 0xff);

				*pDest = (a == 0) ? transPixel : dest.format.RGBToColor(r, g, b);
			}
		}
	}
}
Beispiel #20
0
bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) {
#ifndef USE_INTERNAL_PNG_DECODER
	png_structp png_ptr = NULL;
	png_infop   info_ptr = NULL;

	int         bitDepth;
	int         colorType;
	int         interlaceType;
	int         i;

	// Check for valid PNG signature
	if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) {
		error("png_check_sig failed");
	}

	// Create both PNG structures
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		error("Could not create libpng read struct.");
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		error("Could not create libpng info struct.");
	}

	// Use alternative reading function
	const byte **ref = &fileDataPtr;
	png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);

	// Read PNG header
	png_read_info(png_ptr, info_ptr);

	// Read out PNG informations

	png_uint_32 w, h;
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
	width = w;
	height = h;

	// Calculate pitch of output image
	pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width);

	// Allocate memory for the final image data.
	// To keep memory framentation low this happens before allocating memory for temporary image data.
	uncompressedDataPtr = new byte[pitch * height];
	if (!uncompressedDataPtr) {
		error("Could not allocate memory for output image.");
	}

	// Images of all color formates will be transformed into ARGB images
	if (bitDepth == 16)
		png_set_strip_16(png_ptr);
	if (colorType == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);
	if (bitDepth < 8)
		png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);
	if (colorType == PNG_COLOR_TYPE_GRAY ||
	        colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);

	png_set_bgr(png_ptr);

	if (colorType != PNG_COLOR_TYPE_RGB_ALPHA)
		png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

	// After the transformations have been registered, the image data is read again.
	png_read_update_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);
	width = w;
	height = h;

	if (interlaceType == PNG_INTERLACE_NONE) {
		// PNGs without interlacing can simply be read row by row.
		for (i = 0; i < height; i++) {
			png_read_row(png_ptr, uncompressedDataPtr + i * pitch, NULL);
		}
	} else {
		// PNGs with interlacing require us to allocate an auxillary
		// buffer with pointers to all row starts.

		// Allocate row pointer buffer
		png_bytep *pRowPtr = new png_bytep[height];
		if (!pRowPtr) {
			error("Could not allocate memory for row pointers.");
		}

		// Initialize row pointers
		for (i = 0; i < height; i++)
			pRowPtr[i] = uncompressedDataPtr + i * pitch;

		// Read image data
		png_read_image(png_ptr, pRowPtr);

		// Free row pointer buffer
		delete[] pRowPtr;
	}

	// Read additional data at the end.
	png_read_end(png_ptr, NULL);

	// Destroy libpng structures
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
#else
	Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);
	Graphics::PNG *png = new Graphics::PNG();
	if (!png->read(fileStr))	// the fileStr pointer, and thus pFileData will be deleted after this is done
		error("Error while reading PNG image");

	Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
	Graphics::Surface *pngSurface = png->getSurface(format);

	width = pngSurface->w;
	height = pngSurface->h;
	uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h];
	memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h);
	pngSurface->free();

	delete pngSurface;
	delete png;

#endif
	// Signal success
	return true;
}
Beispiel #21
0
bool VideoManager::updateMovies() {
	bool updateScreen = false;

	for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
		// Skip deleted videos
		if (!_videoStreams[i].video)
			continue;

		// Remove any videos that are over
		if (_videoStreams[i].endOfVideo()) {
			if (_videoStreams[i].loop) {
				_videoStreams[i]->seek(_videoStreams[i].start);
			} else {
				// Check the video time one last time before deleting it
				_vm->doVideoTimer(i, true);
				delete _videoStreams[i].video;
				_videoStreams[i].clear();
				continue;
			}
		}

		// Nothing more to do if we're paused
		if (_videoStreams[i]->isPaused())
			continue;

		// Check if we need to draw a frame
		if (_videoStreams[i]->needsUpdate()) {
			const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
			Graphics::Surface *convertedFrame = 0;

			if (frame && _videoStreams[i].enabled) {
				Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();

				if (frame->format != pixelFormat) {
					// We don't support downconverting to 8bpp
					if (pixelFormat.bytesPerPixel == 1)
						error("Cannot convert high color video frame to 8bpp");

					// Convert to the current screen format
					convertedFrame = frame->convertTo(pixelFormat, _videoStreams[i]->getPalette());
					frame = convertedFrame;
				} else if (pixelFormat.bytesPerPixel == 1 && _videoStreams[i]->hasDirtyPalette()) {
					// Set the palette when running in 8bpp mode only
					_vm->_system->getPaletteManager()->setPalette(_videoStreams[i]->getPalette(), 0, 256);
				}

				// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
				uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
				uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
				_vm->_system->copyRectToScreen(frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);

				// We've drawn something to the screen, make sure we update it
				updateScreen = true;

				// Delete 8bpp conversion surface
				if (convertedFrame) {
					convertedFrame->free();
					delete convertedFrame;
				}
			}
		}

		// Check the video time
		_vm->doVideoTimer(i, false);
	}

	// Return true if we need to update the screen
	return updateScreen;
}
Beispiel #22
0
bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) {
#ifdef USE_PNG
	const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 16, 8, 0, 0);
	const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24);

	if (input.format.bytesPerPixel == 3) {
		if (input.format != requiredFormat_3byte) {
			warning("Cannot currently write PNG with 3-byte pixel format other than %s", requiredFormat_3byte.toString().c_str());
			return false;
		}
	} else if (input.format.bytesPerPixel != 4) {
		warning("Cannot currently write PNG with pixel format of bpp other than 3, 4");
		return false;
	}

	int colorType;
	Graphics::Surface *tmp = NULL;
	const Graphics::Surface *surface;

	if (input.format == requiredFormat_3byte) {
		surface = &input;
		colorType = PNG_COLOR_TYPE_RGB;
	} else {
		if (input.format == requiredFormat_4byte) {
			surface = &input;
		} else {
			surface = tmp = input.convertTo(requiredFormat_4byte);
		}
		colorType = PNG_COLOR_TYPE_RGB_ALPHA;
	}

	png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!pngPtr) {
		return false;
	}
	png_infop infoPtr = png_create_info_struct(pngPtr);
	if (!infoPtr) {
		png_destroy_write_struct(&pngPtr, NULL);
		return false;
	}

	png_set_error_fn(pngPtr, NULL, pngError, pngWarning);
	// TODO: The manual says errors should be handled via setjmp

	png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream);

	png_set_IHDR(pngPtr, infoPtr, surface->w, surface->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	Common::Array<const uint8 *> rows;
	rows.reserve(surface->h);
	if (bottomUp) {
		for (uint y = surface->h; y-- > 0;) {
			rows.push_back((const uint8 *)surface->getBasePtr(0, y));
		}
	} else {
		for (uint y = 0; y < surface->h; ++y) {
			rows.push_back((const uint8 *)surface->getBasePtr(0, y));
		}
	}

	png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front()));
	png_write_png(pngPtr, infoPtr, 0, NULL);
	png_destroy_write_struct(&pngPtr, &infoPtr);

	// free tmp surface
	if (tmp) {
		tmp->free();
		delete tmp;
	}

	return true;
#else
	return false;
#endif
}
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) {
	//TextLineList lines;
	// TODO: Use WideString-conversion here.
	//WrapText(text, width, maxHeight, lines);
	Common::Array<WideString> lines;
	_font->wordWrapText(text, width, lines);

	while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) {
		lines.pop_back();
	}
	if (lines.size() == 0) {
		return nullptr;
	}

	Graphics::TextAlign alignment = Graphics::kTextAlignInvalid;
	if (align == TAL_LEFT) {
		alignment = Graphics::kTextAlignLeft;
	} else if (align == TAL_CENTER) {
		alignment = Graphics::kTextAlignCenter;
	} else if (align == TAL_RIGHT) {
		alignment = Graphics::kTextAlignRight;
	}

	// TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array.
	//debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
//	void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
	Graphics::Surface *surface = new Graphics::Surface();
	surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
	uint32 useColor = 0xffffffff;
	Common::Array<WideString>::iterator it;
	int heightOffset = 0;
	for (it = lines.begin(); it != lines.end(); ++it) {
		_font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment);
		heightOffset += (int)_lineHeight;
	}

	BaseSurface *retSurface = _gameRef->_renderer->createSurface();

	if (_deletableFont) {
		// Reconstruct the alpha channel of the font.

		// Since we painted it with color 0xFFFFFFFF onto a black background,
		// the alpha channel is gone, but the color value of each pixel corresponds
		// to its original alpha value.

		Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat();
		uint32 *pixels = (uint32 *)surface->getPixels();

		// This is a Surface we created ourselves, so no empty space between rows.
		for (int i = 0; i < surface->w * surface->h; ++i) {
			uint8 a, r, g, b;
			format.colorToRGB(*pixels, r, g, b);
			a = r;
			*pixels++ = format.ARGBToColor(a, r, g, b);
		}
	}

	retSurface->putSurface(*surface, true);
	surface->free();
	delete surface;
	return retSurface;
	// TODO: _isUnderline, _isBold, _isItalic, _isStriked
}
Beispiel #24
0
bool VideoManager::updateMovies() {
	bool updateScreen = false;

	for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
		// Skip deleted videos
		if (!_videoStreams[i].video)
			continue;

		// Remove any videos that are over
		if (_videoStreams[i].endOfVideo()) {
			if (_videoStreams[i].loop) {
				_videoStreams[i]->seekToTime(_videoStreams[i].start);
			} else {
				delete _videoStreams[i].video;
				_videoStreams[i].clear();
				continue;
			}
		}

		// Check if we need to draw a frame
		if (!_videoStreams[i]->isPaused() && _videoStreams[i]->needsUpdate()) {
			const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
			Graphics::Surface *convertedFrame = 0;

			if (frame && _videoStreams[i].enabled) {
				// Convert from 8bpp to the current screen format if necessary
				Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();

				if (frame->format.bytesPerPixel == 1) {
					if (pixelFormat.bytesPerPixel == 1) {
						if (_videoStreams[i]->hasDirtyPalette())
							_videoStreams[i]->setSystemPalette();
					} else {
						convertedFrame = new Graphics::Surface();
						const byte *palette = _videoStreams[i]->getPalette();
						assert(palette);

						convertedFrame->create(frame->w, frame->h, pixelFormat);

						for (uint16 j = 0; j < frame->h; j++) {
							for (uint16 k = 0; k < frame->w; k++) {
								byte palIndex = *((const byte *)frame->getBasePtr(k, j));
								byte r = palette[palIndex * 3];
								byte g = palette[palIndex * 3 + 1];
								byte b = palette[palIndex * 3 + 2];
								if (pixelFormat.bytesPerPixel == 2)
									*((uint16 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
								else
									*((uint32 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
							}
						}

						frame = convertedFrame;
					}
				}

				// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
				uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
				uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);
				_vm->_system->copyRectToScreen((byte*)frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);

				// We've drawn something to the screen, make sure we update it
				updateScreen = true;

				// Delete 8bpp conversion surface
				if (convertedFrame) {
					convertedFrame->free();
					delete convertedFrame;
				}
			}
		}
	}

	// Return true if we need to update the screen
	return updateScreen;
}
Beispiel #25
0
void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, bool skippable, Subtitle *sub) {
	Common::Rect dst = destRect;
	// If destRect is empty, no specific scaling was requested. However, we may choose to do scaling anyway
	if (dst.isEmpty())
		dst = Common::Rect(vid.getWidth(), vid.getHeight());

	Graphics::Surface *scaled = NULL;

	if (vid.getWidth() != dst.width() || vid.getHeight() != dst.height()) {
		scaled = new Graphics::Surface;
		scaled->create(dst.width(), dst.height(), vid.getPixelFormat());
	}

	uint16 x = _workingWindow.left + dst.left;
	uint16 y = _workingWindow.top + dst.top;
	uint16 finalWidth = dst.width() < _workingWindow.width() ? dst.width() : _workingWindow.width();
	uint16 finalHeight = dst.height() < _workingWindow.height() ? dst.height() : _workingWindow.height();
	bool showSubs = (_scriptManager->getStateValue(StateKey_Subtitles) == 1);

	_clock.stop();
	vid.start();
	_videoIsPlaying = true;

	// Only continue while the video is still playing
	while (!shouldQuit() && !vid.endOfVideo() && vid.isPlaying()) {
		// Check for engine quit and video stop key presses
		while (_eventMan->pollEvent(_event)) {
			switch (_event.type) {
			case Common::EVENT_KEYDOWN:
				switch (_event.kbd.keycode) {
				case Common::KEYCODE_q:
					if (_event.kbd.hasFlags(Common::KBD_CTRL))
						quitGame();
					break;
				case Common::KEYCODE_SPACE:
					if (skippable) {
						vid.stop();
					}
					break;
				default:
					break;
				}
			default:
				break;
			}
		}

		if (vid.needsUpdate()) {
			const Graphics::Surface *frame = vid.decodeNextFrame();
			if (sub && showSubs)
				sub->process(vid.getCurFrame());

			if (frame) {
				if (scaled) {
					_renderManager->scaleBuffer(frame->getPixels(), scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, scaled->w, scaled->h);
					frame = scaled;
				}
				Common::Rect rect = Common::Rect(x, y, x + finalWidth, y + finalHeight);
				_renderManager->copyToScreen(*frame, rect, 0, 0);
				_renderManager->processSubs(0);
			}
		}

		// Always update the screen so the mouse continues to render
		_system->updateScreen();

		_system->delayMillis(vid.getTimeToNextFrame() / 2);
	}

	_videoIsPlaying = false;
	_clock.start();

	if (scaled) {
		scaled->free();
		delete scaled;
	}
}
Beispiel #26
0
bool VideoManager::drawNextFrame(VideoEntryPtr videoEntry) {
	Video::VideoDecoder *video = videoEntry->_video;
	const Graphics::Surface *frame = video->decodeNextFrame();

	if (!frame || !videoEntry->isEnabled()) {
		return false;
	}

	Graphics::Surface *convertedFrame = nullptr;
	Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();

	if (frame->format != pixelFormat) {
		// We don't support downconverting to 8bpp without having
		// support in the codec. Set _enableDither if shows up.
		if (pixelFormat.bytesPerPixel == 1) {
			warning("Cannot convert high color video frame to 8bpp");
			return false;
		}

		// Convert to the current screen format
		convertedFrame = frame->convertTo(pixelFormat, video->getPalette());
		frame = convertedFrame;
	} else if (pixelFormat.bytesPerPixel == 1 && video->hasDirtyPalette()) {
		// Set the palette when running in 8bpp mode only
		// Don't do this for Myst, which has its own per-stack handling
		if (_vm->getGameType() != GType_MYST)
			_vm->_system->getPaletteManager()->setPalette(video->getPalette(), 0, 256);
	}

	// Clip the video to make sure it stays on the screen (Myst does this a few times)
	Common::Rect targetRect = Common::Rect(video->getWidth(), video->getHeight());
	targetRect.translate(videoEntry->getX(), videoEntry->getY());

	Common::Rect frameRect = Common::Rect(video->getWidth(), video->getHeight());

	if (targetRect.left < 0) {
		frameRect.left -= targetRect.left;
		targetRect.left = 0;
	}

	if (targetRect.top < 0) {
		frameRect.top -= targetRect.top;
		targetRect.top = 0;
	}

	if (targetRect.right > _vm->_system->getWidth()) {
		frameRect.right -= targetRect.right - _vm->_system->getWidth();
		targetRect.right = _vm->_system->getWidth();
	}

	if (targetRect.bottom > _vm->_system->getHeight()) {
		frameRect.bottom -= targetRect.bottom - _vm->_system->getHeight();
		targetRect.bottom = _vm->_system->getHeight();
	}

	_vm->_system->copyRectToScreen(frame->getBasePtr(frameRect.left, frameRect.top), frame->pitch,
	                               targetRect.left, targetRect.top, targetRect.width(), targetRect.height());

	// Delete 8bpp conversion surface
	if (convertedFrame) {
		convertedFrame->free();
		delete convertedFrame;
	}

	// We've drawn something to the screen, make sure we update it
	return true;
}
Beispiel #27
0
bool VideoManager::updateMovies() {
	bool updateScreen = false;

	for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
		// Skip deleted videos
		if (!_videoStreams[i].video)
			continue;

		// Remove any videos that are over
		if (_videoStreams[i].endOfVideo()) {
			if (_videoStreams[i].loop) {
				_videoStreams[i]->seekToTime(_videoStreams[i].start);
			} else {
				// Check the video time one last time before deleting it
				_vm->doVideoTimer(i, true);
				delete _videoStreams[i].video;
				_videoStreams[i].clear();
				continue;
			}
		}

		// Nothing more to do if we're paused
		if (_videoStreams[i]->isPaused())
			continue;

		// Check if we need to draw a frame
		if (_videoStreams[i]->needsUpdate()) {
			const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
			Graphics::Surface *convertedFrame = 0;

			if (frame && _videoStreams[i].enabled) {
				Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();

				// Create (or resize) the off-screen surface
				if (frame->w > _videoStreams[i].surface.w || frame->h > _videoStreams[i].surface.h) {
					_videoStreams[i].surface.create(frame->w, frame->h, pixelFormat);
				}

				// Convert from 8bpp to the current screen format if necessary
				if (frame->format.bytesPerPixel == 1) {
					if (pixelFormat.bytesPerPixel == 1) {
						if (_videoStreams[i]->hasDirtyPalette())
							_videoStreams[i]->setSystemPalette();
					} else {
						convertedFrame = new Graphics::Surface();
						const byte *palette = _videoStreams[i]->getPalette();
						assert(palette);

						convertedFrame->create(frame->w, frame->h, pixelFormat);

						for (uint16 j = 0; j < frame->h; j++) {
							for (uint16 k = 0; k < frame->w; k++) {
								byte palIndex = *((const byte *)frame->getBasePtr(k, j));
								byte r = palette[palIndex * 3];
								byte g = palette[palIndex * 3 + 1];
								byte b = palette[palIndex * 3 + 2];
								if (pixelFormat.bytesPerPixel == 2)
									*((uint16 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
								else
									*((uint32 *)convertedFrame->getBasePtr(k, j)) = pixelFormat.RGBToColor(r, g, b);
							}
						}

						frame = convertedFrame;
					}
				}

				// Copy frame to the off-screen surface
				for (int y = 0; y < frame->h; ++y) {
					memcpy(_videoStreams[i].surface.getBasePtr(0, y), frame->getBasePtr(0, y), frame->w * pixelFormat.bytesPerPixel);
				}

				// Delete 8bpp conversion surface
				if (convertedFrame) {
					convertedFrame->free();
					delete convertedFrame;
				}
			}
		}

		// Don't draw anything until we have a valid surface
		if (_videoStreams[i].surface.w == 0 || _videoStreams[i].surface.h == 0) continue;

		// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
		uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x);
		uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y);

		// Render the off-screen surface
		_vm->_system->copyRectToScreen((byte *)_videoStreams[i].surface.pixels, _videoStreams[i].surface.pitch, _videoStreams[i].x, _videoStreams[i].y, width, height);
		updateScreen = true;

		// Check the video time
		_vm->doVideoTimer(i, false);
	}

	// Return true if we need to update the screen
	return updateScreen;
}
Beispiel #28
0
bool AnimationEffect::process(uint32 deltaTimeInMillis) {
	ScriptManager *scriptManager = _engine->getScriptManager();
	RenderManager *renderManager = _engine->getRenderManager();
	RenderTable::RenderState renderState = renderManager->getRenderTable()->getRenderState();
	bool isPanorama = (renderState == RenderTable::PANORAMA);
	int16 velocity = _engine->getMouseVelocity() + _engine->getKeyboardVelocity();

	// Do not update animation nodes in panoramic mode while turning, if the user
	// has set this option
	if (scriptManager->getStateValue(StateKey_NoTurnAnim) == 1 && isPanorama && velocity)
		return false;

	PlayNodes::iterator it = _playList.begin();
	if (it != _playList.end()) {
		playnode *nod = &(*it);

		if (nod->_curFrame == -1) {
			// The node is just beginning playback
			nod->_curFrame = nod->start;

			_animation->start();
			_animation->seekToFrame(nod->start);
			_animation->setEndFrame(nod->stop);

			nod->_delay = deltaTimeInMillis; // Force the frame to draw
			if (nod->slot)
				scriptManager->setStateValue(nod->slot, 1);
		} else if (_animation->endOfVideo()) {
			// The node has reached the end; check if we need to loop
			nod->loop--;

			if (nod->loop == 0) {
				if (nod->slot >= 0)
					scriptManager->setStateValue(nod->slot, 2);
				if (nod->_scaled) {
					nod->_scaled->free();
					delete nod->_scaled;
				}
				_playList.erase(it);
				return _disposeAfterUse;
			}

			nod->_curFrame = nod->start;
			_animation->seekToFrame(nod->start);
		}

		// Check if we need to draw a frame
		bool needsUpdate = false;
		if (_frmDelayOverride == 0) {
			// If not overridden, use the VideoDecoder's check
			needsUpdate = _animation->needsUpdate();
		} else {
			// Otherwise, implement our own timing
			nod->_delay -= deltaTimeInMillis;

			if (nod->_delay <= 0) {
				nod->_delay += _frmDelayOverride;
				needsUpdate = true;
			}
		}

		if (needsUpdate) {
			const Graphics::Surface *frame = _animation->decodeNextFrame();

			if (frame) {
				uint32 dstw;
				uint32 dsth;
				if (isPanorama) {
					dstw = nod->pos.height();
					dsth = nod->pos.width();
				} else {
					dstw = nod->pos.width();
					dsth = nod->pos.height();
				}

				// We only scale down the animation to fit its frame, not up, otherwise we
				// end up with distorted animations - e.g. the armor visor in location cz1e
				// in Nemesis (one of the armors inside Irondune), or the planet in location
				// aa10 in Nemesis (Juperon, outside the asylum). We do allow scaling up only
				// when a simple 2x filter is requested (e.g. the alchemists and cup sequence
				// in Nemesis)
				if (frame->w > dstw || frame->h > dsth || (frame->w == dstw / 2 && frame->h == dsth / 2)) {
					if (nod->_scaled)
						if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) {
							nod->_scaled->free();
							delete nod->_scaled;
							nod->_scaled = NULL;
						}

					if (!nod->_scaled) {
						nod->_scaled = new Graphics::Surface;
						nod->_scaled->create(dstw, dsth, frame->format);
					}

					renderManager->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth);
					frame = nod->_scaled;
				}

				if (isPanorama) {
					Graphics::Surface *transposed = RenderManager::tranposeSurface(frame);
					renderManager->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask);
					transposed->free();
					delete transposed;
				} else {
					renderManager->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask);
				}
			}
		}
	}

	return false;
}
Beispiel #29
0
void Design::drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadStream &in) {
	int numBytes = in.readSint16BE();
	int y1 = in.readSint16BE();
	int x1 = in.readSint16BE();
	int y2 = in.readSint16BE();
	int x2 = in.readSint16BE();
	int w = x2 - x1;
	int h = y2 - y1;
	Graphics::Surface tmp;

	tmp.create(w, h, Graphics::PixelFormat::createFormatCLUT8());

	numBytes -= 10;

	int x = 0, y = 0;
	while (numBytes > 0 && y < h) {
		int n = in.readSByte();
		int count;
		int b = 0;
		int state = 0;

		numBytes--;

		if ((n >= 0) && (n <= 127)) { // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
			count = n + 1;
			state = 1;
		} else if ((n >= -127) && (n <= -1)) { // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
			b = in.readByte();
			numBytes--;
			count = -n + 1;
			state = 2;
		} else { // Else if n is -128, noop.
			count = 0;
		}

		for (int i = 0; i < count && y < h; i++) {
			byte color = 0;
			if (state == 1) {
				color = in.readByte();
				numBytes--;
			} else if (state == 2)
				color = b;

			for (int c = 0; c < 8; c++) {
				if (_boundsCalculationMode) {
					adjustBounds(x1 + x, y1 + y);
				} else if (x1 + x >= 0 && x1 + x < surface->w && y1 + y >= 0 && y1 + y < surface->h)
					*((byte *)tmp.getBasePtr(x, y)) = (color & (1 << (7 - c % 8))) ? kColorBlack : kColorWhite;
				x++;
				if (x == w) {
					y++;
					x = 0;
					break;
				}
			}
		}
	}

	in.skip(numBytes);

	if (!_boundsCalculationMode) {
		Graphics::FloodFill ff(&tmp, kColorWhite, kColorGreen);
		for (int yy = 0; yy < h; yy++) {
			ff.addSeed(0, yy);
			ff.addSeed(w - 1, yy);
		}
		for (int xx = 0; xx < w; xx++) {
			ff.addSeed(xx, 0);
			ff.addSeed(xx, h - 1);
		}
		ff.fill();

		for (y = 0; y < h && y1 + y < surface->h; y++) {
			byte *src = (byte *)tmp.getBasePtr(0, y);
			byte *dst = (byte *)surface->getBasePtr(x1, y1 + y);
			for (x = 0; x < w; x++) {
				if (*src != kColorGreen)
					*dst = *src;
				src++;
				dst++;
			}
		}
	}

	tmp.free();
}
Beispiel #30
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;
}