rich text: Optionally return cursor position from dry run & allow

indenting text
This commit is contained in:
jonko0493 2025-06-06 16:08:02 +09:00
parent b67c60d5f0
commit 60d1824e56
6 changed files with 283 additions and 83 deletions

View File

@ -20,9 +20,9 @@ void Draw3DScene1(void *arg)
NE_2DViewInit();
NE_RichTextRender3D(3, "VAWATa\ntajl", 0, 0);
NE_RichTextRender3D(1, "VAWATa\ntajl", 0, 0);
NE_RichTextRender3DAlpha(2, "Text with alpha", 10, 80,
NE_RichTextRender3DAlpha(0, "Text with alpha", 10, 80,
POLY_ALPHA(20) | POLY_CULL_BACK, 30);
}
@ -70,28 +70,28 @@ int main(int argc, char *argv[])
// Load a 16-color font to be used for rendering text as quads
NE_RichTextInit(2);
NE_RichTextMetadataLoadFAT(2, "fonts/font.fnt");
NE_RichTextMaterialLoadGRF(2, "fonts/font_16_png.grf");
NE_RichTextInit(0);
NE_RichTextMetadataLoadFAT(0, "fonts/font.fnt");
NE_RichTextMaterialLoadGRF(0, "fonts/font_16_png.grf");
// Load a 256-color font to be used for rendering text as quads
NE_RichTextInit(3);
NE_RichTextMetadataLoadFAT(3, "fonts/font.fnt");
NE_RichTextMaterialLoadGRF(3, "fonts/font_256_png.grf");
NE_RichTextInit(1);
NE_RichTextMetadataLoadFAT(1, "fonts/font.fnt");
NE_RichTextMaterialLoadGRF(1, "fonts/font_256_png.grf");
// Load a 16-color font to be used for rendering text to textures.
NE_RichTextInit(5);
NE_RichTextMetadataLoadFAT(5, "fonts/font.fnt");
NE_RichTextBitmapLoadGRF(5, "fonts/font_16_png.grf");
NE_RichTextInit(2);
NE_RichTextMetadataLoadFAT(2, "fonts/font.fnt");
NE_RichTextBitmapLoadGRF(2, "fonts/font_16_png.grf");
// Render text to a texture using the last font we've loaded
// We don't care about managing the palette. Passing NULL will tell Nitro
// Engine to delete the palete automatically when the material is deleted.
NE_Material *Material = NULL;
NE_RichTextRenderMaterial(5,
NE_RichTextRenderMaterial(2,
"Sample: AWAV.\nÿ_ßðñÑü(o´Áá)|\nInvalid char: ŋ",
&Material, NULL);
@ -114,9 +114,7 @@ int main(int argc, char *argv[])
NE_SpriteDelete(Scene.TextSprite);
NE_MaterialDelete(Material);
NE_RichTextEnd(2);
NE_RichTextEnd(3);
NE_RichTextEnd(5);
NE_RichTextResetSystem();
return 0;
}

View File

@ -23,9 +23,9 @@ void Draw3DScene(void *arg)
NE_2DViewInit();
NE_RichTextRender3D(3, "VAWATa\ntajl", 0, 0);
NE_RichTextRender3D(1, "VAWATa\ntajl", 0, 0);
NE_RichTextRender3DAlpha(2, "Text with alpha", 10, 80,
NE_RichTextRender3DAlpha(0, "Text with alpha", 10, 80,
POLY_ALPHA(20) | POLY_CULL_BACK, 30);
}
@ -55,8 +55,8 @@ int main(int argc, char *argv[])
// Load a 16-color font to be used for rendering text as quads
NE_RichTextInit(2);
NE_RichTextMetadataLoadMemory(2, font_fnt_bin, font_fnt_bin_size);
NE_RichTextInit(0);
NE_RichTextMetadataLoadMemory(0, font_fnt_bin, font_fnt_bin_size);
{
NE_Material *Font16 = NE_MaterialCreate();
@ -71,13 +71,13 @@ int main(int argc, char *argv[])
// The material and palette will be deleted when the rich text font is
// deleted.
NE_RichTextMaterialSet(2, Font16, Pal16);
NE_RichTextMaterialSet(0, Font16, Pal16);
}
// Load a 256-color font to be used for rendering text as quads
NE_RichTextInit(3);
NE_RichTextMetadataLoadMemory(3, font_fnt_bin, font_fnt_bin_size);
NE_RichTextInit(1);
NE_RichTextMetadataLoadMemory(1, font_fnt_bin, font_fnt_bin_size);
{
NE_Material *Font256 = NE_MaterialCreate();
@ -92,14 +92,14 @@ int main(int argc, char *argv[])
// The material and palette will be deleted when the rich text font is
// deleted.
NE_RichTextMaterialSet(3, Font256, Pal256);
NE_RichTextMaterialSet(1, Font256, Pal256);
}
// Load a 16-color font to be used for rendering text to textures.
NE_RichTextInit(5);
NE_RichTextMetadataLoadMemory(5, font_fnt_bin, font_fnt_bin_size);
NE_RichTextBitmapSet(5, font_16Bitmap, 256, 256, NE_PAL16,
NE_RichTextInit(2);
NE_RichTextMetadataLoadMemory(2, font_fnt_bin, font_fnt_bin_size);
NE_RichTextBitmapSet(2, font_16Bitmap, 256, 256, NE_PAL16,
font_16Pal, font_16PalLen);
// Render text to a texture using the last font we've loaded
@ -107,7 +107,7 @@ int main(int argc, char *argv[])
// We don't care about managing the palette. Passing NULL will tell Nitro
// Engine to delete the palete automatically when the material is deleted.
NE_Material *Material = NULL;
NE_RichTextRenderMaterial(5,
NE_RichTextRenderMaterial(2,
"Sample: AWAV.\nÿ_ßðñÑü(o´Áá)|\nInvalid char: ŋ",
&Material, NULL);
@ -130,9 +130,7 @@ int main(int argc, char *argv[])
NE_SpriteDelete(Scene.TextSprite);
NE_MaterialDelete(Material);
NE_RichTextEnd(2);
NE_RichTextEnd(3);
NE_RichTextEnd(5);
NE_RichTextResetSystem();
return 0;
}

View File

@ -34,7 +34,8 @@
///
/// @{
#define NE_MAX_RICH_TEXT_FONTS 8 ///< Default max number of rich text fonts
#define NE_DEFAULT_RICH_TEXT_FONTS 8 ///< Default max number of rich text fonts
#define NE_MAX_RICH_TEXT_FONTS NE_DEFAULT_RICH_TEXT_FONTS ///< Deprecated and unused, left for compatibility
/// Change the priority of rich text drawn after this function call.
///
@ -44,12 +45,20 @@ void NE_RichTextPrioritySet(int priority);
/// Set to 0 the priority of rich text drawn after this function call.
void NE_RichTextPriorityReset(void);
/// Initializes the rich text system with the specified number of slots.
///
/// This must be called before initializing any rich text slots.
///
/// @param numSlots The number of rich text slots to allocate.
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextStartSystem(u32 numSlots);
/// Clears all rich text font slots.
void NE_RichTextResetSystem(void);
/// Initialize a rich text slot.
///
/// @param slot The slot to initialize (from 0 to NE_MAX_RICH_TEXT_FONTS).
/// @param slot The slot to initialize (from 0 to the number of slots specified in NE_RichTextSystemStart).
void NE_RichTextInit(u32 slot);
/// End a rich text slot and free all the resources used by it.
@ -157,6 +166,19 @@ int NE_RichTextBitmapSet(u32 slot, const void *texture_buffer,
NE_TextureFormat texture_fmt,
const void *palette_buffer, size_t palette_size);
/// Calculates the final size and cursor position of rendering the provided string.
///More actions
/// @param slot The slot to use.
/// @param str The string to render.
/// @param size_x Pointer to store the width of the resulting image.
/// @param size_y Pointer to store the height of the resulting image.
/// @param final_x Pointer to store the final X position of the cursor.
/// @param final_y Pointer to store the final Y position of the cursor.
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRenderDryRunWithPos(u32 slot, const char *str,
size_t *size_x, size_t *size_y,
size_t *final_x, size_t *final_y);
/// Calculates the final size of rendering the provided string.
///
/// @param slot The slot to use.
@ -167,6 +189,19 @@ int NE_RichTextBitmapSet(u32 slot, const void *texture_buffer,
int NE_RichTextRenderDryRun(u32 slot, const char *str,
size_t *size_x, size_t *size_y);
/// Render a string by rendering one 3D quad per codepoint.
///
/// This preserves the polygon format that is currently active.
///
/// @param slot The slot to use.
/// @param str The string to render.
/// @param x The left coordinate of the text.
/// @param y The top coordinate of the text.
/// @param xIndent The horizontal indentation to apply to the first line of text.
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRender3DWithIndent(u32 slot, const char *str, s32 x, s32 y,
s32 xIndent);
/// Render a string by rendering one 3D quad per codepoint.
///
/// This preserves the polygon format that is currently active.
@ -178,6 +213,49 @@ int NE_RichTextRenderDryRun(u32 slot, const char *str,
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y);
/// Render a string by rendering one 3D quad per codepoint.More actions
///
/// This preserves the polygon format that is currently active.
///
/// @param slot The slot to use.
/// @param str The string to render.
/// @param x The left coordinate of the text.
/// @param y The top coordinate of the text.
/// @param xIndent The horizontal indentation to apply to the first line of text.
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRender3DWithIndent(u32 slot, const char *str, s32 x, s32 y,
s32 xIndent);
/// Render a string by rendering one 3D quad per codepoint.
///
/// This preserves the polygon format that is currently active.
@@ -178,6 +204,29 @@
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y);
/// Render a string by rendering one 3D quad per codepoint with alternating
/// polygon IDs.
///
/// This function will alternate between polygon IDs so that alpha blending
/// works between multiple polygons when they overlap. This is a requirement of
/// the NDS 3D hardware.
///
/// It is required to pass the base polygon format as a parameter because the
/// polygon format data is write-only. Whenever the polygon ID needs to be
/// changed, the rest of the polygon format flags need to be set as well.
///
/// @param slot The slot to use.
/// @param str The string to render.
/// @param x The left coordinate of the text.
/// @param y The top coordinate of the text.
/// @param poly_fmt The polygon format values to be used for the quads.
/// @param poly_id_base The base polygon ID to use for the quads.
/// @param xIndent The horizontal indentation to apply to the first line of text.
/// @return Returns 1 on success, 0 on failure.
int NE_RichTextRender3DAlphaWithIndent(u32 slot, const char *str, s32 x, s32 y,
uint32_t poly_fmt, int poly_id_base,
s32 xIndent);
/// Render a string by rendering one 3D quad per codepoint with alternating
/// polygon IDs.
///

View File

@ -29,7 +29,9 @@ typedef struct {
bool active;
} ne_rich_textinfo_t;
static ne_rich_textinfo_t NE_RichTextInfo[NE_MAX_RICH_TEXT_FONTS];
static u32 NE_NumRichTextSlots = 0;
static ne_rich_textinfo_t *NE_RichTextInfo;
static int NE_RICH_TEXT_PRIORITY = 0;
@ -45,8 +47,17 @@ void NE_RichTextPriorityReset(void)
void NE_RichTextInit(u32 slot)
{
if (slot >= NE_MAX_RICH_TEXT_FONTS)
// Compatibility mode -- if someone tries to allocate a slot
// without having called start system, we allocate the old maximum
// number of slots for safety
if (NE_NumRichTextSlots == 0)
NE_RichTextStartSystem(NE_DEFAULT_RICH_TEXT_FONTS);
if (slot >= NE_NumRichTextSlots)
{
NE_DebugPrint("Attempted to initialize a slot greater than the number of slots allocated; skipping");
return;
}
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
if (info->active)
@ -60,7 +71,7 @@ void NE_RichTextInit(u32 slot)
int NE_RichTextEnd(u32 slot)
{
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -97,17 +108,31 @@ int NE_RichTextEnd(u32 slot)
return 1;
}
int NE_RichTextStartSystem(u32 numSlots)
{
NE_NumRichTextSlots = numSlots;
NE_RichTextInfo = calloc(sizeof(ne_rich_textinfo_t), NE_NumRichTextSlots);
if (NE_RichTextInfo == NULL)
{
NE_DebugPrint("Failed to allocate array for NE_RichTextInfo");
return 0;
}
return 1;
}
void NE_RichTextResetSystem(void)
{
for (int i = 0; i < NE_MAX_RICH_TEXT_FONTS; i++)
for (int i = 0; i < NE_NumRichTextSlots; i++)
NE_RichTextEnd(i);
free(NE_RichTextInfo);
NE_NumRichTextSlots = 0;
}
int NE_RichTextMetadataLoadFAT(u32 slot, const char *path)
{
NE_AssertPointer(path, "NULL path pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -131,7 +156,7 @@ int NE_RichTextMetadataLoadMemory(u32 slot, const void *data, size_t data_size)
{
NE_AssertPointer(data, "NULL data pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -155,7 +180,7 @@ int NE_RichTextMaterialLoadGRF(u32 slot, const char *path)
{
NE_AssertPointer(path, "NULL path pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -181,7 +206,7 @@ int NE_RichTextMaterialSet(u32 slot, NE_Material *mat, NE_Palette *pal)
{
NE_AssertPointer(mat, "NULL material pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -204,7 +229,7 @@ int NE_RichTextBitmapLoadGRF(u32 slot, const char *path)
#else // NE_BLOCKSDS
NE_AssertPointer(path, "NULL path pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -307,7 +332,7 @@ int NE_RichTextBitmapSet(u32 slot, const void *texture_buffer,
NE_AssertPointer(texture_buffer, "NULL texture pointer");
NE_AssertPointer(palette_buffer, "NULL palette pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -334,22 +359,55 @@ int NE_RichTextBitmapSet(u32 slot, const void *texture_buffer,
return 1;
}
int NE_RichTextRenderDryRun(u32 slot, const char *str,
size_t *size_x, size_t *size_y)
int NE_RichTextRenderDryRunWithPos(u32 slot, const char *str,
size_t *size_x, size_t *size_y,
size_t *final_x, size_t *final_y)
{
NE_AssertPointer(str, "NULL str pointer");
NE_AssertPointer(size_x, "NULL size X pointer");
NE_AssertPointer(size_y, "NULL size Y pointer");
NE_AssertPointer(size_y, "NULL size Y pointer");Add commentMore actions
NE_AssertPointer(final_x, "NULL final X pointer");
NE_AssertPointer(final_y, "NULL final Y pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
if (!info->active)
return 0;
dsf_error err = DSF_StringRenderDryRun(info->handle, str,
size_x, size_y);
dsf_error err = DSF_StringRenderDryRunWithCursor(info->handle, str,
size_x, size_y,
final_x, final_y);
if (err != DSF_NO_ERROR)
return 0;
return 1;
}
int NE_RichTextRenderDryRun(u32 slot, const char *str,
size_t *size_x, size_t *size_y)
{
size_t final_x, final_y;
return NE_RichTextRenderDryRunWithPos(slot, str, size_x, size_y, &final_x, &final_y);
}
int NE_RichTextRender3DWithIndent(u32 slot, const char *str, s32 x, s32 y,
s32 xIndent)
{
NE_AssertPointer(str, "NULL str pointer");
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
if (!info->active)
return 0;
NE_MaterialUse(info->material);
dsf_error err = DSF_StringRender3DWithIndent(info->handle, str, x, y,
NE_RICH_TEXT_PRIORITY, xIndent);
if (err != DSF_NO_ERROR)
return 0;
@ -357,6 +415,13 @@ int NE_RichTextRenderDryRun(u32 slot, const char *str,
}
int NE_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y)
{
return NE_RichTextRender3DWithIndent(slot, str, x, y, 0);
}
int NE_RichTextRender3DAlphaWithIndent(u32 slot, const char *str, s32 x, s32 y,
uint32_t poly_fmt, int poly_id_base,
s32 xIndent)
{
NE_AssertPointer(str, "NULL str pointer");
@ -369,8 +434,9 @@ int NE_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y)
NE_MaterialUse(info->material);
dsf_error err = DSF_StringRender3D(info->handle, str, x, y,
NE_RICH_TEXT_PRIORITY);
dsf_error err = DSF_StringRender3DAlphaWithIndent(info->handle, str, x, y,
NE_RICH_TEXT_PRIORITY,
poly_fmt, poly_id_base, xIndent);
if (err != DSF_NO_ERROR)
return 0;
@ -380,24 +446,7 @@ int NE_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y)
int NE_RichTextRender3DAlpha(u32 slot, const char *str, s32 x, s32 y,
uint32_t poly_fmt, int poly_id_base)
{
NE_AssertPointer(str, "NULL str pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
if (!info->active)
return 0;
NE_MaterialUse(info->material);
dsf_error err = DSF_StringRender3DAlpha(info->handle, str, x, y,
NE_RICH_TEXT_PRIORITY,
poly_fmt, poly_id_base);
if (err != DSF_NO_ERROR)
return 0;
return 1;
return NE_RichTextRender3DAlphaWithIndent(slot, str, x, y, poly_fmt, poly_id_base, 0);
}
int NE_RichTextRenderMaterial(u32 slot, const char *str, NE_Material **mat,
@ -407,7 +456,7 @@ int NE_RichTextRenderMaterial(u32 slot, const char *str, NE_Material **mat,
NE_AssertPointer(mat, "NULL mat pointer");
NE_AssertPointer(pal, "NULL pal pointer");
if (slot >= NE_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];

View File

@ -537,16 +537,19 @@ static dsf_error DSF_CodepointRender3D(dsf_handle handle, uint32_t codepoint,
return DSF_NO_ERROR;
}
dsf_error DSF_StringRenderDryRun(dsf_handle handle, const char *str,
size_t *size_x, size_t *size_y)
dsf_error DSF_StringRenderDryRunWithCursor(dsf_handle handle, const char *str,
size_t *size_x, size_t *size_y,
size_t *final_x, size_t *final_y)
{
if ((handle == 0) || (str == NULL) || (size_x == NULL) || (size_y == NULL))
if ((handle == 0) || (str == NULL) || (size_x == NULL) || (size_y == NULL) || (final_x == NULL) || (final_y == NULL))
return DSF_INVALID_ARGUMENT;
if (strlen(str) == 0)
{
*size_x = 0;
*size_y = 0;
*final_x = font->pointer_x;
*final_y = font->pointer_y;
return DSF_NO_ERROR;
}
@ -587,8 +590,16 @@ dsf_error DSF_StringRenderDryRun(dsf_handle handle, const char *str,
return ret;
}
dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z)
dsf_error DSF_StringRenderDryRun(dsf_handle handle, const char *str,
size_t *size_x, size_t *size_y)
{
size_t final_x, final_y;
return DSF_StringRenderDryRunWithCursor(handle, str, size_x, size_y, &final_x, &final_y);
}
dsf_error DSF_StringRender3DWithIndent(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
int32_t xStart)
{
if ((handle == 0) || (str == NULL))
return DSF_INVALID_ARGUMENT;
@ -597,7 +608,7 @@ dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
dsf_font_internal_state *font = (dsf_font_internal_state *)handle;
font->pointer_x = x;
font->pointer_x = x + xStart;
font->pointer_y = y;
font->box_left = x;
font->box_top = y;
@ -623,9 +634,16 @@ dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
return ret;
}
dsf_error DSF_StringRender3DAlpha(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
uint32_t poly_fmt, int poly_id_base)
dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z)
{
return DSF_StringRender3DWithIndent(handle, str, x, y, z, 0);
}
dsf_error DSF_StringRender3DAlphaWithIndent(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
uint32_t poly_fmt, int poly_id_base,
int32_t xStart)
{
if ((handle == 0) || (str == NULL))
return DSF_INVALID_ARGUMENT;
@ -634,7 +652,7 @@ dsf_error DSF_StringRender3DAlpha(dsf_handle handle, const char *str,
dsf_font_internal_state *font = (dsf_font_internal_state *)handle;
font->pointer_x = x;
font->pointer_x = x + xStart;
font->pointer_y = y;
font->box_left = x;
font->box_top = y;
@ -663,6 +681,13 @@ dsf_error DSF_StringRender3DAlpha(dsf_handle handle, const char *str,
return ret;
}
dsf_error DSF_StringRender3DAlpha(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
uint32_t poly_fmt, int poly_id_base)
{
return DSF_StringRender3DAlphaWithIndent(handle, str, x, y, z, poly_fmt, poly_id_base, 0);
}
static dsf_error DSF_CodepointRenderBuffer(dsf_handle handle,
uint32_t codepoint, unsigned int texture_fmt,
const void *font_texture, size_t font_width, size_t font_height,

View File

@ -93,16 +93,42 @@ dsf_error DSF_FreeFont(dsf_handle *handle);
/// @defgroup libdsf_render Functions to draw text strings.
/// @{
/// @param handle Handler of the font to use.
/// @param str String to print.
/// @param size_x Pointer to a variable to store the size.
/// @param size_y Pointer to a variable to store the size.
/// @param final_x Pointer to a variable to store the final X cursor position.
/// @param final_y Pointer to a variable to store the final Y cursor position.
///
/// @return An error code or DSF_NO_ERROR on success.
dsf_error DSF_StringRenderDryRunWithCursor(dsf_handle handle, const char *str,
size_t *size_x, size_t *size_y,
size_t *final_x, size_t *final_y);
/// Pretend to render a string to calculate its final size once rendered.
///
/// @param handle Handler of the font to use.
/// @param str String to print.
/// @param size_x Pointer to a variable to store the size.
/// @param size_y Pointer to a variable to store the size.
/// @param handle Handler of the font to use.
/// @param str String to print.
/// @param size_x Pointer to a variable to store the size.
/// @param size_y Pointer to a variable to store the size.
///
/// @return An error code or DSF_NO_ERROR on success.
dsf_error DSF_StringRenderDryRun(dsf_handle handle, const char *str,
size_t *size_x, size_t *size_y);
/// Render a string by rendering one 3D quad per codepoint.
///
/// @param handle Handler of the font to use.
/// @param str String to print.
/// @param x Top x coordinate (0 to 255, but you can go outside of that).
/// @param y Left y coordinate (0 to 191, but you can go outside of that).
/// @param z Z coordinate (depth).
/// @param xStart The horizontal component of the cursor's starting offset (reset to x on line break)
///
/// @return An error code or DSF_NO_ERROR on success.
dsf_error DSF_StringRender3DWithIndent(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
int32_t xStart);
/// Render a string by rendering one 3D quad per codepoint.
///
@ -116,6 +142,32 @@ dsf_error DSF_StringRenderDryRun(dsf_handle handle, const char *str,
dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z);
/// Render a string by rendering one 3D quad per codepoint with alternating
/// polygon IDs.
///
/// This function will alternate between polygon IDs so that alpha blending
/// works between multiple polygons when they overlap. This is a requirement of
/// the NDS 3D hardware.
///
/// It is required to pass the base polygon format as a parameter because the
/// polygon format data is write-only. Whenever the polygon ID needs to be
/// changed, the rest of the polygon format flags need to be set as well.
///
/// @param handle Handler of the font to use.
/// @param str String to print.
/// @param x Top x coordinate (0 to 255, but you can go outside of that).
/// @param y Left y coordinate (0 to 191, but you can go outside of that).
/// @param z Z coordinate (depth).
/// @param poly_fmt Polygon formats to apply to the characters.
/// @param poly_id_base poly_id_base and poly_id_base + 1 will be used.
/// @param xStart The horizontal component of the cursor's starting offset (reset to x on line break)
///
/// @return An error code or DSF_NO_ERROR on success.
dsf_error DSF_StringRender3DAlphaWithIndent(dsf_handle handle, const char *str,
int32_t x, int32_t y, int32_t z,
uint32_t poly_fmt, int poly_id_base,
int32_t xStart);
/// Render a string by rendering one 3D quad per codepoint with alternating
/// polygon IDs.
///