From 9525dfd51bb410306050b7f7f61b8be5b9a85720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 4 Mar 2013 14:41:35 +0100 Subject: [PATCH] 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. --- src/Text/AbstractFont.cpp | 26 ++++++ src/Text/AbstractFont.h | 103 ++++++++++++++++++++++ src/Text/CMakeLists.txt | 6 +- src/Text/{Font.cpp => FreeTypeFont.cpp} | 96 ++++++++++---------- src/Text/{Font.h => FreeTypeFont.h} | 112 +++++------------------- src/Text/Text.h | 8 +- src/Text/TextRenderer.cpp | 63 ++++++------- src/Text/TextRenderer.h | 12 +-- 8 files changed, 249 insertions(+), 177 deletions(-) create mode 100644 src/Text/AbstractFont.cpp create mode 100644 src/Text/AbstractFont.h rename src/Text/{Font.cpp => FreeTypeFont.cpp} (80%) rename src/Text/{Font.h => FreeTypeFont.h} (63%) diff --git a/src/Text/AbstractFont.cpp b/src/Text/AbstractFont.cpp new file mode 100644 index 000000000..5daef1fa2 --- /dev/null +++ b/src/Text/AbstractFont.cpp @@ -0,0 +1,26 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + 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() {} + +}} diff --git a/src/Text/AbstractFont.h b/src/Text/AbstractFont.h new file mode 100644 index 000000000..561133bcc --- /dev/null +++ b/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š + + 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 +#include + +#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 renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) = 0; + + #ifdef DOXYGEN_GENERATING_OUTPUT + private: + #else + protected: + #endif + UnsignedInt _glyphCount; +}; + +}} + +#endif diff --git a/src/Text/CMakeLists.txt b/src/Text/CMakeLists.txt index 42d2586d7..dd747e59e 100644 --- a/src/Text/CMakeLists.txt +++ b/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 diff --git a/src/Text/Font.cpp b/src/Text/FreeTypeFont.cpp similarity index 80% rename from src/Text/Font.cpp rename to src/Text/FreeTypeFont.cpp index f95802d6b..9444f3bce 100644 --- a/src/Text/Font.cpp +++ b/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 #include @@ -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 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 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& Font::operator[](char32_t character) const { +const std::tuple& FreeTypeFont::operator[](char32_t character) const { auto it = glyphs.find(character); if(it == glyphs.end()) @@ -205,7 +196,13 @@ const std::tuple& 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 TextLayouter::renderGlyph(const Vector2& cursorPosition, const UnsignedInt i) { +std::tuple 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 TextLayouter::renderGlyph(const Vector return std::make_tuple(quadPosition, textureCoordinates, advance); } +} + }} diff --git a/src/Text/Font.h b/src/Text/FreeTypeFont.h similarity index 63% rename from src/Text/Font.h rename to src/Text/FreeTypeFont.h index e14040c33..62da7c0b9 100644 --- a/src/Text/Font.h +++ b/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š @@ -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 #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& 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> 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 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 glyphs; - #endif - - const Float size; -}; - }} #endif diff --git a/src/Text/Text.h b/src/Text/Text.h index 03e126beb..d3ba2db87 100644 --- a/src/Text/Text.h +++ b/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 class TextRenderer; diff --git a/src/Text/TextRenderer.cpp b/src/Text/TextRenderer.cpp index 218fa0a77..5de5724f1 100644 --- a/src/Text/TextRenderer.cpp +++ b/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, std::vector, 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, std::vector, 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 positions, texcoords; @@ -63,11 +62,11 @@ std::tuple, std::vector, std::vector, /* 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, std::vector, } /* Create indices */ - std::vector indices(layouter.glyphCount()*6); - createIndices(indices.data(), layouter.glyphCount()); + std::vector indices(layouter->glyphCount()*6); + createIndices(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 AbstractTextRenderer::render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) { - TextLayouter layouter(font, size, text); +std::tuple 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 vertices; @@ -109,11 +109,11 @@ std::tuple 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 AbstractTextRenderer::render(Font& font, Float size, indexType = Mesh::IndexType::UnsignedByte; indicesSize = indexCount*sizeof(UnsignedByte); indices = new char[indicesSize]; - createIndices(indices, layouter.glyphCount()); + createIndices(indices, layouter->glyphCount()); } else if(vertexCount < 65535) { indexType = Mesh::IndexType::UnsignedShort; indicesSize = indexCount*sizeof(UnsignedShort); indices = new char[indicesSize]; - createIndices(indices, layouter.glyphCount()); + createIndices(indices, layouter->glyphCount()); } else { indexType = Mesh::IndexType::UnsignedInt; indicesSize = indexCount*sizeof(UnsignedInt); indices = new char[indicesSize]; - createIndices(indices, layouter.glyphCount()); + createIndices(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 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 std::tuple TextRenderer::render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage) { +template std::tuple TextRenderer::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 std::tuple TextRenderer TextRenderer::TextRenderer(Font& font, const Float size): AbstractTextRenderer(font, size) { +template TextRenderer::TextRenderer(AbstractFont& font, const Float size): AbstractTextRenderer(font, size) { /* Finalize mesh configuration */ _mesh.addInterleavedVertexBuffer(&vertexBuffer, 0, typename Shaders::AbstractVectorShader::Position(Shaders::AbstractVectorShader::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(vertexBuffer.map(0, layouter.glyphCount()*4*sizeof(Vertex), + Vertex* const vertices = static_cast(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>; diff --git a/src/Text/TextRenderer.h b/src/Text/TextRenderer.h index f4932fdf2..32d792521 100644 --- a/src/Text/TextRenderer.h +++ b/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, std::vector, Rectangle> render(Font& font, Float size, const std::string& text); + static std::tuple, std::vector, std::vector, 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 MAGNUM_LOCAL render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage); + static std::tuple 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 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 render(Font& font, Float size, const std::string& text, Buffer* vertexBuffer, Buffer* indexBuffer, Buffer::Usage usage); + static std::tuple 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; };