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 <Corrade/PluginManager/AbstractPlugin.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Text/Text.h" #include "Magnum/Text/Text.h"
#include "Magnum/Text/visibility.h" #include "Magnum/Text/visibility.h"

71
src/Magnum/Text/DistanceFieldGlyphCache.cpp

@ -25,65 +25,69 @@
#include "DistanceFieldGlyphCache.h" #include "DistanceFieldGlyphCache.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
#include "Magnum/PixelFormat.h" #include "Magnum/GL/PixelFormat.h"
#endif #endif
#include "Magnum/TextureFormat.h" #include "Magnum/GL/TextureFormat.h"
#include "Magnum/TextureTools/DistanceField.h" #include "Magnum/TextureTools/DistanceField.h"
namespace Magnum { namespace Text { namespace Magnum { namespace Text {
DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& size, const UnsignedInt radius): DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& size, const UnsignedInt radius):
#if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2)) #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) #elif !defined(MAGNUM_TARGET_WEBGL)
/* Luminance is not renderable in most cases */ /* Luminance is not renderable in most cases */
GlyphCache(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>() ? GlyphCache(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>() ?
TextureFormat::Red : TextureFormat::RGB, originalSize, size, Vector2i(radius)), GL::TextureFormat::Red : GL::TextureFormat::RGB, originalSize, size, Vector2i(radius)),
#else #else
GlyphCache(TextureFormat::RGB, originalSize, size, Vector2i(radius)), GlyphCache(GL::TextureFormat::RGB, originalSize, size, Vector2i(radius)),
#endif #endif
scale(Vector2(size)/Vector2(originalSize)), radius(radius) scale(Vector2(size)/Vector2(originalSize)), radius(radius)
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::texture_rg);
#endif #endif
#if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Luminance is not renderable in most cases */ /* Luminance is not renderable in most cases */
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>())
Warning() << "Text::DistanceFieldGlyphCache:" << Extensions::GL::EXT::texture_rg::string() << "not supported, using inefficient RGB format for glyph cache texture"; Warning() << "Text::DistanceFieldGlyphCache:" << GL::Extensions::EXT::texture_rg::string() << "not supported, using inefficient RGB format for glyph cache texture";
#endif #endif
} }
void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageView2D& image) { 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)) #if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2))
const TextureFormat internalFormat = TextureFormat::R8; const GL::TextureFormat internalFormat = GL::TextureFormat::R8;
CORRADE_ASSERT(image.format() == PixelFormat::Red, CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Red << "but got" << format, );
#else #else
TextureFormat internalFormat; GL::TextureFormat internalFormat;
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>()) { if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>()) {
internalFormat = TextureFormat::Red; internalFormat = GL::TextureFormat::Red;
CORRADE_ASSERT(image.format() == PixelFormat::Red, CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Red << "but got" << format, );
} else } else
#endif #endif
{ {
internalFormat = TextureFormat::Luminance; internalFormat = GL::TextureFormat::Luminance;
CORRADE_ASSERT(image.format() == PixelFormat::Luminance, CORRADE_ASSERT(format == GL::PixelFormat::Luminance,
"Text::DistanceFieldGlyphCache::setImage(): expected" << PixelFormat::Luminance << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setImage(): expected"
<< GL::PixelFormat::Luminance << "but got" << format, );
} }
#endif #endif
Texture2D input; GL::Texture2D input;
input.setWrapping(Sampler::Wrapping::ClampToEdge) input.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMinificationFilter(Sampler::Filter::Linear) .setMinificationFilter(GL::SamplerFilter::Linear)
.setMagnificationFilter(Sampler::Filter::Linear) .setMagnificationFilter(GL::SamplerFilter::Linear)
.setImage(0, internalFormat, image); .setImage(0, internalFormat, image);
/* Create distance field from input texture */ /* 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) { 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)) #if !(defined(MAGNUM_TARGET_GLES) && defined(MAGNUM_TARGET_GLES2))
CORRADE_ASSERT(image.format() == PixelFormat::Red, CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::Red << "but got" << format, );
#else #else
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>()) if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_rg>())
CORRADE_ASSERT(image.format() == PixelFormat::Red, CORRADE_ASSERT(format == GL::PixelFormat::Red,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::Red << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::Red << "but got" << format, );
else else
#endif #endif
{ {
/* Luminance is not renderable in most cases */ /* Luminance is not renderable in most cases */
CORRADE_ASSERT(image.format() == PixelFormat::RGB, CORRADE_ASSERT(format == GL::PixelFormat::RGB,
"Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << PixelFormat::RGB << "but got" << image.format(), ); "Text::DistanceFieldGlyphCache::setDistanceFieldImage(): expected" << GL::PixelFormat::RGB << "but got" << format, );
} }
#endif #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 * the parameters. Sets internal texture format to red channel only. On
* desktop OpenGL requires @extension{ARB,texture_rg} (also part of * desktop OpenGL requires @extension{ARB,texture_rg} (also part of
* OpenGL ES 3.0), in ES2 uses @extension{EXT,texture_rg} if * 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 * @todo Is Luminance format renderable anywhere? Also would it be
* possible to convert the RGB texture to Luminance after it has * possible to convert the RGB texture to Luminance after it has
* been rendered when blitting is not supported to save memory? * been rendered when blitting is not supported to save memory?

34
src/Magnum/Text/GlyphCache.cpp

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

14
src/Magnum/Text/GlyphCache.h

@ -33,7 +33,7 @@
#include <unordered_map> #include <unordered_map>
#include "Magnum/Math/Range.h" #include "Magnum/Math/Range.h"
#include "Magnum/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Text/visibility.h" #include "Magnum/Text/visibility.h"
namespace Magnum { namespace Text { namespace Magnum { namespace Text {
@ -68,14 +68,14 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
* although the actual glyph cache texture has @p size. Glyph * although the actual glyph cache texture has @p size. Glyph
* @p padding can be used to account for e.g. glyph shadows. * @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 * @brief Constructor
* *
* Same as calling the above with @p originalSize and @p size the same. * 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 * @brief Constructor
@ -83,7 +83,7 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
* Sets internal texture format to red channel only. On desktop OpenGL * Sets internal texture format to red channel only. On desktop OpenGL
* requires @extension{ARB,texture_rg} (also part of OpenGL ES 3.0), in * requires @extension{ARB,texture_rg} (also part of OpenGL ES 3.0), in
* ES2 uses @extension{EXT,texture_rg}, if available, or * 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); 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(); } std::size_t glyphCount() const { return glyphs.size(); }
/** @brief Cache texture */ /** @brief Cache texture */
Texture2D& texture() { return _texture; } GL::Texture2D& texture() { return _texture; }
/** /**
* @brief Parameters of given glyph * @brief Parameters of given glyph
@ -183,10 +183,10 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
virtual void setImage(const Vector2i& offset, const ImageView2D& image); virtual void setImage(const Vector2i& offset, const ImageView2D& image);
private: private:
void MAGNUM_LOCAL initialize(TextureFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL initialize(GL::TextureFormat internalFormat, const Vector2i& size);
Vector2i _size, _padding; Vector2i _size, _padding;
Texture2D _texture; GL::Texture2D _texture;
std::unordered_map<UnsignedInt, std::pair<Vector2i, Range2Di>> glyphs; 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 <Corrade/Containers/Array.h>
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Mesh.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/Math/Functions.h"
#include "Magnum/Shaders/AbstractVector.h" #include "Magnum/Shaders/AbstractVector.h"
#include "Magnum/Text/AbstractFont.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); 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 vertexCount = glyphCount*4;
const UnsignedInt indexCount = glyphCount*6; const UnsignedInt indexCount = glyphCount*6;
Containers::Array<char> indices; Containers::Array<char> indices;
Mesh::IndexType indexType; MeshIndexType indexType;
if(vertexCount <= 256) { if(vertexCount <= 256) {
indexType = Mesh::IndexType::UnsignedByte; indexType = MeshIndexType::UnsignedByte;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedByte)); indices = Containers::Array<char>(indexCount*sizeof(UnsignedByte));
createIndices<UnsignedByte>(indices, glyphCount); createIndices<UnsignedByte>(indices, glyphCount);
} else if(vertexCount <= 65536) { } else if(vertexCount <= 65536) {
indexType = Mesh::IndexType::UnsignedShort; indexType = MeshIndexType::UnsignedShort;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedShort)); indices = Containers::Array<char>(indexCount*sizeof(UnsignedShort));
createIndices<UnsignedShort>(indices, glyphCount); createIndices<UnsignedShort>(indices, glyphCount);
} else { } else {
indexType = Mesh::IndexType::UnsignedInt; indexType = MeshIndexType::UnsignedInt;
indices = Containers::Array<char>(indexCount*sizeof(UnsignedInt)); indices = Containers::Array<char>(indexCount*sizeof(UnsignedInt));
createIndices<UnsignedInt>(indices, glyphCount); createIndices<UnsignedInt>(indices, glyphCount);
} }
@ -196,7 +197,7 @@ std::pair<Containers::Array<char>, Mesh::IndexType> renderIndicesInternal(const
return {std::move(indices), indexType}; 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 */ /* Render vertices and upload them */
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
Range2D rectangle; Range2D rectangle;
@ -208,13 +209,13 @@ std::tuple<Mesh, Range2D> renderInternal(AbstractFont& font, const GlyphCache& c
/* Render indices and upload them */ /* Render indices and upload them */
Containers::Array<char> indices; Containers::Array<char> indices;
Mesh::IndexType indexType; MeshIndexType indexType;
std::tie(indices, indexType) = renderIndicesInternal(glyphCount); std::tie(indices, indexType) = renderIndicesInternal(glyphCount);
indexBuffer.setData(indices, usage); indexBuffer.setData(indices, usage);
/* Configure mesh except for vertex buffer (depends on dimension count, done /* Configure mesh except for vertex buffer (depends on dimension count, done
in subclass) */ in subclass) */
Mesh mesh; GL::Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles) mesh.setPrimitive(MeshPrimitive::Triangles)
.setCount(indexCount) .setCount(indexCount)
.setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size()); .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); 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 */ /* Finalize mesh configuration and return the result */
auto r = renderInternal(font, cache, size, text, vertexBuffer, indexBuffer, usage, alignment); 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, mesh.addVertexBuffer(vertexBuffer, 0,
typename Shaders::AbstractVector<dimensions>::Position( typename Shaders::AbstractVector<dimensions>::Position(
Shaders::AbstractVector<dimensions>::Position::Components::Two), 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::BufferMapImplementation AbstractRenderer::bufferMapImplementation = &AbstractRenderer::bufferMapImplementationFull;
AbstractRenderer::BufferUnmapImplementation AbstractRenderer::bufferUnmapImplementation = &AbstractRenderer::bufferUnmapImplementationDefault; AbstractRenderer::BufferUnmapImplementation AbstractRenderer::bufferUnmapImplementation = &AbstractRenderer::bufferUnmapImplementationDefault;
void* AbstractRenderer::bufferMapImplementationFull(Buffer& buffer, GLsizeiptr) { void* AbstractRenderer::bufferMapImplementationFull(GL::Buffer& buffer, GLsizeiptr) {
return buffer.map(Buffer::MapAccess::WriteOnly); return buffer.map(GL::Buffer::MapAccess::WriteOnly);
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN) #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 #else
void* AbstractRenderer::bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length) void* AbstractRenderer::bufferMapImplementationRange(GL::Buffer& buffer, GLsizeiptr length)
#endif #endif
{ {
#ifndef CORRADE_TARGET_EMSCRIPTEN #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 #else
static_cast<void>(length); static_cast<void>(length);
return &buffer == &_indexBuffer ? _indexBufferData : _vertexBufferData; return &buffer == &_indexBuffer ? _indexBufferData : _vertexBufferData;
@ -282,9 +283,9 @@ void* AbstractRenderer::bufferMapImplementationRange(Buffer& buffer, GLsizeiptr
} }
#if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN) #if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN)
inline void AbstractRenderer::bufferUnmapImplementation(Buffer& buffer) inline void AbstractRenderer::bufferUnmapImplementation(GL::Buffer& buffer)
#else #else
void AbstractRenderer::bufferUnmapImplementationDefault(Buffer& buffer) void AbstractRenderer::bufferUnmapImplementationDefault(GL::Buffer& buffer)
#endif #endif
{ {
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
@ -294,16 +295,16 @@ void AbstractRenderer::bufferUnmapImplementationDefault(Buffer& buffer)
#endif #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 #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) #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; bufferMapImplementation = &AbstractRenderer::bufferMapImplementationRange;
} else { } else {
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::mapbuffer); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::mapbuffer);
Warning() << "Text::Renderer:" << Extensions::GL::EXT::map_buffer_range::string() Warning() << "Text::Renderer:" << GL::Extensions::EXT::map_buffer_range::string()
<< "is not supported, using inefficient" << Extensions::GL::OES::mapbuffer::string() << "is not supported, using inefficient" << GL::Extensions::OES::mapbuffer::string()
<< "instead"; << "instead";
} }
#endif #endif
@ -321,7 +322,7 @@ template<UnsignedInt dimensions> Renderer<dimensions>::Renderer(AbstractFont& fo
typename Shaders::AbstractVector<dimensions>::TextureCoordinates()); 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; _capacity = glyphCount;
const UnsignedInt vertexCount = glyphCount*4; const UnsignedInt vertexCount = glyphCount*4;
@ -335,7 +336,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert
/* Render indices */ /* Render indices */
Containers::Array<char> indexData; Containers::Array<char> indexData;
Mesh::IndexType indexType; MeshIndexType indexType;
std::tie(indexData, indexType) = renderIndicesInternal(glyphCount); std::tie(indexData, indexType) = renderIndicesInternal(glyphCount);
/* Allocate index buffer, reset index count and reconfigure buffer binding */ /* Allocate index buffer, reset index count and reconfigure buffer binding */

36
src/Magnum/Text/Renderer.h

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

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

@ -25,12 +25,12 @@
#include <tuple> #include <tuple>
#include "Magnum/OpenGLTester.h" #include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Text/GlyphCache.h" #include "Magnum/Text/GlyphCache.h"
namespace Magnum { namespace Text { namespace Test { namespace Magnum { namespace Text { namespace Test {
struct GlyphCacheGLTest: OpenGLTester { struct GlyphCacheGLTest: GL::OpenGLTester {
explicit GlyphCacheGLTest(); explicit GlyphCacheGLTest();
void initialize(); void initialize();
@ -46,7 +46,7 @@ GlyphCacheGLTest::GlyphCacheGLTest() {
void GlyphCacheGLTest::initialize() { void GlyphCacheGLTest::initialize() {
Text::GlyphCache cache({1024, 2048}); Text::GlyphCache cache({1024, 2048});
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_COMPARE(cache.texture().imageSize(0), Vector2i(1024, 2048)); 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/Containers/Array.h>
#include <Corrade/TestSuite/Compare/Container.h> #include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/OpenGLTester.h" #include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Text/AbstractFont.h" #include "Magnum/Text/AbstractFont.h"
#include "Magnum/Text/Renderer.h" #include "Magnum/Text/Renderer.h"
namespace Magnum { namespace Text { namespace Test { namespace Magnum { namespace Text { namespace Test {
struct RendererGLTest: OpenGLTester { struct RendererGLTest: GL::OpenGLTester {
explicit RendererGLTest(); explicit RendererGLTest();
void renderData(); void renderData();
@ -177,13 +177,13 @@ void RendererGLTest::renderData() {
void RendererGLTest::renderMesh() { void RendererGLTest::renderMesh() {
TestFont font; TestFont font;
Mesh mesh{NoCreate}; GL::Mesh mesh{NoCreate};
Buffer vertexBuffer{Buffer::TargetHint::Array}, GL::Buffer vertexBuffer{GL::Buffer::TargetHint::Array},
indexBuffer{Buffer::TargetHint::ElementArray}; indexBuffer{GL::Buffer::TargetHint::ElementArray};
Range2D bounds; Range2D bounds;
std::tie(mesh, bounds) = Text::Renderer3D::render(font, nullGlyphCache, std::tie(mesh, bounds) = Text::Renderer3D::render(font, nullGlyphCache,
0.25f, "abc", vertexBuffer, indexBuffer, BufferUsage::StaticDraw, Alignment::TopCenter); 0.25f, "abc", vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw, Alignment::TopCenter);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
/* Alignment offset */ /* Alignment offset */
const Vector2 offset{-2.5f, -1.0f}; const Vector2 offset{-2.5f, -1.0f};
@ -226,16 +226,16 @@ void RendererGLTest::renderMesh() {
void RendererGLTest::renderMeshIndexType() { void RendererGLTest::renderMeshIndexType() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
TestFont font; TestFont font;
Mesh mesh{NoCreate}; GL::Mesh mesh{NoCreate};
Buffer vertexBuffer, indexBuffer; GL::Buffer vertexBuffer, indexBuffer;
/* Sizes: four vertices per glyph, each vertex has 2D position and 2D /* Sizes: four vertices per glyph, each vertex has 2D position and 2D
texture coordinates, each float is four bytes; six indices per glyph. */ texture coordinates, each float is four bytes; six indices per glyph. */
/* 8-bit indices (exactly 256 vertices) */ /* 8-bit indices (exactly 256 vertices) */
std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache, std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache,
1.0f, std::string(64, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw); 1.0f, std::string(64, 'a'), vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> indicesByte = indexBuffer.data(); Containers::Array<char> indicesByte = indexBuffer.data();
CORRADE_COMPARE(vertexBuffer.size(), 256*(2 + 2)*4); CORRADE_COMPARE(vertexBuffer.size(), 256*(2 + 2)*4);
CORRADE_COMPARE(indicesByte.size(), 64*6); CORRADE_COMPARE(indicesByte.size(), 64*6);
@ -248,8 +248,8 @@ void RendererGLTest::renderMeshIndexType() {
/* 16-bit indices (260 vertices) */ /* 16-bit indices (260 vertices) */
std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache, std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache,
1.0f, std::string(65, 'a'), vertexBuffer, indexBuffer, BufferUsage::StaticDraw); 1.0f, std::string(65, 'a'), vertexBuffer, indexBuffer, GL::BufferUsage::StaticDraw);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
Containers::Array<char> indicesShort = indexBuffer.data(); Containers::Array<char> indicesShort = indexBuffer.data();
CORRADE_COMPARE(vertexBuffer.size(), 260*(2 + 2)*4); CORRADE_COMPARE(vertexBuffer.size(), 260*(2 + 2)*4);
CORRADE_COMPARE(indicesShort.size(), 65*6*2); CORRADE_COMPARE(indicesShort.size(), 65*6*2);
@ -266,23 +266,23 @@ void RendererGLTest::renderMeshIndexType() {
void RendererGLTest::mutableText() { void RendererGLTest::mutableText() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported"));
#elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::GL::EXT::map_buffer_range>() && if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>() &&
!Context::current().isExtensionSupported<Extensions::GL::OES::mapbuffer>()) !GL::Context::current().isExtensionSupported<GL::Extensions::OES::mapbuffer>())
CORRADE_SKIP("No required extension is supported"); CORRADE_SKIP("No required extension is supported");
#endif #endif
TestFont font; TestFont font;
Text::Renderer2D renderer(font, nullGlyphCache, 0.25f); Text::Renderer2D renderer(font, nullGlyphCache, 0.25f);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(renderer.capacity(), 0); CORRADE_COMPARE(renderer.capacity(), 0);
CORRADE_COMPARE(renderer.rectangle(), Range2D()); CORRADE_COMPARE(renderer.rectangle(), Range2D());
/* Reserve some capacity */ /* Reserve some capacity */
renderer.reserve(4, BufferUsage::DynamicDraw, BufferUsage::DynamicDraw); renderer.reserve(4, GL::BufferUsage::DynamicDraw, GL::BufferUsage::DynamicDraw);
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(renderer.capacity(), 4); CORRADE_COMPARE(renderer.capacity(), 4);
/** @todo How to verify this on ES? */ /** @todo How to verify this on ES? */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -298,7 +298,7 @@ void RendererGLTest::mutableText() {
/* Render text */ /* Render text */
renderer.render("abc"); renderer.render("abc");
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
/* Updated bounds */ /* Updated bounds */
CORRADE_COMPARE(renderer.rectangle(), Range2D({0.0f, -0.5f}, {5.0f, 1.0f})); 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 - `--output-size "X Y"` --- output atlas size. If set to zero size, distance
field computation will not be used. (default: `"256 256"`) field computation will not be used. (default: `"256 256"`)
- `--radius N` --- distance field computation radius (default: `24`) - `--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 The resulting font files can be then used as specified in the documentation of
`converter` plugin. `converter` plugin.

Loading…
Cancel
Save