Browse Source

Text: abstract base for fonts and layouters.

Font and text layouting is now abstracted out from its implementation.
Font class is renamed to FreeTypeFont and all the work can be done
through AbstractFont and AbstractLayouter interface.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
9525dfd51b
  1. 26
      src/Text/AbstractFont.cpp
  2. 103
      src/Text/AbstractFont.h
  3. 6
      src/Text/CMakeLists.txt
  4. 96
      src/Text/FreeTypeFont.cpp
  5. 112
      src/Text/FreeTypeFont.h
  6. 8
      src/Text/Text.h
  7. 63
      src/Text/TextRenderer.cpp
  8. 12
      src/Text/TextRenderer.h

26
src/Text/AbstractFont.cpp

@ -0,0 +1,26 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "Text/AbstractFont.h"
namespace Magnum { namespace Text {
AbstractFont::AbstractFont() {}
AbstractFont::~AbstractFont() {}
AbstractLayouter::AbstractLayouter(): _glyphCount(0) {}
AbstractLayouter::~AbstractLayouter() {}
}}

103
src/Text/AbstractFont.h

@ -0,0 +1,103 @@
#ifndef Magnum_Text_AbstractFont_h
#define Magnum_Text_AbstractFont_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Text::AbstractFont, Magnum::Text::AbstractLayouter
*/
#include <tuple>
#include <string>
#include "Magnum.h"
#include "Texture.h"
#include "Text/Text.h"
#include "Text/magnumTextVisibility.h"
namespace Magnum { namespace Text {
/**
@brief Base for fonts
*/
class MAGNUM_TEXT_EXPORT AbstractFont {
AbstractFont(const AbstractFont&) = delete;
AbstractFont(AbstractFont&&) = delete;
AbstractFont& operator=(const AbstractFont&) = delete;
AbstractFont& operator=(const AbstractFont&&) = delete;
public:
AbstractFont();
virtual ~AbstractFont() = 0;
/** @brief %Font texture atlas */
inline Texture2D& texture() { return _texture; }
/**
* @brief Layout the text using fon't own layouter
* @param size %Font size
* @param text Text to layout
*/
virtual AbstractLayouter* layout(const Float size, const std::string& text) = 0;
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected:
#endif
Texture2D _texture;
};
/**
@brief Base for text layouters
Returned by AbstractFont::layout().
*/
class MAGNUM_TEXT_EXPORT AbstractLayouter {
AbstractLayouter(const AbstractLayouter&) = delete;
AbstractLayouter(AbstractLayouter&&) = delete;
AbstractLayouter& operator=(const AbstractLayouter&) = delete;
AbstractLayouter& operator=(const AbstractLayouter&&) = delete;
public:
AbstractLayouter();
virtual ~AbstractLayouter() = 0;
/** @brief Count of glyphs in laid out text */
inline UnsignedInt glyphCount() const {
return _glyphCount;
}
/**
* @brief Render glyph
* @param i Glyph index
* @param cursorPosition Cursor position
*
* Returns quad position, texture coordinates and advance to next
* glyph.
*/
virtual std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) = 0;
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected:
#endif
UnsignedInt _glyphCount;
};
}}
#endif

6
src/Text/CMakeLists.txt

