[aseprite] 71/196: Simplify ft::Face API
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 2fd94ed884250a837a846d5323f475dabbc01217
Author: David Capello <davidcapello at gmail.com>
Date: Tue Mar 15 15:15:37 2016 -0300
Simplify ft::Face API
Changes:
* Added ft::FaceBase to create a future Face impl with HarfBuzz as text
shaping engine
* Define ft::FaceBase::Glyph as the parameter given to the forEachGlyph
parameter
* forEachGlyph and calcTextBounds
* Remove operator FT_Face (we can use FaceBase::isValid() to know if the
face isn't null)
---
src/app/util/freetype_utils.cpp | 20 ++++-----
src/ft/face.h | 93 +++++++++++++++++++++++++---------------
src/she/common/freetype_font.cpp | 10 +++--
src/she/common/generic_surface.h | 56 +++++++++++++++---------
4 files changed, 109 insertions(+), 70 deletions(-)
diff --git a/src/app/util/freetype_utils.cpp b/src/app/util/freetype_utils.cpp
index 69c4b66..ca095a8 100644
--- a/src/app/util/freetype_utils.cpp
+++ b/src/app/util/freetype_utils.cpp
@@ -11,7 +11,6 @@
#include "app/util/freetype_utils.h"
-#include "base/string.h"
#include "base/unique_ptr.h"
#include "doc/blend_funcs.h"
#include "doc/blend_internals.h"
@@ -34,14 +33,13 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
ft::Lib ft;
ft::Face face(ft.open(fontfile));
- if (face) {
+ if (face.isValid()) {
// Set font size
face.setSize(fontsize);
face.setAntialias(antialias);
// Calculate text size
- base::utf8_const_iterator begin(text.begin()), end(text.end());
- gfx::Rect bounds = face.calcTextBounds(begin, end);
+ gfx::Rect bounds = face.calcTextBounds(text);
// Render the image and copy it to the clipboard
if (!bounds.isEmpty()) {
@@ -49,16 +47,16 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
doc::clear_image(image, 0);
face.forEachGlyph(
- begin, end,
- [&bounds, &image, color, antialias](FT_BitmapGlyph glyph, int x) {
- int t, yimg = - bounds.y - glyph->top;
+ text,
+ [&bounds, &image, color, antialias](const ft::Face::Glyph& glyph) {
+ int t, yimg = - bounds.y + int(glyph.y);
- for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++yimg) {
- const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
- int ximg = x - bounds.x + glyph->left;
+ for (int v=0; v<int(glyph.bitmap->rows); ++v, ++yimg) {
+ const uint8_t* p = glyph.bitmap->buffer + v*glyph.bitmap->pitch;
+ int ximg = - bounds.x + int(glyph.x);
int bit = 0;
- for (int u=0; u<(int)glyph->bitmap.width; ++u, ++ximg) {
+ for (int u=0; u<int(glyph.bitmap->width); ++u, ++ximg) {
int alpha;
if (antialias) {
diff --git a/src/ft/face.h b/src/ft/face.h
index 0abfed4..437e85b 100644
--- a/src/ft/face.h
+++ b/src/ft/face.h
@@ -9,6 +9,7 @@
#pragma once
#include "base/disable_copying.h"
+#include "base/string.h"
#include "ft/freetype_headers.h"
#include "gfx/rect.h"
@@ -17,19 +18,23 @@
namespace ft {
template<typename Cache>
- class FaceT {
+ class FaceBase {
public:
- FaceT(FT_Face face = nullptr) : m_face(face) {
+ struct Glyph {
+ FT_UInt glyph_index;
+ FT_Bitmap* bitmap;
+ double x;
+ double y;
+ };
+
+ FaceBase(FT_Face face) : m_face(face) {
}
- ~FaceT() {
+ ~FaceBase() {
if (m_face)
FT_Done_Face(m_face);
}
- operator FT_Face() { return m_face; }
- FT_Face operator->() { return m_face; }
-
bool isValid() const {
return (m_face != nullptr);
}
@@ -48,56 +53,74 @@ namespace ft {
m_cache.invalidate();
}
- template<typename Iterator,
- typename Callback>
- void forEachGlyph(Iterator first, Iterator end, Callback callback) {
- bool use_kerning = (FT_HAS_KERNING(m_face) ? true: false);
+ protected:
+ FT_Face m_face;
+ bool m_antialias;
+ Cache m_cache;
+
+ private:
+ DISABLE_COPYING(FaceBase);
+ };
+
+ template<typename Cache>
+ class FaceFT : public FaceBase<Cache> {
+ public:
+ FaceFT(FT_Face face)
+ : FaceBase<Cache>(face) {
+ }
+ template<typename Callback>
+ void forEachGlyph(const std::string& str, Callback callback) {
+ bool use_kerning = (FT_HAS_KERNING(m_face) ? true: false);
FT_UInt prev_glyph = 0;
- int x = 0;
- for (; first != end; ++first) {
- FT_UInt glyph_index = m_cache.getGlyphIndex(m_face, *first);
+ double x = 0, y = 0;
+
+ auto it = base::utf8_const_iterator(str.begin());
+ auto end = base::utf8_const_iterator(str.end());
+ for (; it != end; ++it) {
+ FT_UInt glyph_index = m_cache.getGlyphIndex(m_face, *it);
if (use_kerning && prev_glyph && glyph_index) {
FT_Vector kerning;
FT_Get_Kerning(m_face, prev_glyph, glyph_index,
FT_KERNING_DEFAULT, &kerning);
- x += kerning.x >> 6;
+ x += kerning.x / 64.0;
}
- FT_Glyph glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
- if (glyph) {
- callback((FT_BitmapGlyph)glyph, x);
- x += glyph->advance.x >> 16;
- m_cache.doneGlyph(glyph);
+ FT_Glyph bitmapGlyph = m_cache.loadGlyph(m_face, glyph_index, 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;
+
+ callback(glyph);
+
+ x += bitmapGlyph->advance.x / double(1 << 16);
+ y += bitmapGlyph->advance.y / double(1 << 16);
+
+ m_cache.doneGlyph(bitmapGlyph);
}
prev_glyph = glyph_index;
}
}
- template<typename Iterator>
- gfx::Rect calcTextBounds(Iterator first, Iterator end) {
+ gfx::Rect calcTextBounds(const std::string& str) {
gfx::Rect bounds(0, 0, 0, 0);
forEachGlyph(
- first, end,
- [&bounds](FT_BitmapGlyph glyph, int x) {
- bounds |= gfx::Rect(x + glyph->left,
- -glyph->top,
- glyph->bitmap.width,
- glyph->bitmap.rows);
+ str,
+ [&bounds](Glyph& glyph) {
+ bounds |= gfx::Rect(int(glyph.x),
+ int(glyph.y),
+ glyph.bitmap->width,
+ glyph.bitmap->rows);
});
return bounds;
}
-
- private:
- FT_Face m_face;
- bool m_antialias;
- Cache m_cache;
-
- DISABLE_COPYING(FaceT);
};
class NoCache {
@@ -180,7 +203,7 @@ namespace ft {
std::map<FT_UInt, FT_Glyph> m_glyphMap;
};
- typedef FaceT<SimpleCache> Face;
+ typedef FaceFT<SimpleCache> Face;
} // namespace ft
diff --git a/src/she/common/freetype_font.cpp b/src/she/common/freetype_font.cpp
index ca9d3c5..0ed2662 100644
--- a/src/she/common/freetype_font.cpp
+++ b/src/she/common/freetype_font.cpp
@@ -10,6 +10,7 @@
#include "she/common/freetype_font.h"
+#include "base/string.h"
#include "gfx/point.h"
#include "gfx/size.h"
@@ -45,17 +46,20 @@ FontType FreeTypeFont::type()
int FreeTypeFont::height() const
{
static std::string str = "Tgjp";
- return m_face.calcTextBounds(str.begin(), str.end()).h;
+ return m_face.calcTextBounds(str).h;
}
int FreeTypeFont::charWidth(int chr) const
{
- return m_face.calcTextBounds(&chr, (&chr)+1).w;
+ // TODO avoid creating a temporary string
+ std::wstring tmp;
+ tmp.push_back(chr);
+ return m_face.calcTextBounds(base::to_utf8(tmp)).w;
}
int FreeTypeFont::textLength(const std::string& str) const
{
- return m_face.calcTextBounds(str.begin(), str.end()).w;
+ return m_face.calcTextBounds(str).w;
}
bool FreeTypeFont::isScalable() const
diff --git a/src/she/common/generic_surface.h b/src/she/common/generic_surface.h
index 69c5a22..051e7a6 100644
--- a/src/she/common/generic_surface.h
+++ b/src/she/common/generic_surface.h
@@ -140,34 +140,52 @@ public:
bool antialias = ttFont->face().antialias();
int fg_alpha = gfx::geta(fg);
- gfx::Rect bounds =
- ttFont->face().calcTextBounds(str.begin(), str.end());
+ gfx::Rect bounds = ttFont->face().calcTextBounds(str);
+ gfx::Rect clipBounds = static_cast<Base*>(this)->getClipBounds();
she::SurfaceFormatData fd;
static_cast<Base*>(this)->getFormat(&fd);
- gfx::Rect clip = static_cast<Base*>(this)->getClipBounds();
-
ttFont->face().forEachGlyph(
- str.begin(), str.end(),
- [this, x, y, fg, fg_alpha, bg, antialias, &clip, &bounds, &fd](FT_BitmapGlyph glyph, int local_x) {
- int dst_y = y - bounds.y - glyph->top;
+ 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),
+ int(glyph.bitmap->width),
+ int(glyph.bitmap->rows));
+ gfx::Rect dstBounds = origDstBounds;
+ dstBounds &= clipBounds;
+ if (dstBounds.isEmpty())
+ return;
+
+ int clippedRows = dstBounds.y - origDstBounds.y;
+ int dst_y = dstBounds.y;
int t;
-
- for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++dst_y) {
- const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
+ for (int v=0; v<dstBounds.h; ++v, ++dst_y) {
int bit = 0;
- int dst_x = x + local_x - bounds.x + glyph->left;
-
- if (!clip.contains(gfx::Point(dst_x, dst_y)))
- break;
-
+ const uint8_t* p = glyph.bitmap->buffer
+ + (v+clippedRows)*glyph.bitmap->pitch;
+ int dst_x = dstBounds.x;
uint32_t* dst_address =
(uint32_t*)static_cast<Base*>(this)->getData(dst_x, dst_y);
- for (int u=0; u<(int)glyph->bitmap.width; ++u) {
- int alpha;
+ // Skip first clipped pixels
+ for (int u=0; u<dstBounds.x-origDstBounds.x; ++u) {
+ if (antialias) {
+ ++p;
+ }
+ else {
+ if (bit == 8) {
+ bit = 0;
+ ++p;
+ }
+ }
+ }
+
+ for (int u=0; u<dstBounds.w; ++u, ++dst_x) {
+ ASSERT(clipBounds.contains(gfx::Point(dst_x, dst_y)));
+ int alpha;
if (antialias) {
alpha = *(p++);
}
@@ -202,10 +220,6 @@ public:
((gfx::getb(output) << fd.blueShift ) & fd.blueMask ) |
((gfx::geta(output) << fd.alphaShift) & fd.alphaMask);
- ++dst_x;
- if (dst_x >= clip.x2())
- break;
-
++dst_address;
}
}
--
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