int TTFFont::getKerningOffset(uint32 left, uint32 right) const { if (!_hasKerning) return 0; assureCached(left); assureCached(right); FT_UInt leftGlyph, rightGlyph; GlyphCache::const_iterator glyphEntry; glyphEntry = _glyphs.find(left); if (glyphEntry != _glyphs.end()) { leftGlyph = glyphEntry->_value.slot; } else { return 0; } glyphEntry = _glyphs.find(right); if (glyphEntry != _glyphs.end()) { rightGlyph = glyphEntry->_value.slot; } else { return 0; } if (!leftGlyph || !rightGlyph) return 0; FT_Vector kerningVector; FT_Get_Kerning(_face, leftGlyph, rightGlyph, FT_KERNING_DEFAULT, &kerningVector); return (kerningVector.x / 64); }
int TTFFont::getCharWidth(uint32 chr) const { assureCached(chr); GlyphCache::const_iterator glyphEntry = _glyphs.find(chr); if (glyphEntry == _glyphs.end()) return 0; else return glyphEntry->_value.advance; }
Common::Rect TTFFont::getBoundingBox(uint32 chr) const { assureCached(chr); GlyphCache::const_iterator glyphEntry = _glyphs.find(chr); if (glyphEntry == _glyphs.end()) { return Common::Rect(); } else { const int xOffset = glyphEntry->_value.xOffset; const int yOffset = glyphEntry->_value.yOffset; const Graphics::Surface &image = glyphEntry->_value.image; return Common::Rect(xOffset, yOffset, xOffset + image.w, yOffset + image.h); } }
Common::InSaveFile *DefaultSaveFileManager::openRawFile(const Common::String &filename) { // Assure the savefile name cache is up-to-date. assureCached(getSavePath()); if (getError().getCode() != Common::kNoError) return nullptr; SaveFileCache::const_iterator file = _saveFileCache.find(filename); if (file == _saveFileCache.end()) { return nullptr; } else { // Open the file for loading. Common::SeekableReadStream *sf = file->_value.createReadStream(); return sf; } }
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) { // Assure the savefile name cache is up-to-date. assureCached(getSavePath()); if (getError().getCode() != Common::kNoError) return Common::StringArray(); Common::HashMap<Common::String, bool> locked; for (Common::StringArray::const_iterator i = _lockedFiles.begin(), end = _lockedFiles.end(); i != end; ++i) { locked[*i] = true; } Common::StringArray results; for (SaveFileCache::const_iterator file = _saveFileCache.begin(), end = _saveFileCache.end(); file != end; ++file) { if (!locked.contains(file->_key) && file->_key.matchString(pattern, true)) { results.push_back(file->_key); } } return results; }
bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) { // Assure the savefile name cache is up-to-date. assureCached(getSavePath()); if (getError().getCode() != Common::kNoError) return false; #ifdef USE_LIBCURL // Update file's timestamp Common::HashMap<Common::String, uint32> timestamps = loadTimestamps(); Common::HashMap<Common::String, uint32>::iterator it = timestamps.find(filename); if (it != timestamps.end()) { timestamps.erase(it); saveTimestamps(timestamps); } #endif // Obtain node if exists. SaveFileCache::const_iterator file = _saveFileCache.find(filename); if (file == _saveFileCache.end()) { return false; } else { const Common::FSNode fileNode = file->_value; // Remove from cache, this invalidates the 'file' iterator. _saveFileCache.erase(file); file = _saveFileCache.end(); // FIXME: remove does not exist on all systems. If your port fails to // compile because of this, please let us know (scummvm-devel). // There is a nicely portable workaround, too: Make this method overloadable. if (remove(fileNode.getPath().c_str()) != 0) { #ifndef _WIN32_WCE if (errno == EACCES) setError(Common::kWritePermissionDenied, "Search or write permission denied: "+fileNode.getName()); if (errno == ENOENT) setError(Common::kPathDoesNotExist, "removeSavefile: '"+fileNode.getName()+"' does not exist or path is invalid"); #endif return false; } else { return true; } } }
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename, bool compress) { // Assure the savefile name cache is up-to-date. const Common::String savePathName = getSavePath(); assureCached(savePathName); if (getError().getCode() != Common::kNoError) return nullptr; for (Common::StringArray::const_iterator i = _lockedFiles.begin(), end = _lockedFiles.end(); i != end; ++i) { if (filename == *i) { return nullptr; //file is locked, no saving available } } #ifdef USE_LIBCURL // Update file's timestamp Common::HashMap<Common::String, uint32> timestamps = loadTimestamps(); timestamps[filename] = INVALID_TIMESTAMP; saveTimestamps(timestamps); #endif // Obtain node. SaveFileCache::const_iterator file = _saveFileCache.find(filename); Common::FSNode fileNode; // If the file did not exist before, we add it to the cache. if (file == _saveFileCache.end()) { const Common::FSNode savePath(savePathName); fileNode = savePath.getChild(filename); } else { fileNode = file->_value; } // Open the file for saving. Common::WriteStream *const sf = fileNode.createWriteStream(); Common::OutSaveFile *const result = new Common::OutSaveFile(compress ? Common::wrapCompressedWriteStream(sf) : sf); // Add file to cache now that it exists. _saveFileCache[filename] = Common::FSNode(fileNode.getPath()); return result; }
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) { // Assure the savefile name cache is up-to-date. assureCached(getSavePath()); if (getError().getCode() != Common::kNoError) return nullptr; for (Common::StringArray::const_iterator i = _lockedFiles.begin(), end = _lockedFiles.end(); i != end; ++i) { if (filename == *i) { return nullptr; //file is locked, no loading available } } SaveFileCache::const_iterator file = _saveFileCache.find(filename); if (file == _saveFileCache.end()) { return nullptr; } else { // Open the file for loading. Common::SeekableReadStream *sf = file->_value.createReadStream(); return Common::wrapCompressedReadStream(sf); } }
void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const { assureCached(chr); GlyphCache::const_iterator glyphEntry = _glyphs.find(chr); if (glyphEntry == _glyphs.end()) return; const Glyph &glyph = glyphEntry->_value; x += glyph.xOffset; y += glyph.yOffset; if (x > dst->w) return; if (y > dst->h) return; int w = glyph.image.w; int h = glyph.image.h; const uint8 *srcPos = (const uint8 *)glyph.image.getPixels(); // Make sure we are not drawing outside the screen bounds if (x < 0) { srcPos -= x; w += x; x = 0; } if (x + w > dst->w) w = dst->w - x; if (w <= 0) return; if (y < 0) { srcPos -= y * glyph.image.pitch; h += y; y = 0; } if (y + h > dst->h) h = dst->h - y; if (h <= 0) return; uint8 *dstPos = (uint8 *)dst->getBasePtr(x, y); if (dst->format.bytesPerPixel == 1) { for (int cy = 0; cy < h; ++cy) { uint8 *rDst = dstPos; const uint8 *src = srcPos; for (int cx = 0; cx < w; ++cx) { // We assume a 1Bpp mode is a color indexed mode, thus we can // not take advantage of anti-aliasing here. if (*src >= 0x80) *rDst = color; ++rDst; ++src; } dstPos += dst->pitch; srcPos += glyph.image.pitch; } } else if (dst->format.bytesPerPixel == 2) { renderGlyph<uint16>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format); } else if (dst->format.bytesPerPixel == 4) { renderGlyph<uint32>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format); } }