CUGL 2.1
Cornell University Game Library
Classes | Public Member Functions | Static Public Member Functions | Friends | List of all members
cugl::TextLayout Class Reference

#include <CUTextLayout.h>

Public Member Functions

 TextLayout ()
 
 ~TextLayout ()
 
void dispose ()
 
bool init ()
 
bool initWithWidth (float width)
 
bool initWithText (const std::string text, const std::shared_ptr< Font > &font)
 
bool initWithTextWidth (const std::string text, const std::shared_ptr< Font > &font, float width)
 
const std::string & getText () const
 
void setText (const std::string text)
 
const std::shared_ptr< Font > & getFont () const
 
void setFont (const std::shared_ptr< Font > &font)
 
float getWidth () const
 
void setWidth (float width)
 
float getSpacing () const
 
void setSpacing (float spacing)
 
HorizontalAlign getHorizontalAlignment () const
 
void setHorizontalAlignment (HorizontalAlign halign)
 
VerticalAlign getVerticalAlignment () const
 
void setVerticalAlignment (VerticalAlign valign)
 
void layout ()
 
void invalidate ()
 
bool validated () const
 
const RectgetBounds () const
 
const Rect getTightBounds () const
 
const Rect getTrueBounds () const
 
size_t getLineCount () const
 
std::string getLine (size_t line) const
 
Rect getGlyphBounds (size_t index) const
 
size_t getGlyphIndex (Vec2 p) const
 
size_t getGlyphIndex (float x, float y) const
 
size_t getNearestIndex (Vec2 p) const
 
size_t getNearestIndex (float x, float y) const
 
std::unordered_map< GLuint, std::shared_ptr< GlyphRun > > getGlyphs () const
 
std::unordered_map< GLuint, std::shared_ptr< GlyphRun > > getGlyphs (Rect rect) const
 
size_t getGlyphs (std::unordered_map< GLuint, std::shared_ptr< GlyphRun >> &runs) const
 
size_t getGlyphs (std::unordered_map< GLuint, std::shared_ptr< GlyphRun >> &runs, Rect rect) const
 

Static Public Member Functions

static std::shared_ptr< TextLayoutalloc ()
 
static std::shared_ptr< TextLayoutallocWithWidth (float width)
 
static std::shared_ptr< TextLayoutallocWithText (const std::string text, const std::shared_ptr< Font > &font)
 
static std::shared_ptr< TextLayoutallocWithTextWidth (const std::string text, const std::shared_ptr< Font > &font, float width)
 

Friends

class cugl::scene2::Label
 
class cugl::scene2::TextField
 

Detailed Description

This class manages the layout of (potentially) multiple lines of text.

The purpose of this class is to decouple text layout from the scene2::Label scene graph class, so we can draw text directly to a SpriteBatch. Given a string, it potentially breaks the string up into multiple lines and allows you to control the relative alignment of each line.

In addition, a text layout object has an implicit coordinate system with an origin. This origin is defined by the getHorizontalAlignment and getVerticalAlignment options. This origin is used to place the text when it is rendered with a sprite batch.

Changing any of the layout attributes will obviously invalidate the text layout. For performance reasons, we do not automatically recompute the layout in that case. Instead, the user must call layout to arrange the text.

By default, the text layout will only break lines at newline characters in the string. However, you can perform more agressive line breaking with the optional getWidth attribute. When this attribute is positive, the text layout will break lines so that each line does not exceed this width.

Lines will be broken at the last white space character found before exceeding the width. If there is no such whitespace character, it will break the line before the first character exceeding the width. While this class does not support more sophisticated line breaking like hyphenation, the end result is good enough for most in-game multi-line text support.

When formatting multiline text, whitespace at the beginning and end of each line will be "swallowed", causing it to be ignored for purposes of alignment. The exception is at the beginning and end of a paragraph. Whitespace there will be preserved. A paragraph is defined as any piece of text separated by a newline. So the first part of the string before a newline is a paragraph, and each substring after a newline is also a paragraph.

Finally, it is possible to disable all line breaking in a text layout (including newlines). Simply set the width to a negative value.

Constructor & Destructor Documentation

◆ TextLayout()

cugl::TextLayout::TextLayout ( )

Creates a degenerate text layout with no data.

NEVER USE A CONSTRUCTOR WITH NEW. If you want to allocate an object on the heap, use one of the static constructors instead.

◆ ~TextLayout()

