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; }
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]); }
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; }
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 }
/* 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; }
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; }
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; }