Load and render ttf fonts

This commit is contained in:
Joel Teichroeb 2015-02-01 15:36:56 -08:00
parent 178b31822a
commit 6df76c20df
10 changed files with 145 additions and 21 deletions

View file

@ -22,6 +22,9 @@
#include "common/endian.h"
#include "graphics/fonts/ttf.h"
#include "graphics/font.h"
#include "engines/grim/debug.h"
#include "engines/grim/grim.h"
#include "engines/grim/savegame.h"
@ -82,6 +85,8 @@ void Font::load(const Common::String &filename, Common::SeekableReadStream *data
g_driver->createFont(this);
}
uint16 Font::getCharIndex(unsigned char c) const {
uint16 c2 = uint16(c);
@ -160,6 +165,12 @@ void Font::restoreState(SaveGame *state) {
delete stream;
}
void FontTTF::loadTTF(const Common::String &filename, Common::SeekableReadStream *data, int size) {
_font = Graphics::loadTTFFont(*data, size);
//f->
}
// Hardcoded default font for GUI, etc
const uint8 Font::emerFont[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},

View file

@ -25,6 +25,8 @@
#include "engines/grim/pool.h"
#include "graphics/font.h"
namespace Common {
class SeekableReadStream;
}
@ -42,23 +44,24 @@ public:
void load(const Common::String &filename, Common::SeekableReadStream *data);
const Common::String &getFilename() const { return _filename; }
int32 getKernedHeight() const { return _kernedHeight; }
int32 getBaseOffsetY() const { return _baseOffsetY; }
int32 getCharBitmapWidth(unsigned char c) const { return _charHeaders[getCharIndex(c)].bitmapWidth; }
int32 getCharBitmapHeight(unsigned char c) const { return _charHeaders[getCharIndex(c)].bitmapHeight; }
int32 getCharKernedWidth(unsigned char c) const { return _charHeaders[getCharIndex(c)].kernedWidth; }
int32 getCharStartingCol(unsigned char c) const { return _charHeaders[getCharIndex(c)].startingCol; }
int32 getCharStartingLine(unsigned char c) const { return _charHeaders[getCharIndex(c)].startingLine; }
int32 getCharOffset(unsigned char c) const { return _charHeaders[getCharIndex(c)].offset; }
virtual int32 getKernedHeight() const { return _kernedHeight; }
virtual int32 getBaseOffsetY() const { return _baseOffsetY; }
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; }
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; }
const byte *getCharData(unsigned char c) const { return _fontData + (_charHeaders[getCharIndex(c)].offset); }
const byte *getFontData() const { return _fontData; }
uint32 getDataSize() const { return _dataSize; }
int getKernedStringLength(const Common::String &text) const;
int getBitmapStringLength(const Common::String &text) const;
int getStringHeight(const Common::String &text) const;
virtual int getKernedStringLength(const Common::String &text) const;
virtual int getBitmapStringLength(const Common::String &text) const;
virtual int getStringHeight(const Common::String &text) const;
const void *getUserData() const { return _userData; }
void setUserData(void *data) { _userData = data; }
@ -90,6 +93,20 @@ private:
void *_userData;
};
class FontTTF : public Font
{
public:
void loadTTF(const Common::String &filename, Common::SeekableReadStream *data, int size);
int32 getKernedHeight() const override { return _font->getFontHeight(); }
int32 getBaseOffsetY() const override { return 0; }
int32 getCharKernedWidth(unsigned char c) const override { return _font->getCharWidth(c); }
int getKernedStringLength(const Common::String &text) const override { return _font->getStringWidth(text); }
Graphics::Font *_font;
};
} // end of namespace Grim
#endif

View file

@ -292,7 +292,10 @@ protected:
Texture _specialtyTextures[_numSpecialtyTextures];
static const int _gameHeight = 480;
static const int _gameWidth = 640;
static const int _globalHeight = 1080;
static const int _globalWidth = 1920;
float _scaleW, _scaleH;
float _globalScaleW, _globalScaleH;
int _screenWidth, _screenHeight;
bool _isFullscreen;
Shadow *_currentShadowArray;

View file