cugl::TextLayout::~TextLayout ( )
inline

Deletes this text layout, disposing of all resources.

Member Function Documentation

◆ alloc()

static std::shared_ptr<TextLayout> cugl::TextLayout::alloc ( )
inlinestatic

Returns a newly allocated empty text layout

You will need to add both text and a font, as well as call the method layout to properly use this object.

This layout will have a size of 0, which menas that this method will only break lines at newlines. This guarantees multi-line text support without taking control away from the programmer.

Returns
a newly allocated empty text layout

◆ allocWithText()

static std::shared_ptr<TextLayout> cugl::TextLayout::allocWithText ( const std::string  text,
const std::shared_ptr< Font > &  font 
)
inlinestatic

Returns a newly allocated text layout with the given text and font

This layout will have a size of 0, which menas that this method will only break lines at newlines. This guarantees multi-line text support without taking control away from the programmer.

Note that this method does not actually arrange the text. You must call layout to complete the layout. This gives you time to change the horizontal or vertical alignment before performing the layout.

Parameters
textThe text to layout
fontThe font to arrange the text
Returns
a newly allocated text layout with the given text and font

◆ allocWithTextWidth()

static std::shared_ptr<TextLayout> cugl::TextLayout::allocWithTextWidth ( const std::string  text,
const std::shared_ptr< Font > &  font,
float  width 
)
inlinestatic

Returns a newly allocated text layout with the given text, font, and width.

A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the layout manager to break up lines so that no individual line exceeds that width.

Note that this method does not actually arrange the text. You must call layout to complete the layout. This gives you time to change the horizontal or vertical alignment before performing the layout.

Parameters
textThe text to layout
fontThe font to arrange the text
widthThe width for each line
Returns
a newly allocated text layout with the given text, font, and width.

◆ allocWithWidth()

static std::shared_ptr<TextLayout> cugl::TextLayout::allocWithWidth ( float  width)
inlinestatic

Returns a newly allocated empty text layout with the given width.

You will need to add both text and a font, as well as call the method layout to properly use this object.

A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the layout manager to break up lines so that no individual line exceeds that width.

Parameters
widthThe width for each line
Returns
a newly allocated empty text layout with the given width.

◆ dispose()

void cugl::TextLayout::dispose ( )

Deletes the layout resources and resets all attributes.

You must reinitialize the text layout to use it.

◆ getBounds()

const Rect& cugl::TextLayout::getBounds ( ) const
inline

Returns the bounds of this text layout

This rectangle is in the coordinate space whose origin is defined by the horizontal and vertical alignment. This rectangle has zero size if the layout method has not been called or if the layout has been invalidated.

Returns
the bounds of this text layout

◆ getFont()

const std::shared_ptr<Font>& cugl::TextLayout::getFont ( ) const
inline

Returns the font associated with this layout.

Changing this value will invalidate the layout.

Returns
the font associated with this layout.

◆ getGlyphBounds()

Rect cugl::TextLayout::getGlyphBounds ( size_t  index) const

Returns the glyph bounds of the character at the given index

The rectangle will be in the coordinate system of this text layout. In addition to the size, it will accurately reflect the position of the character in the layout, including any possible tracking.

The index represents a position in the layout text string. The index must be the first byte of a valid UTF8 character. If it is a successive byte (and hence undecodable as a unicode character), this method will return the empty rectangle.

Parameters
indexThe position in the layout text
Returns
the glyph bounds of the character at the given index

◆ getGlyphIndex() [1/2]

size_t cugl::TextLayout::getGlyphIndex ( float  x,
float  y 
) const

Returns the index of the character whose glyph is located at (x,y)

If the point (x,y) is not on top of a glyph, this method will return the size of the text. Use getNearestIndex for cases in which the point is out of bounds.

The point (x,y) is assumed to be in the coordinate system of this layout. This method will never return the index of white space "swallowed" at the end of multiline text, even when this point is beyond the edges of the text.

Parameters
xThe x-coordinate in layout space
yThe y-coordinate in layout space
Returns
the index of the character whose glyph is located at (x,y)

◆ getGlyphIndex() [2/2]

size_t cugl::TextLayout::getGlyphIndex ( Vec2  p) const
inline

Returns the index of the character whose glyph is located at p

If the point p is not on top of a glyph, this method will return the size of the text. Use getNearestIndex for cases in which the point is out of bounds.

