diff options
Diffstat (limited to 'graphics/fonts/ttf.cpp')
-rw-r--r-- | graphics/fonts/ttf.cpp | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp index b9e9610d77..be3cd94efa 100644 --- a/graphics/fonts/ttf.cpp +++ b/graphics/fonts/ttf.cpp @@ -107,11 +107,11 @@ public: virtual int getMaxCharWidth() const; - virtual int getCharWidth(byte chr) const; + virtual int getCharWidth(uint32 chr) const; - virtual int getKerningOffset(byte left, byte right) const; + virtual int getKerningOffset(uint32 left, uint32 right) const; - virtual void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const; + virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const; private: bool _initialized; FT_Face _face; @@ -126,13 +126,14 @@ private: Surface image; int xOffset, yOffset; int advance; + FT_UInt slot; }; - bool cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr); - typedef Common::HashMap<byte, Glyph> GlyphCache; - GlyphCache _glyphs; - - FT_UInt _glyphSlots[256]; + bool cacheGlyph(Glyph &glyph, uint32 chr) const; + typedef Common::HashMap<uint32, Glyph> GlyphCache; + mutable GlyphCache _glyphs; + bool _allowLateCaching; + void assureCached(uint32 chr) const; bool _monochrome; bool _hasKerning; @@ -140,7 +141,7 @@ private: TTFFont::TTFFont() : _initialized(false), _face(), _ttfFile(0), _size(0), _width(0), _height(0), _ascent(0), - _descent(0), _glyphs(), _glyphSlots(), _monochrome(false), _hasKerning(false) { + _descent(0), _glyphs(), _monochrome(false), _hasKerning(false) { } TTFFont::~TTFFont() { @@ -212,19 +213,26 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool _height = _ascent - _descent + 1; if (!mapping) { + // Allow loading of all unicode characters. + _allowLateCaching = true; + // Load all ISO-8859-1 characters. for (uint i = 0; i < 256; ++i) { - if (!cacheGlyph(_glyphs[i], _glyphSlots[i], i)) - _glyphSlots[i] = 0; + if (!cacheGlyph(_glyphs[i], i)) { + _glyphs.erase(i); + } } } else { + // We have a fixed map of characters do not load more later. + _allowLateCaching = false; + for (uint i = 0; i < 256; ++i) { const uint32 unicode = mapping[i] & 0x7FFFFFFF; const bool isRequired = (mapping[i] & 0x80000000) != 0; // Check whether loading an important glyph fails and error out if // that is the case. - if (!cacheGlyph(_glyphs[i], _glyphSlots[i], unicode)) { - _glyphSlots[i] = 0; + if (!cacheGlyph(_glyphs[i], unicode)) { + _glyphs.erase(i); if (isRequired) return false; } @@ -243,7 +251,8 @@ int TTFFont::getMaxCharWidth() const { return _width; } -int TTFFont::getCharWidth(byte chr) const { +int TTFFont::getCharWidth(uint32 chr) const { + assureCached(chr); GlyphCache::const_iterator glyphEntry = _glyphs.find(chr); if (glyphEntry == _glyphs.end()) return 0; @@ -251,12 +260,29 @@ int TTFFont::getCharWidth(byte chr) const { return glyphEntry->_value.advance; } -int TTFFont::getKerningOffset(byte left, byte right) const { +int TTFFont::getKerningOffset(uint32 left, uint32 right) const { if (!_hasKerning) return 0; - FT_UInt leftGlyph = _glyphSlots[left]; - FT_UInt rightGlyph = _glyphSlots[right]; + 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; @@ -304,7 +330,8 @@ void renderGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos, const i } // End of anonymous namespace -void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const { +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; @@ -376,11 +403,13 @@ void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const } } -bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) { - slot = FT_Get_Char_Index(_face, chr); +bool TTFFont::cacheGlyph(Glyph &glyph, uint32 chr) const { + FT_UInt slot = FT_Get_Char_Index(_face, chr); if (!slot) return false; + glyph.slot = slot; + // We use the light target and render mode to improve the looks of the // glyphs. It is most noticable in FreeSansBold.ttf, where otherwise the // 't' glyph looks like it is cut off on the right side. @@ -456,12 +485,24 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) { default: warning("TTFFont::cacheGlyph: Unsupported pixel mode %d", bitmap.pixel_mode); + glyph.image.free(); return false; } return true; } +void TTFFont::assureCached(uint32 chr) const { + if (!chr || !_allowLateCaching || _glyphs.contains(chr)) { + return; + } + + Glyph newGlyph; + if (cacheGlyph(newGlyph, chr)) { + _glyphs[chr] = newGlyph; + } +} + Font *loadTTFFont(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping) { TTFFont *font = new TTFFont(); |