From 1125e77e2ab0b4b82c32b7d5938d5e47665f8fc2 Mon Sep 17 00:00:00 2001 From: piepie62 Date: Wed, 30 Jan 2019 12:10:31 -0700 Subject: [PATCH] Allow fonts other than the system font --- libctru/include/3ds/font.h | 52 ++++++++++++++++++++++++++++++-------- libctru/source/font.c | 43 +++++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/libctru/include/3ds/font.h b/libctru/include/3ds/font.h index bf69040..3d3ce62 100644 --- a/libctru/include/3ds/font.h +++ b/libctru/include/3ds/font.h @@ -157,49 +157,79 @@ enum /// Ensures the shared system font is mapped. Result fontEnsureMapped(void); -/// Retrieves the font information structure of the shared system font. -static inline FINF_s* fontGetInfo(void) +/** + * @brief Fixes the pointers internal to a just-loaded font + * @param font Font to fix + * @remark Should never be run on the system font, and only once + * on any other font. + */ +void fontFixPointers(CFNT_s* font); + +/// Gets the currently loaded system font +static inline CFNT_s* fontGetSystemFont(void) { extern CFNT_s* g_sharedFont; - return &g_sharedFont->finf; + return g_sharedFont; } -/// Retrieves the texture sheet information of the shared system font. -static inline TGLP_s* fontGetGlyphInfo(void) +/** + * @brief Retrieves the font information structure of the shared system font. + * @param font Font from which to get information + */ +static inline FINF_s* fontGetInfo(CFNT_s* font) { - return fontGetInfo()->tglp; + if (!font) + font = fontGetSystemFont(); + return &font->finf; +} + +/** + * @brief Retrieves the texture sheet information of the shared system font. + * @param font Font from which to get information + */ +static inline TGLP_s* fontGetGlyphInfo(CFNT_s* font) +{ + if (!font) + font = fontGetSystemFont(); + return fontGetInfo(font)->tglp; } /** * @brief Retrieves the pointer to texture data for the specified texture sheet. + * @param font Font from which to get information. * @param sheetIndex Index of the texture sheet. */ -static inline void* fontGetGlyphSheetTex(int sheetIndex) +static inline void* fontGetGlyphSheetTex(CFNT_s* font, int sheetIndex) { - TGLP_s* tglp = fontGetGlyphInfo(); + if (!font) + font = fontGetSystemFont(); + TGLP_s* tglp = fontGetGlyphInfo(font); return &tglp->sheetData[sheetIndex*tglp->sheetSize]; } /** * @brief Retrieves the glyph index of the specified Unicode codepoint. + * @param font Font from which to get information. * @param codePoint Unicode codepoint. */ -int fontGlyphIndexFromCodePoint(u32 codePoint); +int fontGlyphIndexFromCodePoint(CFNT_s* font, u32 codePoint); /** * @brief Retrieves character width information of the specified glyph. + * @param font Font from which to get information. * @param glyphIndex Index of the glyph. */ -charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex); +charWidthInfo_s* fontGetCharWidthInfo(CFNT_s* font, int glyphIndex); /** * @brief Calculates position information for the specified glyph. * @param out Output structure in which to write the information. + * @param font Font from which to get information. * @param glyphIndex Index of the glyph. * @param flags Calculation flags (see GLYPH_POS_* flags). * @param scaleX Scale factor to apply horizontally. * @param scaleY Scale factor to apply vertically. */ -void fontCalcGlyphPos(fontGlyphPos_s* out, int glyphIndex, u32 flags, float scaleX, float scaleY); +void fontCalcGlyphPos(fontGlyphPos_s* out, CFNT_s* font, int glyphIndex, u32 flags, float scaleX, float scaleY); ///@} diff --git a/libctru/source/font.c b/libctru/source/font.c index 29d9e35..5e5f0fc 100644 --- a/libctru/source/font.c +++ b/libctru/source/font.c @@ -8,7 +8,6 @@ CFNT_s* g_sharedFont; static u32 sharedFontAddr; -static int charPerSheet; Result fontEnsureMapped(void) { @@ -26,17 +25,34 @@ Result fontEnsureMapped(void) return res; g_sharedFont = (CFNT_s*)(sharedFontAddr+0x80); - charPerSheet = g_sharedFont->finf.tglp->nRows * g_sharedFont->finf.tglp->nLines; return 0; } -int fontGlyphIndexFromCodePoint(u32 codePoint) +void fontFixPointers(CFNT_s* font) { - int ret = g_sharedFont->finf.alterCharIndex; + font->finf.tglp = (TGLP_s*)((u32)(font->finf.tglp) + (u32) font); + font->finf.tglp->sheetData = (u8*)((u32)(font->finf.tglp->sheetData) + (u32) font); + + font->finf.cmap = (CMAP_s*)((u32)(font->finf.cmap) + (u32) font); + CMAP_s* cmap = font->finf.cmap; + for (; cmap->next; cmap = cmap->next) + cmap->next = (CMAP_s*)((u32)(cmap->next) + (u32) font); + + font->finf.cwdh = (CWDH_s*)((u32)(font->finf.cwdh) + (u32) font); + CWDH_s* cwdh; + for (cwdh = font->finf.cwdh; cwdh->next; cwdh = cwdh->next) + cwdh->next = (CWDH_s*)((u32)(cwdh->next) + (u32) font); +} + +int fontGlyphIndexFromCodePoint(CFNT_s* font, u32 codePoint) +{ + if (!font) + font = fontGetSystemFont(); + int ret = font->finf.alterCharIndex; if (codePoint < 0x10000) { CMAP_s* cmap; - for (cmap = g_sharedFont->finf.cmap; cmap; cmap = cmap->next) + for (cmap = font->finf.cmap; cmap; cmap = cmap->next) { if (codePoint < cmap->codeBegin || codePoint > cmap->codeEnd) continue; @@ -67,26 +83,31 @@ int fontGlyphIndexFromCodePoint(u32 codePoint) return ret; } -charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex) +charWidthInfo_s* fontGetCharWidthInfo(CFNT_s* font, int glyphIndex) { + if (!font) + font = fontGetSystemFont(); charWidthInfo_s* info = NULL; CWDH_s* cwdh; - for (cwdh = g_sharedFont->finf.cwdh; cwdh && !info; cwdh = cwdh->next) + for (cwdh = font->finf.cwdh; cwdh && !info; cwdh = cwdh->next) { if (glyphIndex < cwdh->startIndex || glyphIndex > cwdh->endIndex) continue; info = &cwdh->widths[glyphIndex - cwdh->startIndex]; } if (!info) - info = &g_sharedFont->finf.defaultWidth; + info = &font->finf.defaultWidth; return info; } -void fontCalcGlyphPos(fontGlyphPos_s* out, int glyphIndex, u32 flags, float scaleX, float scaleY) +void fontCalcGlyphPos(fontGlyphPos_s* out, CFNT_s* font, int glyphIndex, u32 flags, float scaleX, float scaleY) { - FINF_s* finf = &g_sharedFont->finf; + if (!font) + font = fontGetSystemFont(); + FINF_s* finf = &font->finf; TGLP_s* tglp = finf->tglp; - charWidthInfo_s* cwi = fontGetCharWidthInfo(glyphIndex); + charWidthInfo_s* cwi = fontGetCharWidthInfo(font, glyphIndex); + int charPerSheet = font->finf.tglp->nRows * font->finf.tglp->nLines; int sheetId = glyphIndex / charPerSheet; int glInSheet = glyphIndex % charPerSheet;