Before I post my initial design idea, I just wanted to jot down my understanding of the JUCE text system.
There may be mistakes in my understanding so if you feel that any part of the text below is wrong, please let me know.
Components
The following is a list of built-in components which an end user is capable of editing text with a keyboard and/or mouse:
- TextEditor
- CodeEditorComponent
- Label
- Slider
- Combo Box
The last three components in that list (Label/Slider/Combo Box) don’t actually have editing functionality themselves, they simply show and use a TextEditor Component to do the actual editing.
Thus there are effectively only two components that can edit text (TextEditor/CodeEditor). These widgets handle all editing related functionality like text selection and caret location.
Text can be drawn using either the Graphics class or the GlyphArrangement class. The Graphics class acts as a higher level way of drawing text and calls the lower level GlyphArrangement draw function to do the actual text drawing.
The only components that use GlyphArrangement to draw text directly are:
- TextEditor
- FileChooserDialogBox
- PluginListComponent
All other components use the Graphics class to draw text.
Displaying Characters
After a GlyphArrangement object is created, you need to provide the object with the font you want to use and the text you want to display.
When doing this, the object examines your text character by character using the font you specified to determine what single glyph is associated with that character as well as the horizontal spacing information associated with that character.
If the character has any kerning information, this is taken into consideration in the horizontal spacing information. This information is determined either using Platform Specific Text APIs or the internal API in the CustomTypeFace class.
The single glyph and horizontal spacing information for a glyph is stored in a PositionedGlyph object and is added to an array that stores the PositionedGlyphs for all the characters in your text.
When you want to display your text (after you have added it) you call the draw member function on your GlyphArrangement object. The text is drawn Glyph by Glyph by calling the draw member function of each PositionedGlyph object from the PositionedGlyph Array of your text.
The draw member function of PositionedGlyph renders a single Glyph using a platform specific Text API or the internal text renderer.
Text Rendering
JUCE can render text on all platforms using its internal text renderer. JUCE can only render platform specific text using the following platforms:
- Mac OS X (via CoreGraphics)
- iOS (via CoreGraphics)
- Android (via Android Canvas)
The fact that Windows is not in the above list is not a mistake. JUCE does not use GDI to render text on Windows, it uses it’s own internal text renderer. This is why text in JUCE does not look exactly the same as text in native windows apps and it is also why JUCE does not have aliased or cleartype support.
When using the internal text renderer, each glyph is rendered by JUCE from a Path. This path is generated using one of two ways:
- Font Outlines (from truetype/opentype font file)
- EdgeTables (from an image rasterization)
Due to platform restrictions, JUCE can only generate Font Outlines on Windows, Mac OS X and Linux. JUCE can generate EdgeTables on all platforms. Font Outlines are preferred over EdgeTables.
Glyphs generated by the internal text renderer are stored in a Glyph Cache to increase application speed.