GRIM: Split TTF fonts from bitmap fonts and add a drawing interface

This cleans up the code and allows adding double-byte charsets easier
This commit is contained in:
Vladimir Serbinenko 2023-03-04 02:41:08 +01:00 committed by Eugene Sandulenko
parent 34db914a09
commit 829eab2f72
13 changed files with 258 additions and 139 deletions

View File

@ -219,18 +219,13 @@ void Lua_V2::GetFontDimensions() {
const char *fontName = lua_getstring(fontObj);
Font *font = nullptr;
for (Font *f : Font::getPool()) {
if (f->getFilename() == fontName) {
font = f;
}
}
Font *font = Font::getByFileName(fontName);
if (!font) {
font = g_resourceloader->loadFont(fontName);
}
if (font) {
int32 h = font->getBaseOffsetY();
int32 w = font->getCharKernedWidth('w');
int32 w = font->getFontWidth();
lua_pushnumber(w);
lua_pushnumber(h);
} else {

View File

@ -23,6 +23,7 @@
#include "graphics/fonts/ttf.h"
#include "graphics/font.h"
#include "graphics/surface.h"
#include "engines/grim/debug.h"
#include "engines/grim/grim.h"
@ -33,21 +34,71 @@
namespace Grim {
Font::Font() :
void Font::save(const Font *font, SaveGame *state) {
const FontTTF *ttf = dynamic_cast<const FontTTF *>(font);
if (ttf) {
state->writeLESint32(-2);
state->writeLESint32(ttf->getId());
return;
}
const BitmapFont *bitmapFont = dynamic_cast<const BitmapFont *>(font);
if (bitmapFont) {
state->writeLESint32(bitmapFont->getId());
return;
}
state->writeLESint32(-1);
}
Font *Font::load(SaveGame *state) {
int32 fontId = state->readLESint32();
if (fontId == -1) {
return nullptr;
}
if (fontId == -2) {
fontId = state->readLESint32();
return FontTTF::getPool().getObject(fontId);
}
return BitmapFont::getPool().getObject(fontId);
}
Font *Font::getByFileName(const Common::String& fontName) {
for (Font *f : BitmapFont::getPool()) {
if (f->getFilename() == fontName) {
return f;
}
}
for (Font *f : FontTTF::getPool()) {
if (f->getFilename() == fontName) {
return f;
}
}
return nullptr;
}
Font *Font::getFirstFont() {
if (BitmapFont::getPool().begin() != BitmapFont::getPool().end())
return *BitmapFont::getPool().begin();
if (FontTTF::getPool().begin() != FontTTF::getPool().end())
return *FontTTF::getPool().begin();
return nullptr;
}
BitmapFont::BitmapFont() :
_userData(nullptr),
_fontData(nullptr), _charHeaders(nullptr), _charIndex(nullptr),
_numChars(0), _dataSize(0), _kernedHeight(0), _baseOffsetY(0),
_firstChar(0), _lastChar(0) {
}
Font::~Font() {
BitmapFont::~BitmapFont() {
delete[] _charIndex;
delete[] _charHeaders;
delete[] _fontData;
g_driver->destroyFont(this);
}
void Font::load(const Common::String &filename, Common::SeekableReadStream *data) {
void BitmapFont::load(const Common::String &filename, Common::SeekableReadStream *data) {
_filename = filename;
_numChars = data->readUint32LE();
_dataSize = data->readUint32LE();
@ -83,7 +134,7 @@ void Font::load(const Common::String &filename, Common::SeekableReadStream *data
g_driver->createFont(this);
}
uint16 Font::getCharIndex(unsigned char c) const {
uint16 BitmapFont::getCharIndex(unsigned char c) const {
uint16 c2 = uint16(c);
// In order to ensure the correct character codes for
@ -113,7 +164,7 @@ uint16 Font::getCharIndex(unsigned char c) const {
return 0;
}
int Font::getKernedStringLength(const Common::String &text) const {
int BitmapFont::getKernedStringLength(const Common::String &text) const {
int result = 0;
for (uint32 i = 0; i < text.size(); ++i) {
result += getCharKernedWidth(text[i]);
@ -121,7 +172,7 @@ int Font::getKernedStringLength(const Common::String &text) const {
return result;
}
int Font::getBitmapStringLength(const Common::String &text) const {
int BitmapFont::getBitmapStringLength(const Common::String &text) const {
int result = 0;
for (uint32 i = 0; i < text.size(); ++i) {
result += getCharKernedWidth(text[i]) + getCharStartingCol(text[i]);
@ -129,7 +180,7 @@ int Font::getBitmapStringLength(const Common::String &text) const {
return result;
}
int Font::getStringHeight(const Common::String &text) const {
int BitmapFont::getStringHeight(const Common::String &text) const {
int result = 0;
for (uint32 i = 0; i < text.size(); ++i) {
int verticalOffset = getCharStartingLine(text[i]) + getBaseOffsetY();
@ -140,11 +191,11 @@ int Font::getStringHeight(const Common::String &text) const {
return result;
}
void Font::saveState(SaveGame *state) const {
void BitmapFont::saveState(SaveGame *state) const {
state->writeString(getFilename());
}
void Font::restoreState(SaveGame *state) {
void BitmapFont::restoreState(SaveGame *state) {
Common::String fname = state->readString();
Common::SeekableReadStream *stream;
@ -161,7 +212,73 @@ void Font::restoreState(SaveGame *state) {
delete stream;
}
void FontTTF::saveState(SaveGame *state) const {
state->writeString(getFilename());
state->writeLESint32(_size);
}
void FontTTF::restoreState(SaveGame *state) {
Common::String fname = state->readString();
int size = state->readLESint32();
Common::SeekableReadStream *stream;
g_driver->destroyFont(this);
delete _font;
stream = g_resourceloader->openNewStreamFile(fname.c_str(), true);
loadTTF(fname, stream, size);
delete stream;
}
void BitmapFont::render(Graphics::Surface &buf, const Common::String &currentLine,
const Graphics::PixelFormat &pixelFormat, uint32 blackColor, uint32 color, uint32 colorKey) const {
int width = getBitmapStringLength(currentLine) + 1;
int height = getStringHeight(currentLine) + 1;
uint8 *_textBitmap = new uint8[height * width]();
int startColumn = 0;
for (unsigned int d = 0; d < currentLine.size(); d++) {
int ch = currentLine[d];
int32 charBitmapWidth = getCharBitmapWidth(ch);
int8 fontRow = getCharStartingLine(ch) + getBaseOffsetY();
int8 fontCol = getCharStartingCol(ch);
for (int line = 0; line < getCharBitmapHeight(ch); line++) {
int lineOffset = ((fontRow + line) * width);
for (int bitmapCol = 0; bitmapCol < charBitmapWidth; bitmapCol++) {
int columnOffset = startColumn + fontCol + bitmapCol;
int fontOffset = (charBitmapWidth * line) + bitmapCol;
int8 pixel = getCharData(ch)[fontOffset];
assert(lineOffset + columnOffset < width*height);
if (pixel != 0)
_textBitmap[lineOffset + columnOffset] = pixel;
}
}
startColumn += getCharKernedWidth(ch);
}
buf.create(width, height, pixelFormat);
uint8 *bitmapData = _textBitmap;
for (int iy = 0; iy < height; iy++) {
for (int ix = 0; ix < width; ix++, bitmapData++) {
byte pixel = *bitmapData;
if (pixel == 0x00) {
buf.setPixel(ix, iy, colorKey);
} else if (pixel == 0x80) {
buf.setPixel(ix, iy, blackColor);
} else if (pixel == 0xFF) {
buf.setPixel(ix, iy, color);
}
}
}
delete[] _textBitmap;
}
void FontTTF::loadTTF(const Common::String &filename, Common::SeekableReadStream *data, int size) {
_filename = filename;
_size = size;
#ifdef USE_FREETYPE2
_font = Graphics::loadTTFFont(*data, size);
#else
@ -169,8 +286,17 @@ void FontTTF::loadTTF(const Common::String &filename, Common::SeekableReadStream
#endif
}
void FontTTF::render(Graphics::Surface &surface, const Common::String &currentLine, const Graphics::PixelFormat &pixelFormat, uint32 blackColor, uint32 color, uint32 colorKey) const {
#ifdef USE_FREETYPE2
Common::Rect bbox = _font->getBoundingBox(currentLine);
surface.create(bbox.right, bbox.bottom, pixelFormat);
surface.fillRect(Common::Rect(0, 0, bbox.right, bbox.bottom), colorKey);
_font->drawString(&surface, currentLine, 0, 0, bbox.right, 0xFFFFFFFF);
#endif
}
// Hardcoded default font for FPS, GUI, etc
const uint8 Font::emerFont[][13] = {
const uint8 BitmapFont::emerFont[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},

View File

@ -25,6 +25,7 @@
#include "engines/grim/pool.h"
#include "graphics/font.h"
#include "graphics/pixelformat.h"
namespace Common {
class SeekableReadStream;
@ -34,22 +35,50 @@ namespace Grim {
class SaveGame;
class Font : public PoolObject<Font> {
class Font {
public:
Font();
~Font();
virtual ~Font() {}
virtual int32 getKernedHeight() const = 0;
virtual int32 getFontWidth() const = 0;
virtual int getKernedStringLength(const Common::String &text) const = 0;
virtual int32 getBaseOffsetY() const = 0;
virtual void render(Graphics::Surface &buf, const Common::String &currentLine, const Graphics::PixelFormat &pixelFormat, uint32 blackColor, uint32 color, uint32 colorKey) const = 0;
virtual int32 getCharKernedWidth(unsigned char c) const = 0;
virtual int getPoolId() const = 0;
virtual int32 getPoolTag() const = 0;
virtual bool is8Bit() const = 0;
const Common::String &getFilename() const { return _filename; }
static Font *getByFileName(const Common::String& fileName);
static Font *getFirstFont();
static void save(const Font *font, SaveGame *state);
static Font *load(SaveGame *state);
protected:
Common::String _filename;
};
class BitmapFont : public Font, public PoolObject<BitmapFont> {
public:
BitmapFont();
~BitmapFont();
static int32 getStaticTag() { return MKTAG('F', 'O', 'N', 'T'); }
int getPoolId() const override { return getId(); }
int32 getPoolTag() const override { return getStaticTag(); }
void load(const Common::String &filename, Common::SeekableReadStream *data);
const Common::String &getFilename() const { return _filename; }
virtual int32 getKernedHeight() const { return _kernedHeight; }
virtual int32 getBaseOffsetY() const { return _baseOffsetY; }
int32 getKernedHeight() const override { return _kernedHeight; }
int32 getFontWidth() const override { return getCharKernedWidth('w'); }
int32 getBaseOffsetY() const override { return _baseOffsetY; }
void render(Graphics::Surface &buf, const Common::String &currentLine, const Graphics::PixelFormat &pixelFormat, uint32 blackColor, uint32 color, uint32 colorKey) const override;
virtual int32 getCharBitmapWidth(unsigned char c) const { return _charHeaders[getCharIndex(c)].bitmapWidth; }
virtual int32 getCharBitmapHeight(unsigned char c) const { return _charHeaders[getCharIndex(c)].bitmapHeight; }
virtual int32 getCharKernedWidth(unsigned char c) const { return _charHeaders[getCharIndex(c)].kernedWidth; }
int32 getCharKernedWidth(unsigned char c) const override { return _charHeaders[getCharIndex(c)].kernedWidth; }
virtual int32 getCharStartingCol(unsigned char c) const { return _charHeaders[getCharIndex(c)].startingCol; }
virtual int32 getCharStartingLine(unsigned char c) const { return _charHeaders[getCharIndex(c)].startingLine; }
virtual int32 getCharOffset(unsigned char c) const { return _charHeaders[getCharIndex(c)].offset; }
@ -57,6 +86,7 @@ public:
const byte *getFontData() const { return _fontData; }
uint32 getDataSize() const { return _dataSize; }
bool is8Bit() const override { return true; }
virtual int getKernedStringLength(const Common::String &text) const;
virtual int getBitmapStringLength(const Common::String &text) const;
@ -88,21 +118,32 @@ private:
uint16 *_charIndex;
CharHeader *_charHeaders;
byte *_fontData;
Common::String _filename;
void *_userData;
};
class FontTTF : public Font {
class FontTTF : public Font, public PoolObject<FontTTF> {
public:
void loadTTF(const Common::String &filename, Common::SeekableReadStream *data, int size);
static int32 getStaticTag() { return MKTAG('T', 'T', 'F', ' '); }
int getPoolId() const override { return getId(); }
int32 getPoolTag() const override { return getStaticTag(); }
int32 getKernedHeight() const override { return _font->getFontHeight(); }
int32 getBaseOffsetY() const override { return 0; }
int32 getCharKernedWidth(unsigned char c) const override { return _font->getCharWidth(c); }
int32 getFontWidth() const override { return getCharKernedWidth('w'); }
int getKernedStringLength(const Common::String &text) const override { return _font->getStringWidth(text); }
void render(Graphics::Surface &buf, const Common::String &currentLine, const Graphics::PixelFormat &pixelFormat, uint32 blackColor, uint32 color, uint32 colorKey) const override;
bool is8Bit() const override { return false; }
void saveState(SaveGame *state) const;
void restoreState(SaveGame *state);
private:
Graphics::Font *_font;
int _size;
};
} // end of namespace Grim

View File

@ -1286,7 +1286,10 @@ struct FontUserData {
GLuint texture;
};
void GfxOpenGL::createFont(Font *font) {
void GfxOpenGL::createFont(Font *f) {
if (!f->is8Bit())
return;
BitmapFont *font = static_cast<BitmapFont *>(f);
const byte *bitmapData = font->getFontData();
uint dataSize = font->getDataSize();
@ -1372,10 +1375,12 @@ void GfxOpenGL::createFont(Font *font) {
}
void GfxOpenGL::destroyFont(Font *font) {
const FontUserData *data = (const FontUserData *)font->getUserData();
if (data) {
glDeleteTextures(1, &(data->texture));
delete data;
if (font->is8Bit()) {
const FontUserData *data = static_cast<const FontUserData *>(static_cast<const BitmapFont *>(font)->getUserData());
if (data) {
glDeleteTextures(1, &(data->texture));
delete data;
}
}
}
@ -1384,14 +1389,12 @@ struct TextObjectUserData {
};
void GfxOpenGL::createTextObject(TextObject *text) {
if (g_grim->getGameType() != GType_GRIM || !g_grim->isRemastered())
return;
#ifdef USE_FREETYPE2
//error("Could not get font userdata");
const Font *font = text->getFont();
const FontTTF *f = static_cast<const FontTTF *>(font);
Graphics::Font *gf = f->_font;
if (font->is8Bit())
return;
int numLines = text->getNumLines();
GLuint *texids = new GLuint[numLines];
glGenTextures(numLines, texids);
@ -1399,10 +1402,8 @@ void GfxOpenGL::createTextObject(TextObject *text) {
for (int i = 0; i < numLines; i++) {
Graphics::Surface surface;
int width = gf->getStringWidth(text->getLines()[i]);
int height = width;
surface.create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
gf->drawString(&surface, text->getLines()[i], 0, 0, width, 0xFFFFFFFF);
font->render(surface, text->getLines()[i], Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24),
0xFF000000, 0xFFFFFFFF, 0x00000000);
byte *bitmap = (byte *)surface.getPixels();
@ -1411,7 +1412,7 @@ void GfxOpenGL::createTextObject(TextObject *text) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface.w, surface.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
surface.free();
}
@ -1419,7 +1420,6 @@ void GfxOpenGL::createTextObject(TextObject *text) {
ud->_texids = texids;
text->setUserData(ud);
#endif
}
void GfxOpenGL::drawTextObject(const TextObject *text) {
@ -1442,23 +1442,15 @@ void GfxOpenGL::drawTextObject(const TextObject *text) {
glDepthMask(GL_FALSE);
const Color &color = text->getFGColor();
const Font *font = text->getFont();
const Font *f = text->getFont();
glColor3ub(color.getRed(), color.getGreen(), color.getBlue());
const FontUserData *userData = (const FontUserData *)font->getUserData();
if (!userData) {
if (g_grim->getGameType() != GType_GRIM || !g_grim->isRemastered())
error("Could not get font userdata");
#ifdef USE_FREETYPE2
const FontTTF *f = static_cast<const FontTTF *>(font);
Graphics::Font *gf = f->_font;
if (!f->is8Bit()) {
const TextObjectUserData *ud = (const TextObjectUserData *)text->getUserData();
int numLines = text->getNumLines();
for (int i = 0; i < numLines; ++i) {
float width = gf->getStringWidth(text->getLines()[i]);
float width = f->getKernedStringLength(text->getLines()[i]);
float height = width;
float x = text->getLineX(i);
@ -1498,10 +1490,13 @@ void GfxOpenGL::drawTextObject(const TextObject *text) {
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
#endif
return;
}
const BitmapFont *font = static_cast<const BitmapFont *>(f);
const FontUserData *userData = (const FontUserData *)font->getUserData();
if (!userData)
error("Could not get font userdata");
float sizeW = userData->size * _scaleW;
float sizeH = userData->size * _scaleH;
GLuint texture = userData->texture;
@ -1821,7 +1816,7 @@ void GfxOpenGL::loadEmergFont() {
_emergFont = glGenLists(128);
for (int i = 32; i < 128; i++) {
glNewList(_emergFont + i, GL_COMPILE);
glBitmap(8, 13, 0, 2, 10, 0, Font::emerFont[i - 32]);
glBitmap(8, 13, 0, 2, 10, 0, BitmapFont::emerFont[i - 32]);
glEndList();
}
}

View File

@ -1519,7 +1519,10 @@ void GfxOpenGLS::destroyBitmap(BitmapData *bitmap) {
}
}
void GfxOpenGLS::createFont(Font *font) {
void GfxOpenGLS::createFont(Font *f) {
if (!f->is8Bit())
error("non-8bit fonts are not supported in GL shaders renderer");
BitmapFont *font = static_cast<BitmapFont *>(f);
const byte *bitmapData = font->getFontData();
uint dataSize = font->getDataSize();
@ -1604,16 +1607,21 @@ void GfxOpenGLS::createFont(Font *font) {
}
void GfxOpenGLS::destroyFont(Font *font) {
const FontUserData *data = (const FontUserData *)font->getUserData();
if (data) {
glDeleteTextures(1, &(data->texture));
delete data;
if (font->is8Bit()) {
const FontUserData *data = static_cast<const FontUserData *>(static_cast<const BitmapFont *>(font)->getUserData());
if (data) {
glDeleteTextures(1, &(data->texture));
delete data;
}
}
}
void GfxOpenGLS::createTextObject(TextObject *text) {
const Color &color = text->getFGColor();
const Font *font = text->getFont();
const Font *f = text->getFont();
if (!f->is8Bit())
error("non-8bit fonts are not supported in GL shaders renderer");
const BitmapFont *font = static_cast<const BitmapFont *>(f);
const FontUserData *userData = (const FontUserData *)font->getUserData();
if (!userData)
@ -1860,7 +1868,7 @@ void GfxOpenGLS::loadEmergFont() {
int blockcol = c & 0xf;
for (int row = 0; row < 13; ++row) {
int base = 128 * (16 * blockrow + row) + 8 * blockcol;
uint8 val = Font::emerFont[c - 32][row];
uint8 val = BitmapFont::emerFont[c - 32][row];
atlas[base + 0] = (val & 0x80) ? 255 : 0;
atlas[base + 1] = (val & 0x40) ? 255 : 0;
atlas[base + 2] = (val & 0x20) ? 255 : 0;

View File

@ -1055,52 +1055,12 @@ void GfxTinyGL::createTextObject(TextObject *text) {
}
for (int j = 0; j < numLines; j++) {
const Common::String &currentLine = lines[j];
int width = font->getBitmapStringLength(currentLine) + 1;
int height = font->getStringHeight(currentLine) + 1;
uint8 *_textBitmap = new uint8[height * width]();
int startColumn = 0;
for (unsigned int d = 0; d < currentLine.size(); d++) {
int ch = currentLine[d];
int32 charBitmapWidth = font->getCharBitmapWidth(ch);
int8 fontRow = font->getCharStartingLine(ch) + font->getBaseOffsetY();
int8 fontCol = font->getCharStartingCol(ch);
for (int line = 0; line < font->getCharBitmapHeight(ch); line++) {
int lineOffset = ((fontRow + line) * width);
for (int bitmapCol = 0; bitmapCol < charBitmapWidth; bitmapCol++) {
int columnOffset = startColumn + fontCol + bitmapCol;
int fontOffset = (charBitmapWidth * line) + bitmapCol;
int8 pixel = font->getCharData(ch)[fontOffset];
assert(lineOffset + columnOffset < width*height);
if (pixel != 0)
_textBitmap[lineOffset + columnOffset] = pixel;
}
}
startColumn += font->getCharKernedWidth(ch);
}
Graphics::Surface buf;
buf.create(width, height, _pixelFormat);
uint8 *bitmapData = _textBitmap;
for (int iy = 0; iy < height; iy++) {
for (int ix = 0; ix < width; ix++, bitmapData++) {
byte pixel = *bitmapData;
if (pixel == 0x00) {
buf.setPixel(ix, iy, kKitmapColorkey);
} else if (pixel == 0x80) {
buf.setPixel(ix, iy, blackColor);
} else if (pixel == 0xFF) {
buf.setPixel(ix, iy, color);
}
}
}
font->render(buf, currentLine, _pixelFormat, blackColor, color, kKitmapColorkey);
userData[j].width = width;
userData[j].height = height;
userData[j].width = buf.w;
userData[j].height = buf.h;
userData[j].image = tglGenBlitImage();
tglUploadBlitImage(userData[j].image, buf, kKitmapColorkey, true);
userData[j].x = text->getLineX(j);
@ -1113,7 +1073,6 @@ void GfxTinyGL::createTextObject(TextObject *text) {
}
buf.free();
delete[] _textBitmap;
}
}
@ -1227,7 +1186,7 @@ void GfxTinyGL::loadEmergFont() {
uint32 colorTransparent = textureFormat.ARGBToColor(0, 255, 255, 255);
for (int i = 0; i < 96; i++) {
_emergFont[i] = tglGenBlitImage();
const uint8 *ptr = Font::emerFont[i];
const uint8 *ptr = BitmapFont::emerFont[i];
for (int py = 0; py < 13; py++) {
int line = ptr[12 - py];
for (int px = 0; px < 8; px++) {

View File

@ -242,7 +242,8 @@ void GrimEngine::clearPools() {
PrimitiveObject::getPool().deleteObjects();
TextObject::getPool().deleteObjects();
Bitmap::getPool().deleteObjects();
Font::getPool().deleteObjects();
BitmapFont::getPool().deleteObjects();
FontTTF::getPool().deleteObjects();
ObjectState::getPool().deleteObjects();
_currSet = nullptr;
@ -1187,7 +1188,10 @@ void GrimEngine::savegameRestore() {
Bitmap::getPool().restoreObjects(_savedState);
Debug::debug(Debug::Engine, "Bitmaps restored successfully.");
Font::getPool().restoreObjects(_savedState);
BitmapFont::getPool().restoreObjects(_savedState);
if (_savedState->saveMinorVersion() >= 28) {
FontTTF::getPool().restoreObjects(_savedState);
}
Debug::debug(Debug::Engine, "Fonts restored successfully.");
ObjectState::getPool().restoreObjects(_savedState);
@ -1270,7 +1274,7 @@ void GrimEngine::restoreGRIM() {
//TextObject stuff
_sayLineDefaults.setFGColor(_savedState->readColor());
_sayLineDefaults.setFont(Font::getPool().getObject(_savedState->readLESint32()));
_sayLineDefaults.setFont(Font::load(_savedState));
_sayLineDefaults.setHeight(_savedState->readLESint32());
_sayLineDefaults.setJustify(_savedState->readLESint32());
_sayLineDefaults.setWidth(_savedState->readLESint32());
@ -1359,7 +1363,8 @@ void GrimEngine::savegameSave() {
Bitmap::getPool().saveObjects(_savedState);
Debug::debug(Debug::Engine, "Bitmaps saved successfully.");
Font::getPool().saveObjects(_savedState);
BitmapFont::getPool().saveObjects(_savedState);
FontTTF::getPool().saveObjects(_savedState);
Debug::debug(Debug::Engine, "Fonts saved successfully.");
ObjectState::getPool().saveObjects(_savedState);
@ -1428,7 +1433,7 @@ void GrimEngine::saveGRIM() {
//TextObject stuff
_savedState->writeColor(_sayLineDefaults.getFGColor());
_savedState->writeLESint32(_sayLineDefaults.getFont()->getId());
Font::save(_sayLineDefaults.getFont(), _savedState);
_savedState->writeLESint32(_sayLineDefaults.getHeight());
_savedState->writeLESint32(_sayLineDefaults.getJustify());
_savedState->writeLESint32(_sayLineDefaults.getWidth());

View File

@ -373,8 +373,12 @@ TextObject *LuaBase::gettextobject(lua_Object obj) {
return TextObject::getPool().getObject(lua_getuserdata(obj));
}
Font *LuaBase::getfont(lua_Object obj) {
return Font::getPool().getObject(lua_getuserdata(obj));
Font *LuaBase::getfont(lua_Object fontObj) {
if (lua_tag(fontObj) == BitmapFont::getStaticTag())
return BitmapFont::getPool().getObject(lua_getuserdata(fontObj));
if (lua_tag(fontObj) == FontTTF::getStaticTag())
return FontTTF::getPool().getObject(lua_getuserdata(fontObj));
return nullptr;
}
Color LuaBase::getcolor(lua_Object obj) {
@ -511,23 +515,18 @@ void LuaBase::setTextObjectParams(TextObjectCommon *textObject, lua_Object table
if (keyObj) {
if (g_grim->getGameType() == GType_MONKEY4 && lua_isstring(keyObj)) {
const char *str = lua_getstring(keyObj);
Font *font = nullptr;
for (Font *f : Font::getPool()) {
if (f->getFilename() == str) {
font = f;
}
}
Font *font = Font::getByFileName(str);
if (!font) {
font = g_resourceloader->loadFont(str);
}
textObject->setFont(font);
} else if (lua_isuserdata(keyObj) && lua_tag(keyObj) == MKTAG('F','O','N','T')) {
} else if (lua_isuserdata(keyObj) && (lua_tag(keyObj) == BitmapFont::getStaticTag() || lua_tag(keyObj) == FontTTF::getStaticTag())) {
textObject->setFont(getfont(keyObj));
} else if (g_grim->getGameType() == GType_MONKEY4 && !textObject->getFont() && g_grim->getGamePlatform() == Common::kPlatformPS2) {
// HACK:
warning("HACK: No default font set for PS2-version, just picking one for now");
textObject->setFont(*Font::getPool().begin());
textObject->setFont(Font::getFirstFont());
}
}

View File

@ -724,7 +724,7 @@ void Lua_V1::LockFont() {
const char *fontName = lua_getstring(param1);
Font *result = g_resourceloader->loadFont(fontName);
if (result) {
lua_pushusertag(result->getId(), MKTAG('F','O','N','T'));
lua_pushusertag(result->getPoolId(), result->getPoolTag());
return;
}
}

View File

@ -44,14 +44,14 @@ void Lua_Remastered::WidescreenCorrectionFactor() {
void Lua_Remastered::GetFontDimensions() {
// Taken from Lua_v2 and modified
lua_Object fontObj = lua_getparam(1);
if (!lua_isuserdata(fontObj) || lua_tag(fontObj) != Font::getStaticTag())
if (!lua_isuserdata(fontObj))
return;
Font *font = Font::getPool().getObject(lua_getuserdata(fontObj));
Font *font = getfont(fontObj);
if (font) {
int32 h = font->getKernedHeight();
int32 w = font->getCharKernedWidth('w');
int32 w = font->getFontWidth();
lua_pushnumber(w);
lua_pushnumber(h);
} else {

View File

@ -394,7 +394,7 @@ Font *ResourceLoader::loadFont(const Common::String &filename) {
if (!stream)
error("Could not find font file %s", filename.c_str());
Font *result = new Font();
BitmapFont *result = new BitmapFont();
result->load(filename, stream);
delete stream;

View File

@ -34,7 +34,7 @@ namespace Grim {
#define SAVEGAME_FOOTERTAG 'ESAV'
uint SaveGame::SAVEGAME_MAJOR_VERSION = 22;
uint SaveGame::SAVEGAME_MINOR_VERSION = 27;
uint SaveGame::SAVEGAME_MINOR_VERSION = 28;
SaveGame *SaveGame::openForLoading(const Common::String &filename) {
Common::InSaveFile *inSaveFile = g_system->getSavefileManager()->openForLoading(filename);

View File

@ -87,11 +87,7 @@ void TextObject::saveState(SaveGame *state) const {
state->writeBool(_isSpeech);
state->writeLESint32(_elapsedTime);
if (_font) {
state->writeLESint32(_font->getId());
} else {
state->writeLESint32(-1);
}
Font::save(_font, state);
state->writeString(_textID);
@ -116,12 +112,7 @@ bool TextObject::restoreState(SaveGame *state) {
_isSpeech = state->readBool();
_elapsedTime = state->readLESint32();
int32 fontId = state->readLESint32();
if (fontId == -1) {
_font = nullptr;
} else {
_font = Font::getPool().getObject(fontId);
}
_font = Font::load(state);
_textID = state->readString();