mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
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:
parent
34db914a09
commit
829eab2f72
@ -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 {
|
||||
|
@ -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 ¤tLine,
|
||||
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 ¤tLine, 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},
|
||||
|
@ -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 ¤tLine, 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 ¤tLine, 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 ¤tLine, 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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1055,52 +1055,12 @@ void GfxTinyGL::createTextObject(TextObject *text) {
|
||||
}
|
||||
for (int j = 0; j < numLines; j++) {
|
||||
const Common::String ¤tLine = 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++) {
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user