Esempio n. 1
0
static ParseRule *_vsatisfy_rule(ParseRule *rule, const ResultWordList &input) {
	int dep;

	if (!rule->_numSpecials)
		return NULL;

	dep = rule->_data[rule->_firstSpecial];

	int count = 0;
	int match = 0;
	ResultWordList::const_iterator iter;
	// TODO: Inserting an array in the middle of another array is slow
	Common::Array<int> matches;
	matches.reserve(input.size());

	// We store the first match in 'match', and any subsequent matches in
	// 'matches'. 'match' replaces the special in the rule, and 'matches' gets
	// inserted after it.
	for (iter = input.begin(); iter != input.end(); ++iter)
		if (((dep & TOKEN_TERMINAL_CLASS) && ((dep & 0xffff) & iter->_class)) ||
			((dep & TOKEN_TERMINAL_GROUP) && ((dep & 0xffff) & iter->_group))) {
			if (count == 0)
				match = TOKEN_STUFFING_WORD | iter->_group;
			else
				matches.push_back(TOKEN_STUFFING_WORD | iter->_group);
			count++;
		}

	if (count) {
		ParseRule *retval = new ParseRule(*rule);
		++_allocd_rules;
		retval->_data[rule->_firstSpecial] = match;
		if (count > 1)
			retval->_data.insert_at(rule->_firstSpecial+1, matches);
		retval->_numSpecials--;
		retval->_firstSpecial = 0;

		if (retval->_numSpecials) { // find first special, if it exists
			for (uint i = rule->_firstSpecial; i < retval->_data.size(); ++i) {
				int tmp = retval->_data[i];
				if (!(tmp & TOKEN_NON_NT) || (tmp & TOKEN_TERMINAL)) {
					retval->_firstSpecial = i;
					break;
				}
			}
		}

		return retval;
	} else
		return NULL;
}
Esempio n. 2
0
static void tablePolygonToPolygon(lua_State *L, Polygon &polygon) {
#ifdef DEBUG
	int __startStackDepth = lua_gettop(L);
#endif

	// Ensure that a valid polygon definition is on the stack.
	// It is not necessary to catch the return value, since all errors are reported on luaL_error
	// End script.
	isValidPolygonDefinition(L);

	int vertexCount = luaL_getn(L, -1) / 2;

	// Memory is reserved for Vertecies
	Common::Array<Vertex> vertices;
	vertices.reserve(vertexCount);

	// Create Vertecies
	for (int i = 0; i < vertexCount; i++) {
		// X Value
		lua_rawgeti(L, -1, (i * 2) + 1);
		int X = static_cast<int>(lua_tonumber(L, -1));
		lua_pop(L, 1);

		// Y Value
		lua_rawgeti(L, -1, (i * 2) + 2);
		int Y = static_cast<int>(lua_tonumber(L, -1));
		lua_pop(L, 1);

		// Vertex
		vertices.push_back(Vertex(X, Y));
	}
	assert((int)vertices.size() == vertexCount);

#ifdef DEBUG
	assert(__startStackDepth == lua_gettop(L));
#endif

	// Create polygon
	polygon.init(vertexCount, &vertices[0]);
}
Esempio n. 3
0
bool RenderObjectManager::render() {
	// Den Objekt-Status des Wurzelobjektes aktualisieren. Dadurch werden rekursiv alle Baumelemente aktualisiert.
	// Beim aktualisieren des Objekt-Status werden auch die Update-Rects gefunden, so dass feststeht, was neu gezeichnet
	// werden muss.
	if (!_rootPtr.isValid() || !_rootPtr->updateObjectState())
		return false;

	_frameStarted = false;

	// Die Render-Methode der Wurzel aufrufen. Dadurch wird das rekursive Rendern der Baumelemente angestoßen.

	_currQueue->clear();
	_rootPtr->preRender(_currQueue);

	_uta->clear();

	// Add rectangles of objects which don't exist in this frame any more
	for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it) {
		if (!_currQueue->exists(*it))
			_uta->addRect((*it)._bbox);
	}

	// Add rectangles of objects which are different from the previous frame
	for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it) {
		if (!_prevQueue->exists(*it))
			_uta->addRect((*it)._bbox);
	}

	RectangleList *updateRects = _uta->getRectangles();
	Common::Array<int> updateRectsMinZ;

	updateRectsMinZ.reserve(updateRects->size());

	// Calculate the minimum drawing Z value of each update rectangle
	// Solid bitmaps with a Z order less than the value calculated here would be overdrawn again and
	// so don't need to be drawn in the first place which speeds things up a bit.
	for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
		int minZ = 0;
		for (RenderObjectQueue::iterator it = _currQueue->reverse_begin(); it != _currQueue->end(); --it) {
			if ((*it)._renderObject->isVisible() && (*it)._renderObject->isSolid() &&
				(*it)._renderObject->getBbox().contains(*rectIt)) {
				minZ = (*it)._renderObject->getAbsoluteZ();
				break;
			}
		}
		updateRectsMinZ.push_back(minZ);
	}

	if (_rootPtr->render(updateRects, updateRectsMinZ)) {
		// Copy updated rectangles to the video screen
		Graphics::Surface *backSurface = Kernel::getInstance()->getGfx()->getSurface();
		for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
			const int x = (*rectIt).left;
			const int y = (*rectIt).top;
			const int width = (*rectIt).width();
			const int height = (*rectIt).height();
			g_system->copyRectToScreen(backSurface->getBasePtr(x, y), backSurface->pitch, x, y, width, height);
		}
	}

	delete updateRects;

	SWAP(_currQueue, _prevQueue);

	return true;
}
Esempio n. 4
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
}
Esempio n. 5
0
/*
	Island Sections (Num Entries HQR - 3 / 6 = Total Sections available)
		3 (0) - Objects layout
		4 (1) - Objects data
		5 (2) - Quads (2 triangles)
		6 (3) - Texture UV mapping
		7 (4) - Height Maps
		8 (5) - Intensity
*/
void Island::loadIslandSection(int sectionIdx, int entryIdx) {
	// 7 (4) - Height Maps
	int16 heightmap[65][65];
	Common::SeekableReadStream *stream = _ile->createReadStreamForIndex(entryIdx + 4);
	_sectionsLayout = new byte[256];
	stream->read(heightmap, 65*65);
	delete stream;

	// 6 (3) - Texture UV mapping
	GroundTextureInfo *textureInfo;
	stream = _ile->createReadStreamForIndex(entryIdx + 3);
	textureInfo = new GroundTextureInfo[stream->size() / 12];
	stream->read(textureInfo, 65*65);
	delete stream;

	// 8 (5) - Intensity
	byte intensity[65][65];
	stream = _ile->createReadStreamForIndex(entryIdx + 5);
	stream->read(intensity, 65*65);
	delete stream;

	// 5 (2) - Quads (2 triangles)
	GroundSquare squares[64][64];
	stream = _ile->createReadStreamForIndex(entryIdx + 2);
	stream->read(squares, 64 * 64 * 8);
	delete stream;

	// Parse data
	int16 maxHeight = 0;
	
	Common::Array<float> vertices;
	vertices.reserve(9 * 64 * 64 * 4 * 2);
	
	Common::Array<uint16> faces;
	faces.reserve(6 * 64 * 64);

	// Vertex Count - In order of verts that make tris
	uint16  idx = 0;
	uint16 uvOrder[6] = {0, 1, 2, 2, 0, 1};
	uint16 idxOrder1[6] = {0, 2, 3, 0, 3, 1};
	uint16 idxOrder2[6] = {0, 2, 1, 1, 2, 3};

	// For Every QUAD
	for (int32 x = 0; x < 64; ++x)
	{
		for (int32 y = 0; y < 64; ++y)
		{
			// Pass the pointer from the quad database to this quad (2 triangles passed)
			GroundTriangle *tri = squares[x][y].triangle;
			// Orientation
			uint16 *idxOrder = (tri[0].orientation == 0) ? idxOrder1 : idxOrder2;

			// For both tris in this quad...
			for (int32 t = 0; t < 2; ++t)
			{
				// Data Usage for this Tri
				int mdMax = 0;

				if (tri[t].useColor)
					mdMax++;
				if (tri[t].useTexture)
					mdMax++;

				// For all the data usage in this tri
				for (int32 md = 0; md < mdMax; ++md)
				{
					// For each vertex, offset by triangle num in quad
					for (int32 i = 3 * t; i < (3 + 3 * t); ++i)
					{
						int32 xi = x + idxOrder[i] / 2;
						int32 yi = y + idxOrder[i] % 2;

						// Vertex position
						vertices.push_back(((float)(xi) - 32) / 0x20);
						vertices.push_back(((float)(heightmap[xi][yi])) / 0x4000);
						vertices.push_back(((float)(64 - yi) - 32) / 0x20);

						if (heightmap[xi][yi] > maxHeight)
							maxHeight = heightmap[xi][yi];

						// Vertex color and UV
						if (tri[t].useTexture && (mdMax < 2 || md == 1))
						{
							float intens = intensity[xi][yi] / 16.0f + 0.3;
							
							if (intens > 1.0)
								intens = 1.0;

							vertices.push_back(intens);
							vertices.push_back(intens);
							vertices.push_back(intens);
							vertices.push_back(1.0);
							vertices.push_back((textureInfo[tri[t].textureIndex].uv[uvOrder[i]].u / 65535.0f) * 0.5);
							vertices.push_back(textureInfo[tri[t].textureIndex].uv[uvOrder[i]].v / 65535.0f);

						}
						else if (mdMax < 2 || md == 0)
						{
							byte colorIdx = (tri[t].textureBank * 16) + intensity[xi][yi];
							
							// TODO get palette RGB components for colorIdx
							float r = 0;
							float g = 0;
							float b = 0;

							vertices.push_back(r);
							vertices.push_back(g);
							vertices.push_back(b);
							vertices.push_back(1.0);
							vertices.push_back(0.75f);
							vertices.push_back(0.5f);
						}
					}

					/* Index */
					faces.push_back(idx);
					faces.push_back(idx + 1);
					faces.push_back(idx + 2);
					idx += 3;
				}
			}
		}

	}

	delete [] textureInfo;
}
Esempio n. 6
0
bool T7GFont::load(Common::SeekableReadStream &stream) {
	// Read the mapping of characters to glyphs
	if (stream.read(_mapChar2Glyph, 128) < 128) {
		error("Groovie::T7GFont: Couldn't read the character to glyph map");
		return false;
	}

	// Calculate the number of glyphs
	byte numGlyphs = 0;
	for (int i = 0; i < 128; i++)
		if (_mapChar2Glyph[i] >= numGlyphs)
			numGlyphs = _mapChar2Glyph[i] + 1;

	// Read the glyph offsets
	uint16 *glyphOffsets = new uint16[numGlyphs];
	for (int i = 0; i < numGlyphs; i++)
		glyphOffsets[i] = stream.readUint16LE();

	if (stream.eos()) {
		error("Groovie::T7GFont: Couldn't read the glyph offsets");
		delete[] glyphOffsets;
		return false;
	}

	// Allocate the glyph data
	delete[] _glyphs;
	_glyphs = new Glyph[numGlyphs];

	// Ensure we're ready to read the first glyph. (Most versions don't
	// need it, but the russian one does. This fixes bug #3095031.)
	stream.seek(glyphOffsets[0]);

	// Read the glyphs
	_maxHeight = _maxWidth = 0;
	for (int i = 0; (i < numGlyphs) && !stream.eos(); i++) {
		// Verify we're at the expected stream position
		if (stream.pos() != glyphOffsets[i]) {
			uint16 offset = glyphOffsets[i];
			delete[] glyphOffsets;
			error("Groovie::T7GFont: Glyph %d starts at %d but the current "
				"offset is %d", i, offset, stream.pos());
			return false;
		}

		// Read the glyph information
		Glyph *g = &_glyphs[i];
		g->width = stream.readByte();
		g->julia = stream.readByte();

		// Read the pixels data into a dynamic array (we don't know its length)
		Common::Array<byte> data;
		data.reserve(300);
		byte b = stream.readByte();
		while (!stream.eos() && (b != 0xFF)) {
			data.push_back(b);
			b = stream.readByte();
		}

		// Verify the pixel data size
		assert (data.size() % g->width == 0);
		g->height = data.size() / g->width;

		// Copy the pixel data into the definitive static array
		g->pixels = new byte[data.size()];
		memcpy(g->pixels, data.begin(), data.size());

		// Update the max values
		if (g->width > _maxWidth)
			_maxWidth = g->width;
		if (g->height > _maxHeight)
			_maxHeight = g->height;
	}

	delete[] glyphOffsets;
	return true;
}
Esempio n. 7
0
static uint tableRegionToRegion(lua_State *L, const char *className) {
#ifdef DEBUG
	int __startStackDepth = lua_gettop(L);
#endif

	// You can define a region in Lua in two ways:
	// 1. A table that defines a polygon (polgon = table with numbers, which define
	// two consecutive numbers per vertex)
	// 2. A table containing more polygon definitions
	// Then the first polygon is the contour of the region, and the following are holes
	// defined in the first polygon.

	// It may be passed only one parameter, and this must be a table
	if (lua_gettop(L) != 1 || !lua_istable(L, -1)) {
		luaL_error(L, "First and only parameter has to be of type \"table\".");
		return 0;
	}

	uint regionHandle = 0;
	if (!strcmp(className, REGION_CLASS_NAME)) {
		regionHandle = Region::create(Region::RT_REGION);
	} else if (!strcmp(className, WALKREGION_CLASS_NAME)) {
		regionHandle = WalkRegion::create(Region::RT_WALKREGION);
	} else {
		assert(false);
	}

	assert(regionHandle);

	// If the first element of the parameter is a number, then case 1 is accepted
	// If the first element of the parameter is a table, then case 2 is accepted
	// If the first element of the parameter has a different type, there is an error
	lua_rawgeti(L, -1, 1);
	int firstElementType = lua_type(L, -1);
	lua_pop(L, 1);

	switch (firstElementType) {
	case LUA_TNUMBER: {
		Polygon polygon;
		tablePolygonToPolygon(L, polygon);
		RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon);
	}
	break;

	case LUA_TTABLE: {
		lua_rawgeti(L, -1, 1);
		Polygon polygon;
		tablePolygonToPolygon(L, polygon);
		lua_pop(L, 1);

		int polygonCount = luaL_getn(L, -1);
		if (polygonCount == 1)
			RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon);
		else {
			Common::Array<Polygon> holes;
			holes.reserve(polygonCount - 1);

			for (int i = 2; i <= polygonCount; i++) {
				lua_rawgeti(L, -1, i);
				holes.resize(holes.size() + 1);
				tablePolygonToPolygon(L, holes.back());
				lua_pop(L, 1);
			}
			assert((int)holes.size() == polygonCount - 1);

			RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon, &holes);
		}
	}
	break;

	default:
		luaL_error(L, "Illegal region definition.");
		return 0;
	}

#ifdef DEBUG
	assert(__startStackDepth == lua_gettop(L));
#endif

	return regionHandle;
}