Browse Source

Split the OpenGL layer out, pt 22: adapted Text.

pull/233/head
Vladimír Vondruš 8 years ago
parent
commit
23b46ac91a
  1. 2
      src/Magnum/Text/AbstractFont.h
  2. 71
      src/Magnum/Text/DistanceFieldGlyphCache.cpp
  3. 2
      src/Magnum/Text/DistanceFieldGlyphCache.h
  4. 34
      src/Magnum/Text/GlyphCache.cpp
  5. 14
      src/Magnum/Text/GlyphCache.h
  6. 55
      src/Magnum/Text/Renderer.cpp
  7. 36
      src/Magnum/Text/Renderer.h
  8. 6
      src/Magnum/Text/Test/GlyphCacheGLTest.cpp
  9. 46
      src/Magnum/Text/Test/RendererGLTest.cpp
  10. 3
      src/Magnum/Text/fontconverter.cpp

2
src/Magnum/Text/AbstractFont.h

@ -36,7 +36,7 @@
#include <Corrade/PluginManager/AbstractPlugin.h>
#include "Magnum/Magnum.h"
#include "Magnum/Texture.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Text/Text.h"
#include "Magnum/Text/visibility.h"

71
src/Magnum/Text/DistanceFieldGlyphCache.cpp

@ -25,65 +25,69 @@
#include "DistanceFieldGlyphCache.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/ImageView.h"
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#ifndef CORRADE_NO_ASSERT
#include "Magnum/PixelFormat.h"
#include "Magnum/GL/PixelFormat.h"
#endif
#include "Magnum/TextureFormat.h"
#include "Magnum/GL/TextureFormat.h"
#include "Magnum/TextureTools/DistanceField.h"
namespace Magnum { namespace Text {
DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& size, const UnsignedInt radius):
#if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2))
GlyphCache(TextureFormat::R8, originalSize, size, Vector2i(radius)),
GlyphCache(GL::TextureFormat::R8, originalSize, size, Vector2i(radius)),
#elif !defined(MAGNUM_TARGET_WEBGL)
/* Luminance is not renderable in most cases */
GlyphCache(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>() ?
TextureFormat::Red : TextureFormat::RGB, originalSize, size, Vector2i(radius)),
GlyphCache(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>() ?
GL::TextureFormat::Red : GL::TextureFormat::RGB, originalSize, size, Vector2i(radius)),
#else
GlyphCache(TextureFormat::RGB, originalSize, size, Vector2i(radius)),
GlyphCache(GL::TextureFormat::RGB, originalSize, size, Vector2i(radius)),
#endif
scale(Vector2(size)/Vector2(originalSize)), radius(radius)
{
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::texture_rg);
#endif
#if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Luminance is not renderable in most cases */
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>())
Warning() << "Text::DistanceFieldGlyphCache:" << Extensions::GL::EXT::texture_rg::string() << "not supported, using inefficient RGB format for glyph cache texture";
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>())
Warning() << "Text::DistanceFieldGlyphCache:" << GL::Extensions::EXT::texture_rg::string() << "not supported, using inefficient RGB format for glyph cache texture";
#endif
}
void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageView2D& image) {
const GL::PixelFormat format = GL::pixelFormat(image.format());
#if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2))
const TextureFormat internalFormat = TextureFormat::R8;
CORRADE_ASSERT(image.format() == PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Red << "but got" << image.format(), );
const GL::TextureFormat internalFormat = GL::TextureFormat::R8;
CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Red << "but got" << format, );
#else
TextureFormat internalFormat;
GL::TextureFormat internalFormat;
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>()) {
internalFormat = TextureFormat::Red;
CORRADE_ASSERT(image.format() == PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Red << "but got" << image.format(), );
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>()) {
internalFormat = GL::TextureFormat::Red;
CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Red << "but got" << format, );
} else
#endif
{
internalFormat = TextureFormat::Luminance;
CORRADE_ASSERT(image.format() == PixelFormat::Luminance,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Luminance << "but got" << image.format(), );
internalFormat = GL::TextureFormat::Luminance;
CORRADE_ASSERT(format == GL::PixelFormat::Luminance,
"Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Luminance << "but got" << format, );
}
#endif
Texture2D input;
input.setWrapping(Sampler::Wrapping::ClampToEdge)
.setMinificationFilter(Sampler::Filter::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
GL::Texture2D input;
input.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMinificationFilter(GL::SamplerFilter::Linear)
.setMagnificationFilter(GL::SamplerFilter::Linear)
.setImage(0, internalFormat, image);
/* Create distance field from input texture */
@ -91,20 +95,21 @@ void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageView2D
}
void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, const ImageView2D& image) {
const GL::PixelFormat format = GL::pixelFormat(image.format());
#if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2))
CORRADE_ASSERT(image.format() == PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::Red << "but got" << image.format(), );
CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::Red << "but got" << format, );
#else
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>())
CORRADE_ASSERT(image.format() == PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::Red << "but got" << image.format(), );
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>())
CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::Red << "but got" << format, );
else
#endif
{
/* Luminance is not renderable in most cases */
CORRADE_ASSERT(image.format() == PixelFormat::RGB,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::RGB << "but got" << image.format(), );
CORRADE_ASSERT(format == GL::PixelFormat::RGB,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::RGB << "but got" << format, );
}
#endif

