Browse Source

Text: moved TextLayouter from TextRenderer internals to Font header.

Preparation for the whole thing to be testable, moving
implementation-dependent (FreeType/HarfBuzz) things together.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
b4950b59ac
  1. 64
      src/Text/Font.cpp
  2. 56
      src/Text/Font.h
  3. 1
      src/Text/Text.h
  4. 103
      src/Text/TextRenderer.cpp

64
src/Text/Font.cpp

@ -197,4 +197,68 @@ const std::tuple<Rectangle, Rectangle>& Font::operator[](char32_t character) con
return it->second;
}
TextLayouter::TextLayouter(Font& font, const Float size, const std::string& text): font(font), size(size) {
#ifdef MAGNUM_USE_HARFBUZZ
/* Prepare HarfBuzz buffer */
buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
hb_buffer_set_script(buffer, HB_SCRIPT_LATIN);
hb_buffer_set_language(buffer, hb_language_from_string("en", 2));
/* Layout the text */
hb_buffer_add_utf8(buffer, text.c_str(), -1, 0, -1);
hb_shape(font.font(), buffer, nullptr, 0);
glyphInfo = hb_buffer_get_glyph_infos(buffer, &_glyphCount);
glyphPositions = hb_buffer_get_glyph_positions(buffer, &_glyphCount);
#else
/* Get glyph codes from characters */
glyphs.reserve(text.size()+1);
for(std::size_t i = 0; i != text.size(); ) {
UnsignedInt codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i);
glyphs.push_back(FT_Get_Char_Index(font.font(), codepoint));
}
#endif
}
TextLayouter::~TextLayouter() {
#ifdef MAGNUM_USE_HARFBUZZ
/* Destroy HarfBuzz buffer */
hb_buffer_destroy(buffer);
#endif
}
std::tuple<Rectangle, Rectangle, Vector2> TextLayouter::renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle texturePosition, textureCoordinates;
#ifdef MAGNUM_USE_HARFBUZZ
std::tie(texturePosition, textureCoordinates) = font[glyphInfo[i].codepoint];
#else
std::tie(texturePosition, textureCoordinates) = font[glyphs[i]];
#endif
#ifdef MAGNUM_USE_HARFBUZZ
/* Glyph offset and advance to next glyph in normalized coordinates */
Vector2 offset = Vector2(glyphPositions[i].x_offset,
glyphPositions[i].y_offset)/(64*font.size());
Vector2 advance = Vector2(glyphPositions[i].x_advance,
glyphPositions[i].y_advance)/(64*font.size());
#else
/* Load glyph */
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(font.font(), glyphs[i], FT_LOAD_DEFAULT) == 0);
const FT_GlyphSlot slot = font.font()->glyph;
Vector2 offset = Vector2(0, 0); /** @todo really? */
Vector2 advance = Vector2(slot->advance.x, slot->advance.y)/(64*font.size());
#endif
/* Absolute quad position, composed from cursor position, glyph offset
and texture position, denormalized to requested text size */
Rectangle quadPosition = Rectangle::fromSize(
(cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*size,
texturePosition.size()*size);
return std::make_tuple(quadPosition, textureCoordinates, advance);
}
}}

56
src/Text/Font.h

@ -16,7 +16,7 @@
*/
/** @file
* @brief Class Magnum::Text::Font
* @brief Class Magnum::Text::Font, Magnum::Text::TextLayouter
*/
#include <unordered_map>
@ -31,6 +31,9 @@
struct FT_FaceRec_;
typedef FT_FaceRec_* FT_Face;
struct hb_font_t;
struct hb_buffer_t;
struct hb_glyph_info_t;
struct hb_glyph_position_t;
#endif
namespace Magnum { namespace Text {
@ -159,6 +162,57 @@ class MAGNUM_TEXT_EXPORT Font {
#endif
};
/**
@brief %Text layouter
Provides low-level text rendering using Font, used internally in TextRenderer.
*/
class TextLayouter {
public:
/**
* @brief Constructor
* @param font %Font
* @param size %Font size
* @param text Text to layout
*/
TextLayouter(Font& font, const Float size, const std::string& text);
~TextLayouter();
/** @brief Count of glyphs in laid out text */
inline UnsignedInt glyphCount() {
#ifdef MAGNUM_USE_HARFBUZZ
return _glyphCount;
#else
return glyphs.size();
#endif
}
/**
* @brief Render glyph
* @param i Glyph index
* @param cursorPosition Cursor position
*
* Returns quad position, texture coordinates and advance to next
* glyph.
*/
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i);
private:
#ifdef MAGNUM_USE_HARFBUZZ
const Font& font;
hb_buffer_t* buffer;
hb_glyph_info_t* glyphInfo;
hb_glyph_position_t* glyphPositions;
UnsignedInt _glyphCount;
#else
Font& font;
std::vector<FT_UInt> glyphs;
#endif
const Float size;
};
}}
#endif

