diff --git a/libctru/include/3ds/font.h b/libctru/include/3ds/font.h index bf69040..c546782 100644 --- a/libctru/include/3ds/font.h +++ b/libctru/include/3ds/font.h @@ -157,49 +157,78 @@ 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 a font. + * @param font Pointer to font structure. If NULL, the shared system font is used. + */ +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 a font. + * @param font Pointer to font structure. If NULL, the shared system font is used. + */ +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 Pointer to font structure. If NULL, the shared system font is used. * @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 Pointer to font structure. If NULL, the shared system font is used. * @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 Pointer to font structure. If NULL, the shared system font is used. * @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 Pointer to font structure. If NULL, the shared system font is used. * @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..1272cdd 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,33 @@ 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); + for (CMAP_s* cmap = font->finf.cmap; 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); + for (CWDH_s* 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 = g_sharedFont; + if (!font) + return -1; + int ret = font->finf.alterCharIndex; if (codePoint < 0x10000) { - CMAP_s* cmap; - for (cmap = g_sharedFont->finf.cmap; cmap; cmap = cmap->next) + for (CMAP_s* cmap = font->finf.cmap; cmap; cmap = cmap->next) { if (codePoint < cmap->codeBegin || codePoint > cmap->codeEnd) continue; @@ -67,26 +82,34 @@ int fontGlyphIndexFromCodePoint(u32 codePoint) return ret; } -charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex) +charWidthInfo_s* fontGetCharWidthInfo(CFNT_s* font, int glyphIndex) { + if (!font) + font = g_sharedFont; + if (!font) + return NULL; charWidthInfo_s* info = NULL; - CWDH_s* cwdh; - for (cwdh = g_sharedFont->finf.cwdh; cwdh && !info; cwdh = cwdh->next) + for (CWDH_s* 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 = g_sharedFont; + if (!font) + return; + 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;