Browse Source

Text: random improvements to font and glyph cache docs.

Not touching DistanceFieldGlyphCacheGL docs yet, but the rest was so bad
that I just had to go and fix it all.
pull/674/head
Vladimír Vondruš 1 year ago
parent
commit
b26d694d13
  1. 38
      doc/snippets/Text-gl.cpp
  2. 52
      doc/snippets/Text.cpp
  3. 55
      src/Magnum/Text/AbstractFont.h
  4. 70
      src/Magnum/Text/AbstractGlyphCache.h
  5. 4
      src/Magnum/Text/DistanceFieldGlyphCacheGL.h
  6. 28
      src/Magnum/Text/GlyphCacheGL.h
  7. 12
      src/Magnum/Text/Renderer.h

38
doc/snippets/Text-gl.cpp

@ -61,17 +61,18 @@ Containers::Pointer<Text::AbstractFont> font =
if(!font->openFile("font.ttf", 12.0f)) if(!font->openFile("font.ttf", 12.0f))
Fatal{} << "Can't open font.ttf with StbTrueTypeFont"; Fatal{} << "Can't open font.ttf with StbTrueTypeFont";
Text::GlyphCacheGL cache{PixelFormat::R8Unorm, Vector2i{128}}; Text::GlyphCacheGL cache{PixelFormat::R8Unorm, {256, 256}};
font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" if(!font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789?!:;,. "); "0123456789?!:;,. "))
Fatal{} << "Glyph cache too small to fit all characters";
/* [AbstractFont-usage] */ /* [AbstractFont-usage] */
} }
{ {
/* [AbstractGlyphCache-filling-construct] */ /* [AbstractGlyphCache-usage-construct] */
Text::GlyphCacheGL cache{PixelFormat::R8Unorm, Vector2i{512}}; Text::GlyphCacheGL cache{PixelFormat::R8Unorm, {256, 256}};
/* [AbstractGlyphCache-filling-construct] */ /* [AbstractGlyphCache-usage-construct] */
} }
{ {
@ -84,28 +85,13 @@ Containers::Pointer<Text::AbstractFont> font = DOXYGEN_ELLIPSIS(manager.loadAndI
font->openFile("font.ttf", 96.0f); font->openFile("font.ttf", 96.0f);
Text::DistanceFieldGlyphCacheGL cache{Vector2i{1024}, Vector2i{128}, 12}; Text::DistanceFieldGlyphCacheGL cache{Vector2i{1024}, Vector2i{128}, 12};
font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" if(!font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789?!:;,. "); "0123456789?!:;,. "))
Fatal{} << "Glyph cache too small to fit all characters";
/* [DistanceFieldGlyphCacheGL-usage] */ /* [DistanceFieldGlyphCacheGL-usage] */
} }
{
/* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize
the font pointer. I don't care, I just want you to check compilation errors,
not more! */
PluginManager::Manager<Text::AbstractFont> manager;
/* [GlyphCacheGL-usage] */
Containers::Pointer<Text::AbstractFont> font = DOXYGEN_ELLIPSIS(manager.loadAndInstantiate(""));
font->openFile("font.ttf", 12.0f);
Text::GlyphCacheGL cache{PixelFormat::R8Unorm, Vector2i{128}};
font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789?!:;,. ");
/* [GlyphCacheGL-usage] */
}
{ {
/* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize /* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize
the font pointer. I don't care, I just want you to check compilation errors, the font pointer. I don't care, I just want you to check compilation errors,

52
doc/snippets/Text.cpp

@ -43,6 +43,7 @@
#include <Corrade/Utility/Resource.h> #include <Corrade/Utility/Resource.h>
#include "Magnum/FileCallback.h" #include "Magnum/FileCallback.h"
#include "Magnum/Image.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
@ -98,6 +99,33 @@ CORRADE_PLUGIN_REGISTER(MyFontConverter, MyNamespace::MyFontConverter,
avoid -Wmisssing-prototypes */ avoid -Wmisssing-prototypes */
void mainText(); void mainText();
void mainText() { void mainText() {
{
PluginManager::Manager<Text::AbstractFont> manager;
Containers::Pointer<Text::AbstractFont> font =
manager.loadAndInstantiate("StbTrueTypeFont");
struct: Text::AbstractGlyphCache {
using Text::AbstractGlyphCache::AbstractGlyphCache;
Text::GlyphCacheFeatures doFeatures() const override { return {}; }
} cache{PixelFormat::R8Unorm, Vector2i{256}};
/* [AbstractFont-glyph-cache-by-id] */
CORRADE_INTERNAL_ASSERT_OUTPUT(font->fillGlyphCache(cache, {
font->glyphForName("fi"),
font->glyphForName("f_f"),
font->glyphForName("fl"),
DOXYGEN_ELLIPSIS()
}));
/* [AbstractFont-glyph-cache-by-id] */
/* [AbstractFont-glyph-cache-all] */
Containers::Array<UnsignedInt> glyphs{NoInit, font->glyphCount()};
for(UnsignedInt i = 0; i != font->glyphCount(); ++i)
glyphs[i] = i;
CORRADE_INTERNAL_ASSERT_OUTPUT(font->fillGlyphCache(cache, glyphs));
/* [AbstractFont-glyph-cache-all] */
}
{ {
PluginManager::Manager<Text::AbstractFont> manager; PluginManager::Manager<Text::AbstractFont> manager;
Containers::Pointer<Text::AbstractFont> font = Containers::Pointer<Text::AbstractFont> font =
@ -179,6 +207,26 @@ font->setFileCallback([](const std::string& filename,
/* [AbstractFont-setFileCallback-template] */ /* [AbstractFont-setFileCallback-template] */
} }
{
/* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize
the font pointer. I don't care, I just want you to check compilation errors,
not more! */
PluginManager::Manager<Text::AbstractFont> manager;
struct: Text::AbstractGlyphCache {
using Text::AbstractGlyphCache::AbstractGlyphCache;
Text::GlyphCacheFeatures doFeatures() const override { return {}; }
} cache{PixelFormat::R8Unorm, Vector2i{256}};
/* [AbstractGlyphCache-usage-fill] */
Containers::Pointer<Text::AbstractFont> font = DOXYGEN_ELLIPSIS(manager.loadAndInstantiate(""));
if(!font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789?!:;,. "))
Fatal{} << "Glyph cache too small to fit all characters";
/* [AbstractGlyphCache-usage-fill] */
}
{ {
struct: Text::AbstractGlyphCache { struct: Text::AbstractGlyphCache {
using Text::AbstractGlyphCache::AbstractGlyphCache; using Text::AbstractGlyphCache::AbstractGlyphCache;
@ -186,7 +234,7 @@ struct: Text::AbstractGlyphCache {
Text::GlyphCacheFeatures doFeatures() const override { return {}; } Text::GlyphCacheFeatures doFeatures() const override { return {}; }
} cache{PixelFormat::R8Unorm, Vector2i{256}}; } cache{PixelFormat::R8Unorm, Vector2i{256}};
/* [AbstractGlyphCache-filling-images] */ /* [AbstractGlyphCache-filling-images] */
Containers::ArrayView<const ImageView2D> images = DOXYGEN_ELLIPSIS({}); Containers::Array<Image2D> images = DOXYGEN_ELLIPSIS({}); /* or ImageView2D, Trade::ImageData2D... */
/* [AbstractGlyphCache-filling-images] */ /* [AbstractGlyphCache-filling-images] */
/* [AbstractGlyphCache-filling-font] */ /* [AbstractGlyphCache-filling-font] */
@ -200,7 +248,7 @@ cache.atlas().clearFlags(
TextureTools::AtlasLandfillFlag::RotatePortrait| TextureTools::AtlasLandfillFlag::RotatePortrait|
TextureTools::AtlasLandfillFlag::RotateLandscape); TextureTools::AtlasLandfillFlag::RotateLandscape);
Containers::Optional<Range2Di> range = cache.atlas().add( Containers::Optional<Range2Di> range = cache.atlas().add(
stridedArrayView(images).slice(&ImageView2D::size), stridedArrayView(images).slice(&Image2D::size),
offsets); offsets);
CORRADE_INTERNAL_ASSERT(range); CORRADE_INTERNAL_ASSERT(range);
/* [AbstractGlyphCache-filling-atlas] */ /* [AbstractGlyphCache-filling-atlas] */

55
src/Magnum/Text/AbstractFont.h

@ -114,17 +114,21 @@ glyphs will be rasterized. Then it stays open until the font is destroyed,
@ref close() or another font is opened. @ref close() or another font is opened.
In the following example a font is loaded from the filesystem using the In the following example a font is loaded from the filesystem using the
@ref StbTrueTypeFont plugin, prerendering all needed glyphs, completely with @ref StbTrueTypeFont plugin, prerendering desired glyphs into a
all error handling: @ref GlyphCacheGL, completely with all error handling --- depending on the
font file, font plugin implementation, font size and cache size, it may happen
that the characters won't all fit, which should be checked by the application:
@snippet Text-gl.cpp AbstractFont-usage @snippet Text-gl.cpp AbstractFont-usage
See @ref plugins for more information about general plugin usage and the list See @ref plugins for more information about general plugin usage and the list
of @m_class{m-doc} <a href="#derived-classes">derived classes</a> for available of @m_class{m-doc} <a href="#derived-classes">derived classes</a> for available
font plugins. See @ref GlyphCache for more information about glyph caches and font plugins. See @ref AbstractGlyphCache for more information about glyph
@ref BasicRenderer "Renderer*D" for information about actual text rendering. caches, @ref BasicRenderer "Renderer*D" for high-level text rendering, and
@ref AbstractShaper for low-level access to the font text shaping
functionality.
@subsection Text-AbstractFont-usage-font-size Font size @section Text-AbstractFont-font-size Font size
Font libraries specify font size in *points*, where 1 pt = ~1.333 px at 96 DPI, Font libraries specify font size in *points*, where 1 pt = ~1.333 px at 96 DPI,
so in the above snippet a 12 pt font corresponds to 16 px on a 96 DPI display. so in the above snippet a 12 pt font corresponds to 16 px on a 96 DPI display.
@ -136,18 +140,47 @@ properties are specified *in pixels* in @ref lineHeight(), @ref ascent() and
@ref descent(). @ref descent().
The font size used when opening the font affects how large the glyphs will be The font size used when opening the font affects how large the glyphs will be
when rendered into the @ref GlyphCache. Actual text rendering with when rendered into the glyph cache. Actual text rendering with
@ref BasicRenderer "Renderer*D" however uses its own font size, and the @ref BasicRenderer "Renderer*D" however uses its own font size, and the
rendered size is then additionally depending on the actual projection used. rendered size is then additionally depending on the actual projection used.
This decoupling of font sizes is useful for example in case of This decoupling of font sizes is useful for example in case of
@ref DistanceFieldGlyphCache, where a single prerendered glyph size can be used @ref DistanceFieldGlyphCacheGL, where a single prerendered glyph size can be
to render arbitrarily large font sizes without becoming blurry or jaggy. When used to render arbitrarily large font sizes without becoming blurry or jaggy.
not using a distance field glyph cache, it's usually desirable to have the font When not using a distance field glyph cache, it's usually desirable to have the
size and the actual rendered size match. See font size and the actual rendered size match. See
@ref Text-BasicRenderer-usage-font-size "the Renderer*D documentation" for @ref Text-BasicRenderer-usage-font-size "the Renderer*D documentation" for
further information about picking font sizes. further information about picking font sizes.
@subsection Text-AbstractFont-usage-callbacks Loading data from memory, using file callbacks @section Text-AbstractFont-glyph-cache Glyph cache filling options
Besides filling the cache with glyphs corresponding to individual characters in
a UTF-8 string, it's possible to directly specify glyph IDs with
@ref fillGlyphCache(AbstractGlyphCache&, const Containers::StridedArrayView1D<const UnsignedInt>&).
That's useful for example with ligatures like *fl* or *ff* that can get used by
a particular font implementation instead of individual letters, and which thus
don't have a clear mapping to a Unicode codepoint. You can use some font
introspection utility to retrieve either directly the glyph IDs, or get just
glyph names and match them with IDs using @ref glyphForName() at runtime. The
following snippet prerenders a few of the named ligatures present in the
[Source Sans](https://github.com/adobe-fonts/source-sans) font that this
website uses. Again explicitly checking that the operation succeeds, this time
with a @ref CORRADE_INTERNAL_ASSERT_OUTPUT() macro:
@snippet Text.cpp AbstractFont-glyph-cache-by-id
Subsequent calls to @ref fillGlyphCache() add to already existing glyphs,
allowing for incremental filling based on which glyphs are needed by actual
text. Such as by passing the output of @ref AbstractShaper::glyphIdsInto()
through @ref AbstractGlyphCache::glyphIdsInto() and adding all glyphs which it
didn't find. Note that, however, the glyph cache packing is the most efficient
when all glyphs are added at once.
Finally, it's possible to use this overload to populate the glyph cache with
all glyphs in the font:
@snippet Text.cpp AbstractFont-glyph-cache-all
@section Text-AbstractFont-usage-callbacks Loading data from memory, using file callbacks
Besides loading data directly from the filesystem using @ref openFile() like Besides loading data directly from the filesystem using @ref openFile() like
shown above, it's possible to use @ref openData() to import data from memory. shown above, it's possible to use @ref openData() to import data from memory.

70
src/Magnum/Text/AbstractGlyphCache.h

@ -107,37 +107,44 @@ MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& output, GlyphCacheFeatures value);
@m_since{2019,10} @m_since{2019,10}
A GPU-API-agnostic base for glyph caches, supporting multiple fonts and both 2D A GPU-API-agnostic base for glyph caches, supporting multiple fonts and both 2D
and 2D array textures. See the @ref GlyphCache and @ref DistanceFieldGlyphCache and 2D array textures. Provides a common interface for adding fonts, glyph
subclasses for concrete OpenGL implementations. The base class provides a properties, uploading glyph data and retrieving glyph properties back, the
common interface for adding fonts, glyph properties, uploading glyph data and @ref GlyphCacheGL and @ref DistanceFieldGlyphCacheGL subclasses then provide
retrieving glyph properties back. concrete implementations backed with an OpenGL texture.
@section Text-AbstractGlyphCache-filling Filling the glyph cache @section Text-AbstractGlyphCache-usage Basic usage
A glyph cache is constructed through the concrete GPU-API-specific subclasses, A glyph cache is constructed through the concrete GPU-API-specific subclasses,
namely the @ref GlyphCache and @ref DistanceFieldGlyphCache classes mentioned such as @ref GlyphCacheGL. Its constructor takes a @ref PixelFormat and desired
above. Depending on the use case and platform capabilities it's also possible texture size. @ref PixelFormat::R8Unorm is the usual choice,
to create glyph caches with 2D texture arrays, for example when large alphabets @ref PixelFormat::RGBA8Unorm is useful for emoji fonts or when arbitrary icon
are used or when the cache may get filled on-demand with many additional data are put into the cache.
glyphs.
@snippet Text-gl.cpp AbstractGlyphCache-usage-construct
A glyph cache is created in an appropriate @ref PixelFormat and a size.
@ref PixelFormat::R8Unorm is the usual choice, @ref PixelFormat::RGBA8Unorm is Afterwards, assuming there's an opened @ref AbstractFont instance and a known
useful for emoji fonts or when arbitrary icon data are put into the cache. set of glyphs to prerender, the high-level use involves just calling
@ref AbstractFont::fillGlyphCache(), which then does all packing and data
@snippet Text-gl.cpp AbstractGlyphCache-filling-construct copying on its own. Note that depending on the font file, font plugin
implementation, font size and cache size, it may happen that the characters
The rest of this section describes low level usage of the glyph cache filling won't all fit, which should be checked by the application:
APIs, which are useful mainly when implementing an @ref AbstractFont itself or
when adding arbitrary other image data to the cache. When using the glyph cache @snippet Text.cpp AbstractGlyphCache-usage-fill
with an existing @ref AbstractFont instance, often the high level use involves
just calling @ref AbstractFont::fillGlyphCache(), which does all of the As long as the cache size allows, you can call
following on its own. @ref AbstractFont::fillGlyphCache() multiple times with additional glyphs and
other fonts. See the @ref Text-AbstractFont-glyph-cache "AbstractFont documentation"
Let's say we want to fill the glyph cache with a custom set of images that for more options for glyph cache filling.
don't necessarily need to be a font per se. Assuming the input images are
stored in a simple array, and the goal is to put them all together into the @section Text-AbstractGlyphCache-filling Filling the glyph cache directly
cache and reference them later simply by their array indices.
This section describes low level usage of the glyph cache filling APIs, which
are useful mainly when implementing an @ref AbstractFont itself or when adding
arbitrary other image data to the cache. Let's say we want to fill the glyph
cache with a custom set of images that don't necessarily need to be a font per
se. Assuming the input images are stored in a simple array, and the goal is to
put them all together into the cache and reference them later simply by their
array indices.
@snippet Text.cpp AbstractGlyphCache-filling-images @snippet Text.cpp AbstractGlyphCache-filling-images
@ -192,7 +199,7 @@ letters *j* or *q* that reach below the baseline).
Important is to call @ref flushImage() at the end, which makes the glyph cache Important is to call @ref flushImage() at the end, which makes the glyph cache
update its actual GPU-side texture based on what area of the image was updated. update its actual GPU-side texture based on what area of the image was updated.
In case of @ref DistanceFieldGlyphCache for example it also triggers distance In case of @ref DistanceFieldGlyphCacheGL for example it also triggers distance
field generation for given area. field generation for given area.
If the images put into the cache are meant to be used with general meshes, the If the images put into the cache are meant to be used with general meshes, the
@ -852,8 +859,9 @@ class MAGNUM_TEXT_EXPORT AbstractGlyphCache {
* @param[in] fontGlyphIds Glyph IDs in given font * @param[in] fontGlyphIds Glyph IDs in given font
* @param[out] glyphIds Resulting cache-global glyph IDs * @param[out] glyphIds Resulting cache-global glyph IDs
* *
* A batch variant of @ref glyphId(), mainly meant to be used to index * A batch variant of @ref glyphId(), mainly meant to be used with the
* the @ref glyphOffsets() const, @ref glyphLayers() const and * output of @ref AbstractShaper::glyphIdsInto() to then index the
* @ref glyphOffsets() const, @ref glyphLayers() const and
* @ref glyphRectangles() const views. * @ref glyphRectangles() const views.
* *
* The @p fontId is expected to be less than @ref fontCount(), all * The @p fontId is expected to be less than @ref fontCount(), all

4
src/Magnum/Text/DistanceFieldGlyphCacheGL.h

@ -44,8 +44,8 @@ namespace Magnum { namespace Text {
@m_since_latest @m_since_latest
Unlike the base @ref GlyphCacheGL, this class converts each binary image to a Unlike the base @ref GlyphCacheGL, this class converts each binary image to a
distance field. It's not possible to only use this cache for monochrome glyphs distance field. It's possible to only use this cache for monochrome glyphs as
as the internal texture format is single-channel. the internal texture format is single-channel.
@section Text-DistanceFieldGlyphCacheGL-usage Usage @section Text-DistanceFieldGlyphCacheGL-usage Usage

28
src/Magnum/Text/GlyphCacheGL.h

@ -40,28 +40,21 @@
namespace Magnum { namespace Text { namespace Magnum { namespace Text {
/** /**
@brief OpenGL glyph cache @brief OpenGL implementation of a glyph cache
@m_since_latest @m_since_latest
Contains font glyphs rendered into a texture atlas. Implementation of an @ref AbstractGlyphCache backed by a @ref GL::Texture2D.
See the @ref AbstractGlyphCache class documentation for information about
@section Text-GlyphCacheGL-usage Usage setting up an instance of this class and filling it with glyphs. See the
@ref DistanceFieldGlyphCacheGL subclass for a variant that adds distance field
Create the @ref GlyphCacheGL object with sufficient size and then call processing on top.
@ref AbstractFont::createGlyphCache() to fill it with glyphs.
@snippet Text-gl.cpp GlyphCacheGL-usage
See the @ref BasicRenderer "Renderer*D" class for information about text
rendering. The @ref AbstractGlyphCache base class has more information about
general glyph cache usage.
@section Text-GlyphCacheGL-internal-format Internal texture format @section Text-GlyphCacheGL-internal-format Internal texture format
The @ref GL::TextureFormat used by @ref texture() is implicitly coming from The @ref GL::TextureFormat used by @ref texture() is implicitly coming from
@ref GL::textureFormat(Magnum::PixelFormat) applied to @ref format(), or if @ref GL::textureFormat(Magnum::PixelFormat) applied to the @ref format() that
@ref GlyphCacheFeature::ImageProcessing is supported, to @ref processedFormat() was passed at construction time, or if @ref GlyphCacheFeature::ImageProcessing
instead. is supported, to @ref processedFormat() instead.
If @ref PixelFormat::R8Unorm is used for @ref format() or if If @ref PixelFormat::R8Unorm is used for @ref format() or if
@ref GlyphCacheFeature::ImageProcessing is supported and @ref GlyphCacheFeature::ImageProcessing is supported and
@ -195,8 +188,7 @@ class MAGNUM_TEXT_EXPORT GlyphCacheGL: public AbstractGlyphCache {
private: private:
MAGNUM_TEXT_LOCAL GlyphCacheFeatures doFeatures() const override; MAGNUM_TEXT_LOCAL GlyphCacheFeatures doFeatures() const override;
/** @todo make those MAGNUM_TEXT_LOCAL again once MagnumFont doesn't /* These are not MAGNUM_TEXT_LOCAL because the test makes a subclass */
need to subclass anything anymore */
void doSetImage(const Vector2i& offset, const ImageView2D& image) override; void doSetImage(const Vector2i& offset, const ImageView2D& image) override;
/* Used if a subclass advertises GlyphCacheFeature::ImageProcessing / /* Used if a subclass advertises GlyphCacheFeature::ImageProcessing /
ProcessedImageDownload in its doFeatures() */ ProcessedImageDownload in its doFeatures() */

12
src/Magnum/Text/Renderer.h

@ -524,7 +524,7 @@ that doesn't recreate everything on each text change:
@subsection Text-BasicRenderer-usage-font-size Font size @subsection Text-BasicRenderer-usage-font-size Font size
As mentioned in @ref Text-AbstractFont-usage-font-size "AbstractFont class documentation", As mentioned in @ref Text-AbstractFont-font-size "AbstractFont class documentation",
the size at which the font is loaded is decoupled from the size at which a the size at which the font is loaded is decoupled from the size at which a
concrete text is rendered. In particular, with a concrete projection matrix, concrete text is rendered. In particular, with a concrete projection matrix,
the size you pass to either @ref render() or to the @ref BasicRenderer() the size you pass to either @ref render() or to the @ref BasicRenderer()
@ -539,7 +539,7 @@ proportional to the window size. The first approach results in e.g. a 12 pt
font matching a 12 pt font in other applications, and is what's shown in the font matching a 12 pt font in other applications, and is what's shown in the
above snippets. The most straightforward way to achieve that is to set up the above snippets. The most straightforward way to achieve that is to set up the
projection matrix size to match actual window pixels, such as @ref Platform::Sdl2Application::windowSize() "Platform::*Application::windowSize()". projection matrix size to match actual window pixels, such as @ref Platform::Sdl2Application::windowSize() "Platform::*Application::windowSize()".
If using the regular @ref GlyphCache, for best visual quality it should be If using the regular @ref GlyphCacheGL, for best visual quality it should be
created with the @ref AbstractFont loaded at the same size as the text to be created with the @ref AbstractFont loaded at the same size as the text to be
rendered, although often a double supersampling achieves a crisper result. rendered, although often a double supersampling achieves a crisper result.
I.e., loading the font with 24 pt, but rendering with 12 pt. See below for I.e., loading the font with 24 pt, but rendering with 12 pt. See below for
@ -549,8 +549,8 @@ The second approach, with text size being relative to the window size, is for
cases where the text is meant to match surrounding art, such as in a game menu. cases where the text is meant to match surrounding art, such as in a game menu.
In this case the projection size is usually something arbitrary that doesn't In this case the projection size is usually something arbitrary that doesn't
match window pixels, and the text point size then has to be relative to that. match window pixels, and the text point size then has to be relative to that.
For this use case a @ref DistanceFieldGlyphCache is the better match, as it can For this use case a @ref DistanceFieldGlyphCacheGL is the better match, as it
provide text at different sizes with minimal quality loss. See its can provide text at different sizes with minimal quality loss. See its
documentation for details about picking the right font size and other documentation for details about picking the right font size and other
parameters for best results. parameters for best results.
@ -571,7 +571,7 @@ concepts for DPI-aware rendering:
display has a 200% interface scale, a 12 pt font would be 32 pixels. But if display has a 200% interface scale, a 12 pt font would be 32 pixels. But if
it only has a 150% scale, all interface elements will be smaller, and a 12 it only has a 150% scale, all interface elements will be smaller, and a 12
pt font would be only 24 pixels. The size used by the @ref AbstractFont and pt font would be only 24 pixels. The size used by the @ref AbstractFont and
@ref GlyphCache should be chosen with respect to the actual physical @ref GlyphCacheGL should be chosen with respect to the actual physical
pixels. pixels.
When using for example @ref Platform::Sdl2Application or other `*Application` When using for example @ref Platform::Sdl2Application or other `*Application`
@ -585,7 +585,7 @@ would be calculated like this:
@snippet Text-gl.cpp BasicRenderer-dpi-interface-size @snippet Text-gl.cpp BasicRenderer-dpi-interface-size
And a multiplier for the @ref AbstractFont and @ref GlyphCache font size like And a multiplier for the @ref AbstractFont and @ref GlyphCacheGL font size like
this. The @ref BasicRenderer "Renderer*D" keeps using the size without this this. The @ref BasicRenderer "Renderer*D" keeps using the size without this
multiplier. multiplier.

Loading…
Cancel
Save