aboutsummaryrefslogtreecommitdiff
path: root/graphics/fonts/ttf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/fonts/ttf.cpp')
-rw-r--r--graphics/fonts/ttf.cpp114
1 files changed, 86 insertions, 28 deletions
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index b9e9610d77..09a00672e3 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -101,17 +101,17 @@ public:
TTFFont();
virtual ~TTFFont();
- bool load(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping);
+ bool load(Common::SeekableReadStream &stream, int size, uint dpi, TTFRenderMode renderMode, const uint32 *mapping);
virtual int getFontHeight() const;
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,21 +126,24 @@ 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;
+ bool cacheGlyph(Glyph &glyph, uint32 chr) const;
+ typedef Common::HashMap<uint32, Glyph> GlyphCache;
+ mutable GlyphCache _glyphs;
+ bool _allowLateCaching;
+ void assureCached(uint32 chr) const;
- FT_UInt _glyphSlots[256];
-
- bool _monochrome;
+ FT_Int32 _loadFlags;
+ FT_Render_Mode _renderMode;
bool _hasKerning;
};
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(), _loadFlags(FT_LOAD_TARGET_NORMAL), _renderMode(FT_RENDER_MODE_NORMAL),
+ _hasKerning(false), _allowLateCaching(false) {
}
TTFFont::~TTFFont() {
@@ -157,7 +160,7 @@ TTFFont::~TTFFont() {
}
}
-bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping) {
+bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, TTFRenderMode renderMode, const uint32 *mapping) {
if (!g_ttf.isInitialized())
return false;
@@ -202,7 +205,22 @@ bool TTFFont::load(Common::SeekableReadStream &stream, int size, uint dpi, bool
return false;
}
- _monochrome = monochrome;
+ switch (renderMode) {
+ case kTTFRenderModeNormal:
+ _loadFlags = FT_LOAD_TARGET_NORMAL;
+ _renderMode = FT_RENDER_MODE_NORMAL;
+ break;
+
+ case kTTFRenderModeLight:
+ _loadFlags = FT_LOAD_TARGET_LIGHT;
+ _renderMode = FT_RENDER_MODE_LIGHT;
+ break;
+
+ case kTTFRenderModeMonochrome:
+ _loadFlags = FT_LOAD_TARGET_MONO;
+ _renderMode = FT_RENDER_MODE_MONO;
+ break;
+ }
FT_Fixed yScale = _face->size->metrics.y_scale;
_ascent = ftCeil26_6(FT_MulFix(_face->ascender, yScale));
@@ -212,19 +230,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 +268,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 +277,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 +347,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,18 +420,20 @@ 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.
- if (FT_Load_Glyph(_face, slot, (_monochrome ? FT_LOAD_TARGET_MONO : FT_LOAD_TARGET_LIGHT)))
+ if (FT_Load_Glyph(_face, slot, _loadFlags))
return false;
- if (FT_Render_Glyph(_face->glyph, (_monochrome ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_LIGHT)))
+ if (FT_Render_Glyph(_face->glyph, _renderMode))
return false;
if (_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
@@ -456,16 +502,28 @@ 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;
}
-Font *loadTTFFont(Common::SeekableReadStream &stream, int size, uint dpi, bool monochrome, const uint32 *mapping) {
+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, TTFRenderMode renderMode, const uint32 *mapping) {
TTFFont *font = new TTFFont();
- if (!font->load(stream, size, dpi, monochrome, mapping)) {
+ if (!font->load(stream, size, dpi, renderMode, mapping)) {
delete font;
return 0;
}