2
src/Magnum/Text/DistanceFieldGlyphCache.h

@ -61,7 +61,7 @@ class MAGNUM_TEXT_EXPORT DistanceFieldGlyphCache: public GlyphCache {
* the parameters. Sets internal texture format to red channel only. On
* desktop OpenGL requires @extension{ARB,texture_rg} (also part of
* OpenGL ES 3.0), in ES2 uses @extension{EXT,texture_rg} if
* available or @ref TextureFormat::RGB as fallback.
* available or @ref GL::TextureFormat::RGB as fallback.
* @todo Is Luminance format renderable anywhere? Also would it be
* possible to convert the RGB texture to Luminance after it has
* been rendered when blitting is not supported to save memory?

34
src/Magnum/Text/GlyphCache.cpp

@ -25,17 +25,17 @@
#include "GlyphCache.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Image.h"
#include "Magnum/TextureFormat.h"
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/TextureFormat.h"
#include "Magnum/TextureTools/Atlas.h"
namespace Magnum { namespace Text {
GlyphCache::GlyphCache(const TextureFormat internalFormat, const Vector2i& size, const Vector2i& padding): GlyphCache{internalFormat, size, size, padding} {}
GlyphCache::GlyphCache(const GL::TextureFormat internalFormat, const Vector2i& size, const Vector2i& padding): GlyphCache{internalFormat, size, size, padding} {}
GlyphCache::GlyphCache(const TextureFormat internalFormat, const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding): _size(originalSize), _padding(padding) {
GlyphCache::GlyphCache(const GL::TextureFormat internalFormat, const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding): _size(originalSize), _padding(padding) {
initialize(internalFormat, size);
}
@ -43,20 +43,20 @@ GlyphCache::GlyphCache(const Vector2i& size, const Vector2i& padding): GlyphCach
GlyphCache::GlyphCache(const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding): _size(originalSize), _padding(padding) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::texture_rg);
#endif
/** @todo Is there any better way to select proper sized/unsized format on ES2? */
#ifndef MAGNUM_TARGET_GLES2
const TextureFormat internalFormat = TextureFormat::R8;
const GL::TextureFormat internalFormat = GL::TextureFormat::R8;
#elif !defined(MAGNUM_TARGET_WEBGL)
TextureFormat internalFormat;
if(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>()) {
internalFormat = Context::current().isExtensionSupported<Extensions::GL::EXT::texture_storage>() ?
TextureFormat::R8 : TextureFormat::Red;
} else internalFormat = TextureFormat::Luminance;
GL::TextureFormat internalFormat;
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>()) {
internalFormat = GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_storage>() ?
GL::TextureFormat::R8 : GL::TextureFormat::Red;
} else internalFormat = GL::TextureFormat::Luminance;
#else
const TextureFormat internalFormat = TextureFormat::Luminance;
const GL::TextureFormat internalFormat = GL::TextureFormat::Luminance;
#endif
initialize(internalFormat, size);
@ -64,11 +64,11 @@ GlyphCache::GlyphCache(const Vector2i& originalSize, const Vector2i& size, const
GlyphCache::~GlyphCache() = default;
void GlyphCache::initialize(const TextureFormat internalFormat, const Vector2i& size) {
void GlyphCache::initialize(const GL::TextureFormat internalFormat, const Vector2i& size) {
/* Initialize texture */
_texture.setWrapping(Sampler::Wrapping::ClampToEdge)
.setMinificationFilter(Sampler::Filter::Linear)
.setMagnificationFilter(Sampler::Filter::Linear)
_texture.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMinificationFilter(GL::SamplerFilter::Linear)
.setMagnificationFilter(GL::SamplerFilter::Linear)
.setStorage(1, internalFormat, size);
/* Default "Not Found" glyph */

14
src/Magnum/Text/GlyphCache.h

@ -33,7 +33,7 @@
#include <unordered_map>
#include "Magnum/Math/Range.h"
#include "Magnum/Texture.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Text/visibility.h"
namespace Magnum { namespace Text {
@ -68,14 +68,14 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
* although the actual glyph cache texture has @p size. Glyph
* @p padding can be used to account for e.g. glyph shadows.
*/
explicit GlyphCache(TextureFormat internalFormat, const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding);
explicit GlyphCache(GL::TextureFormat internalFormat, const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding);
/**
* @brief Constructor
*
* Same as calling the above with @p originalSize and @p size the same.
*/
explicit GlyphCache(TextureFormat internalFormat, const Vector2i& size, const Vector2i& padding = {});
explicit GlyphCache(GL::TextureFormat internalFormat, const Vector2i& size, const Vector2i& padding = {});
/**
* @brief Constructor
@ -83,7 +83,7 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
* Sets internal texture format to red channel only. On desktop OpenGL
* requires @extension{ARB,texture_rg} (also part of OpenGL ES 3.0), in
* ES2 uses @extension{EXT,texture_rg}, if available, or
* @ref TextureFormat::Luminance as fallback.
* @ref GL::TextureFormat::Luminance as fallback.
*/
explicit GlyphCache(const Vector2i& originalSize, const Vector2i& size, const Vector2i& padding);
@ -110,7 +110,7 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
std::size_t glyphCount() const { return glyphs.size(); }
/** @brief Cache texture */
Texture2D& texture() { return _texture; }
GL::Texture2D& texture() { return _texture; }
/**
* @brief Parameters of given glyph
@ -183,10 +183,10 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
virtual void setImage(const Vector2i& offset, const ImageView2D& image);
private:
void MAGNUM_LOCAL initialize(TextureFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL initialize(GL::TextureFormat internalFormat, const Vector2i& size);
Vector2i _size, _padding;
Texture2D _texture;
GL::Texture2D _texture;
std::unordered_map<UnsignedInt, std::pair<Vector2i, Range2Di>> glyphs;
};

55
src/Magnum/Text/Renderer.cpp

@ -27,9 +27,10 @@
#include <Corrade/Containers/Array.h>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Mesh.h"
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Mesh.h"
#include "Magnum/Math/Functions.h"
#include "Magnum/Shaders/AbstractVector.h"
#include "Magnum/Text/AbstractFont.h"
@ -173,22 +174,22 @@ std::tuple<std::vector<Vertex>, Range2D> renderVerticesInternal(AbstractFont& fo
return std::make_tuple(std::move(vertices), rectangle);
}
std::pair<Containers::Array<char>, Mesh::IndexType> renderIndicesInternal(const UnsignedInt glyphCount) {
std::pair<Containers::Array<char>, MeshIndexType> renderIndicesInternal(const UnsignedInt glyphCount) {
const UnsignedInt vertexCount = glyphCount*4;
const UnsignedInt indexCount = glyphCount*6;
Containers::Array<char> indices;
Mesh::IndexType indexType;
MeshIndexType indexType;
if(vertexCount <= 256) {
indexType = Mesh::IndexType::UnsignedByte;
indexType = MeshIndexType::UnsignedByte;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedByte));
createIndices<UnsignedByte>(indices, glyphCount);
} else if(vertexCount <= 65536) {
indexType = Mesh::IndexType::UnsignedShort;
indexType = MeshIndexType::UnsignedShort;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedShort));
createIndices<UnsignedShort>(indices, glyphCount);
} else {
indexType = Mesh::IndexType::UnsignedInt;
indexType = MeshIndexType::UnsignedInt;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedInt));
createIndices<UnsignedInt>(indices, glyphCount);
}
@ -196,7 +197,7 @@ std::pair<Containers::Array<char>, Mesh::IndexType> renderIndicesInternal(const
return {std::move(indices), indexType};
}
std::tuple<Mesh, Range2D> renderInternal(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, BufferUsage usage, Alignment alignment) {
std::tuple<GL::Mesh, Range2D> renderInternal(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, GL::Buffer& vertexBuffer, GL::Buffer& indexBuffer, GL::BufferUsage usage, Alignment alignment) {
/* Render vertices and upload them */
std::vector<Vertex> vertices;
Range2D rectangle;
@ -208,13 +209,13 @@ std::tuple<Mesh, Range2D> renderInternal(AbstractFont& font, const GlyphCache& c
/* Render indices and upload them */
Containers::Array<char> indices;
Mesh::IndexType indexType;
MeshIndexType indexType;
std::tie(indices, indexType) = renderIndicesInternal(glyphCount);
indexBuffer.setData(indices, usage);
/* Configure mesh except for vertex buffer (depends on dimension count, done
in subclass) */
Mesh mesh;
GL::Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles)
.setCount(indexCount)
.setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size());
@ -247,10 +248,10 @@ std::tuple<std::vector<Vector2>, std::vector<Vector2>, std::vector<UnsignedInt>,
return std::make_tuple(std::move(positions), std::move(textureCoordinates), std::move(indices), rectangle);
}
template<UnsignedInt dimensions> std::tuple<Mesh, Range2D> Renderer<dimensions>::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, BufferUsage usage, Alignment alignment) {
template<UnsignedInt dimensions> std::tuple<GL::Mesh, Range2D> Renderer<dimensions>::render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, GL::Buffer& vertexBuffer, GL::Buffer& indexBuffer, GL::BufferUsage usage, Alignment alignment) {
/* Finalize mesh configuration and return the result */
auto r = renderInternal(font, cache, size, text, vertexBuffer, indexBuffer, usage, alignment);
Mesh& mesh = std::get<0>(r);
GL::Mesh& mesh = std::get<0>(r);
mesh.addVertexBuffer(vertexBuffer, 0,
typename Shaders::AbstractVector<dimensions>::Position(
Shaders::AbstractVector<dimensions>::Position::Components::Two),
@ -262,19 +263,19 @@ template<UnsignedInt dimensions> std::tuple<Mesh, Range2D> Renderer<dimensions>:
AbstractRenderer::BufferMapImplementation AbstractRenderer::bufferMapImplementation = &AbstractRenderer::bufferMapImplementationFull;
AbstractRenderer::BufferUnmapImplementation AbstractRenderer::bufferUnmapImplementation = &AbstractRenderer::bufferUnmapImplementationDefault;
void* AbstractRenderer::bufferMapImplementationFull(Buffer& buffer, GLsizeiptr) {
return buffer.map(Buffer::MapAccess::WriteOnly);
void* AbstractRenderer::bufferMapImplementationFull(GL::Buffer& buffer, GLsizeiptr) {
return buffer.map(GL::Buffer::MapAccess::WriteOnly);
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN)
inline void* AbstractRenderer::bufferMapImplementation(Buffer& buffer, GLsizeiptr length)
inline void* AbstractRenderer::bufferMapImplementation(GL::Buffer& buffer, GLsizeiptr length)
#else
void* AbstractRenderer::bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length)
void* AbstractRenderer::bufferMapImplementationRange(GL::Buffer& buffer, GLsizeiptr length)
#endif
{
#ifndef CORRADE_TARGET_EMSCRIPTEN
return buffer.map(0, length, Buffer::MapFlag::InvalidateBuffer|Buffer::MapFlag::Write);
return buffer.map(0, length, GL::Buffer::MapFlag::InvalidateBuffer|GL::Buffer::MapFlag::Write);
#else
static_cast<void>(length);
return &buffer == &_indexBuffer ? _indexBufferData : _vertexBufferData;
@ -282,9 +283,9 @@ void* AbstractRenderer::bufferMapImplementationRange(Buffer& buffer, GLsizeiptr
}
#if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN)
inline void AbstractRenderer::bufferUnmapImplementation(Buffer& buffer)
inline void AbstractRenderer::bufferUnmapImplementation(GL::Buffer& buffer)
#else
void AbstractRenderer::bufferUnmapImplementationDefault(Buffer& buffer)
void AbstractRenderer::bufferUnmapImplementationDefault(GL::Buffer& buffer)
#endif
{
#ifndef CORRADE_TARGET_EMSCRIPTEN
@ -294,16 +295,16 @@ void AbstractRenderer::bufferUnmapImplementationDefault(Buffer& buffer)
#endif
}
AbstractRenderer::AbstractRenderer(AbstractFont& font, const GlyphCache& cache, const Float size, const Alignment alignment): _vertexBuffer{Buffer::TargetHint::Array}, _indexBuffer{Buffer::TargetHint::ElementArray}, font(font), cache(cache), size(size), _alignment(alignment), _capacity(0) {
AbstractRenderer::AbstractRenderer(AbstractFont& font, const GlyphCache& cache, const Float size, const Alignment alignment): _vertexBuffer{GL::Buffer::TargetHint::Array}, _indexBuffer{GL::Buffer::TargetHint::ElementArray}, font(font), cache(cache), size(size), _alignment(alignment), _capacity(0) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range);
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::map_buffer_range);
#elif defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN)
if(Context::current().isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) {
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>()) {
bufferMapImplementation = &AbstractRenderer::bufferMapImplementationRange;
} else {
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::mapbuffer);
Warning() << "Text::Renderer:" << Extensions::GL::EXT::map_buffer_range::string()
<< "is not supported, using inefficient" << Extensions::GL::OES::mapbuffer::string()
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::mapbuffer);
Warning() << "Text::Renderer:" << GL::Extensions::EXT::map_buffer_range::string()
<< "is not supported, using inefficient" << GL::Extensions::OES::mapbuffer::string()
<< "instead";
}
#endif
@ -321,7 +322,7 @@ template<UnsignedInt dimensions> Renderer<dimensions>::Renderer(AbstractFont& fo
typename Shaders::AbstractVector<dimensions>::TextureCoordinates());
}
void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vertexBufferUsage, const BufferUsage indexBufferUsage) {
void AbstractRenderer::reserve(const uint32_t glyphCount, const GL::BufferUsage vertexBufferUsage, const GL::BufferUsage indexBufferUsage) {
_capacity = glyphCount;
const UnsignedInt vertexCount = glyphCount*4;
@ -335,7 +336,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert
/* Render indices */
Containers::Array<char> indexData;
Mesh::IndexType indexType;
MeshIndexType indexType;
std::tie(indexData, indexType) = renderIndicesInternal(glyphCount);
/* Allocate index buffer, reset index count and reconfigure buffer binding */

36
src/Magnum/Text/Renderer.h

@ -33,10 +33,10 @@
#include <tuple>
#include <vector>
#include "Magnum/Math/Range.h"
#include "Magnum/Buffer.h"
#include "Magnum/DimensionTraits.h"
#include "Magnum/Mesh.h"
#include "Magnum/Math/Range.h"
#include "Magnum/GL/Buffer.h"
#include "Magnum/GL/Mesh.h"
#include "Magnum/Text/Text.h"
#include "Magnum/Text/Alignment.h"
#include "Magnum/Text/visibility.h"
@ -79,13 +79,13 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
Range2D rectangle() const { return _rectangle; }
/** @brief Vertex buffer */
Buffer& vertexBuffer() { return _vertexBuffer; }
GL::Buffer& vertexBuffer() { return _vertexBuffer; }
/** @brief Index buffer */
Buffer& indexBuffer() { return _indexBuffer; }
GL::Buffer& indexBuffer() { return _indexBuffer; }
/** @brief Mesh */
Mesh& mesh() { return _mesh; }
GL::Mesh& mesh() { return _mesh; }
/**
* @brief Reserve capacity for rendered glyphs
@ -99,7 +99,7 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
* Initially zero capacity is reserved.
* @see @ref capacity()
*/
void reserve(UnsignedInt glyphCount, BufferUsage vertexBufferUsage, BufferUsage indexBufferUsage);
void reserve(UnsignedInt glyphCount, GL::BufferUsage vertexBufferUsage, GL::BufferUsage indexBufferUsage);
/**
* @brief Render text
@ -123,8 +123,8 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
~AbstractRenderer();
Mesh _mesh;
Buffer _vertexBuffer, _indexBuffer;
GL::Mesh _mesh;
GL::Buffer _vertexBuffer, _indexBuffer;
#ifdef CORRADE_TARGET_EMSCRIPTEN
Containers::Array<UnsignedByte> _vertexBufferData, _indexBufferData;
#endif
@ -138,9 +138,9 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
Range2D _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* bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length);
typedef void*(*BufferMapImplementation)(GL::Buffer&, GLsizeiptr);
static MAGNUM_TEXT_LOCAL void* bufferMapImplementationFull(GL::Buffer& buffer, GLsizeiptr length);
static MAGNUM_TEXT_LOCAL void* bufferMapImplementationRange(GL::Buffer& buffer, GLsizeiptr length);
static BufferMapImplementation bufferMapImplementation;
#else
#ifndef CORRADE_TARGET_EMSCRIPTEN
@ -148,12 +148,12 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
#else
MAGNUM_TEXT_LOCAL
#endif
void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length);
void* bufferMapImplementation(GL::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);
typedef void(*BufferUnmapImplementation)(GL::Buffer&);
static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationDefault(GL::Buffer& buffer);
static MAGNUM_TEXT_LOCAL BufferUnmapImplementation bufferUnmapImplementation;
#else
#ifndef CORRADE_TARGET_EMSCRIPTEN
@ -161,7 +161,7 @@ class MAGNUM_TEXT_EXPORT AbstractRenderer {
#else
MAGNUM_TEXT_LOCAL
#endif
void bufferUnmapImplementation(Buffer& buffer);
void bufferUnmapImplementation(GL::Buffer& buffer);
#endif
};
@ -181,7 +181,7 @@ mesh:
@snippet MagnumText.cpp Renderer-usage1
See @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Alignment)
and @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, Buffer&, Buffer&, BufferUsage, Alignment)
and @ref render(AbstractFont&, const GlyphCache&, Float, const std::string&, GL::Buffer&, GL::Buffer&, GL::BufferUsage, Alignment)
for more information.
While this method is sufficient for one-shot rendering of static texts, for
@ -217,7 +217,7 @@ template<UnsignedInt dimensions> class MAGNUM_TEXT_EXPORT Renderer: public Abstr
* Returns mesh prepared for use with @ref Shaders::AbstractVector
* subclasses and rectangle spanning the rendered text.
*/
static std::tuple<Mesh, Range2D> render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, Buffer& vertexBuffer, Buffer& indexBuffer, BufferUsage usage, Alignment alignment = Alignment::LineLeft);
static std::tuple<GL::Mesh, Range2D> render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, GL::Buffer& vertexBuffer, GL::Buffer& indexBuffer, GL::BufferUsage usage, Alignment alignment = Alignment::LineLeft);
/**
* @brief Constructor

6
src/Magnum/Text/Test/GlyphCacheGLTest.cpp

@ -25,12 +25,12 @@
#include <tuple>
#include "Magnum/OpenGLTester.h"
#include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Text/GlyphCache.h"
namespace Magnum { namespace Text { namespace Test {
struct GlyphCacheGLTest: OpenGLTester {
struct GlyphCacheGLTest: GL::OpenGLTester {
explicit GlyphCacheGLTest();
void initialize();
@ -46,7 +46,7 @@ GlyphCacheGLTest::GlyphCacheGLTest() {
void GlyphCacheGLTest::initialize() {
Text::GlyphCache cache({1024, 2048});
MAGNUM_VERIFY_NO_ERROR();
MAGNUM_VERIFY_NO_GL_ERROR();
#ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(cache.texture().imageSize(0), Vector2i(1024, 2048));

46
src/Magnum/Text/Test/RendererGLTest.cpp

@ -26,15 +26,15 @@
#include <Corrade/Containers/Array.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/OpenGLTester.h"
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Text/AbstractFont.h"
#include "Magnum/Text/Renderer.h"
namespace Magnum { namespace Text { namespace Test {
struct RendererGLTest: OpenGLTester {
struct RendererGLTest: GL::OpenGLTester {
explicit RendererGLTest();
void renderData();
@ -177,13 +177,13 @@ void RendererGLTest::renderData() {
void RendererGLTest::renderMesh() {
TestFont font;
Mesh mesh{NoCreate};
Buffer vertexBuffer{Buffer::TargetHint::Array},
indexBuffer{Buffer::TargetHint::ElementArray};
GL::Mesh mesh{NoCreate};
GL::Buffer vertexBuffer{GL::Buffer::TargetHint::Array},
indexBuffer{GL::Buffer::TargetHint::ElementArray};
Range2D bounds;
std::tie(mesh, bounds) = Text::Renderer3D::render(font, nullGlyphCache,
0.25f, "abc", vertexBuffer, indexBuffer, BufferUsage::StaticDraw, Alignment::TopCenter);
MAGNUM_VERIFY_NO_ERROR();
0.25f, "abc", vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw, Alignment::TopCenter);
MAGNUM_VERIFY_NO_GL_ERROR();
/* Alignment offset */
const Vector2 offset{-2.5f, -1.0f};
@ -226,16 +226,16 @@ void RendererGLTest::renderMesh() {
void RendererGLTest::renderMeshIndexType() {
#ifndef MAGNUM_TARGET_GLES
TestFont font;
Mesh mesh{NoCreate};
Buffer vertexBuffer, indexBuffer;
GL::Mesh mesh{NoCreate};
GL::Buffer vertexBuffer, indexBuffer;
/* Sizes: four vertices per glyph, each vertex has 2D position and 2D
texture coordinates, each float is four bytes; six indices per glyph. */
/* 8-bit indices (exactly 256 vertices) */
std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache,
1.0f, std::string(64, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_ERROR();
1.0f, std::string(64, 'a'), vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> indicesByte = indexBuffer.data();
CORRADE_COMPARE(vertexBuffer.size(), 256*(2 + 2)*4);
CORRADE_COMPARE(indicesByte.size(), 64*6);
@ -248,8 +248,8 @@ void RendererGLTest::renderMeshIndexType() {
/* 16-bit indices (260 vertices) */
std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache,
1.0f, std::string(65, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_ERROR();
1.0f, std::string(65, 'a'), vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> indicesShort = indexBuffer.data();
CORRADE_COMPARE(vertexBuffer.size(), 260*(2 + 2)*4);
CORRADE_COMPARE(indicesShort.size(), 65*6*2);
@ -266,23 +266,23 @@ void RendererGLTest::renderMeshIndexType() {
void RendererGLTest::mutableText() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::map_buffer_range>())
CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported"));
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported"));
#elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::map_buffer_range>() &&
!Context::current().isExtensionSupported<Extensions::GL::OES::mapbuffer>())
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>() &&
!GL::Context::current().isExtensionSupported<GL::Extensions::OES::mapbuffer>())
CORRADE_SKIP("No required extension is supported");
#endif
TestFont font;
Text::Renderer2D renderer(font, nullGlyphCache, 0.25f);
MAGNUM_VERIFY_NO_ERROR();
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(renderer.capacity(), 0);
CORRADE_COMPARE(renderer.rectangle(), Range2D());
/* Reserve some capacity */
renderer.reserve(4, BufferUsage::DynamicDraw, BufferUsage::DynamicDraw);
MAGNUM_VERIFY_NO_ERROR();
renderer.reserve(4, GL::BufferUsage::DynamicDraw, GL::BufferUsage::DynamicDraw);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(renderer.capacity(), 4);
/** @todo How to verify this on ES? */
#ifndef MAGNUM_TARGET_GLES
@ -298,7 +298,7 @@ void RendererGLTest::mutableText() {
/* Render text */
renderer.render("abc");
MAGNUM_VERIFY_NO_ERROR();
MAGNUM_VERIFY_NO_GL_ERROR();
/* Updated bounds */
CORRADE_COMPARE(renderer.rectangle(), Range2D({0.0f, -0.5f}, {5.0f, 1.0f}));

3
src/Magnum/Text/fontconverter.cpp

@ -86,7 +86,8 @@ Arguments:
- `--output-size "X Y"` --- output atlas size. If set to zero size, distance
field computation will not be used. (default: `"256 256"`)
- `--radius N` --- distance field computation radius (default: `24`)
- `--magnum-...` --- engine-specific options (see @ref Context for details)
- `--magnum-...` --- engine-specific options (see
@ref GL-Context-command-line for details)
The resulting font files can be then used as specified in the documentation of
`converter` plugin.

Loading…
Cancel
Save