Browse Source

Text: simplified font layouters, removed remaining public API.

Now the font classes are prepared to be plugins.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
e222fc5eb8
  1. 46
      src/Text/FreeTypeFont.cpp
  2. 5
      src/Text/FreeTypeFont.h
  3. 28
      src/Text/HarfBuzzFont.cpp
  4. 5
      src/Text/HarfBuzzFont.h

46
src/Text/FreeTypeFont.cpp

@ -41,14 +41,14 @@ namespace {
class FreeTypeLayouter: public AbstractLayouter { class FreeTypeLayouter: public AbstractLayouter {
public: public:
explicit FreeTypeLayouter(FreeTypeFont& font, const GlyphCache* const cache, const Float size, const std::string& text); explicit FreeTypeLayouter(FT_Face ftFont, const GlyphCache* const cache, const Float fontSize, const Float textSize, const std::string& text);
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) override; std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) override;
private: private:
FreeTypeFont& font; FT_Face font;
const GlyphCache* const cache; const GlyphCache* const cache;
const Float size; const Float fontSize, textSize;
std::vector<FT_UInt> glyphs; std::vector<FT_UInt> glyphs;
}; };
@ -63,13 +63,13 @@ FreeTypeFontRenderer::~FreeTypeFontRenderer() {
} }
FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const std::string& fontFile, Float size): AbstractFont(size) { FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const std::string& fontFile, Float size): AbstractFont(size) {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Face(renderer.library(), fontFile.c_str(), 0, &_ftFont) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Face(renderer.library(), fontFile.c_str(), 0, &ftFont) == 0);
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(_ftFont, 0, size*64, 100, 100) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(ftFont, 0, size*64, 100, 100) == 0);
} }
FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size): AbstractFont(size) { FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size): AbstractFont(size) {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Memory_Face(renderer.library(), data, dataSize, 0, &_ftFont) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Memory_Face(renderer.library(), data, dataSize, 0, &ftFont) == 0);
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(_ftFont, 0, size*64, 100, 100) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(ftFont, 0, size*64, 100, 100) == 0);
} }
void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string& characters) { void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string& characters) {
@ -82,7 +82,7 @@ void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string&
for(std::size_t i = 0; i != characters.size(); ) { for(std::size_t i = 0; i != characters.size(); ) {
UnsignedInt codepoint; UnsignedInt codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(characters, i); std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(characters, i);
charIndices.push_back(FT_Get_Char_Index(_ftFont, codepoint)); charIndices.push_back(FT_Get_Char_Index(ftFont, codepoint));
} }
/* Remove duplicates (e.g. uppercase and lowercase mapped to same glyph) */ /* Remove duplicates (e.g. uppercase and lowercase mapped to same glyph) */
@ -93,8 +93,8 @@ void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string&
std::vector<Vector2i> charSizes; std::vector<Vector2i> charSizes;
charSizes.reserve(charIndices.size()); charSizes.reserve(charIndices.size());
for(FT_UInt c: charIndices) { for(FT_UInt c: charIndices) {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(_ftFont, c, FT_LOAD_DEFAULT) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(ftFont, c, FT_LOAD_DEFAULT) == 0);
charSizes.push_back(Vector2i(_ftFont->glyph->metrics.width, _ftFont->glyph->metrics.height)/64); charSizes.push_back(Vector2i(ftFont->glyph->metrics.width, ftFont->glyph->metrics.height)/64);
} }
/* Create texture atlas */ /* Create texture atlas */
@ -106,8 +106,8 @@ void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string&
for(std::size_t i = 0; i != charPositions.size(); ++i) { for(std::size_t i = 0; i != charPositions.size(); ++i) {
/* Load and render glyph */ /* Load and render glyph */
/** @todo B&W only if radius != 0 */ /** @todo B&W only if radius != 0 */
FT_GlyphSlot glyph = _ftFont->glyph; FT_GlyphSlot glyph = ftFont->glyph;
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(_ftFont, charIndices[i], FT_LOAD_DEFAULT) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(ftFont, charIndices[i], FT_LOAD_DEFAULT) == 0);
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL) == 0);
/* Copy rendered bitmap to texture image */ /* Copy rendered bitmap to texture image */
@ -129,22 +129,22 @@ void FreeTypeFont::createGlyphCache(GlyphCache* const cache, const std::string&
} }
FreeTypeFont::~FreeTypeFont() { FreeTypeFont::~FreeTypeFont() {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Done_Face(_ftFont) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Done_Face(ftFont) == 0);
} }
AbstractLayouter* FreeTypeFont::layout(const GlyphCache* const cache, const Float size, const std::string& text) { AbstractLayouter* FreeTypeFont::layout(const GlyphCache* const cache, const Float size, const std::string& text) {
return new FreeTypeLayouter(*this, cache, size, text); return new FreeTypeLayouter(ftFont, cache, this->size(), size, text);
} }
namespace { namespace {
FreeTypeLayouter::FreeTypeLayouter(FreeTypeFont& font, const GlyphCache* const cache, const Float size, const std::string& text): font(font), cache(cache), size(size) { FreeTypeLayouter::FreeTypeLayouter(FT_Face font, const GlyphCache* const cache, const Float fontSize, const Float textSize, const std::string& text): font(font), cache(cache), fontSize(fontSize), textSize(textSize) {
/* Get glyph codes from characters */ /* Get glyph codes from characters */
glyphs.reserve(text.size()); glyphs.reserve(text.size());
for(std::size_t i = 0; i != text.size(); ) { for(std::size_t i = 0; i != text.size(); ) {
UnsignedInt codepoint; UnsignedInt codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i); std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i);
glyphs.push_back(FT_Get_Char_Index(font.font(), codepoint)); glyphs.push_back(FT_Get_Char_Index(font, codepoint));
} }
_glyphCount = glyphs.size(); _glyphCount = glyphs.size();
} }
@ -155,22 +155,22 @@ std::tuple<Rectangle, Rectangle, Vector2> FreeTypeLayouter::renderGlyph(const Ve
Rectanglei rectangle; Rectanglei rectangle;
std::tie(position, rectangle) = (*cache)[glyphs[i]]; std::tie(position, rectangle) = (*cache)[glyphs[i]];
Rectangle texturePosition = Rectangle::fromSize(Vector2(position)/font.size(), Rectangle texturePosition = Rectangle::fromSize(Vector2(position)/fontSize,
Vector2(rectangle.size())/font.size()); Vector2(rectangle.size())/fontSize);
Rectangle textureCoordinates(Vector2(rectangle.bottomLeft())/cache->textureSize(), Rectangle textureCoordinates(Vector2(rectangle.bottomLeft())/cache->textureSize(),
Vector2(rectangle.topRight())/cache->textureSize()); Vector2(rectangle.topRight())/cache->textureSize());
/* Load glyph */ /* Load glyph */
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(font.font(), glyphs[i], FT_LOAD_DEFAULT) == 0); CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(font, glyphs[i], FT_LOAD_DEFAULT) == 0);
const FT_GlyphSlot slot = font.font()->glyph; const FT_GlyphSlot slot = font->glyph;
Vector2 offset = Vector2(0, 0); /** @todo really? */ Vector2 offset = Vector2(0, 0); /** @todo really? */
Vector2 advance = Vector2(slot->advance.x, slot->advance.y)/(64*font.size()); Vector2 advance = Vector2(slot->advance.x, slot->advance.y)/(64*fontSize);
/* Absolute quad position, composed from cursor position, glyph offset /* Absolute quad position, composed from cursor position, glyph offset
and texture position, denormalized to requested text size */ and texture position, denormalized to requested text size */
Rectangle quadPosition = Rectangle::fromSize( Rectangle quadPosition = Rectangle::fromSize(
(cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*size, (cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*textSize,
texturePosition.size()*size); texturePosition.size()*textSize);
return std::make_tuple(quadPosition, textureCoordinates, advance); return std::make_tuple(quadPosition, textureCoordinates, advance);
} }

