4. Displaying Characters

There are two ways to display characters: by using glyph information obtained from the font resources, or by using the character rendering classes provided by the Font library.

4.1. Displaying Characters Based on Glyph Information

The GetGlyph function of the Font class returns glyph information in a Glyph structure. This structure contains the information required to display glyphs as characters and is defined as follows.

Code 4-1. Glyph Structure
struct Glyph
{
    const void* pTexture;
    struct CharWidths
    {
        s8  left;
        u8  glyphWidth;
        s8  charWidth;
    } widths;
    u8      height;
    u16     texWidth;
    u16     texHeight;
    u16     cellX;
    u16     cellY;
    u8      isSheetUpdated;
    TexFmt  texFormat;
    const TextureObject* pTextureObject;
};

The values stored in the various members are as follows. The values of the widths and heights are stored in pixel units.

Table 4-1. Members of the Glyph Structure
Member Description
pTexture Pointer to the sheet (the texture image).
widths.left Left space width.
widths.glyphWidth Glyph width.
widths.charWidth

Character width.

The right space width can be found by this formula: [character width – glyph width – left space width].

height Cell (glyph image) height.
texWidth Sheet width.
texHeight Sheet height.
cellX X-coordinate of the upper-left corner of the cell, taking the upper-left corner of the sheet as the origin.
cellY Y-coordinate of the upper-left corner of the cell, taking the upper-left corner of the sheet as the origin.
isSheetUpdated Sheet update flag. Referenced by the Font library.
texFormat Sheet (texture) format.
pTextureObject Texture object information and other information. Referenced by the Font library.

The sheet format definitions correspond as follows to the argument values specified to the glTexImage2D function.

Table 4-2. Sheet Format Definitions and Argument Values Specified to the glTexImage2D Function
Format format type
FONT_SHEET_FORMAT_A4 GL_ALPHA_NATIVE_DMP GL_UNSIGNED_4BITS_DMP
FONT_SHEET_FORMAT_A8 GL_ALPHA_NATIVE_DMP GL_UNSIGNED_BYTE
FONT_SHEET_FORMAT_LA4 GL_LUMINANCE_ALPHA_NATIVE_DMP GL_UNSIGNED_BYTE_4_4_DMP
FONT_SHEET_FORMAT_LA8 GL_LUMINANCE_ALPHA_NATIVE_DMP GL_UNSIGNED_BYTE
FONT_SHEET_FORMAT_RGBA4 GL_RGBA_NATIVE_DMP GL_UNSIGNED_SHORT_4_4_4_4
FONT_SHEET_FORMAT_RGB5A1 GL_RGBA_NATIVE_DMP GL_UNSIGNED_SHORT_5_5_5_1
FONT_SHEET_FORMAT_RGBA8 GL_RGBA_NATIVE_DMP GL_UNSIGNED_BYTE
FONT_SHEET_FORMAT_RGB565 GL_RGB_NATIVE_DMP GL_UNSIGNED_SHORT_5_6_5
FONT_SHEET_FORMAT_RGB8 GL_RGB_NATIVE_DMP GL_UNSIGNED_BYTE

The following structure members are required in order to identify the location in the sheet of the glyph image to display.

Figure 4-1. Glyph Structure Members Required to Identify the Location of a Glyph Image

pTexture cellX texWidth texHeight cellY height widths.glyphWidth

You must note that while the 3DS texture coordinates have their origin at the lower left, the origin of the cell (glyph image) coordinates is at the upper left. Because of this, the calculation of texture coordinates is implemented as in the following sample code.

Code 4-2. Calculation of Texture Coordinates
Glyph glyph;
myFont.GetGlyph(&glyph, character);

const f32 texLeft   = 1.0f * glyph.cellX / glyph.texWidth;
const f32 texRight  = 1.0f * (glyph.cellX + glyph.widths.glyphWidth)
                      / glyph.texWidth;
// Be careful about the differences between glyph image coordinates and texture coordinate origins. 
const f32 texTop    = 1.0f * (glyph.texHeight - glyph.cellY) / glyph.texHeight;
const f32 texBottom = 1.0f * (glyph.texHeight - (glyph.cellY + glyph.height))
                      / glyph.texHeight;

