Browse Source

Text: non-templated base for TextRenderer.

Saves a lot of duplicated generated code.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
2944a4e205
  1. 1
      src/Text/Text.h
  2. 38
      src/Text/TextRenderer.cpp
  3. 148
      src/Text/TextRenderer.h

1
src/Text/Text.h

@ -26,6 +26,7 @@ namespace Magnum { namespace Text {
class Font;
class FontRenderer;
class AbstractTextRenderer;
template<UnsignedInt> class TextRenderer;
typedef TextRenderer<2> TextRenderer2D;
typedef TextRenderer<3> TextRenderer3D;

38
src/Text/TextRenderer.cpp

@ -154,7 +154,7 @@ struct Vertex {
}
template<UnsignedInt dimensions> std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> TextRenderer<dimensions>::render(Font& font, Float size, const std::string& text) {
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;
@ -200,7 +200,7 @@ template<UnsignedInt dimensions> std::tuple<std::vector<Vector2>, std::vector<Ve
return std::make_tuple(std::move(positions), std::move(texcoords), std::move(indices), 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) {
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);
const UnsignedInt vertexCount = layouter.glyphCount()*4;
@ -257,19 +257,28 @@ template<UnsignedInt dimensions> std::tuple<Mesh, Rectangle> TextRenderer<dimens
Rectangle rectangle;
if(layouter.glyphCount()) rectangle = {vertices[1].position, vertices[vertices.size()-2].position};
/* Configure mesh */
/* Configure mesh except for vertex buffer (depends on dimension count, done
in subclass) */
Mesh mesh;
mesh.setPrimitive(Mesh::Primitive::Triangles)
->setIndexCount(indexCount)
->addInterleavedVertexBuffer(vertexBuffer, 0,
typename Shaders::AbstractVectorShader<dimensions>::Position(Shaders::AbstractVectorShader<dimensions>::Position::Components::Two),
typename Shaders::AbstractVectorShader<dimensions>::TextureCoordinates())
->setIndexBuffer(indexBuffer, 0, indexType, 0, vertexCount);
return std::make_tuple(std::move(mesh), rectangle);
}
template<UnsignedInt dimensions> TextRenderer<dimensions>::TextRenderer(Font& font, const Float size): font(font), size(size), _capacity(0), vertexBuffer(Buffer::Target::Array), indexBuffer(Buffer::Target::ElementArray) {
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) {
/* Finalize mesh configuration and return the result */
auto r = AbstractTextRenderer::render(font, size, text, vertexBuffer, indexBuffer, usage);
Mesh& mesh = std::get<0>(r);
mesh.addInterleavedVertexBuffer(vertexBuffer, 0,
typename Shaders::AbstractVectorShader<dimensions>::Position(
Shaders::AbstractVectorShader<dimensions>::Position::Components::Two),
typename Shaders::AbstractVectorShader<dimensions>::TextureCoordinates());
return std::move(r);
}
AbstractTextRenderer::AbstractTextRenderer(Font& 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
@ -278,13 +287,20 @@ template<UnsignedInt dimensions> TextRenderer<dimensions>::TextRenderer(Font& fo
#endif
#endif
_mesh.setPrimitive(Mesh::Primitive::Triangles)
->addInterleavedVertexBuffer(&vertexBuffer, 0,
/* Vertex buffer configuration depends on dimension count, done in subclass */
_mesh.setPrimitive(Mesh::Primitive::Triangles);
}
AbstractTextRenderer::~AbstractTextRenderer() {}
template<UnsignedInt dimensions> TextRenderer<dimensions>::TextRenderer(Font& 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),
typename Shaders::AbstractVectorShader<dimensions>::TextureCoordinates());
}
template<UnsignedInt dimensions> void TextRenderer<dimensions>::reserve(const uint32_t glyphCount, const Buffer::Usage vertexBufferUsage, const Buffer::Usage indexBufferUsage) {
void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usage vertexBufferUsage, const Buffer::Usage indexBufferUsage) {
_capacity = glyphCount;
const UnsignedInt vertexCount = glyphCount*4;
@ -322,7 +338,7 @@ template<UnsignedInt dimensions> void TextRenderer<dimensions>::reserve(const ui
CORRADE_INTERNAL_ASSERT_OUTPUT(indexBuffer.unmap());
}
template<UnsignedInt dimensions> void TextRenderer<dimensions>::render(const std::string& text) {
void AbstractTextRenderer::render(const std::string& text) {
TextLayouter layouter(font, size, text);
CORRADE_ASSERT(layouter.glyphCount() <= _capacity, "Text::TextRenderer::render(): capacity" << _capacity << "too small to render" << layouter.glyphCount() << "glyphs", );

148
src/Text/TextRenderer.h

@ -16,7 +16,7 @@
*/
/** @file
* @brief Class Magnum::Text::TextRenderer
* @brief Class Magnum::Text::AbstractTextRenderer, Magnum::Text::TextRenderer, typedef Magnum::Text::TextRenderer2D, Magnum::Text::TextRenderer3D
*/
#include "Math/Geometry/Rectangle.h"
@ -33,6 +33,91 @@
namespace Magnum { namespace Text {
/**
@brief Base for text renderers
Not meant to be used directly, see TextRenderer for more information.
@see TextRenderer2D, TextRenderer3D
*/
class MAGNUM_TEXT_EXPORT AbstractTextRenderer {
public:
/**
* @brief Render text
* @param font %Font to use
* @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<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> render(Font& font, Float size, const std::string& text);
/**
* @brief Constructor
* @param font %Font to use
* @param size %Font size
*/
AbstractTextRenderer(Font& font, Float size);
virtual ~AbstractTextRenderer() = 0;
/**
* @brief Capacity for rendered glyphs
*
* @see reserve()
*/
inline UnsignedInt capacity() const { return _capacity; }
/** @brief Rectangle spanning the rendered text */
inline Rectangle rectangle() const { return _rectangle; }
/** @brief Text mesh */
inline 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(const UnsignedInt glyphCount, const Buffer::Usage vertexBufferUsage, const 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);
#ifndef DOXYGEN_GENERATING_OUTPUT
protected:
#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);
Mesh _mesh;
Buffer vertexBuffer, indexBuffer;
private:
Font& font;
Float size;
UnsignedInt _capacity;
Rectangle _rectangle;
};
/**
@brief %Text renderer
@ -98,19 +183,8 @@ for asynchronous buffer updates.
@see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader
*/
template<UnsignedInt dimensions> class MAGNUM_TEXT_EXPORT TextRenderer {
template<UnsignedInt dimensions> class MAGNUM_TEXT_EXPORT TextRenderer: public AbstractTextRenderer {
public:
/**
* @brief Render text
* @param font %Font to use
* @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<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>, Rectangle> render(Font& font, Float size, const std::string& text);
/**
* @brief Render text
* @param font %Font to use
@ -132,53 +206,7 @@ template<UnsignedInt dimensions> class MAGNUM_TEXT_EXPORT TextRenderer {
*/
TextRenderer(Font& font, Float size);
/**
* @brief Capacity for rendered glyphs
*
* @see reserve()
*/
inline UnsignedInt capacity() const { return _capacity; }
/** @brief Rectangle spanning the rendered text */
inline Rectangle rectangle() const { return _rectangle; }
/** @brief Text mesh */
inline 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(const UnsignedInt glyphCount, const Buffer::Usage vertexBufferUsage, const 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);
private:
Font& font;
Float size;
UnsignedInt _capacity;
Rectangle _rectangle;
Buffer vertexBuffer, indexBuffer;
Mesh _mesh;
using AbstractTextRenderer::render;
};
/** @brief Two-dimensional text renderer */

Loading…
Cancel
Save