mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #4560 from unknownbrackets/font-minor
Fix fields in char info and font info, speed up font loading a little
This commit is contained in:
commit
ce11fd7e4b
3 changed files with 152 additions and 85 deletions
|
@ -34,13 +34,31 @@ static bool isJPCSPFont(const char *fontName) {
|
|||
}
|
||||
|
||||
// Gets a number of bits from an offset.
|
||||
// TODO: Make more efficient.
|
||||
static int getBits(int numBits, const u8 *buf, size_t pos) {
|
||||
int v = 0;
|
||||
for (int i = 0; i < numBits; i++) {
|
||||
v = v | (((buf[pos >> 3] >> (pos & 7)) & 1) << i);
|
||||
pos++;
|
||||
_dbg_assert_msg_(SCEFONT, numBits <= 32, "Unable to return more than 32 bits, %d requested", numBits);
|
||||
|
||||
const size_t wordpos = pos >> 5;
|
||||
const u32 *wordbuf = (const u32 *)buf;
|
||||
const u8 bitoff = pos & 31;
|
||||
|
||||
// Might just be in one, has to be within two.
|
||||
if (bitoff + numBits < 32) {
|
||||
const u32 mask = (1 << numBits) - 1;
|
||||
return (wordbuf[wordpos] >> bitoff) & mask;
|
||||
} else {
|
||||
int v = wordbuf[wordpos] >> bitoff;
|
||||
|
||||
const u8 done = 32 - bitoff;
|
||||
const u8 remaining = numBits - done;
|
||||
const u32 mask = (1 << remaining) - 1;
|
||||
v |= (wordbuf[wordpos + 1] & mask) << done;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int consumeBits(int numBits, const u8 *buf, size_t &pos) {
|
||||
int v = getBits(numBits, buf, pos);
|
||||
pos += numBits;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -64,8 +82,47 @@ PGF::~PGF() {
|
|||
}
|
||||
}
|
||||
|
||||
struct GlyphFromPGF1State {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
int left;
|
||||
int top;
|
||||
int flags;
|
||||
int shadowID;
|
||||
int advanceH;
|
||||
int advanceV;
|
||||
int dimensionWidth, dimensionHeight;
|
||||
int xAdjustH, xAdjustV;
|
||||
int yAdjustH, yAdjustV;
|
||||
u32 ptr;
|
||||
|
||||
operator Glyph() {
|
||||
Glyph ret;
|
||||
ret.w = w;
|
||||
ret.h = h;
|
||||
ret.left = left;
|
||||
ret.top = top;
|
||||
ret.flags = flags;
|
||||
// Wasn't read before.
|
||||
ret.shadowFlags = 0;
|
||||
ret.shadowID = shadowID;
|
||||
ret.advanceH = advanceH;
|
||||
ret.advanceV = advanceV;
|
||||
ret.dimensionWidth = dimensionWidth;
|
||||
ret.dimensionHeight = dimensionHeight;
|
||||
ret.xAdjustH = xAdjustH;
|
||||
ret.xAdjustV = xAdjustV;
|
||||
ret.yAdjustH = yAdjustH;
|
||||
ret.yAdjustV = yAdjustV;
|
||||
ret.ptr = ptr;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
void PGF::DoState(PointerWrap &p) {
|
||||
auto s = p.Section("PGF", 1);
|
||||
auto s = p.Section("PGF", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -98,8 +155,22 @@ void PGF::DoState(PointerWrap &p) {
|
|||
|
||||
p.Do(charmap_compr);
|
||||
p.Do(charmap);
|
||||
p.Do(glyphs);
|
||||
p.Do(shadowGlyphs);
|
||||
if (s == 1) {
|
||||
std::vector<GlyphFromPGF1State> oldGlyphs;
|
||||
p.Do(oldGlyphs);
|
||||
glyphs.resize(oldGlyphs.size());
|
||||
for (size_t i = 0; i < oldGlyphs.size(); ++i) {
|
||||
glyphs[i] = oldGlyphs[i];
|
||||
}
|
||||
p.Do(oldGlyphs);
|
||||
shadowGlyphs.resize(oldGlyphs.size());
|
||||
for (size_t i = 0; i < oldGlyphs.size(); ++i) {
|
||||
shadowGlyphs[i] = oldGlyphs[i];
|
||||
}
|
||||
} else {
|
||||
p.Do(glyphs);
|
||||
p.Do(shadowGlyphs);
|
||||
}
|
||||
p.Do(firstGlyph);
|
||||
}
|
||||
|
||||
|
@ -149,10 +220,8 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
const u8 *uptr = (const u8 *)wptr;
|
||||
|
||||
int shadowCharMapSize = ((header.shadowMapLength * header.shadowMapBpe + 31) & ~31) / 8;
|
||||
u8 *shadowCharMap = new u8[shadowCharMapSize];
|
||||
for (int i = 0; i < shadowCharMapSize; i++) {
|
||||
shadowCharMap[i] = *uptr++;
|
||||
}
|
||||
const u8 *shadowCharMap = uptr;
|
||||
uptr += shadowCharMapSize;
|
||||
|
||||
const u16_le *sptr = (const u16_le *)uptr;
|
||||
if (header.revision == 3) {
|
||||
|
@ -174,17 +243,12 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
uptr = (const u8 *)sptr;
|
||||
|
||||
int charMapSize = ((header.charMapLength * header.charMapBpe + 31) & ~31) / 8;
|
||||
|
||||
u8 *charMap = new u8[charMapSize];
|
||||
for (int i = 0; i < charMapSize; i++) {
|
||||
charMap[i] = *uptr++;
|
||||
}
|
||||
const u8 *charMap = uptr;
|
||||
uptr += charMapSize;
|
||||
|
||||
int charPointerSize = (((header.charPointerLength * header.charPointerBpe + 31) & ~31) / 8);
|
||||
u8 *charPointerTable = new u8[charPointerSize];
|
||||
for (int i = 0; i < charPointerSize; i++) {
|
||||
charPointerTable[i] = *uptr++;
|
||||
}
|
||||
const u8 *charPointerTable = uptr;
|
||||
uptr += charPointerSize;
|
||||
|
||||
// PGF Fontdata.
|
||||
u32 fontDataOffset = (u32)(uptr - startPtr);
|
||||
|
@ -213,10 +277,6 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
std::vector<int> charPointers = getTable(charPointerTable, header.charPointerBpe, glyphs.size());
|
||||
std::vector<int> shadowMap = getTable(shadowCharMap, header.shadowMapBpe, shadowGlyphs.size());
|
||||
|
||||
delete [] charMap;
|
||||
delete [] shadowCharMap;
|
||||
delete [] charPointerTable;
|
||||
|
||||
// Pregenerate glyphs.
|
||||
for (size_t i = 0; i < glyphs.size(); i++) {
|
||||
GetGlyph(fontData, charPointers[i] * 4 * 8 /* ??? */, FONT_PGF_CHARGLYPH, glyphs[i]);
|
||||
|
@ -247,13 +307,18 @@ int PGF::GetCharIndex(int charCode, const std::vector<int> &charmapCompressed) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) {
|
||||
bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo, int altCharCode) {
|
||||
Glyph glyph;
|
||||
memset(charInfo, 0, sizeof(*charInfo));
|
||||
|
||||
if (!GetCharGlyph(charCode, FONT_PGF_CHARGLYPH, glyph)) {
|
||||
// Character not in font, return zeroed charInfo as on real PSP.
|
||||
return false;
|
||||
if (charCode < firstGlyph) {
|
||||
// Character not in font, return zeroed charInfo as on real PSP.
|
||||
return false;
|
||||
}
|
||||
if (!GetCharGlyph(altCharCode, FONT_PGF_CHARGLYPH, glyph)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
charInfo->bitmapWidth = glyph.w;
|
||||
|
@ -262,14 +327,17 @@ bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) {
|
|||
charInfo->bitmapTop = glyph.top;
|
||||
charInfo->sfp26Width = glyph.dimensionWidth;
|
||||
charInfo->sfp26Height = glyph.dimensionHeight;
|
||||
charInfo->sfp26Ascender = glyph.top << 6;
|
||||
charInfo->sfp26Descender = (glyph.h - glyph.top) << 6;
|
||||
charInfo->sfp26Ascender = glyph.yAdjustH;
|
||||
// Font y goes upwards. If top is 10 and height is 11, the descender is approx. -1 (below 0.)
|
||||
charInfo->sfp26Descender = charInfo->sfp26Ascender - charInfo->sfp26Height;
|
||||
charInfo->sfp26BearingHX = glyph.xAdjustH;
|
||||
charInfo->sfp26BearingHY = glyph.yAdjustH;
|
||||
charInfo->sfp26BearingVX = glyph.xAdjustV;
|
||||
charInfo->sfp26BearingVY = glyph.yAdjustV;
|
||||
charInfo->sfp26AdvanceH = glyph.advanceH;
|
||||
charInfo->sfp26AdvanceV = glyph.advanceV;
|
||||
charInfo->shadowFlags = glyph.shadowFlags;
|
||||
charInfo->shadowId = glyph.shadowID;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -297,7 +365,7 @@ void PGF::GetFontInfo(PGFFontInfo *fi) {
|
|||
|
||||
fi->maxGlyphWidth = header.maxGlyphWidth;
|
||||
fi->maxGlyphHeight = header.maxGlyphHeight;
|
||||
fi->charMapLength = header.charMapLength;
|
||||
fi->numGlyphs = header.charPointerLength;
|
||||
fi->shadowMapLength = 0; // header.shadowMapLength; TODO
|
||||
|
||||
fi->BPP = header.bpp;
|
||||
|
@ -311,40 +379,34 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
if (charPtr + 96 > fontDataSize * 8)
|
||||
return false;
|
||||
}
|
||||
// Skip size.
|
||||
charPtr += 14;
|
||||
|
||||
glyph.w = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.w = consumeBits(7, fontdata, charPtr);
|
||||
glyph.h = consumeBits(7, fontdata, charPtr);
|
||||
|
||||
glyph.h = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
|
||||
glyph.left = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.left = consumeBits(7, fontdata, charPtr);
|
||||
if (glyph.left >= 64) {
|
||||
glyph.left -= 128;
|
||||
}
|
||||
|
||||
glyph.top = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.top = consumeBits(7, fontdata, charPtr);
|
||||
if (glyph.top >= 64) {
|
||||
glyph.top -= 128;
|
||||
}
|
||||
|
||||
glyph.flags = getBits(6, fontdata, charPtr);
|
||||
charPtr += 6;
|
||||
glyph.flags = consumeBits(6, fontdata, charPtr);
|
||||
|
||||
if (glyph.flags & FONT_PGF_CHARGLYPH) {
|
||||
// Skip magic number
|
||||
charPtr += 7;
|
||||
if (glyphType == FONT_PGF_CHARGLYPH) {
|
||||
glyph.shadowFlags = consumeBits(2, fontdata, charPtr) << (2 + 3);
|
||||
glyph.shadowFlags |= consumeBits(2, fontdata, charPtr) << 3;
|
||||
glyph.shadowFlags |= consumeBits(3, fontdata, charPtr);
|
||||
|
||||
glyph.shadowID = getBits(9, fontdata, charPtr);
|
||||
charPtr += 9;
|
||||
glyph.shadowID = consumeBits(9, fontdata, charPtr);
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_DIMENSION_INDEX) == FONT_PGF_METRIC_DIMENSION_INDEX)
|
||||
{
|
||||
int dimensionIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int dimensionIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (dimensionIndex < header.dimTableLength) {
|
||||
glyph.dimensionWidth = dimensionTable[0][dimensionIndex];
|
||||
|
@ -360,16 +422,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.dimensionWidth = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.dimensionHeight = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.dimensionWidth = consumeBits(32, fontdata, charPtr);
|
||||
glyph.dimensionHeight = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_BEARING_X_INDEX) == FONT_PGF_METRIC_BEARING_X_INDEX)
|
||||
{
|
||||
int xAdjustIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int xAdjustIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (xAdjustIndex < header.xAdjustTableLength) {
|
||||
glyph.xAdjustH = xAdjustTable[0][xAdjustIndex];
|
||||
|
@ -386,16 +445,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.xAdjustH = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.xAdjustV = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.xAdjustH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.xAdjustV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_BEARING_Y_INDEX) == FONT_PGF_METRIC_BEARING_Y_INDEX)
|
||||
{
|
||||
int yAdjustIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int yAdjustIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (yAdjustIndex < header.xAdjustTableLength) {
|
||||
glyph.yAdjustH = yAdjustTable[0][yAdjustIndex];
|
||||
|
@ -412,18 +468,23 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.yAdjustH = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.yAdjustV = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.yAdjustH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.yAdjustV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
int advanceIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
if ((glyph.flags & FONT_PGF_METRIC_ADVANCE_INDEX) == FONT_PGF_METRIC_ADVANCE_INDEX)
|
||||
{
|
||||
int advanceIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (advanceIndex < header.advanceTableLength) {
|
||||
glyph.advanceH = advanceTable[0][advanceIndex];
|
||||
glyph.advanceV = advanceTable[1][advanceIndex];
|
||||
if (advanceIndex < header.advanceTableLength) {
|
||||
glyph.advanceH = advanceTable[0][advanceIndex];
|
||||
glyph.advanceV = advanceTable[1][advanceIndex];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph.advanceH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.advanceV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
} else {
|
||||
glyph.shadowID = 65535;
|
||||
|
@ -481,14 +542,12 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
|
||||
while (pixelIndex < numberPixels && bitPtr + 8 < fontDataSize * 8) {
|
||||
// This is some kind of nibble based RLE compression.
|
||||
int nibble = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
int nibble = consumeBits(4, fontData, bitPtr);
|
||||
|
||||
int count;
|
||||
int value = 0;
|
||||
if (nibble < 8) {
|
||||
value = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
value = consumeBits(4, fontData, bitPtr);
|
||||
count = nibble + 1;
|
||||
} else {
|
||||
count = 16 - nibble;
|
||||
|
@ -496,8 +555,7 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
|
||||
for (int i = 0; i < count && pixelIndex < numberPixels; i++) {
|
||||
if (nibble >= 8) {
|
||||
value = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
value = consumeBits(4, fontData, bitPtr);
|
||||
}
|
||||
|
||||
int xx, yy;
|
||||
|
|
|
@ -39,6 +39,7 @@ enum {
|
|||
FONT_PGF_METRIC_DIMENSION_INDEX = 0x04,
|
||||
FONT_PGF_METRIC_BEARING_X_INDEX = 0x08,
|
||||
FONT_PGF_METRIC_BEARING_Y_INDEX = 0x10,
|
||||
FONT_PGF_METRIC_ADVANCE_INDEX = 0x20,
|
||||
FONT_PGF_CHARGLYPH = 0x20,
|
||||
FONT_PGF_SHADOWGLYPH = 0x40,
|
||||
};
|
||||
|
@ -93,13 +94,12 @@ struct PGFFontStyle {
|
|||
|
||||
|
||||
struct Glyph {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
int left;
|
||||
int top;
|
||||
int flags;
|
||||
int shadowFlags;
|
||||
int shadowID;
|
||||
int advanceH;
|
||||
int advanceV;
|
||||
|
@ -142,6 +142,7 @@ struct PGFHeader
|
|||
s32_le charMapBpe;
|
||||
s32_le charPointerBpe;
|
||||
|
||||
// TODO: This has values in it (0404)...
|
||||
u8 pad1[2];
|
||||
u8 bpp;
|
||||
u8 pad2[1];
|
||||
|
@ -159,6 +160,7 @@ struct PGFHeader
|
|||
u16_le firstGlyph;
|
||||
u16_le lastGlyph;
|
||||
|
||||
// TODO: This has a few 01s in it in the official fonts.
|
||||
u8 pad5[26];
|
||||
|
||||
s32_le maxAscender;
|
||||
|
@ -211,7 +213,8 @@ struct PGFCharInfo {
|
|||
s32_le sfp26BearingVY;
|
||||
s32_le sfp26AdvanceH;
|
||||
s32_le sfp26AdvanceV;
|
||||
u8 pad[4];
|
||||
s16_le shadowFlags;
|
||||
s16_le shadowId;
|
||||
};
|
||||
|
||||
struct PGFFontInfo {
|
||||
|
@ -242,13 +245,14 @@ struct PGFFontInfo {
|
|||
// Bitmap dimensions.
|
||||
s16_le maxGlyphWidth;
|
||||
s16_le maxGlyphHeight;
|
||||
s32_le charMapLength; // Number of elements in the font's charmap.
|
||||
s32_le numGlyphs;
|
||||
s32_le shadowMapLength; // Number of elements in the font's shadow charmap.
|
||||
|
||||
// Font style (used by font comparison functions).
|
||||
PGFFontStyle fontStyle;
|
||||
|
||||
s32_le BPP; // Font's BPP.
|
||||
u8 BPP; // Font's BPP.
|
||||
u8 pad[3];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
@ -260,7 +264,7 @@ public:
|
|||
|
||||
void ReadPtr(const u8 *ptr, size_t dataSize);
|
||||
|
||||
bool GetCharInfo(int charCode, PGFCharInfo *ci);
|
||||
bool GetCharInfo(int charCode, PGFCharInfo *ci, int altCharCode);
|
||||
void GetFontInfo(PGFFontInfo *fi);
|
||||
void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType, bool packagedFont);
|
||||
|
||||
|
|
|
@ -338,6 +338,7 @@ public:
|
|||
}
|
||||
}
|
||||
u32 args[2] = { params_.userDataAddr, (u32)handle_ };
|
||||
// TODO: The return value of this is leaking.
|
||||
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
|
||||
handle_ = 0;
|
||||
fonts_.clear();
|
||||
|
@ -825,8 +826,10 @@ int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
|
|||
}
|
||||
|
||||
DEBUG_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
|
||||
auto fontLib = font->GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
auto charInfo = Memory::GetStruct<PGFCharInfo>(charInfoPtr);
|
||||
font->GetPGF()->GetCharInfo(charCode, charInfo);
|
||||
font->GetPGF()->GetCharInfo(charCode, charInfo, altCharCode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -842,11 +845,13 @@ int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
|
|||
DEBUG_LOG(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
|
||||
if (!Memory::IsValidAddress(charRectPtr))
|
||||
return -1;
|
||||
|
||||
|
||||
PGFCharInfo charInfo;
|
||||
LoadedFont *font = GetLoadedFont(fontHandle, false);
|
||||
auto fontLib = font->GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
if (font) {
|
||||
font->GetPGF()->GetCharInfo(charCode, &charInfo);
|
||||
font->GetPGF()->GetCharInfo(charCode, &charInfo, altCharCode);
|
||||
Memory::Write_U16(charInfo.bitmapWidth, charRectPtr); // character bitmap width in pixels
|
||||
Memory::Write_U16(charInfo.bitmapHeight, charRectPtr + 2); // character bitmap height in pixels
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue