Move ft::ForEachGlyph to ft/algorithm.h

This commit is contained in:
David Capello 2017-02-20 09:34:07 -03:00
parent 84c4d1af93
commit 44feaf6676
8 changed files with 104 additions and 80 deletions

View File

@ -16,6 +16,7 @@
#include "doc/color.h"
#include "doc/image.h"
#include "doc/primitives.h"
#include "ft/algorithm.h"
#include "ft/face.h"
#include "ft/lib.h"

View File

@ -1,4 +1,4 @@
Copyright (c) 2016 David Capello
Copyright (c) 2016-2017 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@ -1,4 +1,4 @@
# Aseprite FreeType Wrapper
*Copyright (C) 2016 David Capello*
*Copyright (C) 2016-2017 David Capello*
> Distributed under [MIT license](LICENSE.txt)

92
src/ft/algorithm.h Normal file
View File

@ -0,0 +1,92 @@
// Aseprite FreeType Wrapper
// Copyright (c) 2016-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef FT_ALGORITHM_H_INCLUDED
#define FT_ALGORITHM_H_INCLUDED
#pragma once
#include "base/string.h"
#include "ft/freetype_headers.h"
#include "gfx/rect.h"
namespace ft {
template<typename FaceFT>
class ForEachGlyph {
public:
ForEachGlyph(FaceFT& face)
: m_face(face)
, m_useKerning(FT_HAS_KERNING((FT_Face)face) ? true: false)
, m_prevGlyph(0)
, m_x(0.0), m_y(0.0)
{
}
template<typename ProcessGlyph>
void processChar(const int chr, ProcessGlyph processGlyph) {
FT_UInt glyphIndex = m_face.cache().getGlyphIndex(m_face, chr);
double initialX = m_x;
if (m_useKerning && m_prevGlyph && glyphIndex) {
FT_Vector kerning;
FT_Get_Kerning(m_face, m_prevGlyph, glyphIndex,
FT_KERNING_DEFAULT, &kerning);
m_x += kerning.x / 64.0;
}
typename FaceFT::Glyph* glyph = m_face.cache().loadGlyph(
m_face, glyphIndex, m_face.antialias());
if (glyph) {
glyph->bitmap = &FT_BitmapGlyph(glyph->ft_glyph)->bitmap;
glyph->x = m_x + glyph->bearingX;
glyph->y = m_y
+ m_face.height()
+ m_face.descender() // descender is negative
- glyph->bearingY;
m_x += glyph->ft_glyph->advance.x / double(1 << 16);
m_y += glyph->ft_glyph->advance.y / double(1 << 16);
glyph->startX = initialX;
glyph->endX = m_x;
processGlyph(*glyph);
m_face.cache().doneGlyph(glyph);
}
m_prevGlyph = glyphIndex;
}
private:
FaceFT& m_face;
bool m_useKerning;
FT_UInt m_prevGlyph;
double m_x, m_y;
};
template<typename FaceFT>
gfx::Rect calc_text_bounds(FaceFT& face, const std::string& str) {
gfx::Rect bounds(0, 0, 0, 0);
auto it = base::utf8_const_iterator(str.begin());
auto end = base::utf8_const_iterator(str.end());
ForEachGlyph<FaceFT> feg(face);
for (; it != end; ++it) {
feg.processChar(
*it,
[&bounds](typename FaceFT::Glyph& glyph) {
bounds |= gfx::Rect(int(glyph.x),
int(glyph.y),
glyph.bitmap->width,
glyph.bitmap->rows);
});
}
return bounds;
}
} // namespace ft
#endif

View File