4.2. Using the Font Library Classes

The Font library provides classes for rendering characters and strings. In addition to simply rendering single characters, it also has the following features:

  • Changing the text color
  • Vertical or horizontal color gradation on the per-character level
  • Scaling characters
  • Forced fixed-width (monospaced) font display
  • Character spacing, line spacing, and tab spacing
  • Left-justification or right-justification
  • Automatic line wrapping (newlines) in text
  • Rendering using format strings (printf equivalent)
  • Processing of tagged strings (customizable)

Several classes are used to render characters with the Font library, and they cooperate as illustrated below. In this process flow, the classes denoted by orange rectangles in the figure below are classes that configure settings for rendering text, and they are instantiated by the application. Also, blue denotes base classes, while green denotes implicitly-used classes.

Figure 4-2. Font Library Class Structure (for Text Rendering)

(Wide)TextWriter (Wide)TagProcessor TextWriterBase CharWriter TagProcessorBase CharStrmReader DispStringBuffer RectDrawer Class derived from Font Getting font information Processing tagged text Loading text Accumulation of string display information Render on basis of string display information

 

If you use Font library classes to render text, we recommend using the RectDrawer class, which directly generates 3D commands (PICA register settings).

Table 4-3. Processing Performed by Classes Used in Rendering
Class Processing Performed
CharWriter Renders individual characters. If you do not use TextWriter, inherit this class and form the characters into strings, along with the other processing involved with rendering strings.
TextWriter Renders strings. This class provides the basic features for generating strings.
TagProcessor Processes tag characters (control characters in the range 0x0000 to 0x001F). If you want the tag processor to support characters other than the newline character (0x000A) and the tab character (0x0009), define a custom class that inherits TagProcessor.
RectDrawer Generates 3D commands from the string display information accumulated in a buffer by the TextWriter (or CharWriter) class. Generates 3D commands compatible with dedicated shader programs.

4.2.1. Steps for Implementing in an Application

This section describes the procedures for using the Font library classes to display strings on the screen, using as an example the source code for the ResFont demo included in the sample demos.

4.2.1.1. Loading and Constructing Font Resources

First, load and construct the font resources used to render text. In the sample demo, a pointer to an instance of the ResFont class and the font resource filename (that has an extension of bcfnt) are passed to the InitFont function.

Code 4-3. Loading and Constructing Font Resources
//---------------------------------------------------------------------------
//! @brief      Constructs ResFont. 
//!
//! @param[out] pFont:    Pointer to the font to construct. 
//! @param[in]  filePath: Filename of the font resource to load. 
//!
//! @return     Returns whether ResFont was successfully constructed. 
//---------------------------------------------------------------------------
bool
InitFont(
    nn::font::ResFont*  pFont,
    const char*         filePath)
{
    // Load font resources.
    nn::fs::FileReader fontReader(filePath);

    s32 fileSize = (s32)fontReader.GetSize();
    if ( fileSize <= 0 )
    {
        return false;
    }

    void* buffer = s_AppHeap.Allocate(fileSize, nn::font::GlyphDataAlignment);
    if (buffer == NULL)
    {
        return false;
    }

    s32 readSize = fontReader.Read(buffer, fileSize);
    if (readSize != fileSize)
    {
        s_AppHeap.Free(buffer);
        return false;
    }

    // Set font resources. 
    bool bSuccess = pFont->SetResource(buffer);
    NN_ASSERT(bSuccess);

    //---Fails when resources are already set or already loaded, 
    //    or when the resources are invalid. 
    if (! bSuccess)
    {
        s_AppHeap.Free(buffer);
    }

    // Set the render buffer. 
    const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer);
    void* drawBuffer = s_AppHeap.Allocate(drawBufferSize, 4);
    NN_NULL_ASSERT(drawBuffer);
    pFont->SetDrawBuffer(drawBuffer);

    return bSuccess;
}

In the Font library, textures are loaded with settings such that the GPU directly accesses the sheets that contain the drawn glyph images of the loaded font resources. Accordingly, font resources must be loaded into a buffer in device memory that has 128-byte alignment. Note that the only restriction on the render buffer is the requirement of 4-byte alignment, so this buffer does not need to be allocated in device memory.

For more information about the restrictions that apply when using font resources other than the ResFont class, see 3.3. The ArchiveFont Class and 3.4. The PackedFont Class.

4.2.1.2. Initializing Shaders

Load the shader binary that will be used for text display, and allocate a buffer for the RectDrawer class. In the sample demo, a pointer to an instance of the RectDrawer class is passed to the InitShaders function.

Code 4-4. Initializing the Shaders
//---------------------------------------------------------------------------
//!  @brief      Initializes the shaders. 
//!
//! @param[in,out]  pDrawer    Pointer to the instance to initialize. 
//---------------------------------------------------------------------------
void*
InitShaders(nn::font::RectDrawer* pDrawer)
{
    nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath);

    const u32 fileSize = (u32)shaderReader.GetSize();

    void* shaderBinary = s_AppHeap.Allocate(fileSize);
    NN_NULL_ASSERT(shaderBinary);

#ifndef NN_BUILD_RELEASE
    s32 read =
#endif // NN_BUILD_RELEASE
    shaderReader.Read(shaderBinary, fileSize);
    NN_ASSERT(read == fileSize);

    const u32 vtxBufCmdBufSize =
        nn::font::RectDrawer::GetVertexBufferCommandBufferSize(
            shaderBinary, fileSize);
    void *const vtxBufCmdBuf = s_AppHeap.Allocate(vtxBufCmdBufSize);
    NN_NULL_ASSERT(vtxBufCmdBuf);
    pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize);

    s_AppHeap.Free(shaderBinary);

    return vtxBufCmdBuf;
}

In the RectDrawer class, two buffers are used: the vertex buffer and the command buffer. The vertex buffer contains vertex coordinates for use in rendering. The command buffer stores render commands, but also contains shader binary loading commands (programs, swizzle patterns, constant registers) and other such commands. These buffers are accessed directly by the GPU, so they must be allocated in device memory. There is no required buffer alignment, but we recommend 4-byte or 16-byte alignment.

In the sample demo, the two buffers are allocated in a single region, but functions for getting the required size of each buffer and an initialization function for allocating the buffers separately are also provided. After initialization is successful, you can release the buffer that contains the shader binary.

The SDK contains nnfont_RectDrawerShader.shbin as the shader binary used in the RectDrawer class. This shader assumes that an orthogonal projection matrix has been set in which the sizes of the projected screen in screen space and the LCD screen are identical, with the origin of the projection matrix at the upper left of the screen in screen space (although the directions of the y-axis and z-axis are the reverse of the 3DS axes), and also assumes that the modelview matrix is set to a unit matrix. The adjustment of the character display position and size is managed by accumulating transformation matrices in the floating-point constant registers.

4.2.1.3. Allocating a Display String Buffer

Allocate a buffer that accumulates string display information (the display string buffer). The required size of the display string buffer is calculated based on the maximum number of characters to display. When string rendering is complete, the same buffer can be used to accumulate string display information. If the font and characters to display do not change, the stored string display information can be reused unchanged. If the string has previously been rendered in a single color, you can change just the font color and do not need to accumulate the string display information again.

Code 4-5. Allocating a Display String Buffer
//---------------------------------------------------------------------------
//!  @brief      Allocates a display string buffer. 
//!
//!  @param[in]  charMax: Maximum number of characters in the string to display. 
//!
//!  @return     Returns a pointer to the allocated display string buffer. 
//---------------------------------------------------------------------------
nn::font::DispStringBuffer*
AllocDispStringBuffer(int charMax)
{
    const u32 DrawBufferSize =
        nn::font::CharWriter::GetDispStringBufferSize(charMax);
    void *const bufMem = s_AppHeap.Allocate(DrawBufferSize);
    NN_NULL_ASSERT(bufMem);

    return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax);
}

There is no need to allocate the display string buffer in device memory. There is no required buffer alignment, but we recommend 4-byte alignment.

4.2.1.4. Rendering Settings

The Font library configures the minimum level of settings required for rendering characters, so the application must appropriately set the following render pipeline stages before rendering.

  • Culling
  • Scissor test
  • Polygon offset
  • Early depth test
  • Depth test
  • Stencil test
  • Masking
  • Framebuffer object

If the application makes culling or depth test settings to display 3D models or the like, the settings in effect immediately before the text is rendered are applied to the text. However, you can change these settings before rendering.
In the following sample demo, the InitDraw function generates commands that configure the rendering settings.

Code 4-6. Rendering Settings
//---------------------------------------------------------------------------
//!  @brief      Performs the initial settings for rendering. 
//!
//! @param[in]  width             Screen width. 
//! @param[in]  height            Screen height. 
//---------------------------------------------------------------------------
void
InitDraw(
    int width,
    int height
)
{
    // Color buffer information.
    // Align with the orientation of the LCD, and swap the width with the height.  
    const nn::font::ColorBufferInfo colBufInfo =
    { width, height, PICA_DATA_DEPTH24_STENCIL8_EXT };

    const u32 screenSettingCommands[] =
    {
        // Viewport settings.
        NN_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ),

        // Disable scissoring.
        NN_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ),

        // Disable the w buffer.
        // Depth range settings.
        // Disable polygon offset.
        NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
            0.0f,   // wScale : 0.0 disables the W buffer.  
            0.0f,   // Depth range near.
            1.0f,   // Depth range far.
            0,      // Polygon offset units : 0.0 disables the polygon offset.
            colBufInfo),
    };
    nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true);

    static const u32 s_InitCommands[] =
    {
        // Disable culling.
        NN_FONT_CMD_SET_CULL_FACE( NN_FONT_CMD_CULL_FACE_DISABLE ),

        // Disable stencil test.
        NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(),

        // Disable depth test.
        // Enable writing of all color buffer components.
        NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
            false,  // isDepthTestEnabled
            0,      // depthFunc
            true,   // depthMask
            true,   // red
            true,   // green
            true,   // blue
            true),  // alpha

        // Disable early depth test.
        NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ),

        // Control access to the framebuffer.
        NN_FONT_CMD_SET_FBACCESS(
            true,   // colorRead
            true,   // colorWrite
            false,  // depthRead
            false,  // depthWrite
            false,  // stencilRead
            false), // stencilWrite
    };
    nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true);
}

4.2.1.5. Processing Each Time Text Is Rendered

The processing performed until now is just initialization. This section describes the processing performed each time text is rendered.

The (Wide)TextWriter classes perform the rendering of strings that have a specified display position and font color. An instance of this class is assumed to be generated each frame, so this class has no explicit initialization function. Classes that process tag characters are also configured by default, so as long as there is no need to process custom tag characters, you can use the generated instance with no changes required. In addition, if you set no buffer to receive the fully uncompressed and formatted string, and then call a formatted Printf function, 256 characters of memory is allocated from the stack. If you do not want to use the stack, or if a buffer with a capacity of more than 256 characters is needed, the application must allocate a buffer and set it using the SetBuffer function. The return value is a pointer to the previously set buffer.

The rendered strings are accumulated one character at a time as string display information. Use the SetDispStringBuffer function to set the buffer for accumulating string information. (This buffer was allocated in 4.2.1.3 Allocating a Display String Buffer) for the TextWriter class. Use the SetFont function to set the font resources used in rendering.

The SetCursor or MoveCursor functions are used to set the display position (that is, the cursor position). SetCursor sets a new display position with no reference to a previous position. MoveCursor specifies the display position relative to the previous position. The x, y, and z coordinates can be set individually, or they can all be set at the same time. The default is (0.0, 0.0, 0.0).

The SetDrawFlag function sets how the string is laid out in relation to the display position. This string layout is set by the bitwise OR of three flags: two flags (one each per vertical and horizontal axes) that specify where to place the origin of the rectangular region in which to render the string, and one flag (horizontal axis only) that specifies which direction to align or justify the string toward. The flags are defined by nn::font::PositionFlag enumerators. The default string layout setting is HORIZONTAL_ALIGN_LEFT | HORIZONTAL_ORIGIN_LEFT | VERTICAL_ORIGIN_TOP. Figure 4-3. illustrates how string layout changes as individual flags are changed from the default settings.

Figure 4-3. Changes in String Layout With Different Flags

ABC ghij Cursor position when drawing starts Cursor position when drawing ends Character alignment standard Baseline HORIZONTAL_ALIGN_LEFT HORIZONTAL_ALIGN_CENTER HORIZONTAL_ALIGN_RIGHT HORIZONTAL_ORIGIN_LEFT HORIZONTAL_ORIGIN_CENTER HORIZONTAL_ORIGIN_RIGHT VERTICAL_ORIGIN_TOP VERTICAL_ORIGIN_BASELINE VERTICAL_ORIGIN_MIDDLE VERTICAL_ORIGIN_BOTTOM

Characters are scaled up or scaled down with the SetScale or SetFontSize functions. SetScale sets the width and height of characters as a multiple of the font’s width and height values. SetFontSize sets pixel values for the width and height of the characters to display. Scaling also affects the ascent and descent. For this reason, the GetFontAscent and GetFontDescent functions might return different values than those of the font. The default scaling is 100% (no change).

The SetTextColor function sets the character color. In addition, the SetGradationMode function can apply color gradation effects in the horizontal or vertical directions. The SetColorMapping function can set a linear transform for the gradation effect, and the gradation’s change in color can also be reversed depending on its settings. Note that the SetAlpha function can set an additional alpha value separate from the character color. The default settings are: a character color of (255,255,255,255), no gradation effect, no linear transform, and an additional alpha value of 255.

The SetLineHeight function sets the height of one line. This setting automatically adjusts the line spacing, not the linefeed width. Use the SetLineSpace function to directly set the line spacing. Additionally, the SetTabWidth and SetCharSpace functions set the tab width and character spacing, respectively. The default settings are: 0 for the line spacing and character spacing, and a tab width of 4 characters wide.

To forcibly render strings at a fixed width and ignore the font’s settings, use the SetFixedWidth function to set the rendering width, and use EnableFixedWidth(true) to enable monospaced rendering. Specify false in the EnableFixedWidth function to again disable monospaced rendering. The default setting is false (disabled).

The settings discussed until now are related to the display of text, and are set for the TextWriter class. Graphics-related settings for rendering text are set for the RectDrawer class.

The DrawBegin function performs the initialization required to begin rendering. This function generates rendering commands that initialize the render mode, textures, and other items. This function also initializes internal variables, so if you plan to set the parallax with the SetParallax function, you must do so after this function is called.

Set the projection matrix and view matrix with the SetProjectionMtx function and SetViewMtxForText function, respectively. The Font library assumes that the projection matrix has its origin at the upper left, with the dimensions of the screen in screen space identical to those of the LCD screen, and the positive directions of the y-axis and z-axis are reversed from their sign conventions in the CTR coordinate system. The view matrix is assumed to be a unit matrix.

Strings are rendered by the TextWriter class. When characters are rendered, they are temporarily accumulated in the display string buffer as string display information, and the RectDrawer class generates rendering commands from the accumulated information.

Use the TextWriter::StartPrint function to declare the start of string rendering. When this is done, the display string buffer is cleared.

Render strings using either the TextWriter::Print or TextWriter::Printf function. The former does not specify a format string, while the latter does specify a format string.

When string rendering is complete, use the TextWriter::EndPrint function to declare the end of string rendering. Thereafter, the RectDrawer::BuildTextCommand function generates rendering commands based on the accumulated information and the TextWriter::UseCommandBuffer function sends the rendering commands to the command buffer.

Finally, call the RectDrawer::DrawEnd function to kick off the rendering commands and actually render the characters in the render buffer.

If there is no change to the content or display position of the string to render, you can get the same rendering results without any need to execute again the sequence of functions from the TextWriter::StartPrint function to the TextWriter::EndPrint and RectDrawer::BuildTextCommand functions. You can also render a string again and change only the character color, as long as the string was previously rendered in a solid color. However, this is possible only if the accumulated string display information has been saved.

The following code is the relevant portion of the sample demo.

Code 4-7. Matrix Settings and Drawing Strings
//---------------------------------------------------------------------------
//! @brief      Sets the modelview matrix and projection matrix for the display string. 
//!
//! @param[in]  pDrawer         Pointer to the RectDrawer object. 
//! @param[in]  width             Screen width. 
//! @param[in]  height            Screen height. 
//---------------------------------------------------------------------------
void
SetupTextCamera(
    nn::font::RectDrawer*   pDrawer,
    int                     width,
    int                     height
)
{
    // Set the projection matrix to orthogonal projection.
    {
        // Set as the top-left origin, with the y-axis and z-axis in the reverse orientation. 
        nn::math::MTX44 proj;
        f32 znear   = 0.0f;
        f32 zfar    = -1.0f;
        f32 t       = 0;
        f32 b       = static_cast<f32>(width);
        f32 l       = 0;
        f32 r       = static_cast<f32>(height);
        nn::math::MTX44OrthoPivot(
            &proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP);
        pDrawer->SetProjectionMtx(proj);
    }

    // Set the modelview matrix to an identity matrix.
    {
        nn::math::MTX34 mv;
        nn::math::MTX34Identity(&mv);
        pDrawer->SetViewMtxForText(mv);
    }
}

//---------------------------------------------------------------------------
//! @brief Draw ASCII characters.  
//!
//! @param[in]  pDrawer         Pointer to the RectDrawer  object. 
//! @param[in]  pDrawStringBuf  Pointer to the DispStringBuffer object. 
//! @param[in]  pFont             Pointer to the font. 
//! @param[in]  width             Screen width. 
//! @param[in]  height            Screen height. 
//---------------------------------------------------------------------------
void
DrawAscii(
    nn::font::RectDrawer*       pDrawer,
    nn::font::DispStringBuffer* pDrawStringBuf,
    nn::font::ResFont*          pFont,
    int                         width,
    int                         height
)
{
    nn::font::TextWriter writer;
    writer.SetDispStringBuffer(pDrawStringBuf);
    writer.SetFont(pFont);
    writer.SetCursor(0, 0);

    // The strings are not changed, so the command for drawing strings is only created once.  
    if (! s_InitAsciiString)
    {
        writer.StartPrint();
            (void)writer.Print("DEMO:  ResFont\n");
            (void)writer.Print("\n");
            // Display ASCII character samples 
            (void)writer.Print("All ASCII Character listing:\n");
            (void)writer.Print("\n");
            (void)writer.Print(" !\"#$%&'()*+,-./\n");
            (void)writer.Print("0123456789:;<=>?\n");
            (void)writer.Print("@ABCDEFGHIJKLMNO\n");
            (void)writer.Print("PQRSTUVWXYZ[\\\]^_\n");
            (void)writer.Print("`abcdefghijklmno\n");
            (void)writer.Print("pqrstuvwxyz{|}~\n");
        writer.EndPrint();
        pDrawer->BuildTextCommand(&writer);

        s_InitAsciiString = true;
    }

    // Character color can be changed without regenerating the string rendering commands. 
    writer.SetTextColor(nn::util::Color8(s_Color, 255, s_Color, 255));
    s_Color++;

    pDrawer->DrawBegin();
        SetupTextCamera(pDrawer, width, height);
        writer.UseCommandBuffer();
    pDrawer->DrawEnd();
}

4.2.1.6. Changing the GPU Settings With the Font Library

When fonts are rendered using the RectDrawer class, various GPU settings are changed including the texture sampler type and the vertex attribute load addresses. For this reason, after rendering fonts, have the application validate all of the GPU states and reset all of the GPU settings, although in some cases this processing might be redundant.

This section describes the GPU settings configured when fonts are rendered, as reference material for reducing the cost of resetting the GPU.

Combiner Settings

Combiners 3 through 5 are used and set as follows. Some settings are different depending on whether the sheet’s texture format has an alpha component. Note also that the character color is expressed using the vertex color settings.

Table 4-4. Combiner 3 Settings
Setting Color Alpha
Source 0 GL_TEXTURE0 GL_TEXTURE0
Source 1 GL_CONSTANT GL_CONSTANT
Source 2 GL_CONSTANT GL_CONSTANT
Operand 0

(No alpha) GL_SRC_COLOR

(With alpha) GL_ONE_MINUS_SRC_COLOR

GL_SRC_ALPHA
Operand 1 GL_SRC_COLOR GL_SRC_ALPHA
Operand 2 GL_SRC_COLOR GL_SRC_ALPHA
Combine GL_MODULATE GL_MODULATE
Scale 1.0 1.0
Constant color White (1.0, 1.0, 1.0, 1.0)
Table 4-5. Combiner 4 Settings
Setting Color Alpha
Source 0 GL_TEXTURE0 GL_TEXTURE0
Source 1 GL_CONSTANT GL_CONSTANT
Source 2 GL_PREVIOUS GL_PREVIOUS
Operand 0

(No alpha) GL_ONE_MINUS_SRC_COLOR

(With alpha) GL_SRC_COLOR

GL_ONE_MINUS_SRC_ALPHA
Operand 1 GL_SRC_COLOR GL_SRC_ALPHA
Operand 2 GL_SRC_COLOR GL_SRC_ALPHA
Combine GL_MULT_ADD_DMP GL_MULT_ADD_DMP
Scale 1.0 1.0
Constant color Black (0.0, 0.0, 0.0, 0.0)
Table 4-6. Combiner 5 Settings
Setting Color Alpha
Source 0 GL_PRIMARY_COLOR GL_PRIMARY_COLOR
Source 1 GL_PREVIOUS GL_PREVIOUS
Source 2 GL_PREVIOUS GL_PREVIOUS
Operand 0 GL_SRC_COLOR GL_SRC_ALPHA
Operand 1 GL_SRC_COLOR GL_SRC_ALPHA
Operand 2 GL_SRC_COLOR GL_SRC_ALPHA
Combine GL_MODULATE GL_MODULATE
Scale 1.0 1.0
Constant color Not yet set. Undefined.
Reserved Fragment Shader Settings

The settings of the following reserved fragment shader features are changed.

Table 4-7. Reserved Fragment Shader Settings
Feature Setting
Per-fragment operations mode Standard mode (GL_FRAGOP_MODE_GL_DMP)
Fragment lighting Disabled
Shadows (shadow textures) Disabled
Fog ( and gas) Disabled
Alpha test Disabled
Blending Enabled
Texture Settings

Only texture 0 is used, and it is set to GL_TEXTURE_2D. The texture image address and resolution, and filter settings and other settings are changed.

Shader Settings

Data required for rendering is set in the integer register i0 and the floating-point constant registers c0 through c95.

The shader program outputs the vertex coordinates, vertex color, texture coordinate 0, texture coordinate 1, and texture coordinate 2, but geometry shaders cannot be used.

4.2.2. Customizing the Processing of Tag Characters

By customizing classes that inherit the nn::font::TagProcessorBase class, it is possible to implement custom processing of tag characters (0x0000 to 0x001F).

When a tag character appears as a character to render in the middle of rendering a string, the TextWriter class passes the character to the TagProcessor class set in the TextWriter for processing. By default, the TextWriter class is configured to have a TagProcessor class that processes the tab character (0x0009) and the newline character (0x000A), but you can use the SetTagProcessor function to set a customized TagProcessor class.

When you use customized tag character processing, override the Process and CalcRect functions.

Code 4-8. Functions to Override When Using Customized Tag Character Processing
virtual Operation Process( u16                      code,
                           PrintContext<CharType>*  pContext);
virtual Operation CalcRect(util::Rect*              pRect,
                           u16                      code,
                           PrintContext<CharType>*  pContext);

The TextWriter class adjusts the coordinates at which to render characters based on the values returned from these functions. Implement your application so that the Process and CalcRect functions both return the same value when they process the same tag character.

Table 4-8. Definitions of Return Values of Tag Character Processing
Definition Processing Performed by TextWriter
OPERATION_DEFAULT Inserts no space before the next character if it is the first character in a line, but otherwise always inserts space before the next character.
OPERATION_NO_CHAR_SPACE Never inserts a space before the next character.
OPERATION_CHAR_SPACE Always inserts a space before the next character.
OPERATION_NEXT_LINE Performs newline processing. Only adjusts the x-coordinate; the y-coordinate must be adjusted when processing tags.
OPERATION_END_DRAW Ends string rendering in the middle of a string.

A pointer to the TextWriter class is included in the members of the pContext argument, so it is possible to use tag characters for special processing, such as changing the character color.


CONFIDENTIAL