1
src/Text/Text.h

@ -25,6 +25,7 @@ namespace Magnum { namespace Text {
class Font;
class FontRenderer;
class TextLayouter;
class AbstractTextRenderer;
template<UnsignedInt> class TextRenderer;

103
src/Text/TextRenderer.cpp

@ -15,14 +15,6 @@
#include "TextRenderer.h"
#ifdef MAGNUM_USE_HARFBUZZ
#include <hb.h>
#else
#include <ft2build.h>
#include FT_FREETYPE_H
#include <Utility/Unicode.h>
#endif
#include "Context.h"
#include "Extensions.h"
#include "Mesh.h"
@ -33,101 +25,6 @@ namespace Magnum { namespace Text {
namespace {
class TextLayouter {
public:
TextLayouter(Font& font, const Float size, const std::string& text);
~TextLayouter();
inline UnsignedInt glyphCount() {
#ifdef MAGNUM_USE_HARFBUZZ
return _glyphCount;
#else
return glyphs.size();
#endif
}
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i);
private:
#ifdef MAGNUM_USE_HARFBUZZ
const Font& font;
hb_buffer_t* buffer;
hb_glyph_info_t* glyphInfo;
hb_glyph_position_t* glyphPositions;
UnsignedInt _glyphCount;
#else
Font& font;
std::vector<FT_UInt> glyphs;
#endif
const Float size;
};
TextLayouter::TextLayouter(Font& font, const Float size, const std::string& text): font(font), size(size) {
#ifdef MAGNUM_USE_HARFBUZZ
/* Prepare HarfBuzz buffer */
buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
hb_buffer_set_script(buffer, HB_SCRIPT_LATIN);
hb_buffer_set_language(buffer, hb_language_from_string("en", 2));
/* Layout the text */
hb_buffer_add_utf8(buffer, text.c_str(), -1, 0, -1);
hb_shape(font.font(), buffer, nullptr, 0);
glyphInfo = hb_buffer_get_glyph_infos(buffer, &_glyphCount);
glyphPositions = hb_buffer_get_glyph_positions(buffer, &_glyphCount);
#else
/* Get glyph codes from characters */
glyphs.reserve(text.size()+1);
for(std::size_t i = 0; i != text.size(); ) {
UnsignedInt codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i);
glyphs.push_back(FT_Get_Char_Index(font.font(), codepoint));
}
#endif
}
TextLayouter::~TextLayouter() {
#ifdef MAGNUM_USE_HARFBUZZ
/* Destroy HarfBuzz buffer */
hb_buffer_destroy(buffer);
#endif
}
std::tuple<Rectangle, Rectangle, Vector2> TextLayouter::renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle texturePosition, textureCoordinates;
#ifdef MAGNUM_USE_HARFBUZZ
std::tie(texturePosition, textureCoordinates) = font[glyphInfo[i].codepoint];
#else
std::tie(texturePosition, textureCoordinates) = font[glyphs[i]];
#endif
#ifdef MAGNUM_USE_HARFBUZZ
/* Glyph offset and advance to next glyph in normalized coordinates */
Vector2 offset = Vector2(glyphPositions[i].x_offset,
glyphPositions[i].y_offset)/(64*font.size());
Vector2 advance = Vector2(glyphPositions[i].x_advance,
glyphPositions[i].y_advance)/(64*font.size());
#else
/* Load glyph */
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(font.font(), glyphs[i], FT_LOAD_DEFAULT) == 0);
const FT_GlyphSlot slot = font.font()->glyph;
Vector2 offset = Vector2(0, 0); /** @todo really? */
Vector2 advance = Vector2(slot->advance.x, slot->advance.y)/(64*font.size());
#endif
/* Absolute quad position, composed from cursor position, glyph offset
and texture position, denormalized to requested text size */
Rectangle quadPosition = Rectangle::fromSize(
(cursorPosition + offset + Vector2(texturePosition.left(), texturePosition.bottom()))*size,
texturePosition.size()*size);
return std::make_tuple(quadPosition, textureCoordinates, advance);
}
template<class T> void createIndices(void* output, const UnsignedInt glyphCount) {
T* const out = reinterpret_cast<T*>(output);
for(UnsignedInt i = 0; i != glyphCount; ++i) {

Loading…
Cancel
Save