@ -10,9 +10,7 @@
#include "base/debug.h"
#include "base/disable_copying.h"
#include "base/string.h"
#include "ft/freetype_headers.h"
#include "gfx/rect.h"
#include <map>
@ -33,6 +31,8 @@ namespace ft {
template<typename Cache>
class FaceFT {
public:
typedef ft::Glyph Glyph;
FaceFT(FT_Face face) : m_face(face) {
}
@ -94,79 +94,6 @@ namespace ft {
DISABLE_COPYING(FaceFT);
};
template<typename FaceFT>
class ForEachGlyph {
public:
ForEachGlyph(FaceFT& face)
: m_face(face)
, m_useKerning(FT_HAS_KERNING((FT_Face)face) ? true: false)
, m_prevGlyph(0)
, m_x(0.0), m_y(0.0)
{
}
template<typename ProcessGlyph>
void processChar(const int chr, ProcessGlyph processGlyph) {
FT_UInt glyphIndex = m_face.cache().getGlyphIndex(m_face, chr);
double initialX = m_x;
if (m_useKerning && m_prevGlyph && glyphIndex) {
FT_Vector kerning;
FT_Get_Kerning(m_face, m_prevGlyph, glyphIndex,
FT_KERNING_DEFAULT, &kerning);
m_x += kerning.x / 64.0;
}
Glyph* glyph = m_face.cache().loadGlyph(
m_face, glyphIndex, m_face.antialias());
if (glyph) {
glyph->bitmap = &FT_BitmapGlyph(glyph->ft_glyph)->bitmap;
glyph->x = m_x + glyph->bearingX;
glyph->y = m_y
+ m_face.height()
+ m_face.descender() // descender is negative
- glyph->bearingY;
m_x += glyph->ft_glyph->advance.x / double(1 << 16);
m_y += glyph->ft_glyph->advance.y / double(1 << 16);
glyph->startX = initialX;
glyph->endX = m_x;
processGlyph(*glyph);
m_face.cache().doneGlyph(glyph);
}
m_prevGlyph = glyphIndex;
}
private:
FaceFT& m_face;
bool m_useKerning;
FT_UInt m_prevGlyph;
double m_x, m_y;
};
template<typename FaceFT>
gfx::Rect calc_text_bounds(FaceFT& face, const std::string& str) {
gfx::Rect bounds(0, 0, 0, 0);
auto it = base::utf8_const_iterator(str.begin());
auto end = base::utf8_const_iterator(str.end());
ForEachGlyph<FaceFT> feg(face);
for (; it != end; ++it) {
feg.processChar(
*it,
[&bounds](Glyph& glyph) {
bounds |= gfx::Rect(int(glyph.x),
int(glyph.y),
glyph.bitmap->width,
glyph.bitmap->rows);
});
}
return bounds;
}
class NoCache {
public:
void invalidate() {

View File

@ -11,6 +11,7 @@
#include "she/common/freetype_font.h"
#include "base/string.h"
#include "ft/algorithm.h"
#include "gfx/point.h"
#include "gfx/size.h"

View File

@ -17,6 +17,8 @@ namespace she {
class FreeTypeFont : public Font {
public:
typedef ft::Face Face;
FreeTypeFont(const char* filename, int height);
~FreeTypeFont();
@ -29,11 +31,11 @@ namespace she {
void setSize(int size) override;
void setAntialias(bool antialias) override;
ft::Face& face() { return m_face; }
Face& face() { return m_face; }
private:
mutable ft::Lib m_ft;
mutable ft::Face m_face;
mutable Face m_face;
};
FreeTypeFont* loadFreeTypeFont(const char* filename, int height);

View File

@ -10,6 +10,7 @@
#include "she/draw_text.h"
#include "ft/algorithm.h"
#include "gfx/clip.h"
#include "she/common/freetype_font.h"
#include "she/common/generic_surface.h"
@ -76,7 +77,7 @@ gfx::Rect draw_text(Surface* surface, Font* font,
surface->getFormat(&fd);
}
ft::ForEachGlyph<ft::Face> feg(ttFont->face());
ft::ForEachGlyph<FreeTypeFont::Face> feg(ttFont->face());
while (it != end) {
int chr = *it;
if (delegate)