5
src/Text/FreeTypeFont.h

@ -102,9 +102,6 @@ class MAGNUM_TEXT_EXPORT FreeTypeFont: public AbstractFont {
~FreeTypeFont(); ~FreeTypeFont();
/** @brief FreeType font handle */
inline FT_Face font() { return _ftFont; }
void createGlyphCache(GlyphCache* const cache, const std::string& characters) override; void createGlyphCache(GlyphCache* const cache, const std::string& characters) override;
AbstractLayouter* layout(const GlyphCache* const cache, const Float size, const std::string& text) override; AbstractLayouter* layout(const GlyphCache* const cache, const Float size, const std::string& text) override;
@ -113,7 +110,7 @@ class MAGNUM_TEXT_EXPORT FreeTypeFont: public AbstractFont {
#else #else
protected: protected:
#endif #endif
FT_Face _ftFont; FT_Face ftFont;
}; };
}} }}

28
src/Text/HarfBuzzFont.cpp

@ -34,18 +34,18 @@ namespace {
class HarfBuzzLayouter: public AbstractLayouter { class HarfBuzzLayouter: public AbstractLayouter {
public: public:
explicit HarfBuzzLayouter(HarfBuzzFont& font, const GlyphCache* const cache, const Float size, const std::string& text); explicit HarfBuzzLayouter(hb_font_t* const font, const GlyphCache* const cache, const Float fontSize, const Float textSize, const std::string& text);
~HarfBuzzLayouter(); ~HarfBuzzLayouter();
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) override; std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) override;
private: private:
const HarfBuzzFont& font; const hb_font_t* const font;
const GlyphCache* const cache; const GlyphCache* const cache;
const Float fontSize, textSize;
hb_buffer_t* buffer; hb_buffer_t* buffer;
hb_glyph_info_t* glyphInfo; hb_glyph_info_t* glyphInfo;
hb_glyph_position_t* glyphPositions; hb_glyph_position_t* glyphPositions;
const Float size;
}; };
} }
@ -60,20 +60,20 @@ HarfBuzzFont::HarfBuzzFont(FreeTypeFontRenderer& renderer, const unsigned char*
void HarfBuzzFont::finishConstruction() { void HarfBuzzFont::finishConstruction() {
/* Create Harfbuzz font */ /* Create Harfbuzz font */
_hbFont = hb_ft_font_create(_ftFont, nullptr); hbFont = hb_ft_font_create(ftFont, nullptr);
} }
HarfBuzzFont::~HarfBuzzFont() { HarfBuzzFont::~HarfBuzzFont() {
hb_font_destroy(_hbFont); hb_font_destroy(hbFont);
} }
AbstractLayouter* HarfBuzzFont::layout(const GlyphCache* const cache, const Float size, const std::string& text) { AbstractLayouter* HarfBuzzFont::layout(const GlyphCache* const cache, const Float size, const std::string& text) {
return new HarfBuzzLayouter(*this, cache, size, text); return new HarfBuzzLayouter(hbFont, cache, this->size(), size, text);
} }
namespace { namespace {
HarfBuzzLayouter::HarfBuzzLayouter(HarfBuzzFont& font, const GlyphCache* const cache, const Float size, const std::string& text): font(font), cache(cache), size(size) { HarfBuzzLayouter::HarfBuzzLayouter(hb_font_t* const font, const GlyphCache* const cache, const Float fontSize, const Float textSize, const std::string& text): font(font), cache(cache), fontSize(fontSize), textSize(textSize) {
/* Prepare HarfBuzz buffer */ /* Prepare HarfBuzz buffer */
buffer = hb_buffer_create(); buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
@ -82,7 +82,7 @@ HarfBuzzLayouter::HarfBuzzLayouter(HarfBuzzFont& font, const GlyphCache* const c
/* Layout the text */ /* Layout the text */
hb_buffer_add_utf8(buffer, text.c_str(), -1, 0, -1); hb_buffer_add_utf8(buffer, text.c_str(), -1, 0, -1);
hb_shape(font.font(), buffer, nullptr, 0); hb_shape(font, buffer, nullptr, 0);
glyphInfo = hb_buffer_get_glyph_infos(buffer, &_glyphCount); glyphInfo = hb_buffer_get_glyph_infos(buffer, &_glyphCount);
glyphPositions = hb_buffer_get_glyph_positions(buffer, &_glyphCount); glyphPositions = hb_buffer_get_glyph_positions(buffer, &_glyphCount);
@ -99,22 +99,22 @@ std::tuple<Rectangle, Rectangle, Vector2> HarfBuzzLayouter::renderGlyph(const Ve
Rectanglei rectangle; Rectanglei rectangle;
std::tie(position, rectangle) = (*cache)[glyphInfo[i].codepoint]; std::tie(position, rectangle) = (*cache)[glyphInfo[i].codepoint];
Rectangle texturePosition = Rectangle::fromSize(Vector2(position)/font.size(), Rectangle texturePosition = Rectangle::fromSize(Vector2(position)/fontSize,
Vector2(rectangle.size())/font.size()); Vector2(rectangle.size())/fontSize);
Rectangle textureCoordinates(Vector2(rectangle.bottomLeft())/cache->textureSize(), Rectangle textureCoordinates(Vector2(rectangle.bottomLeft())/cache->textureSize(),
Vector2(rectangle.topRight())/cache->textureSize()); Vector2(rectangle.topRight())/cache->textureSize());
/* Glyph offset and advance to next glyph in normalized coordinates */ /* Glyph offset and advance to next glyph in normalized coordinates */
Vector2 offset = Vector2(glyphPositions[i].x_offset, Vector2 offset = Vector2(glyphPositions[i].x_offset,
glyphPositions[i].y_offset)/(64*font.size()); glyphPositions[i].y_offset)/(64*fontSize);
Vector2 advance = Vector2(glyphPositions[i].x_advance, Vector2 advance = Vector2(glyphPositions[i].x_advance,
glyphPositions[i].y_advance)/(64*font.size()); glyphPositions[i].y_advance)/(64*fontSize);
/* Absolute quad position, composed from cursor position, glyph offset /* Absolute quad position, composed from cursor position, glyph offset
and texture position, denormalized to requested text size */ and texture position, denormalized to requested text size */
Rectangle quadPosition = Rectangle::fromSize( Rectangle quadPosition = Rectangle::fromSize(
(cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*size, (cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*textSize,
texturePosition.size()*size); texturePosition.size()*textSize);
return std::make_tuple(quadPosition, textureCoordinates, advance); return std::make_tuple(quadPosition, textureCoordinates, advance);
} }

5
src/Text/HarfBuzzFont.h

@ -68,15 +68,12 @@ class MAGNUM_TEXT_EXPORT HarfBuzzFont: public FreeTypeFont {
~HarfBuzzFont(); ~HarfBuzzFont();
/** @brief HarfBuzz font handle */
inline hb_font_t* font() { return _hbFont; }
AbstractLayouter* layout(const GlyphCache* const cache, const Float size, const std::string& text) override; AbstractLayouter* layout(const GlyphCache* const cache, const Float size, const std::string& text) override;
private: private:
void MAGNUM_TEXT_LOCAL finishConstruction(); void MAGNUM_TEXT_LOCAL finishConstruction();
hb_font_t* _hbFont; hb_font_t* hbFont;
}; };
}} }}

Loading…
Cancel
Save