From 31dae6ef3321cf136e2e6304010504cd8d246bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 4 Nov 2013 14:52:57 +0100 Subject: [PATCH] Text: renamed Text::TextRenderer to Text::Renderer. No redundant naming. Text::Renderer2D and Text::Renderer3D is typedef'd to old name, the typedefs are deprecated and will be removed in some future release. --- src/Test/AbstractOpenGLTester.h | 2 +- src/Text/AbstractFont.h | 18 +- src/Text/CMakeLists.txt | 9 +- src/Text/GlyphCache.h | 4 +- src/Text/{TextRenderer.cpp => Renderer.cpp} | 52 ++-- src/Text/Renderer.h | 281 ++++++++++++++++++ src/Text/Test/CMakeLists.txt | 2 +- ...tRendererGLTest.cpp => RendererGLTest.cpp} | 28 +- src/Text/Text.h | 13 +- src/Text/TextRenderer.h | 276 +---------------- 10 files changed, 361 insertions(+), 324 deletions(-) rename src/Text/{TextRenderer.cpp => Renderer.cpp} (81%) create mode 100644 src/Text/Renderer.h rename src/Text/Test/{TextRendererGLTest.cpp => RendererGLTest.cpp} (89%) diff --git a/src/Test/AbstractOpenGLTester.h b/src/Test/AbstractOpenGLTester.h index f23a83e67..e551b4639 100644 --- a/src/Test/AbstractOpenGLTester.h +++ b/src/Test/AbstractOpenGLTester.h @@ -50,7 +50,7 @@ class AbstractOpenGLTester: public TestSuite::Tester, public Platform::Windowles int AbstractOpenGLTester::zero = 0; -#define MAGNUM_VERIFY_NO_ERROR() CORRADE_COMPARE(Renderer::error(), Renderer::Error::NoError) +#define MAGNUM_VERIFY_NO_ERROR() CORRADE_COMPARE(Magnum::Renderer::error(), Magnum::Renderer::Error::NoError) }} diff --git a/src/Text/AbstractFont.h b/src/Text/AbstractFont.h index 7ce640cce..45b99143b 100644 --- a/src/Text/AbstractFont.h +++ b/src/Text/AbstractFont.h @@ -45,22 +45,22 @@ namespace Magnum { namespace Text { @section AbstractFont-usage Usage -First step is to open the font using open(), next step is to prerender all the -glyphs which will be used in text rendering later, see GlyphCache for more -information. See TextRenderer for information about text rendering. +First step is to open the font using @ref open(), next step is to prerender all +the glyphs which will be used in text rendering later, see @ref GlyphCache for +more information. See @ref Renderer for information about text rendering. @section AbstractFont-subclassing Subclassing -Plugin implements doFeatures(), doClose(), doCreateGlyphCache(), doLayout() and -one or more of `doOpen*()` functions. +Plugin implements @ref doFeatures(), @ref doClose(), @ref doCreateGlyphCache(), +@ref doLayout() and one or more of `doOpen*()` functions. You don't need to do most of the redundant sanity checks, these things are checked by the implementation: -- Functions doOpenData(), doOpenSingleData() and doOpenFile() are called - after the previous file was closed, function doClose() is called only if - there is any file opened. -- Functions doOpenData() and doOpenSingleData() are called only if +- Functions @ref doOpenData(), @ref doOpenSingleData() and @ref doOpenFile() + are called after the previous file was closed, function @ref doClose() is + called only if there is any file opened. +- Functions @ref doOpenData() and @ref doOpenSingleData() are called only if @ref Feature::OpenData is supported. - All `do*()` implementations working on opened file are called only if there is any file opened. diff --git a/src/Text/CMakeLists.txt b/src/Text/CMakeLists.txt index b6937fdd5..1c31f4bd2 100644 --- a/src/Text/CMakeLists.txt +++ b/src/Text/CMakeLists.txt @@ -27,17 +27,22 @@ set(MagnumText_SRCS AbstractFontConverter.cpp DistanceFieldGlyphCache.cpp GlyphCache.cpp - TextRenderer.cpp) + Renderer.cpp) set(MagnumText_HEADERS AbstractFont.h AbstractFontConverter.h DistanceFieldGlyphCache.h GlyphCache.h + Renderer.h Text.h - TextRenderer.h magnumTextVisibility.h) +if(MAGNUM_BUILD_DEPRECATED) + set(MagnumText_HEADERS ${MagnumText_HEADERS} + TextRenderer.h) +endif() + add_library(MagnumText ${SHARED_OR_STATIC} ${MagnumText_SRCS}) if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property diff --git a/src/Text/GlyphCache.h b/src/Text/GlyphCache.h index 1234fc808..97d56ffce 100644 --- a/src/Text/GlyphCache.h +++ b/src/Text/GlyphCache.h @@ -45,7 +45,7 @@ Contains font glyphs prerendered into texture atlas. @section GlyphCache-usage Usage Create %GlyphCache object with sufficient size and then call -AbstractFont::createGlyphCache() to fill it with glyphs. +@ref AbstractFont::createGlyphCache() to fill it with glyphs. @code Text::AbstractFont* font; Text::GlyphCache* cache = new GlyphCache(Vector2i(512)); @@ -54,7 +54,7 @@ font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" "0123456789 "); @endcode -See TextRenderer for information about text rendering. +See @ref Renderer for information about text rendering. @todo Some way for Font to negotiate or check internal texture format @todo Default glyph 0 with rect 0 0 0 0 will result in negative dimensions when nonzero padding is removed diff --git a/src/Text/TextRenderer.cpp b/src/Text/Renderer.cpp similarity index 81% rename from src/Text/TextRenderer.cpp rename to src/Text/Renderer.cpp index 058d49ca3..a278e0d15 100644 --- a/src/Text/TextRenderer.cpp +++ b/src/Text/Renderer.cpp @@ -22,7 +22,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "TextRenderer.h" +#include "Renderer.h" #include "Context.h" #include "Extensions.h" @@ -60,7 +60,7 @@ struct Vertex { } -std::tuple, std::vector, std::vector, Rectangle> AbstractTextRenderer::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text) { +std::tuple, std::vector, std::vector, Rectangle> AbstractRenderer::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text) { const auto layouter = font.layout(cache, size, text); const UnsignedInt vertexCount = layouter->glyphCount()*4; @@ -118,7 +118,7 @@ std::tuple, std::vector, std::vector, return std::make_tuple(std::move(positions), std::move(texcoords), std::move(indices), rectangle); } -std::tuple AbstractTextRenderer::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage) { +std::tuple AbstractRenderer::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage) { const auto layouter = font.layout(cache, size, text); const UnsignedInt vertexCount = layouter->glyphCount()*4; @@ -192,9 +192,9 @@ std::tuple AbstractTextRenderer::render(AbstractFont& font, con return std::make_tuple(std::move(mesh), rectangle); } -template std::tuple TextRenderer::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage) { +template std::tuple Renderer::render(AbstractFont& font, const GlyphCache& cache, 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, cache, size, text, vertexBuffer, indexBuffer, usage); + auto r = AbstractRenderer::render(font, cache, size, text, vertexBuffer, indexBuffer, usage); Mesh& mesh = std::get<0>(r); mesh.addVertexBuffer(vertexBuffer, 0, typename Shaders::AbstractVector::Position( @@ -204,26 +204,26 @@ template std::tuple TextRendererisExtensionSupported()) { - bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationRange; + bufferMapImplementation = &AbstractRenderer::bufferMapImplementationRange; } else if(Context::current()->isExtensionSupported()) { - bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationSub; - bufferUnmapImplementation = &AbstractTextRenderer::bufferUnmapImplementationSub; + bufferMapImplementation = &AbstractRenderer::bufferMapImplementationSub; + bufferUnmapImplementation = &AbstractRenderer::bufferUnmapImplementationSub; } else { MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::mapbuffer); - Warning() << "Text::TextRenderer: neither" << Extensions::GL::EXT::map_buffer_range::string() + Warning() << "Text::Renderer: neither" << Extensions::GL::EXT::map_buffer_range::string() << "nor" << Extensions::GL::CHROMIUM::map_sub::string() << "is supported, using inefficient" << Extensions::GL::OES::mapbuffer::string() << "instead"; @@ -269,16 +269,16 @@ AbstractTextRenderer::AbstractTextRenderer(AbstractFont& font, const GlyphCache& _mesh.setPrimitive(Mesh::Primitive::Triangles); } -AbstractTextRenderer::~AbstractTextRenderer() {} +AbstractRenderer::~AbstractRenderer() {} -template TextRenderer::TextRenderer(AbstractFont& font, const GlyphCache& cache, const Float size): AbstractTextRenderer(font, cache, size) { +template Renderer::Renderer(AbstractFont& font, const GlyphCache& cache, const Float size): AbstractRenderer(font, cache, size) { /* Finalize mesh configuration */ _mesh.addVertexBuffer(_vertexBuffer, 0, typename Shaders::AbstractVector::Position(Shaders::AbstractVector::Position::Components::Two), typename Shaders::AbstractVector::TextureCoordinates()); } -void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usage vertexBufferUsage, const Buffer::Usage indexBufferUsage) { +void AbstractRenderer::reserve(const uint32_t glyphCount, const Buffer::Usage vertexBufferUsage, const Buffer::Usage indexBufferUsage) { _capacity = glyphCount; const UnsignedInt vertexCount = glyphCount*4; @@ -325,11 +325,11 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag bufferUnmapImplementation(_indexBuffer); } -void AbstractTextRenderer::render(const std::string& text) { +void AbstractRenderer::render(const std::string& text) { const auto layouter = font.layout(cache, size, text); CORRADE_ASSERT(layouter->glyphCount() <= _capacity, - "Text::TextRenderer::render(): capacity" << _capacity << "too small to render" << layouter->glyphCount() << "glyphs", ); + "Text::Renderer::render(): capacity" << _capacity << "too small to render" << layouter->glyphCount() << "glyphs", ); /* Reset rendered rectangle */ _rectangle = {}; @@ -371,8 +371,8 @@ void AbstractTextRenderer::render(const std::string& text) { } #ifndef DOXYGEN_GENERATING_OUTPUT -template class MAGNUM_TEXT_EXPORT TextRenderer<2>; -template class MAGNUM_TEXT_EXPORT TextRenderer<3>; +template class MAGNUM_TEXT_EXPORT Renderer<2>; +template class MAGNUM_TEXT_EXPORT Renderer<3>; #endif }} diff --git a/src/Text/Renderer.h b/src/Text/Renderer.h new file mode 100644 index 000000000..574de03a8 --- /dev/null +++ b/src/Text/Renderer.h @@ -0,0 +1,281 @@ +#ifndef Magnum_Text_Renderer_h +#define Magnum_Text_Renderer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Text::AbstractRenderer, @ref Magnum::Text::Renderer, typedef @ref Magnum::Text::Renderer2D, @ref Magnum::Text::Renderer3D + */ + +#include "Math/Geometry/Rectangle.h" +#include "Buffer.h" +#include "DimensionTraits.h" +#include "Mesh.h" +#include "Text/Text.h" + +#include "magnumTextVisibility.h" + +#include +#include +#include + +namespace Magnum { namespace Text { + +/** +@brief Base for text renderers + +Not meant to be used directly, see @ref Renderer for more information. +@see @ref Renderer2D, @ref Renderer3D +*/ +class MAGNUM_TEXT_EXPORT AbstractRenderer { + public: + /** + * @brief Render text + * @param font Font + * @param cache Glyph cache + * @param size Font size + * @param text Text to render + * + * Returns tuple with vertex positions, texture coordinates, indices + * and rectangle spanning the rendered text. + */ + static std::tuple, std::vector, std::vector, Rectangle> render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text); + + /** + * @brief Capacity for rendered glyphs + * + * @see @ref reserve() + */ + UnsignedInt capacity() const { return _capacity; } + + /** @brief Rectangle spanning the rendered text */ + Rectangle rectangle() const { return _rectangle; } + + /** @brief Vertex buffer */ + Buffer& vertexBuffer() { return _vertexBuffer; } + + /** @brief Index buffer */ + Buffer& indexBuffer() { return _indexBuffer; } + + /** @brief Mesh */ + Mesh& mesh() { return _mesh; } + + /** + * @brief Reserve capacity for rendered glyphs + * + * Reallocates memory in buffers to hold @p glyphCount glyphs and + * prefills index buffer. Consider using appropriate @p vertexBufferUsage + * if the text will be changed frequently. Index buffer is changed + * only by calling this function, thus @p indexBufferUsage generally + * doesn't need to be so dynamic if the capacity won't be changed much. + * + * Initially zero capacity is reserved. + * @see @ref capacity() + */ + void reserve(UnsignedInt glyphCount, Buffer::Usage vertexBufferUsage, Buffer::Usage indexBufferUsage); + + /** + * @brief Render text + * + * Renders the text to vertex buffer, reusing index buffer already + * filled with @ref reserve(). Rectangle spanning the rendered text is + * available through @ref rectangle(). + * + * Initially no text is rendered. + * @attention The capacity must be large enough to contain all glyphs, + * see @ref reserve() for more information. + */ + void render(const std::string& text); + + protected: + /** + * @brief Constructor + * @param font Font + * @param cache Glyph cache + * @param size Font size + */ + explicit AbstractRenderer(AbstractFont& font, const GlyphCache& cache, Float size); + AbstractRenderer(AbstractFont&, GlyphCache&&, Float) = delete; /**< @overload */ + + ~AbstractRenderer(); + + #ifndef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + static std::tuple MAGNUM_LOCAL render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage); + + Mesh _mesh; + Buffer _vertexBuffer, _indexBuffer; + #ifdef CORRADE_TARGET_EMSCRIPTEN + Containers::Array _vertexBufferData, _indexBufferData; + #endif + + private: + AbstractFont& font; + const GlyphCache& cache; + Float size; + UnsignedInt _capacity; + Rectangle _rectangle; + + #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) + typedef void*(*BufferMapImplementation)(Buffer&, GLsizeiptr); + static MAGNUM_TEXT_LOCAL void* bufferMapImplementationFull(Buffer& buffer, GLsizeiptr length); + static MAGNUM_TEXT_LOCAL void* bufferMapImplementationSub(Buffer& buffer, GLsizeiptr length); + static MAGNUM_TEXT_LOCAL void* bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length); + static BufferMapImplementation bufferMapImplementation; + #else + #ifndef CORRADE_TARGET_EMSCRIPTEN + static + #else + MAGNUM_TEXT_LOCAL + #endif + void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length); + #endif + + #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) + typedef void(*BufferUnmapImplementation)(Buffer&); + static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationDefault(Buffer& buffer); + static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationSub(Buffer& buffer); + static MAGNUM_TEXT_LOCAL BufferUnmapImplementation bufferUnmapImplementation; + #else + #ifndef CORRADE_TARGET_EMSCRIPTEN + static + #else + MAGNUM_TEXT_LOCAL + #endif + void bufferUnmapImplementation(Buffer& buffer); + #endif +}; + +/** +@brief %Text renderer + +Lays out the text into mesh using given font. Use of ligatures, kerning etc. +depends on features supported by particular font and its layouter. + +@section Renderer-usage Usage + +Immutable text (e.g. menu items, credits) can be simply rendered using static +methods, returning result either as data arrays or as fully configured mesh. +The text can be then drawn by configuring text shader, binding font texture +and drawing the mesh: +@code +Text::AbstractFont* font; +Text::GlyphCache cache; + +Shaders::VectorShader2D shader; +Buffer vertexBuffer, indexBuffer; +Mesh mesh; + +// Render the text +Rectangle rectangle; +std::tie(mesh, rectangle) = Text::Renderer2D::render(*font, cache, 0.15f, + "Hello World!", vertexBuffer, indexBuffer, Buffer::Usage::StaticDraw); + +// Draw white text centered on the screen +shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-rectangle.width()/2.0f)) + .setColor(Color3(1.0f)); + .use(); +glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); +mesh.draw(); +@endcode +See @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&) and +@ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Buffer&, Buffer&, Buffer::Usage) +for more information. + +While this method is sufficient for one-shot rendering of static texts, for +mutable texts (e.g. FPS counters, chat messages) there is another approach +that doesn't recreate everything on each text change: +@code +Text::AbstractFont* font; +Text::GlyphCache cache; +Shaders::VectorShader2D shader; + +// Initialize renderer and reserve memory for enough glyphs +Text::Renderer2D renderer(*font, cache, 0.15f); +renderer.reserve(32, Buffer::Usage::DynamicDraw, Buffer::Usage::StaticDraw); + +// Update the text occasionally +renderer.render("Hello World Countdown: 10"); + +// Draw the text centered on the screen +shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-renderer.rectangle().width()/2.0f)) + .setColor(Color3(1.0f)); + .use(); +glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); +renderer.mesh().draw(); +@endcode + +@section Renderer-extensions Required OpenGL functionality + +Mutable text rendering requires @extension{ARB,map_buffer_range} on desktop +OpenGL (also part of OpenGL ES 3.0). If neither @es_extension{EXT,map_buffer_range} +nor @es_extension{CHROMIUM,map_sub} is not available in ES 2.0, at least +@es_extension{OES,mapbuffer} must be supported for asynchronous buffer updates. +There is no similar extension in WebGL, thus plain (and slow) buffer updates +are used there. + +@see @ref Renderer2D, @ref Renderer3D, @ref AbstractFont, + @ref Shaders::AbstractVector +*/ +template class MAGNUM_TEXT_EXPORT Renderer: public AbstractRenderer { + public: + /** + * @brief Render text + * @param font Font + * @param cache Glyph cache + * @param size Font size + * @param text %Text to render + * @param vertexBuffer %Buffer where to store vertices + * @param indexBuffer %Buffer where to store indices + * @param usage Usage of vertex and index buffer + * + * Returns mesh prepared for use with @ref Shaders::AbstractVector + * subclasses and rectangle spanning the rendered text. + */ + static std::tuple render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage); + + /** + * @brief Constructor + * @param font Font + * @param cache Glyph cache + * @param size Font size + */ + explicit Renderer(AbstractFont& font, const GlyphCache& cache, Float size); + Renderer(AbstractFont&, GlyphCache&&, Float) = delete; /**< @overload */ + + using AbstractRenderer::render; +}; + +/** @brief Two-dimensional text renderer */ +typedef Renderer<2> Renderer2D; + +/** @brief Three-dimensional text renderer */ +typedef Renderer<3> Renderer3D; + +}} + +#endif diff --git a/src/Text/Test/CMakeLists.txt b/src/Text/Test/CMakeLists.txt index 44adf1510..3f133a008 100644 --- a/src/Text/Test/CMakeLists.txt +++ b/src/Text/Test/CMakeLists.txt @@ -32,5 +32,5 @@ corrade_add_test(TextAbstractFontConverterTest AbstractFontConverterTest.cpp LIB if(BUILD_GL_TESTS) corrade_add_test(TextGlyphCacheGLTest GlyphCacheGLTest.cpp LIBRARIES MagnumText ${GL_TEST_LIBRARIES}) - corrade_add_test(TextRendererGLTest TextRendererGLTest.cpp LIBRARIES MagnumText ${GL_TEST_LIBRARIES}) + corrade_add_test(TextRendererGLTest RendererGLTest.cpp LIBRARIES MagnumText ${GL_TEST_LIBRARIES}) endif() diff --git a/src/Text/Test/TextRendererGLTest.cpp b/src/Text/Test/RendererGLTest.cpp similarity index 89% rename from src/Text/Test/TextRendererGLTest.cpp rename to src/Text/Test/RendererGLTest.cpp index a960ad9a6..467c691f5 100644 --- a/src/Text/Test/TextRendererGLTest.cpp +++ b/src/Text/Test/RendererGLTest.cpp @@ -24,23 +24,23 @@ #include "Test/AbstractOpenGLTester.h" #include "Text/AbstractFont.h" -#include "Text/TextRenderer.h" +#include "Text/Renderer.h" namespace Magnum { namespace Text { namespace Test { -class TextRendererGLTest: public Magnum::Test::AbstractOpenGLTester { +class RendererGLTest: public Magnum::Test::AbstractOpenGLTester { public: - explicit TextRendererGLTest(); + explicit RendererGLTest(); void renderData(); void renderMesh(); void mutableText(); }; -TextRendererGLTest::TextRendererGLTest() { - addTests({&TextRendererGLTest::renderData, - &TextRendererGLTest::renderMesh, - &TextRendererGLTest::mutableText}); +RendererGLTest::RendererGLTest() { + addTests({&RendererGLTest::renderData, + &RendererGLTest::renderMesh, + &RendererGLTest::mutableText}); } namespace { @@ -80,13 +80,13 @@ class TestFont: public Text::AbstractFont { } -void TextRendererGLTest::renderData() { +void RendererGLTest::renderData() { TestFont font; std::vector positions; std::vector textureCoordinates; std::vector indices; Rectangle bounds; - std::tie(positions, textureCoordinates, indices, bounds) = Text::AbstractTextRenderer::render(font, *static_cast(nullptr), 0.25f, "abc"); + std::tie(positions, textureCoordinates, indices, bounds) = Text::AbstractRenderer::render(font, *static_cast(nullptr), 0.25f, "abc"); /* Three glyphs, three quads -> 12 vertices, 18 indices */ CORRADE_COMPARE(positions.size(), 12); @@ -160,12 +160,12 @@ void TextRendererGLTest::renderData() { CORRADE_COMPARE(bounds, Rectangle({0.0f, -0.5f}, {5.0f, 1.0f})); } -void TextRendererGLTest::renderMesh() { +void RendererGLTest::renderMesh() { TestFont font; Mesh mesh; Buffer vertexBuffer, indexBuffer; Rectangle bounds; - std::tie(mesh, bounds) = Text::TextRenderer3D::render(font, *static_cast(nullptr), 0.25f, "abc", vertexBuffer, indexBuffer, Buffer::Usage::StaticDraw); + std::tie(mesh, bounds) = Text::Renderer3D::render(font, *static_cast(nullptr), 0.25f, "abc", vertexBuffer, indexBuffer, Buffer::Usage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify this on ES? */ @@ -201,9 +201,9 @@ void TextRendererGLTest::renderMesh() { CORRADE_COMPARE(bounds, Rectangle({0.0f, -0.5f}, {5.0f, 1.0f})); } -void TextRendererGLTest::mutableText() { +void RendererGLTest::mutableText() { TestFont font; - Text::TextRenderer2D renderer(font, *static_cast(nullptr), 0.25f); + Text::Renderer2D renderer(font, *static_cast(nullptr), 0.25f); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(renderer.capacity(), 0); CORRADE_COMPARE(renderer.rectangle(), Rectangle()); @@ -253,4 +253,4 @@ void TextRendererGLTest::mutableText() { }}} -CORRADE_TEST_MAIN(Magnum::Text::Test::TextRendererGLTest) +CORRADE_TEST_MAIN(Magnum::Text::Test::RendererGLTest) diff --git a/src/Text/Text.h b/src/Text/Text.h index e0b51c2cf..c14bee215 100644 --- a/src/Text/Text.h +++ b/src/Text/Text.h @@ -40,10 +40,15 @@ class AbstractLayouter; class DistanceFieldGlyphCache; class GlyphCache; -class AbstractTextRenderer; -template class TextRenderer; -typedef TextRenderer<2> TextRenderer2D; -typedef TextRenderer<3> TextRenderer3D; +class AbstractRenderer; +template class Renderer; +typedef Renderer<2> Renderer2D; +typedef Renderer<3> Renderer3D; + +#ifdef MAGNUM_BUILD_DEPRECATED +typedef Renderer<2> TextRenderer2D; +typedef Renderer<3> TextRenderer3D; +#endif }} diff --git a/src/Text/TextRenderer.h b/src/Text/TextRenderer.h index 9cc2f97e4..53ed366d6 100644 --- a/src/Text/TextRenderer.h +++ b/src/Text/TextRenderer.h @@ -1,279 +1,25 @@ #ifndef Magnum_Text_TextRenderer_h #define Magnum_Text_TextRenderer_h -/* - This file is part of Magnum. - Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ - -/** @file - * @brief Class Magnum::Text::AbstractTextRenderer, Magnum::Text::TextRenderer, typedef Magnum::Text::TextRenderer2D, Magnum::Text::TextRenderer3D - */ - -#include "Math/Geometry/Rectangle.h" -#include "Buffer.h" -#include "DimensionTraits.h" -#include "Mesh.h" -#include "Text/Text.h" - -#include "magnumTextVisibility.h" - -#include -#include -#include +#include "Text/Renderer.h" namespace Magnum { namespace Text { +#ifdef MAGNUM_BUILD_DEPRECATED /** -@brief Base for text renderers - -Not meant to be used directly, see TextRenderer for more information. -@see TextRenderer2D, TextRenderer3D +@copybrief Renderer2D +@deprecated Use @ref Magnum::Text::Renderer2D "Renderer2D" instead. */ -class MAGNUM_TEXT_EXPORT AbstractTextRenderer { - public: - /** - * @brief Render text - * @param font Font - * @param cache Glyph cache - * @param size Font size - * @param text Text to render - * - * Returns tuple with vertex positions, texture coordinates, indices - * and rectangle spanning the rendered text. - */ - static std::tuple, std::vector, std::vector, Rectangle> render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text); - - /** - * @brief Capacity for rendered glyphs - * - * @see reserve() - */ - UnsignedInt capacity() const { return _capacity; } - - /** @brief Rectangle spanning the rendered text */ - Rectangle rectangle() const { return _rectangle; } - - /** @brief Vertex buffer */ - Buffer& vertexBuffer() { return _vertexBuffer; } - - /** @brief Index buffer */ - Buffer& indexBuffer() { return _indexBuffer; } - - /** @brief Mesh */ - Mesh& mesh() { return _mesh; } - - /** - * @brief Reserve capacity for rendered glyphs - * - * Reallocates memory in buffers to hold @p glyphCount glyphs and - * prefills index buffer. Consider using appropriate @p vertexBufferUsage - * if the text will be changed frequently. Index buffer is changed - * only by calling this function, thus @p indexBufferUsage generally - * doesn't need to be so dynamic if the capacity won't be changed much. - * - * Initially zero capacity is reserved. - * @see capacity() - */ - void reserve(UnsignedInt glyphCount, Buffer::Usage vertexBufferUsage, Buffer::Usage indexBufferUsage); - - /** - * @brief Render text - * - * Renders the text to vertex buffer, reusing index buffer already - * filled with reserve(). Rectangle spanning the rendered text is - * available through rectangle(). - * - * Initially no text is rendered. - * @attention The capacity must be large enough to contain all glyphs, - * see reserve() for more information. - */ - void render(const std::string& text); - - protected: - /** - * @brief Constructor - * @param font Font - * @param cache Glyph cache - * @param size Font size - */ - explicit AbstractTextRenderer(AbstractFont& font, const GlyphCache& cache, Float size); - AbstractTextRenderer(AbstractFont&, GlyphCache&&, Float) = delete; /**< @overload */ - - ~AbstractTextRenderer(); - - #ifndef DOXYGEN_GENERATING_OUTPUT - protected: - #else - private: - #endif - static std::tuple MAGNUM_LOCAL render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage); - - Mesh _mesh; - Buffer _vertexBuffer, _indexBuffer; - #ifdef CORRADE_TARGET_EMSCRIPTEN - Containers::Array _vertexBufferData, _indexBufferData; - #endif - - private: - AbstractFont& font; - const GlyphCache& cache; - Float size; - UnsignedInt _capacity; - Rectangle _rectangle; - - #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) - typedef void*(*BufferMapImplementation)(Buffer&, GLsizeiptr); - static MAGNUM_TEXT_LOCAL void* bufferMapImplementationFull(Buffer& buffer, GLsizeiptr length); - static MAGNUM_TEXT_LOCAL void* bufferMapImplementationSub(Buffer& buffer, GLsizeiptr length); - static MAGNUM_TEXT_LOCAL void* bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length); - static BufferMapImplementation bufferMapImplementation; - #else - #ifndef CORRADE_TARGET_EMSCRIPTEN - static - #else - MAGNUM_TEXT_LOCAL - #endif - void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length); - #endif - - #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) - typedef void(*BufferUnmapImplementation)(Buffer&); - static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationDefault(Buffer& buffer); - static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationSub(Buffer& buffer); - static MAGNUM_TEXT_LOCAL BufferUnmapImplementation bufferUnmapImplementation; - #else - #ifndef CORRADE_TARGET_EMSCRIPTEN - static - #else - MAGNUM_TEXT_LOCAL - #endif - void bufferUnmapImplementation(Buffer& buffer); - #endif -}; +typedef Renderer<2> TextRenderer2D; /** -@brief %Text renderer - -Lays out the text into mesh using given Font. Use of ligatures, kerning etc. -depends on features supported by particular font and its layouter. - -@section TextRenderer-usage Usage - -Immutable text (e.g. menu items, credits) can be simply rendered using static -methods, returning result either as data arrays or as fully configured mesh. -The text can be then drawn by configuring text shader, binding font texture -and drawing the mesh: -@code -Text::AbstractFont* font; -Text::GlyphCache cache; - -Shaders::VectorShader2D shader; -Buffer vertexBuffer, indexBuffer; -Mesh mesh; - -// Render the text -Rectangle rectangle; -std::tie(mesh, rectangle) = Text::TextRenderer2D::render(*font, cache, 0.15f, - "Hello World!", vertexBuffer, indexBuffer, Buffer::Usage::StaticDraw); - -// Draw white text centered on the screen -shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-rectangle.width()/2.0f)) - .setColor(Color3(1.0f)); - .use(); -glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); -mesh.draw(); -@endcode -See render(Font* const, const GlyphCache* const, Float, const std::string&) and -render(Font* const, const GlyphCache* const, Float, const std::string&, Buffer*, Buffer*, Buffer::Usage) -for more information. - -While this method is sufficient for one-shot rendering of static texts, for -mutable texts (e.g. FPS counters, chat messages) there is another approach -that doesn't recreate everything on each text change: -@code -Text::AbstractFont* font; -Text::GlyphCache cache; -Shaders::VectorShader2D shader; - -// Initialize renderer and reserve memory for enough glyphs -Text::TextRenderer2D renderer(*font, cache, 0.15f); -renderer.reserve(32, Buffer::Usage::DynamicDraw, Buffer::Usage::StaticDraw); - -// Update the text occasionally -renderer.render("Hello World Countdown: 10"); - -// Draw the text centered on the screen -shader.setTransformationProjectionMatrix(projection*Matrix3::translation(-renderer.rectangle().width()/2.0f)) - .setColor(Color3(1.0f)); - .use(); -glyphCache->texture()->bind(Shaders::VectorShader2D::FontTextureLayer); -renderer.mesh().draw(); -@endcode - -@section TextRenderer-extensions Required OpenGL functionality - -Mutable text rendering requires @extension{ARB,map_buffer_range} on desktop -OpenGL (also part of OpenGL ES 3.0). If neither @es_extension{EXT,map_buffer_range} -nor @es_extension{CHROMIUM,map_sub} is not available in ES 2.0, at least -@es_extension{OES,mapbuffer} must be supported for asynchronous buffer updates. -There is no similar extension in WebGL, thus plain (and slow) buffer updates -are used there. - -@see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader +@copybrief Renderer3D +@deprecated Use @ref Magnum::Text::Renderer3D "Renderer3D" instead. */ -template class MAGNUM_TEXT_EXPORT TextRenderer: public AbstractTextRenderer { - public: - /** - * @brief Render text - * @param font Font - * @param cache Glyph cache - * @param size Font size - * @param text %Text to render - * @param vertexBuffer %Buffer where to store vertices - * @param indexBuffer %Buffer where to store indices - * @param usage Usage of vertex and index buffer - * - * Returns mesh prepared for use with Shaders::AbstractVectorShader - * subclasses and rectangle spanning the rendered text. - */ - static std::tuple render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, Buffer::Usage usage); - - /** - * @brief Constructor - * @param font Font - * @param cache Glyph cache - * @param size Font size - */ - explicit TextRenderer(AbstractFont& font, const GlyphCache& cache, Float size); - TextRenderer(AbstractFont&, GlyphCache&&, Float) = delete; /**< @overload */ - - using AbstractTextRenderer::render; -}; - -/** @brief Two-dimensional text renderer */ -typedef TextRenderer<2> TextRenderer2D; - -/** @brief Three-dimensional text renderer */ -typedef TextRenderer<3> TextRenderer3D; +typedef Renderer<3> TextRenderer3D; +#else +#error +#endif }}