The point p is assumed to be in the coordinate system of this layout. This method will never return the index of white space "swallowed" at the end of multiline text, even when this point is beyond the edges of the text.

Parameters
pThe position in layout space
Returns
the index of the character whose glyph is located at p

◆ getGlyphs() [1/4]

std::unordered_map<GLuint,std::shared_ptr<GlyphRun> > cugl::TextLayout::getGlyphs ( ) const

Returns a set of glyph runs to render the text layout

Each glyph run will consist of a quad mesh and a texture to render those quads. Rendering all of the glyph runs together will render the entire string. Generally the quads are non-overlapping, so any blending mode is supported. However, if the atlas padding is non-zero (to support font blur), the quads will overlap at the padding intervals. Therefore, we recommend alpha blending when you render a string.

The keys for the glyph runs are the Texture#getBuffer values for the appropriate atlas texture. This, combined with the method Font#getAtlases allows you to identify the atlas for each run.

The origin of the glyph runs will agree with that of the text layout. This method will return the empty map if layout has not been called or the layout has been invalidated.

Returns
a set of glyph runs to render the text layout

◆ getGlyphs() [2/4]

std::unordered_map<GLuint,std::shared_ptr<GlyphRun> > cugl::TextLayout::getGlyphs ( Rect  rect) const

Returns a set of glyph runs to render the text layout

Each glyph run will consist of a quad mesh and a texture to render those quads. Rendering all of the glyph runs together will render the entire string. Generally the quads are non-overlapping, so any blending mode is supported. However, if the atlas padding is non-zero (to support font blur), the quads will overlap at the padding intervals. Therefore, we recommend alpha blending when you render a string.

The keys for the glyph runs are the Texture#getBuffer values for the appropriate atlas texture. This, combined with the method Font#getAtlases allows you to identify the atlas for each run.

The quad sequence is adjusted so that all of the vertices fit in the provided rectangle. The primary use-case for this is to guarantee that glyphs do not spill outside of a window. This may mean that some of the glyphs will be truncrated or even omitted.

The origin of the glyph runs will agree with that of the text layout. This method will return the empty map if layout has not been called or the layout has been invalidated.

Parameters
rectThe bounding box for the quads
Returns
a set of glyph runs to render the text layout

◆ getGlyphs() [3/4]

size_t cugl::TextLayout::getGlyphs ( std::unordered_map< GLuint, std::shared_ptr< GlyphRun >> &  runs) const

Stores the glyph runs to render the text layout in the given map

Each glyph run will consist of a quad mesh and a texture to render those quads. Rendering all of the glyph runs together will render the entire string. Generally the quads are non-overlapping, so any blending mode is supported. However, if the atlas padding is non-zero (to support font blur), the quads will overlap at the padding intervals. Therefore, we recommend alpha blending when you render a string.

The keys for the glyph runs are the Texture#getBuffer values for the appropriate atlas texture. This, combined with the method Font#getAtlases allows you to identify the atlas for each run. If the map is non-empty, the glyph run data will be appended to the relevant existing glyph run (if possible).

The origin of the glyph runs will agree with that of the text layout. This method will do nothing if layout has not been called or the layout has been invalidated.

Parameters
runsThe map to store the glyph runs
Returns
the number of glyphs successfully processed

◆ getGlyphs() [4/4]

size_t cugl::TextLayout::getGlyphs ( std::unordered_map< GLuint, std::shared_ptr< GlyphRun >> &  runs,
Rect  rect 
) const

Stores the glyph runs to render the text layout in the given map

Each glyph run will consist of a quad mesh and a texture to render those quads. Rendering all of the glyph runs together will render the entire string. Generally the quads are non-overlapping, so any blending mode is supported. However, if the atlas padding is non-zero (to support font blur), the quads will overlap at the padding intervals. Therefore, we recommend alpha blending when you render a string.

The keys for the glyph runs are the Texture#getBuffer values for the appropriate atlas texture. This, combined with the method Font#getAtlases allows you to identify the atlas for each run. If the map is non-empty, the glyph run data will be appended to the relevant existing glyph run (if possible).

The quad sequence is adjusted so that all of the vertices fit in the provided rectangle. The primary use-case for this is to guarantee that glyphs do not spill outside of a window. This may mean that some of the glyphs will be truncrated or even omitted.

The origin of the glyph runs will agree with that of the text layout. This method will do nothing if layout has not been called or the layout has been invalidated.

