[aseprite] 75/196: Fix FreeType2 font rendering and font height calculation
Tobias Hansen
thansen at moszumanska.debian.org
Wed Apr 20 18:50:03 UTC 2016
This is an automated email from the git hooks/post-receive script.
thansen pushed a commit to branch master
in repository aseprite.
commit 8304b7511d6a0c121435219cbc704d8d181c947b
Author: David Capello <davidcapello at gmail.com>
Date: Tue Mar 15 18:43:36 2016 -0300
Fix FreeType2 font rendering and font height calculation
We need to catch the glyph's bearingY value to render each glyph
correctly.
---
src/app/util/freetype_utils.cpp | 2 +-
src/ft/face.h | 129 +++++++++++++++++++++++++--------------
src/she/common/freetype_font.cpp | 3 +-
src/she/common/generic_surface.h | 7 +--
4 files changed, 89 insertions(+), 52 deletions(-)
diff --git a/src/app/util/freetype_utils.cpp b/src/app/util/freetype_utils.cpp
index ca095a8..9135fb1 100644
--- a/src/app/util/freetype_utils.cpp
+++ b/src/app/util/freetype_utils.cpp
@@ -48,7 +48,7 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
face.forEachGlyph(
text,
- [&bounds, &image, color, antialias](const ft::Face::Glyph& glyph) {
+ [&bounds, &image, color, antialias](const ft::Glyph& glyph) {
int t, yimg = - bounds.y + int(glyph.y);
for (int v=0; v<int(glyph.bitmap->rows); ++v, ++yimg) {
diff --git a/src/ft/face.h b/src/ft/face.h
index 5b1c58b..d5b10a3 100644
--- a/src/ft/face.h
+++ b/src/ft/face.h
@@ -17,16 +17,18 @@
namespace ft {
+ struct Glyph {
+ FT_UInt glyph_index;
+ FT_Glyph ft_glyph;
+ FT_Bitmap* bitmap;
+ double bearingY;
+ double x;
+ double y;
+ };
+
template<typename Cache>
class FaceBase {
public:
- struct Glyph {
- FT_UInt glyph_index;
- FT_Bitmap* bitmap;
- double x;
- double y;
- };
-
FaceBase(FT_Face face) : m_face(face) {
}
@@ -35,6 +37,9 @@ namespace ft {
FT_Done_Face(m_face);
}
+ operator FT_Face() { return m_face; }
+ FT_Face operator->() { return m_face; }
+
bool isValid() const {
return (m_face != nullptr);
}
@@ -53,6 +58,27 @@ namespace ft {
m_cache.invalidate();
}
+ double height() const {
+ FT_Size_Metrics* metrics = &m_face->size->metrics;
+ double em_size = 1.0 * m_face->units_per_EM;
+ double y_scale = metrics->y_ppem / em_size;
+ return int(m_face->height * y_scale) - 1;
+ }
+
+ double ascender() const {
+ FT_Size_Metrics* metrics = &m_face->size->metrics;
+ double em_size = 1.0 * m_face->units_per_EM;
+ double y_scale = metrics->y_ppem / em_size;
+ return int(m_face->ascender * y_scale);
+ }
+
+ double descender() const {
+ FT_Size_Metrics* metrics = &m_face->size->metrics;
+ double em_size = 1.0 * m_face->units_per_EM;
+ double y_scale = metrics->y_ppem / em_size;
+ return int(m_face->descender * y_scale);
+ }
+
protected:
FT_Face m_face;
bool m_antialias;
@@ -65,7 +91,6 @@ namespace ft {
template<typename Cache>
class FaceFT : public FaceBase<Cache> {
public:
- using FaceBase<Cache>::Glyph;
using FaceBase<Cache>::m_face;
using FaceBase<Cache>::m_cache;
@@ -92,21 +117,22 @@ namespace ft {
x += kerning.x / 64.0;
}
- FT_Glyph bitmapGlyph = this->m_cache.loadGlyph(
+ Glyph* glyph = this->m_cache.loadGlyph(
this->m_face, glyph_index, this->m_antialias);
- if (bitmapGlyph) {
- Glyph glyph;
- glyph.glyph_index = glyph_index;
- glyph.bitmap = &FT_BitmapGlyph(bitmapGlyph)->bitmap;
- glyph.x = x + FT_BitmapGlyph(bitmapGlyph)->left;
- glyph.y = y - FT_BitmapGlyph(bitmapGlyph)->top;
+ if (glyph) {
+ glyph->bitmap = &FT_BitmapGlyph(glyph->ft_glyph)->bitmap;
+ glyph->x = x;
+ glyph->y = y
+ + this->height()
+ + this->descender() // descender is negative
+ - glyph->bearingY;
- callback(glyph);
+ callback(*glyph);
- x += bitmapGlyph->advance.x / double(1 << 16);
- y += bitmapGlyph->advance.y / double(1 << 16);
+ x += glyph->ft_glyph->advance.x / double(1 << 16);
+ y += glyph->ft_glyph->advance.y / double(1 << 16);
- this->m_cache.doneGlyph(bitmapGlyph);
+ this->m_cache.doneGlyph(glyph);
}
prev_glyph = glyph_index;
@@ -118,7 +144,7 @@ namespace ft {
forEachGlyph(
str,
- [&bounds](Glyph& glyph) {
+ [&bounds, this](Glyph& glyph) {
bounds |= gfx::Rect(int(glyph.x),
int(glyph.y),
glyph.bitmap->width,
@@ -139,7 +165,7 @@ namespace ft {
return FT_Get_Char_Index(face, charCode);
}
- FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
+ Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
FT_Error err = FT_Load_Glyph(
face, glyphIndex,
FT_LOAD_RENDER |
@@ -148,26 +174,32 @@ namespace ft {
if (err)
return nullptr;
- FT_Glyph glyph;
- err = FT_Get_Glyph(face->glyph, &glyph);
+ FT_Glyph ft_glyph;
+ err = FT_Get_Glyph(face->glyph, &ft_glyph);
if (err)
return nullptr;
- if (glyph->format != FT_GLYPH_FORMAT_BITMAP) {
- err = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
+ if (ft_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
+ err = FT_Glyph_To_Bitmap(&ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
if (!err) {
- FT_Done_Glyph(glyph);
+ FT_Done_Glyph(ft_glyph);
return nullptr;
}
}
- return glyph;
+ m_glyph.ft_glyph = ft_glyph;
+ m_glyph.bearingY = face->glyph->metrics.horiBearingY / 64.0;
+
+ return &m_glyph;
}
- void doneGlyph(FT_Glyph glyph) {
- FT_Done_Glyph(glyph);
+ void doneGlyph(Glyph* glyph) {
+ ASSERT(glyph);
+ FT_Done_Glyph(glyph->ft_glyph);
}
+ private:
+ Glyph m_glyph;
};
class SimpleCache : public NoCache {
@@ -177,36 +209,43 @@ namespace ft {
}
void invalidate() {
- for (auto& it : m_glyphMap)
- FT_Done_Glyph(it.second);
+ for (auto& it : m_glyphMap) {
+ FT_Done_Glyph(it.second->ft_glyph);
+ delete it.second;
+ }
m_glyphMap.clear();
}
- FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
+ Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
auto it = m_glyphMap.find(glyphIndex);
if (it != m_glyphMap.end())
return it->second;
- FT_Glyph glyph = NoCache::loadGlyph(face, glyphIndex, antialias);
- if (glyph) {
- FT_Glyph newGlyph = nullptr;
- FT_Glyph_Copy(glyph, &newGlyph);
- if (newGlyph) {
- m_glyphMap[glyphIndex] = newGlyph;
- FT_Done_Glyph(glyph);
- return newGlyph;
- }
- }
- return glyph;
+ Glyph* glyph = NoCache::loadGlyph(face, glyphIndex, antialias);
+ if (!glyph)
+ return nullptr;
+
+ FT_Glyph new_ft_glyph = nullptr;
+ FT_Glyph_Copy(glyph->ft_glyph, &new_ft_glyph);
+ if (!new_ft_glyph)
+ return nullptr;
+
+ Glyph* newGlyph = new Glyph(*glyph);
+ newGlyph->ft_glyph = new_ft_glyph;
+
+ m_glyphMap[glyphIndex] = newGlyph;
+ FT_Done_Glyph(glyph->ft_glyph);
+
+ return newGlyph;
}
- void doneGlyph(FT_Glyph glyph) {
+ void doneGlyph(Glyph* glyph) {
// Do nothing
}
private:
- std::map<FT_UInt, FT_Glyph> m_glyphMap;
+ std::map<FT_UInt, Glyph*> m_glyphMap;
};
typedef FaceFT<SimpleCache> Face;
diff --git a/src/she/common/freetype_font.cpp b/src/she/common/freetype_font.cpp
index 0ed2662..5b827e5 100644
--- a/src/she/common/freetype_font.cpp
+++ b/src/she/common/freetype_font.cpp
@@ -45,8 +45,7 @@ FontType FreeTypeFont::type()
int FreeTypeFont::height() const
{
- static std::string str = "Tgjp";
- return m_face.calcTextBounds(str).h;
+ return int(m_face.height());
}
int FreeTypeFont::charWidth(int chr) const
diff --git a/src/she/common/generic_surface.h b/src/she/common/generic_surface.h
index 520353a..2434f84 100644
--- a/src/she/common/generic_surface.h
+++ b/src/she/common/generic_surface.h
@@ -140,7 +140,6 @@ public:
bool antialias = ttFont->face().antialias();
int fg_alpha = gfx::geta(fg);
- gfx::Rect bounds = ttFont->face().calcTextBounds(str);
gfx::Rect clipBounds = this->getClipBounds();
she::SurfaceFormatData fd;
@@ -148,9 +147,9 @@ public:
ttFont->face().forEachGlyph(
str,
- [this, x, y, fg, fg_alpha, bg, antialias, &clipBounds, &bounds, &fd](const ft::Face::Glyph& glyph) {
- gfx::Rect origDstBounds(x - bounds.x + int(glyph.x),
- y - bounds.y + int(glyph.y),
+ [this, x, y, fg, fg_alpha, bg, antialias, &clipBounds, &fd](const ft::Glyph& glyph) {
+ gfx::Rect origDstBounds(x + int(glyph.x),
+ y + int(glyph.y),
int(glyph.bitmap->width),
int(glyph.bitmap->rows));
gfx::Rect dstBounds = origDstBounds;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git
More information about the Pkg-games-commits
mailing list