![]() |
RAMSES Documentation
27.0.130
Information for RAMSES users and developers
|
Stores text data - texture atlas, meshes, glyph bitmap data. It is a cache because the content can be re-generated when necessary, e.g. when cached glyphs take up too much memory. More...
#include <TextCache.h>
Public Member Functions | |
TextCache (Scene &scene, IFontAccessor &fontAccessor, uint32_t atlasTextureWidth, uint32_t atlasTextureHeight) | |
Constructor for text cache. More... | |
~TextCache () | |
Destructor for text cache that cleans up any objects created using the text cache. The scene object passed to the text cache constructor must be still valid at the time of the text cache destruction. More... | |
GlyphMetricsVector | getPositionedGlyphs (const std::u32string &str, FontInstanceId font) |
Create and get glyph metrics for a string using a font instance. More... | |
GlyphMetricsVector | getPositionedGlyphs (const std::u32string &str, const FontInstanceOffsets &fontOffsets) |
Create and get glyph metrics for a string using a list of font instances and offsets. More... | |
TextLineId | createTextLine (const GlyphMetricsVector &glyphs, const Effect &effect) |
Create the scene objects, e.g., mesh and appearance...etc, needed for rendering a text line (represented by glyph metrics). If the provided string of glyphs contains no render-able characters (e.g. it has only white spaces), the method will fail with an error. If you want to avoid having such errors, filter out the glyphs with no visual representation (e.g. control characters) and use the helper method ContainsRenderableGlyphs on top to check if the remaining glyphs contain at least one renderable (size not zero) glyph so they can be used as input for createTextLine. More... | |
TextLine const * | getTextLine (TextLineId textId) const |
Get a const pointer to a (previously created) text line object. More... | |
TextLine * | getTextLine (TextLineId textId) |
Get a (non-const) pointer to a (previously created) text line object. More... | |
bool | deleteTextLine (TextLineId textId) |
Delete an existing text line object. More... | |
TextCache (const TextCache &other)=delete | |
Deleted copy constructor. More... | |
TextCache & | operator= (const TextCache &other)=delete |
Deleted copy assignment. More... | |
Static Public Member Functions | |
static bool | ContainsRenderableGlyphs (const GlyphMetricsVector &glyphMetrics) |
Check if provided GlyphMetricsVector contains at least one renderable glyph If this functions returns false, the provided input cannot be used as input for the function createTextLine. The function call will simply fail. More... | |
static void | ApplyTrackingToGlyphs (GlyphMetricsVector &glyphMetrics, int32_t trackingFactor, int32_t fontSize) |
Apply character tracking (positive or negative) to each glyph in provided GlyphMetricsVector. This means that that the space between the individual glyphs can be increased (positive tracking) or decreased (negative tracking). The tracking factor is calculated in em, so it's relative to the font size (1/1000 of font size in pixels). So having a tracking factor of 1000 and a font size of 10 would result in an extra of 10 pixels space between every glyph (1000/1000 * 10 = 10px). Overdoing the negative tracking is not advised, as the glyphs will then potentially be printed on top of each other. This helper function should only be used on Latin fonts as for all other font types this kind of tracking may lead to unexpected visual output. More... | |
Public Attributes | |
class TextCacheImpl * | impl |
Stores text data - texture atlas, meshes, glyph bitmap data. It is a cache because the content can be re-generated when necessary, e.g. when cached glyphs take up too much memory.
The TextCache class keeps hold of following data:
The TextCache uses IFontAccessor (provided in constructor) to obtain glyph data for various fonts but has otherwise no dependencies to fonts - it treats glyphs as a simple bitmap image placed in one of the texture atlas pages.
The scene objects created for each texture atlas page with glyphs is:
The scene objects created for each text line are:
It's important to note that the Appearance of each TextLine has a reference to the texture page holding its glyph data, and the GeometryBinding has links to the texture quad data generated by TextCache. We highly recommend not to tamper with these objects, unless you have in-depth understanding of how text rendering works and know what you are doing. However, setting custom uniforms in the Appearance is valid, as long as you are not touching the semantic texture sampler which was provided when creating the text line.
The TextCache has a limitation that all characters of a TextLine must fit in one (empty) texture atlas page. This means that if a TextCache was created with size 16x16 and a TextLine with single glyph of size 32 is created, the call to createTextLine() will fail because it can't fit a single glyph in a texture atlas page - it's too small. Therefore, pay special attention to the size of TextCache and the size of text rendered. If you want to optimize memory usage across different and wildly heterogeneous text sizes, it's suggested to use multiple TextCache instances with different sizes if in order to avoid inefficient memory partitioning.
To understand better how TextCache internally works, consider following case. You create a TextCache with size 20x20. You use a latin font with uniform character size 10x10 for all letters. You can thus only create TextLine's with a maximum of 4 letters. If you create two lines with size 4 which use the same 4 characters, the TextCache will create a single texture page and use the glyphs for both lines. If you create two lines with different, but partially overlapping characters, like this: line1 = 'ABC' line2 = 'AXY'
the TextCache will not be able to create a page with all 5 characters (A, B, C, X and Y) and will need to create two pages. The first page will put the letters 'ABC' in one page which will have one empty slot. The second line will not fit in the first page, so the TextCache will create a second page and put the characters 'AXY' there. Note that the character 'A' will be in in both pages, so that each line can be rendered with a single draw call using exactly one mesh and one texture. One may argue that copying glyphs across different pages is bad, but trying to implement a TextCache which creates multiple MeshNodes and partitions them in the worst case across all texture pages quickly leads to the awareness that it's much better to just forbid it and sacriface a bit of memory in favor of much simpler implementation.
The above limitation ensures that each TextLine receives exactly one MeshNode which makes the rendering setup much easier. However, it requires that multi-language texts with large amount of glyphs may result in suboptimal texture atlas layout. This memory overhead can be overcome by either using a texture atlas size large enough to hold any text line or implementing a more sophisticated partitioning of TextLine's to ensure atlas pages are filled proportionally.
Finally, the TextLine object holds pointers to the original vector of glyphs which were used to create it. Be careful to not tamper with it, as it is used when destroying the text line to obtain information which glyphs can be freed.
ramses::TextCache::TextCache | ( | Scene & | scene, |
IFontAccessor & | fontAccessor, | ||
uint32_t | atlasTextureWidth, | ||
uint32_t | atlasTextureHeight | ||
) |
Constructor for text cache.
Choose carefully the size of the atlas textures. Too small will prevent creation of larger strings, because not all of the glyphs will fit on a single page. Too large pages take up more memory than actually needed.
[in] | scene | Scene to use when creating meshes from string glyphs. |
[in] | fontAccessor | Font accessor to be used for getting font instance objects |
[in] | atlasTextureWidth | Width for the texture atlas that gets created to store glyphs |
[in] | atlasTextureHeight | Height for the texture atlas that gets created to store glyphs |
ramses::TextCache::~TextCache | ( | ) |
Destructor for text cache that cleans up any objects created using the text cache. The scene object passed to the text cache constructor must be still valid at the time of the text cache destruction.
|
delete |
Deleted copy constructor.
other | unused |
|
static |
Apply character tracking (positive or negative) to each glyph in provided GlyphMetricsVector. This means that that the space between the individual glyphs can be increased (positive tracking) or decreased (negative tracking). The tracking factor is calculated in em, so it's relative to the font size (1/1000 of font size in pixels). So having a tracking factor of 1000 and a font size of 10 would result in an extra of 10 pixels space between every glyph (1000/1000 * 10 = 10px). Overdoing the negative tracking is not advised, as the glyphs will then potentially be printed on top of each other. This helper function should only be used on Latin fonts as for all other font types this kind of tracking may lead to unexpected visual output.
[in] | glyphMetrics | GlyphMetrics that get tracking applied on |
[in] | trackingFactor | factor of tracking intensity (higher --> bigger tracking effect) |
[in] | fontSize | size of the font that contains the glyphs to be tracked |
|
static |
Check if provided GlyphMetricsVector contains at least one renderable glyph If this functions returns false, the provided input cannot be used as input for the function createTextLine. The function call will simply fail.
[in] | glyphMetrics | GlyphMetrics to be checked @ return True if the provided vector contains at least one renderable glyph |
TextLineId ramses::TextCache::createTextLine | ( | const GlyphMetricsVector & | glyphs, |
const Effect & | effect | ||
) |
Create the scene objects, e.g., mesh and appearance...etc, needed for rendering a text line (represented by glyph metrics). If the provided string of glyphs contains no render-able characters (e.g. it has only white spaces), the method will fail with an error. If you want to avoid having such errors, filter out the glyphs
with no visual representation (e.g. control characters) and use the helper method ContainsRenderableGlyphs on top to check if the remaining glyphs contain at least one renderable (size not zero) glyph so they can be used as input for createTextLine.
This method will always produce exactly one MeshNode. We do this by enforcing that all glyphs are rendered in the same texture atlas page, thus making it possible to create one mesh instead of several. The effect argument has special requirements - it needs to have three semantic uniforms:
[in] | glyphs | The glyph metrics for which to create a text line |
[in] | effect | The effect used for creating the appearance of the text line and rendering the meshes |
bool ramses::TextCache::deleteTextLine | ( | TextLineId | textId | ) |
Delete an existing text line object.
[in] | textId | Id of the text line object to delete |
GlyphMetricsVector ramses::TextCache::getPositionedGlyphs | ( | const std::u32string & | str, |
const FontInstanceOffsets & | fontOffsets | ||
) |
Create and get glyph metrics for a string using a list of font instances and offsets.
Use this version of getPositionedGlyphs if you need more fine-grained control over how glyphs are resolved from multiple fonts. See also documentation of FontInstanceOffset.
[in] | str | The string for which to create glyph metrics |
[in] | fontOffsets | The font offsets created from font cascade to be used for creating the glyph metrics vector. The font instances within the font cascade must all be available at the font accessor passed in the constructor of the text cache. Also see docs of FontInstanceOffsets |
GlyphMetricsVector ramses::TextCache::getPositionedGlyphs | ( | const std::u32string & | str, |
FontInstanceId | font | ||
) |
Create and get glyph metrics for a string using a font instance.
Use this call to obtain glyph metadata - positions, sizes, language and font origin (contained in GlyphKey). You can change the positions if you need to, e.g. if you need to do funky things like re-aligning glyphs coming from different fonts with incompatible baselines. But in the regular case, you just pass the glyphs to createTextLine() as-is.
[in] | str | The string for which to create glyph metrics |
[in] | font | Id of the font instance to be used for creating the glyph metrics vector. The font instance must be available at the font accessor passed in the constructor of the text cache. |
TextLine* ramses::TextCache::getTextLine | ( | TextLineId | textId | ) |
Get a (non-const) pointer to a (previously created) text line object.
[in] | textId | Id of the text line object to get |
TextLine const* ramses::TextCache::getTextLine | ( | TextLineId | textId | ) | const |
Get a const pointer to a (previously created) text line object.
[in] | textId | Id of the text line object to get |
Deleted copy assignment.
other | unused |
class TextCacheImpl* ramses::TextCache::impl |
Stores internal data for implementation specifics of TextCache.