@ -138,6 +138,9 @@ byte *GfxOpenGL::setupScreen(int screenW, int screenH, bool fullscreen) {
_scaleW = _screenWidth / (float)_gameWidth;
_scaleH = _screenHeight / (float)_gameHeight;
_globalScaleW = _screenWidth / (float)_globalWidth;
_globalScaleH = _screenHeight / (float)_globalHeight;
_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
_useDepthShader = false;
_useDimShader = false;
@ -1456,8 +1459,76 @@ void GfxOpenGL::drawTextObject(const TextObject *text) {
glColor3ub(color.getRed(), color.getGreen(), color.getBlue());
const FontUserData *userData = (const FontUserData *)font->getUserData();
if (!userData)
error("Could not get font userdata");
if (!userData) {
//error("Could not get font userdata");
const FontTTF *f = static_cast<const FontTTF *>(font);
Graphics::Font *gf = f->_font;
Graphics::Surface surface;
int height = 1024;
int width = 1024;
surface.create(height, width, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
gf->drawString(&surface, text->getLines()[0], 0, 0, 1024, 0xFFFFFFFF);
byte *bitmap = (byte *)surface.getPixels();
GLuint texid;
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
float x = text->getX();
float y = text->getY();
if (!text->isGlobal()) {
x -= gf->getStringWidth(text->getLines()[0]);
x *= _globalScaleW;
y *= _globalScaleH;
width *= _globalScaleW;
height *= _globalScaleH;
} else {
x *= _scaleW;
y *= _scaleH;
width *= _scaleW;
height *= _scaleH;
}
glBindTexture(GL_TEXTURE_2D, texid);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(x, y);
glTexCoord2f(1.0f, 0.0f);
glVertex2f((x + width), y);
glTexCoord2f(1.0f, 1.0f);
glVertex2f((x + width), (y + height));
glTexCoord2f(0.0f, 1.0f);
glVertex2f(x, (y + height));
glEnd();
glDeleteTextures(1, &texid);
surface.free();
glColor3f(1, 1, 1);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
return;
}
float sizeW = userData->size * _scaleW;
float sizeH = userData->size * _scaleH;
GLuint texture = userData->texture;
@ -1473,9 +1544,8 @@ void GfxOpenGL::drawTextObject(const TextObject *text) {
if (g_grim->getGameType() == GType_GRIM)
w += font->getBaseOffsetY();
float z = x + font->getCharStartingCol(character);
// TODO: We can't scale in the remastered version
//z *= _scaleW;
//w *= _scaleH;
z *= _scaleW;
w *= _scaleH;
glBindTexture(GL_TEXTURE_2D, texture);
float width = 1 / 16.f;
float cx = ((character - 1) % 16) / 16.0f;

View file

@ -693,7 +693,7 @@ void Lua_V1::GetFontDimensions() {
Font *font = Font::getPool().getObject(lua_getuserdata(fontObj));
if (font) {
int32 h = font->getBaseOffsetY();
int32 h = font->getKernedHeight();
int32 w = font->getCharKernedWidth('w');
lua_pushnumber(w);
lua_pushnumber(h);

View file

@ -361,7 +361,6 @@ void Lua_V1::ChangePrimitive() {
if (lua_isnumber(height))
/*y = (int)*/lua_getnumber(height);
// TODO pmodify->setSize(x, y);
assert(0);
}
}

View file

@ -132,8 +132,8 @@ void Lua_V1::GetTextObjectDimensions() {
TextObject *textObject = gettextobject(textObj);
lua_pushnumber(textObject->getBitmapWidth());
lua_pushnumber(textObject->getBitmapHeight());
lua_pushnumber(1);
lua_pushnumber(1);
lua_pushnumber(textObject->getX());
lua_pushnumber(textObject->getY());
}
}

View file

@ -361,6 +361,27 @@ Costume *ResourceLoader::loadCostume(const Common::String &filename, Actor *owne
Font *ResourceLoader::loadFont(const Common::String &filename) {
Common::SeekableReadStream *stream;
Common::String name = "FontsHD/" + filename + ".txt";
stream = openNewStreamFile(name, true);
if (stream) {
Common::String line = stream->readLine();
Common::String font;
Common::String size;
for (int i = 0; i < line.size(); ++i) {
if (line[i] == ' ') {
font = "FontsHD/" + Common::String(line.c_str(), i);
size = Common::String(line.c_str() + i + 1, line.size() - i - 2);
}
}
int s = atoi(size.c_str());
delete stream;
stream = openNewStreamFile(font.c_str(), true);
FontTTF *result = new FontTTF();
result->loadTTF(font, stream, s);
return result;
}
stream = openNewStreamFile(filename.c_str(), true);
if (!stream)
error("Could not find font file %s", filename.c_str());

View file

@ -47,7 +47,7 @@ void TextObjectCommon::setLayer(int layer) {
TextObject::TextObject() :
TextObjectCommon(), _numberLines(1), _textID(""), _elapsedTime(0),
_maxLineWidth(0), _lines(nullptr), _userData(nullptr), _created(false),
_blastDraw(false), _isSpeech(false), _stackLevel(0) {
_blastDraw(false), _isSpeech(false), _stackLevel(0), _global(false) {
}
TextObject::~TextObject() {

View file

@ -101,6 +101,8 @@ public:
void setBlastDraw() { _blastDraw = true; }
bool isBlastDraw() { return _blastDraw; }
bool isGlobal() const { return _global; }
const void *getUserData() const { return _userData; }
void setUserData(void *data) { _userData = data; }
@ -143,6 +145,7 @@ protected:
bool _blastDraw;
bool _isSpeech;
bool _created;
bool _global;
int _stackLevel;
};