@ -7,10 +7,12 @@ if(USE_HARFBUZZ)
endif()
set(MagnumText_SRCS
Font.cpp
AbstractFont.cpp
FreeTypeFont.cpp
TextRenderer.cpp)
set(MagnumText_HEADERS
Font.h
AbstractFont.h
FreeTypeFont.h
Text.h
TextRenderer.h

96
src/Text/Font.cpp → src/Text/FreeTypeFont.cpp

@ -13,7 +13,7 @@
GNU Lesser General Public License version 3 for more details.
*/
#include "Font.h"
#include "FreeTypeFont.h"
#include <algorithm>
#include <ft2build.h>
@ -30,27 +30,52 @@
namespace Magnum { namespace Text {
FontRenderer::FontRenderer() {
namespace {
class FreeTypeLayouter: public AbstractLayouter {
public:
FreeTypeLayouter(FreeTypeFont& font, const Float size, const std::string& text);
~FreeTypeLayouter();
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) override;
private:
#ifdef MAGNUM_USE_HARFBUZZ
const FreeTypeFont& font;
hb_buffer_t* buffer;
hb_glyph_info_t* glyphInfo;
hb_glyph_position_t* glyphPositions;
#else
FreeTypeFont& font;
std::vector<FT_UInt> glyphs;
#endif
const Float size;
};
}
FreeTypeFontRenderer::FreeTypeFontRenderer() {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Init_FreeType(&_library) == 0);
}
FontRenderer::~FontRenderer() {
FreeTypeFontRenderer::~FreeTypeFontRenderer() {
FT_Done_FreeType(_library);
}
Font::Font(FontRenderer& renderer, const std::string& fontFile, Float size): _size(size) {
FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const std::string& fontFile, Float size): _size(size) {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Face(renderer.library(), fontFile.c_str(), 0, &_ftFont) == 0);
finishConstruction();
}
Font::Font(FontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size): _size(size) {
FreeTypeFont::FreeTypeFont(FreeTypeFontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size): _size(size) {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_New_Memory_Face(renderer.library(), data, dataSize, 0, &_ftFont) == 0);
finishConstruction();
}
void Font::finishConstruction() {
void FreeTypeFont::finishConstruction() {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(_ftFont, 0, _size*64, 100, 100) == 0);
#ifdef MAGNUM_USE_HARFBUZZ
@ -70,7 +95,7 @@ void Font::finishConstruction() {
->setMagnificationFilter(Texture2D::Filter::Linear);
}
void Font::prerenderInternal(const std::string& characters, const Vector2i& atlasSize, const Int radius, Texture2D* output) {
void FreeTypeFont::prerenderInternal(const std::string& characters, const Vector2i& atlasSize, const Int radius, Texture2D* output) {
glyphs.clear();
/** @bug Crash when atlas is too small */
@ -137,11 +162,11 @@ void Font::prerenderInternal(const std::string& characters, const Vector2i& atla
#endif
}
void Font::prerender(const std::string& characters, const Vector2i& atlasSize) {
void FreeTypeFont::prerender(const std::string& characters, const Vector2i& atlasSize) {
prerenderInternal(characters, atlasSize, 0, &_texture);
}
void Font::prerenderDistanceField(const std::string& characters, const Vector2i& sourceAtlasSize, const Vector2i& atlasSize, Int radius) {
void FreeTypeFont::prerenderDistanceField(const std::string& characters, const Vector2i& sourceAtlasSize, const Vector2i& atlasSize, Int radius) {
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_storage);
/* Render input texture */
@ -156,48 +181,14 @@ void Font::prerenderDistanceField(const std::string& characters, const Vector2i&
TextureTools::distanceField(&input, &_texture, Rectanglei::fromSize({}, atlasSize), radius);
}
void Font::destroy() {
if(!_ftFont) return;
FreeTypeFont::~FreeTypeFont() {
#ifdef MAGNUM_USE_HARFBUZZ
hb_font_destroy(_hbFont);
#endif
FT_Done_Face(_ftFont);
}
void Font::move() {
#ifdef MAGNUM_USE_HARFBUZZ
_hbFont = nullptr;
#endif
_ftFont = nullptr;
}
Font::~Font() { destroy(); }
Font::Font(Font&& other): glyphs(std::move(other.glyphs)), _texture(std::move(other._texture)), _ftFont(other._ftFont), _size(other._size)
#ifdef MAGNUM_USE_HARFBUZZ
, _hbFont(other._hbFont)
#endif
{
other.move();
}
Font& Font::operator=(Font&& other) {
destroy();
glyphs = std::move(other.glyphs);
_texture = std::move(other._texture);
_ftFont = other._ftFont;
#ifdef MAGNUM_USE_HARFBUZZ
_hbFont = other._hbFont;
#endif
_size = other._size;
other.move();
return *this;
}
const std::tuple<Rectangle, Rectangle>& Font::operator[](char32_t character) const {
const std::tuple<Rectangle, Rectangle>& FreeTypeFont::operator[](char32_t character) const {
auto it = glyphs.find(character);
if(it == glyphs.end())
@ -205,7 +196,13 @@ 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) {
AbstractLayouter* FreeTypeFont::layout(const Float size, const std::string& text) {
return new FreeTypeLayouter(*this, size, text);
}
namespace {
FreeTypeLayouter::FreeTypeLayouter(FreeTypeFont& font, const Float size, const std::string& text): font(font), size(size) {
#ifdef MAGNUM_USE_HARFBUZZ
/* Prepare HarfBuzz buffer */
buffer = hb_buffer_create();
@ -222,6 +219,7 @@ TextLayouter::TextLayouter(Font& font, const Float size, const std::string& text
#else
/* Get glyph codes from characters */
glyphs.reserve(text.size()+1);
_glyphCount = text.size();
for(std::size_t i = 0; i != text.size(); ) {
UnsignedInt codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i);
@ -230,14 +228,14 @@ TextLayouter::TextLayouter(Font& font, const Float size, const std::string& text
#endif
}
TextLayouter::~TextLayouter() {
FreeTypeLayouter::~FreeTypeLayouter() {
#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) {
std::tuple<Rectangle, Rectangle, Vector2> FreeTypeLayouter::renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle texturePosition, textureCoordinates;
#ifdef MAGNUM_USE_HARFBUZZ
@ -269,4 +267,6 @@ std::tuple<Rectangle, Rectangle, Vector2> TextLayouter::renderGlyph(const Vector
return std::make_tuple(quadPosition, textureCoordinates, advance);
}
}
}}

112
src/Text/Font.h → src/Text/FreeTypeFont.h

@ -1,5 +1,5 @@
#ifndef Magnum_Text_Font_h
#define Magnum_Text_Font_h
#ifndef Magnum_Text_FreeTypeFont_h
#define Magnum_Text_FreeTypeFont_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
@ -16,15 +16,15 @@
*/
/** @file
* @brief Class Magnum::Text::FontRenderer, Magnum::Text::Font, Magnum::Text::TextLayouter
* @brief Class Magnum::Text::FreeTypeFontRenderer, Magnum::Text::FreeTypeFont
*/
#include <unordered_map>
#include "Math/Geometry/Rectangle.h"
#include "Texture.h"
#include "magnumTextVisibility.h"
#include "Text/AbstractFont.h"
#include "Text/magnumTextVisibility.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
struct FT_LibraryRec_;
@ -40,16 +40,16 @@ struct hb_glyph_position_t;
namespace Magnum { namespace Text {
/**
@brief %Font renderer
@brief FreeType font renderer
Contains global instance of font renderer. See Font class documentation for
more information.
Contains global instance of font renderer. See FreeTypeFont class documentation
for more information.
*/
class MAGNUM_TEXT_EXPORT FontRenderer {
class MAGNUM_TEXT_EXPORT FreeTypeFontRenderer {
public:
explicit FontRenderer();
explicit FreeTypeFontRenderer();
~FontRenderer();
~FreeTypeFontRenderer();
/** @brief FreeType library handle */
inline FT_Library library() { return _library; }
@ -59,36 +59,33 @@ class MAGNUM_TEXT_EXPORT FontRenderer {
};
/**
@brief %Font
@brief FreeType font
Contains font with characters prerendered into texture atlas.
@section Font-usage Usage
@section FreeTypeFont-usage Usage
You need to maintain instance of FontRenderer during the lifetime of all Font
You need to maintain instance of FreeTypeFontRenderer during the lifetime of all FreeTypeFont
instances. The font can be created either from file or from memory location of
format supported by [FreeType](http://www.freetype.org/) library. Next step is
to prerender all the glyphs which will be used in text rendering later.
@code
Text::FontRenderer fontRenderer;
Text::FreeTypeFontRenderer fontRenderer;
Text::Font font(fontRenderer, "MyFont.ttf", 48.0f);
Text::FreeTypeFont font(fontRenderer, "MyFreeTypeFont.ttf", 48.0f);
font.prerender("abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789 ", Vector2i(512));
@endcode
See TextRenderer for information about text rendering.
@section Font-extensions Required OpenGL functionality
@section FreeTypeFont-extensions Required OpenGL functionality
%Font texture uses one-component internal format, which requires
@extension{ARB,texture_rg} (also part of OpenGL ES 3.0 or available as
@es_extension{EXT,texture_rg} in ES 2.0).
*/
class MAGNUM_TEXT_EXPORT Font {
Font(const Font&) = delete;
Font& operator=(const Font&) = delete;
class MAGNUM_TEXT_EXPORT FreeTypeFont: public AbstractFont {
public:
/**
* @brief Create font from file
@ -96,7 +93,7 @@ class MAGNUM_TEXT_EXPORT Font {
* @param fontFile %Font file
* @param size %Font size
*/
explicit Font(FontRenderer& renderer, const std::string& fontFile, Float size);
explicit FreeTypeFont(FreeTypeFontRenderer& renderer, const std::string& fontFile, Float size);
/**
* @brief Create font from memory
@ -105,7 +102,7 @@ class MAGNUM_TEXT_EXPORT Font {
* @param dataSize %Font data size
* @param size %Font size
*/
explicit Font(FontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size);
explicit FreeTypeFont(FreeTypeFontRenderer& renderer, const unsigned char* data, std::size_t dataSize, Float size);
/**
* @brief Prerender given character set
@ -134,13 +131,7 @@ class MAGNUM_TEXT_EXPORT Font {
*/
void prerenderDistanceField(const std::string& characters, const Vector2i& sourceAtlasSize, const Vector2i& atlasSize, Int radius);
~Font();
/** @brief Move constructor */
Font(Font&& other);
/** @brief Move assignment */
Font& operator=(Font&& other);
~FreeTypeFont();
/** @brief %Font size */
inline Float size() const { return _size; }
@ -157,24 +148,20 @@ class MAGNUM_TEXT_EXPORT Font {
*/
const std::tuple<Rectangle, Rectangle>& operator[](char32_t character) const;
/** @brief %Font texture atlas */
inline Texture2D& texture() { return _texture; }
/** @brief Font handle */
/** @brief %Font handle */
#ifdef MAGNUM_USE_HARFBUZZ
inline hb_font_t* font() { return _hbFont; }
#else
inline FT_Face font() { return _ftFont; }
#endif
AbstractLayouter* layout(const Float size, const std::string& text) override;
private:
void MAGNUM_TEXT_LOCAL finishConstruction();
void MAGNUM_TEXT_LOCAL destroy();
void MAGNUM_TEXT_LOCAL move();
void MAGNUM_TEXT_LOCAL prerenderInternal(const std::string& characters, const Vector2i& atlasSize, const Int radius, Texture2D* output);
std::unordered_map<char32_t, std::tuple<Rectangle, Rectangle>> glyphs;
Texture2D _texture;
FT_Face _ftFont;
Float _size;
#ifdef MAGNUM_USE_HARFBUZZ
@ -182,57 +169,6 @@ 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

8
src/Text/Text.h

@ -23,9 +23,11 @@
namespace Magnum { namespace Text {
class Font;
class FontRenderer;
class TextLayouter;
class AbstractFont;
class AbstractLayouter;
class FreeTypeFontRenderer;
class FreeTypeFont;
class AbstractTextRenderer;
template<UnsignedInt> class TextRenderer;

63
src/Text/TextRenderer.cpp

@ -19,7 +19,7 @@
#include "Extensions.h"
#include "Mesh.h"
#include "Shaders/AbstractVectorShader.h"
#include "Text/Font.h"
#include "Text/AbstractFont.h"
namespace Magnum { namespace Text {
@ -51,10 +51,9 @@ struct Vertex {
}
std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> AbstractTextRenderer::render(Font& font, Float size, const std::string& text) {
TextLayouter layouter(font, size, text);
const UnsignedInt vertexCount = layouter.glyphCount()*4;
std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> AbstractTextRenderer::render(AbstractFont& font, Float size, const std::string& text) {
AbstractLayouter* const layouter = font.layout(size, text);
const UnsignedInt vertexCount = layouter->glyphCount()*4;
/* Output data */
std::vector<Vector2> positions, texcoords;
@ -63,11 +62,11 @@ std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>,
/* Render all glyphs */
Vector2 cursorPosition;
for(UnsignedInt i = 0; i != layouter.glyphCount(); ++i) {
for(UnsignedInt i = 0; i != layouter->glyphCount(); ++i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle quadPosition, textureCoordinates;
Vector2 advance;
std::tie(quadPosition, textureCoordinates, advance) = layouter.renderGlyph(cursorPosition, i);
std::tie(quadPosition, textureCoordinates, advance) = layouter->renderGlyph(cursorPosition, i);
positions.insert(positions.end(), {
quadPosition.topLeft(),
@ -87,21 +86,22 @@ std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>,
}
/* Create indices */
std::vector<UnsignedInt> indices(layouter.glyphCount()*6);
createIndices<UnsignedInt>(indices.data(), layouter.glyphCount());
std::vector<UnsignedInt> indices(layouter->glyphCount()*6);
createIndices<UnsignedInt>(indices.data(), layouter->glyphCount());
/* Rendered rectangle */
Rectangle rectangle;
if(layouter.glyphCount()) rectangle = {positions[1], positions[positions.size()-2]};
if(layouter->glyphCount()) rectangle = {positions[1], positions[positions.size()-2]};
delete layouter;
return std::make_tuple(std::move(positions), std::move(texcoords), std::move(indices), rectangle);
}
std::tuple<Mesh, Rectangle> AbstractTextRenderer::render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) {
TextLayouter layouter(font, size, text);
std::tuple<Mesh, Rectangle> AbstractTextRenderer::render(AbstractFont& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) {
AbstractLayouter* const layouter = font.layout(size, text);
const UnsignedInt vertexCount = layouter.glyphCount()*4;
const UnsignedInt indexCount = layouter.glyphCount()*6;
const UnsignedInt vertexCount = layouter->glyphCount()*4;
const UnsignedInt indexCount = layouter->glyphCount()*6;
/* Vertex buffer */
std::vector<Vertex> vertices;
@ -109,11 +109,11 @@ std::tuple<Mesh, Rectangle> AbstractTextRenderer::render(Font& font, Float size,
/* Render all glyphs */
Vector2 cursorPosition;
for(UnsignedInt i = 0; i != layouter.glyphCount(); ++i) {
for(UnsignedInt i = 0; i != layouter->glyphCount(); ++i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle quadPosition, textureCoordinates;
Vector2 advance;
std::tie(quadPosition, textureCoordinates, advance) = layouter.renderGlyph(cursorPosition, i);
std::tie(quadPosition, textureCoordinates, advance) = layouter->renderGlyph(cursorPosition, i);
vertices.insert(vertices.end(), {
{quadPosition.topLeft(), textureCoordinates.topLeft()},
@ -135,24 +135,24 @@ std::tuple<Mesh, Rectangle> AbstractTextRenderer::render(Font& font, Float size,
indexType = Mesh::IndexType::UnsignedByte;
indicesSize = indexCount*sizeof(UnsignedByte);
indices = new char[indicesSize];
createIndices<UnsignedByte>(indices, layouter.glyphCount());
createIndices<UnsignedByte>(indices, layouter->glyphCount());
} else if(vertexCount < 65535) {
indexType = Mesh::IndexType::UnsignedShort;
indicesSize = indexCount*sizeof(UnsignedShort);
indices = new char[indicesSize];
createIndices<UnsignedShort>(indices, layouter.glyphCount());
createIndices<UnsignedShort>(indices, layouter->glyphCount());
} else {
indexType = Mesh::IndexType::UnsignedInt;
indicesSize = indexCount*sizeof(UnsignedInt);
indices = new char[indicesSize];
createIndices<UnsignedInt>(indices, layouter.glyphCount());
createIndices<UnsignedInt>(indices, layouter->glyphCount());
}
indexBuffer->setData(indicesSize, indices, usage);
delete indices;
/* Rendered rectangle */
Rectangle rectangle;
if(layouter.glyphCount()) rectangle = {vertices[1].position, vertices[vertices.size()-2].position};
if(layouter->glyphCount()) rectangle = {vertices[1].position, vertices[vertices.size()-2].position};
/* Configure mesh except for vertex buffer (depends on dimension count, done
in subclass) */
@ -161,10 +161,11 @@ std::tuple<Mesh, Rectangle> AbstractTextRenderer::render(Font& font, Float size,
->setIndexCount(indexCount)
->setIndexBuffer(indexBuffer, 0, indexType, 0, vertexCount);
delete layouter;
return std::make_tuple(std::move(mesh), rectangle);
}
template<UnsignedInt dimensions> std::tuple<Mesh, Rectangle> TextRenderer<dimensions>::render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) {
template<UnsignedInt dimensions> std::tuple<Mesh, Rectangle> TextRenderer<dimensions>::render(AbstractFont& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) {
/* Finalize mesh configuration and return the result */
auto r = AbstractTextRenderer::render(font, size, text, vertexBuffer, indexBuffer, usage);
Mesh& mesh = std::get<0>(r);
@ -175,7 +176,7 @@ template<UnsignedInt dimensions> std::tuple<Mesh, Rectangle> TextRenderer<dimens
return std::move(r);
}
AbstractTextRenderer::AbstractTextRenderer(Font& font, Float size): vertexBuffer(Buffer::Target::Array), indexBuffer(Buffer::Target::ElementArray), font(font), size(size), _capacity(0) {
AbstractTextRenderer::AbstractTextRenderer(AbstractFont& font, Float size): vertexBuffer(Buffer::Target::Array), indexBuffer(Buffer::Target::ElementArray), font(font), size(size), _capacity(0) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range);
#else
@ -190,7 +191,7 @@ AbstractTextRenderer::AbstractTextRenderer(Font& font, Float size): vertexBuffer
AbstractTextRenderer::~AbstractTextRenderer() {}
template<UnsignedInt dimensions> TextRenderer<dimensions>::TextRenderer(Font& font, const Float size): AbstractTextRenderer(font, size) {
template<UnsignedInt dimensions> TextRenderer<dimensions>::TextRenderer(AbstractFont& font, const Float size): AbstractTextRenderer(font, size) {
/* Finalize mesh configuration */
_mesh.addInterleavedVertexBuffer(&vertexBuffer, 0,
typename Shaders::AbstractVectorShader<dimensions>::Position(Shaders::AbstractVectorShader<dimensions>::Position::Components::Two),
@ -236,23 +237,23 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag
}
void AbstractTextRenderer::render(const std::string& text) {
TextLayouter layouter(font, size, text);
AbstractLayouter* layouter = font.layout(size, text);
CORRADE_ASSERT(layouter.glyphCount() <= _capacity, "Text::TextRenderer::render(): capacity" << _capacity << "too small to render" << layouter.glyphCount() << "glyphs", );
CORRADE_ASSERT(layouter->glyphCount() <= _capacity, "Text::TextRenderer::render(): capacity" << _capacity << "too small to render" << layouter->glyphCount() << "glyphs", );
/* Render all glyphs */
Vertex* const vertices = static_cast<Vertex*>(vertexBuffer.map(0, layouter.glyphCount()*4*sizeof(Vertex),
Vertex* const vertices = static_cast<Vertex*>(vertexBuffer.map(0, layouter->glyphCount()*4*sizeof(Vertex),
Buffer::MapFlag::InvalidateBuffer|Buffer::MapFlag::Write));
Vector2 cursorPosition;
for(UnsignedInt i = 0; i != layouter.glyphCount(); ++i) {
for(UnsignedInt i = 0; i != layouter->glyphCount(); ++i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle quadPosition, textureCoordinates;
Vector2 advance;
std::tie(quadPosition, textureCoordinates, advance) = layouter.renderGlyph(cursorPosition, i);
std::tie(quadPosition, textureCoordinates, advance) = layouter->renderGlyph(cursorPosition, i);
if(i == 0)
_rectangle.bottomLeft() = quadPosition.bottomLeft();
else if(i == layouter.glyphCount()-1)
else if(i == layouter->glyphCount()-1)
_rectangle.topRight() = quadPosition.topRight();
const std::size_t vertex = i*4;
@ -267,7 +268,9 @@ void AbstractTextRenderer::render(const std::string& text) {
CORRADE_INTERNAL_ASSERT_OUTPUT(vertexBuffer.unmap());
/* Update index count */
_mesh.setIndexCount(layouter.glyphCount()*6);
_mesh.setIndexCount(layouter->glyphCount()*6);
delete layouter;
}
template class TextRenderer<2>;

12
src/Text/TextRenderer.h

@ -50,14 +50,14 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer {
* Returns tuple with vertex positions, texture coordinates, indices
* and rectangle spanning the rendered text.
*/
static std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> render(Font& font, Float size, const std::string& text);
static std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> render(AbstractFont& font, Float size, const std::string& text);
/**
* @brief Constructor
* @param font %Font to use
* @param size %Font size
*/
AbstractTextRenderer(Font& font, Float size);
AbstractTextRenderer(AbstractFont& font, Float size);
virtual ~AbstractTextRenderer() = 0;
@ -106,13 +106,13 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer {
#else
private:
#endif
static std::tuple<Mesh, Rectangle> MAGNUM_LOCAL render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage);
static std::tuple<Mesh, Rectangle> MAGNUM_LOCAL render(AbstractFont& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage);
Mesh _mesh;
Buffer vertexBuffer, indexBuffer;
private:
Font& font;
AbstractFont& font;
Float size;
UnsignedInt _capacity;
Rectangle _rectangle;
@ -197,14 +197,14 @@ template<UnsignedInt dimensions> class MAGNUM_TEXT_EXPORT TextRenderer: public A
* Returns mesh prepared for use with Shaders::AbstractVectorShader
* subclasses and rectangle spanning the rendered text.
*/
static std::tuple<Mesh, Rectangle> render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage);
static std::tuple<Mesh, Rectangle> render(AbstractFont& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage);
/**
* @brief Constructor
* @param font %Font to use
* @param size %Font size
*/
TextRenderer(Font& font, Float size);
TextRenderer(AbstractFont& font, Float size);
using AbstractTextRenderer::render;
};

Loading…
Cancel
Save