Add shared system font parsing code.
This commit is contained in:
parent
07f0fe7e65
commit
8b5e753235
@ -68,6 +68,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <3ds/sdmc.h>
|
#include <3ds/sdmc.h>
|
||||||
#include <3ds/romfs.h>
|
#include <3ds/romfs.h>
|
||||||
|
#include <3ds/font.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
205
libctru/include/3ds/font.h
Normal file
205
libctru/include/3ds/font.h
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/**
|
||||||
|
* @file font.h
|
||||||
|
* @brief Shared font support.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <3ds/types.h>
|
||||||
|
|
||||||
|
///@name Data types
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/// Character width information structure.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s8 left; ///< Horizontal offset to draw the glyph with.
|
||||||
|
u8 glyphWidth; ///< Width of the glyph.
|
||||||
|
u8 charWidth; ///< Width of the character, that is, horizontal distance to advance.
|
||||||
|
} charWidthInfo_s;
|
||||||
|
|
||||||
|
/// Font texture sheet information.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 cellWidth; ///< Width of a glyph cell.
|
||||||
|
u8 cellHeight; ///< Height of a glyph cell.
|
||||||
|
u8 baselinePos; ///< Vertical position of the baseline.
|
||||||
|
u8 maxCharWidth; ///< Maximum character width.
|
||||||
|
|
||||||
|
u32 sheetSize; ///< Size in bytes of a texture sheet.
|
||||||
|
u16 nSheets; ///< Number of texture sheets.
|
||||||
|
u16 sheetFmt; ///< GPU texture format (GPU_TEXCOLOR).
|
||||||
|
|
||||||
|
u16 nRows; ///< Number of glyphs per row per sheet.
|
||||||
|
u16 nLines; ///< Number of glyph rows per sheet.
|
||||||
|
|
||||||
|
u16 sheetWidth; ///< Texture sheet width.
|
||||||
|
u16 sheetHeight; ///< Texture sheet height.
|
||||||
|
u8* sheetData; ///< Pointer to texture sheet data.
|
||||||
|
} TGLP_s;
|
||||||
|
|
||||||
|
/// Font character width information block type.
|
||||||
|
typedef struct tag_CWDH_s CWDH_s;
|
||||||
|
|
||||||
|
/// Font character width information block structure.
|
||||||
|
struct tag_CWDH_s
|
||||||
|
{
|
||||||
|
u16 startIndex; ///< First Unicode codepoint the block applies to.
|
||||||
|
u16 endIndex; ///< Last Unicode codepoint the block applies to.
|
||||||
|
CWDH_s* next; ///< Pointer to the next block.
|
||||||
|
|
||||||
|
charWidthInfo_s widths[0]; ///< Table of character width information structures.
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Font character map methods.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CMAP_TYPE_DIRECT = 0, ///< Identity mapping.
|
||||||
|
CMAP_TYPE_TABLE = 1, ///< Mapping using a table.
|
||||||
|
CMAP_TYPE_SCAN = 2, ///< Mapping using a list of mapped characters.
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Font character map type.
|
||||||
|
typedef struct tag_CMAP_s CMAP_s;
|
||||||
|
|
||||||
|
/// Font character map structure.
|
||||||
|
struct tag_CMAP_s
|
||||||
|
{
|
||||||
|
u16 codeBegin; ///< First Unicode codepoint the block applies to.
|
||||||
|
u16 codeEnd; ///< Last Unicode codepoint the block applies to.
|
||||||
|
u16 mappingMethod; ///< Mapping method.
|
||||||
|
u16 reserved;
|
||||||
|
CMAP_s* next; ///< Pointer to the next map.
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u16 indexOffset; ///< For CMAP_TYPE_DIRECT: index of the first glyph.
|
||||||
|
u16 indexTable[0]; ///< For CMAP_TYPE_TABLE: table of glyph indices.
|
||||||
|
/// For CMAP_TYPE_SCAN: Mapping data.
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 nScanEntries; ///< Number of pairs.
|
||||||
|
/// Mapping pairs.
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 code; ///< Unicode codepoint.
|
||||||
|
u16 glyphIndex; ///< Mapped glyph index.
|
||||||
|
} scanEntries[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Font information structure.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 signature; ///< Signature (FINF).
|
||||||
|
u32 sectionSize; ///< Section size.
|
||||||
|
|
||||||
|
u8 fontType; ///< Font type
|
||||||
|
u8 lineFeed; ///< Line feed vertical distance.
|
||||||
|
u16 alterCharIndex; ///< Glyph index of the replacement character.
|
||||||
|
charWidthInfo_s defaultWidth; ///< Default character width information.
|
||||||
|
u8 encoding; ///< Font encoding (?)
|
||||||
|
|
||||||
|
TGLP_s* tglp; ///< Pointer to texture sheet information.
|
||||||
|
CWDH_s* cwdh; ///< Pointer to the first character width information block.
|
||||||
|
CMAP_s* cmap; ///< Pointer to the first character map.
|
||||||
|
|
||||||
|
u8 height; ///< Font height.
|
||||||
|
u8 width; ///< Font width.
|
||||||
|
u8 ascent; ///< Font ascent.
|
||||||
|
u8 padding;
|
||||||
|
} FINF_s;
|
||||||
|
|
||||||
|
/// Font structure.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 signature; ///< Signature (CFNU).
|
||||||
|
u16 endianness; ///< Endianness constant (0xFEFF).
|
||||||
|
u16 headerSize; ///< Header size.
|
||||||
|
u32 version; ///< Format version.
|
||||||
|
u32 fileSize; ///< File size.
|
||||||
|
u32 nBlocks; ///< Number of blocks.
|
||||||
|
|
||||||
|
FINF_s finf; ///< Font information.
|
||||||
|
} CFNT_s;
|
||||||
|
|
||||||
|
/// Font glyph position structure.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int sheetIndex; ///< Texture sheet index to use to render the glyph.
|
||||||
|
float xOffset; ///< Horizontal offset to draw the glyph width.
|
||||||
|
float xAdvance; ///< Horizontal distance to advance after drawing the glyph.
|
||||||
|
float width; ///< Glyph width.
|
||||||
|
///< Texture coordinates to use to render the glyph.
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float left, top, right, bottom;
|
||||||
|
} texcoord;
|
||||||
|
///< Vertex coordinates to use to render the glyph.
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float left, top, right, bottom;
|
||||||
|
} vtxcoord;
|
||||||
|
} fontGlyphPos_s;
|
||||||
|
|
||||||
|
/// Flags for use with fontCalcGlyphPos.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GLYPH_POS_CALC_VTXCOORD = BIT(0), ///< Calculates vertex coordinates in addition to texture coordinates.
|
||||||
|
GLYPH_POS_AT_BASELINE = BIT(1), ///< Position the glyph at the baseline instead of at the top-left corner.
|
||||||
|
GLYPH_POS_Y_POINTS_UP = BIT(2), ///< Indicates that the Y axis points up instead of down.
|
||||||
|
};
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
///@name Initialization and basic operations
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
{
|
||||||
|
extern CFNT_s* g_sharedFont;
|
||||||
|
return &g_sharedFont->finf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the texture sheet information of the shared system font.
|
||||||
|
static inline TGLP_s* fontGetGlyphInfo(void)
|
||||||
|
{
|
||||||
|
return fontGetInfo()->tglp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the pointer to texture data for the specified texture sheet.
|
||||||
|
* @param sheetIndex Index of the texture sheet.
|
||||||
|
*/
|
||||||
|
static inline void* fontGetGlyphSheetTex(int sheetIndex)
|
||||||
|
{
|
||||||
|
TGLP_s* tglp = fontGetGlyphInfo();
|
||||||
|
return &tglp->sheetData[sheetIndex*tglp->sheetSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the glyph index of the specified Unicode codepoint.
|
||||||
|
* @param codePoint Unicode codepoint.
|
||||||
|
*/
|
||||||
|
int fontGlyphIndexFromCodePoint(u32 codePoint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves character width information of the specified glyph.
|
||||||
|
* @param glyphIndex Index of the glyph.
|
||||||
|
*/
|
||||||
|
charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates position information for the specified glyph.
|
||||||
|
* @param out Output structure in which to write the 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);
|
||||||
|
|
||||||
|
///@}
|
@ -444,3 +444,9 @@ Result APT_PrepareToStartSystemApplet(NS_APPID appID);
|
|||||||
*/
|
*/
|
||||||
Result APT_StartSystemApplet(NS_APPID appID, u32 bufSize, Handle applHandle, u8 *buf);
|
Result APT_StartSystemApplet(NS_APPID appID, u32 bufSize, Handle applHandle, u8 *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the shared system font.
|
||||||
|
* @brief fontHandle Pointer to write the handle of the system font memory block to.
|
||||||
|
* @brief mapAddr Pointer to write the mapping address of the system font memory block to.
|
||||||
|
*/
|
||||||
|
Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr);
|
||||||
|
134
libctru/source/font.c
Normal file
134
libctru/source/font.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <3ds/font.h>
|
||||||
|
#include <3ds/svc.h>
|
||||||
|
#include <3ds/synchronization.h>
|
||||||
|
#include <3ds/result.h>
|
||||||
|
#include <3ds/services/apt.h>
|
||||||
|
|
||||||
|
CFNT_s* g_sharedFont;
|
||||||
|
static u32 sharedFontAddr;
|
||||||
|
static int charPerSheet;
|
||||||
|
|
||||||
|
Result fontEnsureMapped(void)
|
||||||
|
{
|
||||||
|
if (g_sharedFont) return 0;
|
||||||
|
Result res = 0;
|
||||||
|
Handle hSharedFont = 0;
|
||||||
|
|
||||||
|
aptOpenSession();
|
||||||
|
res = APT_GetSharedFont(&hSharedFont, &sharedFontAddr);
|
||||||
|
aptCloseSession();
|
||||||
|
if (R_FAILED(res)) return res;
|
||||||
|
|
||||||
|
// Map the shared font if it's not already mapped.
|
||||||
|
res = svcMapMemoryBlock(hSharedFont, 0, MEMPERM_READ, MEMPERM_DONTCARE);
|
||||||
|
svcCloseHandle(hSharedFont);
|
||||||
|
if (R_FAILED(res) && res != 0xE0A01BF5)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int ret = g_sharedFont->finf.alterCharIndex;
|
||||||
|
if (codePoint < 0x10000)
|
||||||
|
{
|
||||||
|
CMAP_s* cmap;
|
||||||
|
for (cmap = g_sharedFont->finf.cmap; cmap; cmap = cmap->next)
|
||||||
|
{
|
||||||
|
if (codePoint < cmap->codeBegin || codePoint > cmap->codeEnd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cmap->mappingMethod == CMAP_TYPE_DIRECT)
|
||||||
|
{
|
||||||
|
ret = cmap->indexOffset + (codePoint - cmap->codeBegin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmap->mappingMethod == CMAP_TYPE_TABLE)
|
||||||
|
{
|
||||||
|
ret = cmap->indexTable[codePoint - cmap->codeBegin];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < cmap->nScanEntries; j ++)
|
||||||
|
if (cmap->scanEntries[j].code == codePoint)
|
||||||
|
break;
|
||||||
|
if (j < cmap->nScanEntries)
|
||||||
|
{
|
||||||
|
ret = cmap->scanEntries[j].glyphIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex)
|
||||||
|
{
|
||||||
|
charWidthInfo_s* info = NULL;
|
||||||
|
CWDH_s* cwdh;
|
||||||
|
for (cwdh = g_sharedFont->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;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fontCalcGlyphPos(fontGlyphPos_s* out, int glyphIndex, u32 flags, float scaleX, float scaleY)
|
||||||
|
{
|
||||||
|
FINF_s* finf = &g_sharedFont->finf;
|
||||||
|
TGLP_s* tglp = finf->tglp;
|
||||||
|
charWidthInfo_s* cwi = fontGetCharWidthInfo(glyphIndex);
|
||||||
|
|
||||||
|
int sheetId = glyphIndex / charPerSheet;
|
||||||
|
int glInSheet = glyphIndex % charPerSheet;
|
||||||
|
out->sheetIndex = sheetId;
|
||||||
|
out->xOffset = scaleX*cwi->left;
|
||||||
|
out->xAdvance = scaleX*cwi->charWidth;
|
||||||
|
out->width = scaleX*cwi->glyphWidth;
|
||||||
|
|
||||||
|
int lineId = glInSheet / tglp->nRows;
|
||||||
|
int rowId = glInSheet % tglp->nRows;
|
||||||
|
|
||||||
|
float tx = (float)(rowId*(tglp->cellWidth+1)+1) / tglp->sheetWidth;
|
||||||
|
float ty = 1.0f - (float)((lineId+1)*(tglp->cellHeight+1)+1) / tglp->sheetHeight;
|
||||||
|
float tw = (float)cwi->glyphWidth / tglp->sheetWidth;
|
||||||
|
float th = (float)tglp->cellHeight / tglp->sheetHeight;
|
||||||
|
out->texcoord.left = tx;
|
||||||
|
out->texcoord.top = ty+th;
|
||||||
|
out->texcoord.right = tx+tw;
|
||||||
|
out->texcoord.bottom = ty;
|
||||||
|
|
||||||
|
if (flags & GLYPH_POS_CALC_VTXCOORD)
|
||||||
|
{
|
||||||
|
float vx = out->xOffset;
|
||||||
|
float vy = (flags & GLYPH_POS_AT_BASELINE) ? (scaleY*tglp->baselinePos) : 0;
|
||||||
|
float vw = out->width;
|
||||||
|
float vh = scaleY*tglp->cellHeight;
|
||||||
|
if (flags & GLYPH_POS_Y_POINTS_UP)
|
||||||
|
{
|
||||||
|
vy = -(vh-vy);
|
||||||
|
out->vtxcoord.left = vx;
|
||||||
|
out->vtxcoord.top = vy+vh;
|
||||||
|
out->vtxcoord.right = vx+vw;
|
||||||
|
out->vtxcoord.bottom = vy;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
vy = -vy;
|
||||||
|
out->vtxcoord.left = vx;
|
||||||
|
out->vtxcoord.top = vy;
|
||||||
|
out->vtxcoord.right = vx+vw;
|
||||||
|
out->vtxcoord.bottom = vy+vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1342,3 +1342,16 @@ Result APT_StartSystemApplet(NS_APPID appID, u32 bufSize, Handle applHandle, u8
|
|||||||
return cmdbuf[1];
|
return cmdbuf[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr)
|
||||||
|
{
|
||||||
|
u32* cmdbuf=getThreadCommandBuffer();
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x44,0,0); // 0x00440000
|
||||||
|
|
||||||
|
Result ret=0;
|
||||||
|
if(R_FAILED(ret=svcSendSyncRequest(aptuHandle)))return ret;
|
||||||
|
|
||||||
|
if(fontHandle) *fontHandle = cmdbuf[4];
|
||||||
|
if(mapAddr) *mapAddr = cmdbuf[2];
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user