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:
Henrik Rydgård 2013-11-17 02:10:27 -08:00
commit ce11fd7e4b
3 changed files with 152 additions and 85 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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 {