Parameters
runsThe map to store the glyph runs
rectThe bounding box for the quads
Returns
the number of glyphs successfully processed

◆ getHorizontalAlignment()

HorizontalAlign cugl::TextLayout::getHorizontalAlignment ( ) const
inline

Returns the horizontal alignment of the text.

The horizontal alignment has two meanings. First, it is the relationship of the relative alignment of multiple lines. In addition, it defines the x-coordinate origin of the text layout. The later is relevant even when the text layout is a single line.

Changing this value will invalidate the layout.

Returns
the horizontal alignment of the text.

◆ getLine()

std::string cugl::TextLayout::getLine ( size_t  line) const

Returns the text for the given line.

Note that line breaking will omit any white space on the ends. Hence adding the text for each line together may not produce the original text.

Parameters
lineThe line number
Returns
the text for the given line.

◆ getLineCount()

size_t cugl::TextLayout::getLineCount ( ) const
inline

Returns the number of lines in this text layout

This value will be zero if layout has not been called or if the layout has been invalidated.

Returns
the number of lines in this text layout

◆ getNearestIndex() [1/2]

size_t cugl::TextLayout::getNearestIndex ( float  x,
float  y 
) const

Returns the index of the character whose glyph is nearest (x,y)

The point (x,y) is assumed to be in the coordinate system of this layout. This method will never return the index of white space "swallowed" at the end of multiline text, even when this point is beyond the edges of the text.

Parameters
xThe x-coordinate in layout space
yThe y-coordinate in layout space
Returns
the index of the character whose glyph is nearest (x,y)

◆ getNearestIndex() [2/2]

size_t cugl::TextLayout::getNearestIndex ( Vec2  p) const
inline

Returns the index of the character whose glyph is nearest p

The point p is assumed to be in the coordinate system of this layout. This method will never return the index of white space "swallowed" at the end of multiline text, even when this point is beyond the edges of the text.

Parameters
pThe position in layout space
Returns
the index of the character whose glyph is nearest p

◆ getSpacing()

float cugl::TextLayout::getSpacing ( ) const
inline

Returns the line spacing of this layout.

This value is multiplied by the font size to determine the space between lines in the layout. So a value of 1 is single-spaced text, while a value of 2 is double spaced. The value should be positive.

Changing this value will invalidate the layout.

Returns
the line spacing of this layout.

◆ getText()

const std::string& cugl::TextLayout::getText ( ) const
inline

Returns the text associated with this layout.

Changing this value will invalidate the layout.

Returns
the text associated with this layout.

◆ getTightBounds()

const Rect cugl::TextLayout::getTightBounds ( ) const

Returns the tightest bounds of the text layout

This rectangle is in the coordinate space whose origin is defined by the horizontal and vertical alignment. This rectangle has zero size if the layout method has not been called or if the layout has been invalidated.

Unlike getBounds, this rectangle sits tight against the text, ignoring any natural spacing such as the ascent or descent. However, it does not include any tracking that the layout may apply.

Returns
the tightest bounds of the text layout

◆ getTrueBounds()

const Rect cugl::TextLayout::getTrueBounds ( ) const

Returns the true bounds of the text layout, including tracking

This rectangle is in the coordinate space whose origin is defined by the horizontal and vertical alignment. This rectangle has zero size if the layout method has not been called or if the layout has been invalidated.

The method is similar to getTightBounds, except that it also includes any tracking that is applied to the layout.

Returns
the true bounds of the text layout, including tracking

◆ getVerticalAlignment()

VerticalAlign cugl::TextLayout::getVerticalAlignment ( ) const
inline

Returns the vertical alignment of the text.

The vertical alignment defines the y-coordinate origin of this text layout. In the case of multiple lines, the alignment is (often) with respect to the entire block of text, not just the first line.

Changing this value will invalidate the layout.

Returns
the vertical alignment of the text.

◆ getWidth()

float cugl::TextLayout::getWidth ( ) const
inline

Returns the line width of this layout.

This value will determine how the layout breaks up lines to arrange text. A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the text layout to break up lines so that no individual line exceeds that width.

Changing this value will invalidate the layout.

Returns
the line width of this layout.

◆ init()

bool cugl::TextLayout::init ( )

Initializes an empty text layout

You will need to add both text and a font, as well as call the method layout to properly use this object.

This layout will have a size of 0, which menas that this method will only break lines at newlines. This guarantees multi-line text support without taking control away from the programmer.

Returns
true if initialization is successful.

◆ initWithText()

bool cugl::TextLayout::initWithText ( const std::string  text,
const std::shared_ptr< Font > &  font 
)

Initializes a text layout with the given text and font.

This layout will have a size of 0, which menas that this method will only break lines at newlines. This guarantees multi-line text support without taking control away from the programmer.

Note that this method does not actually arrange the text. You must call layout to complete the layout. This gives you time to change the horizontal or vertical alignment before performing the layout.

Parameters
textThe text to layout
fontThe font to arrange the text
Returns
true if initialization is successful.

◆ initWithTextWidth()

bool cugl::TextLayout::initWithTextWidth ( const std::string  text,
const std::shared_ptr< Font > &  font,
float  width 
)

Initializes a text layout with the given text, font, and width.

A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the layout manager to break up lines so that no individual line exceeds that width.

Note that this method does not actually arrange the text. You must call layout to complete the layout. This gives you time to change the horizontal or vertical alignment before performing the layout.

Parameters
textThe text to layout
fontThe font to arrange the text
widthThe width for each line
Returns
true if initialization is successful.

◆ initWithWidth()

bool cugl::TextLayout::initWithWidth ( float  width)

Initializes an empty text layout with the given width.

You will need to add both text and a font, as well as call the method layout to properly use this object.

A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the layout manager to break up lines so that no individual line exceeds that width.

Parameters
widthThe width for each line
Returns
true if initialization is successful.

◆ invalidate()

void cugl::TextLayout::invalidate ( )

Invalidates the text layout

This deletes all rows (so the line count is 0). You will need to call layout to reperform the layout.

◆ layout()

void cugl::TextLayout::layout ( )

Arranges the text according to the given font and settings

Changing any of the layout attributes will obviously invalidate the text layout. For performance reasons, we do not automatically recompute the layout in that case. Instead, the user must call layout to arrange the text.

◆ setFont()

void cugl::TextLayout::setFont ( const std::shared_ptr< Font > &  font)

Sets the font associated with this layout.

Changing this value will invalidate the layout.

Parameters
fontThe font associated with this layout.

◆ setHorizontalAlignment()

void cugl::TextLayout::setHorizontalAlignment ( HorizontalAlign  halign)

Sets the horizontal alignment of the text.

The horizontal alignment has two meanings. First, it is the relationship of the relative alignment of multiple lines. In addition, it defines the x-coordinate origin of the text layout. The later is relevant even when the text layout is a single line.

Changing this value will invalidate the layout.

Parameters
halignThe horizontal alignment of the text.

◆ setSpacing()

void cugl::TextLayout::setSpacing ( float  spacing)

Sets the line spacing of this layout.

This value is multiplied by the font size to determine the space between lines in the layout. So a value of 1 is single-spaced text, while a value of 2 is double spaced. The value should be positive.

Changing this value will invalidate the layout.

Parameters
spacingThe line spacing of this layout.

◆ setText()

void cugl::TextLayout::setText ( const std::string  text)

Sets the text associated with this layout.

Changing this value will invalidate the layout.

Parameters
textThe text associated with this layout.

◆ setVerticalAlignment()

void cugl::TextLayout::setVerticalAlignment ( VerticalAlign  valign)

Sets the vertical alignment of the text.

The vertical alignment defines the y-coordinate origin of this text layout. In the case of multiple lines, the alignment is (often) with respect to the entire block of text, not just the first line.

Changing this value will invalidate the layout.

Parameters
valignThe vertical alignment of the text.

◆ setWidth()

void cugl::TextLayout::setWidth ( float  width)

Sets the line width of this layout.

This value will determine how the layout breaks up lines to arrange text. A width of 0 will guarantee that breaks only happen at newlines, while a negative width means that line breaks never happen at all. A postive width will force the text layout to break up lines so that no individual line exceeds that width.

Changing this value will invalidate the layout.

Parameters
widthThe line width of this layout.

◆ validated()

bool cugl::TextLayout::validated ( ) const
inline

Returns true if the layout has been successful.

This method will return false unless layout has been called.

Returns
true if the layout has been successful.

Friends And Related Function Documentation

◆ cugl::scene2::Label

friend class cugl::scene2::Label
friend

Allow label access for fine-tuned control


The documentation for this class was generated from the following file: