Compare commits

...

4 Commits

Author SHA1 Message Date
jonko0493
8932de1fff rich text: Optionally return cursor position from dry run & allow indenting text
Some checks failed
Documentation / Generate website (push) Has been cancelled
Documentation / Publish website with GitHub pages (push) Has been cancelled
The goal of the changes made in this PR is to create something with this
effect ("Jonko" is in in green, the rest is in white):

    "Dear god." Jonko quickly replied,
    crestfallen.

In order to do this, I need to call `NE_RichTextRender3D` or
`NE_RichTextRender3DAlpha` three times: once to draw the first part of
the sentence with the white font, once to draw "Jonko" in turquoise, and
once to draw the remainder of the sentence in white again. In order to
ensure that text is being drawn in the correct location, I need the
position where the previous call stopped drawing, which leads to the
first change this PR makes: I have added a version of
`DSF_StringRenderDryRun` which accepts pointers to `final_x` and
`final_y` and stores the last position of `font->pointer_x` and
`font->pointer_y` in them and I have added a new variant of
`NE_RichTextRenderDryRun` called `NE_RichTextRenderDryRunWithPos` which
uses that DSF function and has analogous parameters.

These functions get us the position where we need to place the next
cursor, but the next issue is that currently NitroEngine and libDSF only
allow for specifying the position of the overall box to draw text in,
but not where to offset the cursor in that box. This leads to the
following problem ("Jonko" is in in green, the rest is in white):

    "Dear god." Jonko quickly replied,
                        crestfallen.

Thus, the second change: I have introduced new versions of
`DSF_StringRender3D` and `DSF_StringRender3DAlpha` which accept an
`xStart` position that is added to the `pointerX`. Correspondingly, I
have added versions of `NE_RichTextRender3D` and
`NE_RichTextRender3DAlpha` that use these new functions as well.

Let me know if there are any issues with how I've written this (C is not
my forte, after all), but the first screenshot is this being tested in
production code.
2025-06-11 00:03:38 +01:00
Antonio Niño Díaz
86955bc0a0 rich text: Allow the number of fonts to be specified dynamically
Some checks failed
Documentation / Generate website (push) Has been cancelled
Documentation / Publish website with GitHub pages (push) Has been cancelled
This switches the rich text library from using a constant for the max
number of fonts to allowing the user to specify how many fonts should be
used dynamically. To accomplish this, a new method is introduced to the
rich text system: `NE_RichTextStartSystem`, which accepts the number of
slots to allocate. Those slots are allocated and then freed when
`NE_RichTextResetSystem` is called.

To maintain compatibility, I have not removed `NE_MAX_RICH_TEXT_FONTS`
(instead opting to mark it as deprecated), and have added functionality
to automatically call `NE_RichTextStartSystem` with that old value (8)
if the user decides to init a rich text slot before calling
`NE_RichTextStartSystem` (which would likely be the previous default
behavior).
2025-05-25 01:32:55 +02:00
jonko0493
6e1dca996c rich text: Allow the number of fonts to be specified dynamically 2025-05-24 09:37:46 -07:00
Antonio Niño Díaz
02f3cd7012 github: Add workflow to publish the documentation
Some checks failed
Documentation / Generate website (push) Has been cancelled
Documentation / Publish website with GitHub pages (push) Has been cancelled
2025-05-14 00:02:21 +01:00
7 changed files with 365 additions and 86 deletions

79
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileContributor: Antonio Niño Díaz, 2025
name: Documentation
on:
push:
branches:
- 'master'
paths-ignore:
- '**.rst'
- 'examples'
- 'licenses'
- 'Makefile*'
- 'source*'
- 'tests'
- 'tools'
workflow_dispatch:
repository_dispatch:
types: [run_build]
permissions:
contents: read
pages: write
id-token: write
packages: write
jobs:
generate_website:
name: Generate website
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- name: Clone project
uses: actions/checkout@v4
with:
ref: 'master'
fetch-depth: 0
- name: Install dependencies
run: |
sudo apt-get install doxygen
- name: Build documentation
run: |
cd documentation
bash generate.sh
# Create tarball with everything to upload to GitHub pages
cd html
tar -cvf ../../repo.tar ./*
- name: Upload repo artifact
uses: actions/upload-artifact@v4
with:
name: github-pages
path: repo.tar
if-no-files-found: error
publish_repo:
name: Publish website with GitHub pages
if: contains(github.ref,'refs/heads/master')
needs: [generate_website]
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

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,48 @@ 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.
/// @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,33 +359,45 @@ 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(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_RichTextRender3D(u32 slot, const char *str, s32 x, s32 y)
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_MAX_RICH_TEXT_FONTS)
if (slot >= NE_NumRichTextSlots)
return 0;
ne_rich_textinfo_t *info = &NE_RichTextInfo[slot];
@ -369,8 +406,37 @@ 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_StringRender3DWithIndent(info->handle, str, x, y,
NE_RICH_TEXT_PRIORITY, xIndent);
if (err != DSF_NO_ERROR)
return 0;
return 1;
}
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");
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_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,23 +537,27 @@ 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;
dsf_font_internal_state *font = (dsf_font_internal_state *)handle;
if (strlen(str) == 0)
{
*size_x = 0;
*size_y = 0;
*final_x = font->pointer_x;
*final_y = font->pointer_y;
return DSF_NO_ERROR;
}
dsf_error ret = DSF_NO_ERROR;
dsf_font_internal_state *font = (dsf_font_internal_state *)handle;
font->pointer_x = 0;
font->pointer_y = 0;
font->box_left = 0;
@ -587,8 +591,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 +609,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 +635,16 @@ dsf_error DSF_StringRender3D(dsf_handle handle, const char *str,
return ret;
}
dsf_error DSF_StringRender3DAlpha(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)
{
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)
uint32_t poly_fmt, int poly_id_base,
int32_t xStart)
{
if ((handle == 0) || (str == NULL))
return DSF_INVALID_ARGUMENT;
@ -634,7 +653,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 +682,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,6 +93,18 @@ 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.
@ -104,6 +116,20 @@ dsf_error DSF_FreeFont(dsf_handle *handle);
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.
///
/// @param handle Handler of the font to use.
@ -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.
///