Initial commit
This commit is contained in:
140
engines/wintermute/base/font/base_font.cpp
Normal file
140
engines/wintermute/base/font/base_font.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
#include "engines/wintermute/base/font/base_font_bitmap.h"
|
||||
#include "engines/wintermute/base/font/base_font_truetype.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_PERSISTENT(BaseFont, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
BaseFont::BaseFont(BaseGame *inGame) : BaseObject(inGame) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
BaseFont::~BaseFont() {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void BaseFont::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int BaseFont::getTextHeight(const byte *text, int width) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int BaseFont::getTextWidth(const byte *text, int maxLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFont::getLetterHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFont::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseObject::persist(persistMgr);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFont *BaseFont::createFromFile(BaseGame *game, const char *filename) {
|
||||
if (isTrueType(game, filename)) {
|
||||
BaseFontTT *font = new BaseFontTT(game);
|
||||
if (font) {
|
||||
if (DID_FAIL(font->loadFile(filename))) {
|
||||
delete font;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return font;
|
||||
} else {
|
||||
BaseFontBitmap *font = new BaseFontBitmap(game);
|
||||
if (font) {
|
||||
if (DID_FAIL(font->loadFile(filename))) {
|
||||
delete font;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TOKEN_DEF_START
|
||||
TOKEN_DEF(FONT)
|
||||
TOKEN_DEF(TTFONT)
|
||||
TOKEN_DEF_END
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFont::isTrueType(BaseGame *game, const char *filename) {
|
||||
TOKEN_TABLE_START(commands)
|
||||
TOKEN_TABLE(FONT)
|
||||
TOKEN_TABLE(TTFONT)
|
||||
TOKEN_TABLE_END
|
||||
|
||||
|
||||
char *buffer = (char *)game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *workBuffer = buffer;
|
||||
|
||||
char *params;
|
||||
BaseParser parser(game);
|
||||
|
||||
bool ret = false;
|
||||
if (parser.getCommand(&workBuffer, commands, ¶ms) == TOKEN_TTFONT) {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
60
engines/wintermute/base/font/base_font.h
Normal file
60
engines/wintermute/base/font/base_font.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_BASE_FONT_H
|
||||
#define WINTERMUTE_BASE_FONT_H
|
||||
|
||||
#include "engines/wintermute/base/base_object.h"
|
||||
|
||||
#define NUM_CHARACTERS 256
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class BaseFont : public BaseObject {
|
||||
public:
|
||||
DECLARE_PERSISTENT(BaseFont, BaseObject)
|
||||
virtual int getTextWidth(const byte *text, int maxLength = -1);
|
||||
virtual int getTextHeight(const byte *text, int width);
|
||||
virtual void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1);
|
||||
virtual int getLetterHeight();
|
||||
|
||||
virtual void initLoop() {}
|
||||
virtual void afterLoad() {}
|
||||
BaseFont(BaseGame *inGame);
|
||||
~BaseFont() override;
|
||||
|
||||
static BaseFont *createFromFile(BaseGame *game, const char *filename);
|
||||
|
||||
private:
|
||||
//bool loadBuffer(char *buffer);
|
||||
//bool loadFile(const char* Filename);
|
||||
static bool isTrueType(BaseGame *game, const char *filename);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
628
engines/wintermute/base/font/base_font_bitmap.cpp
Normal file
628
engines/wintermute/base/font/base_font_bitmap.cpp
Normal file
@@ -0,0 +1,628 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/font/base_font_bitmap.h"
|
||||
#include "engines/wintermute/utils/string_util.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_frame.h"
|
||||
#include "engines/wintermute/base/gfx/base_surface.h"
|
||||
#include "engines/wintermute/base/gfx/base_renderer.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_sub_frame.h"
|
||||
#include "engines/wintermute/base/base_frame.h"
|
||||
#include "engines/wintermute/base/base_sprite.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_PERSISTENT(BaseFontBitmap, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
BaseFontBitmap::BaseFontBitmap(BaseGame *inGame) : BaseFont(inGame) {
|
||||
_subframe = nullptr;
|
||||
_sprite = nullptr;
|
||||
_widthsFrame = 0;
|
||||
memset(_widths, 0, NUM_CHARACTERS);
|
||||
_tileWidth = _tileHeight = _numColumns = 0;
|
||||
_fontextFix = false;
|
||||
_freezable = false;
|
||||
_wholeCell = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
BaseFontBitmap::~BaseFontBitmap() {
|
||||
SAFE_DELETE(_subframe);
|
||||
SAFE_DELETE(_sprite);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void BaseFontBitmap::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
|
||||
textHeightDraw(text, x, y, width, align, true, maxHeight, maxLength);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int BaseFontBitmap::getTextHeight(const byte *text, int width) {
|
||||
return textHeightDraw(text, 0, 0, width, TAL_LEFT, false);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int BaseFontBitmap::getTextWidth(const byte *text, int maxLength) {
|
||||
AnsiString str;
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
WideString wstr = StringUtil::utf8ToWide(Utf8String((const char *)text));
|
||||
str = StringUtil::wideToAnsi(wstr);
|
||||
} else {
|
||||
str = AnsiString((const char *)text);
|
||||
}
|
||||
|
||||
if (maxLength >= 0 && (int)str.size() > maxLength) {
|
||||
str = Common::String(str.c_str(), (uint32)maxLength);
|
||||
}
|
||||
//str.substr(0, maxLength); // TODO: Remove
|
||||
|
||||
int textWidth = 0;
|
||||
for (int i = 0; (uint32)i < str.size(); i++) {
|
||||
textWidth += getCharWidth((byte)str[i]);
|
||||
}
|
||||
|
||||
return textWidth;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int BaseFontBitmap::textHeightDraw(const byte *text, int x, int y, int width, TTextAlign align, bool draw, int maxHeight, int maxLength) {
|
||||
if (maxLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (text == nullptr || text[0] == '\0') {
|
||||
return _tileHeight;
|
||||
}
|
||||
|
||||
AnsiString str;
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
WideString wstr = StringUtil::utf8ToWide(Utf8String((const char *)text));
|
||||
str = StringUtil::wideToAnsi(wstr);
|
||||
} else {
|
||||
str = AnsiString((const char *)text);
|
||||
}
|
||||
if (str.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lineLength = 0;
|
||||
int realLength = 0;
|
||||
int numLines = 0;
|
||||
|
||||
int i;
|
||||
|
||||
int index = -1;
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
int last_end = 0;
|
||||
|
||||
bool done = false;
|
||||
bool newLine = false;
|
||||
bool longLine = false;
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
bool minimizeSpacing = BaseEngine::instance().isFoxTail();
|
||||
#endif
|
||||
|
||||
if (draw) {
|
||||
_game->_renderer->startSpriteBatch();
|
||||
}
|
||||
|
||||
while (!done) {
|
||||
if (maxHeight > 0 && (numLines + 1) * _tileHeight > maxHeight) {
|
||||
if (draw) {
|
||||
_game->_renderer->endSpriteBatch();
|
||||
}
|
||||
return numLines * _tileHeight;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (str[index] == ' ' && (maxHeight < 0 || maxHeight / _tileHeight > 1)) {
|
||||
end = index - 1;
|
||||
realLength = lineLength;
|
||||
}
|
||||
|
||||
if (str[index] == '\n') {
|
||||
end = index - 1;
|
||||
realLength = lineLength;
|
||||
newLine = true;
|
||||
}
|
||||
|
||||
if (lineLength + getCharWidth(str[index]) > width && last_end == end) {
|
||||
end = index - 1;
|
||||
realLength = lineLength;
|
||||
newLine = true;
|
||||
longLine = true;
|
||||
}
|
||||
|
||||
if ((int)str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) {
|
||||
done = true;
|
||||
if (!newLine) {
|
||||
end = index;
|
||||
lineLength += getCharWidth(str[index]);
|
||||
realLength = lineLength;
|
||||
}
|
||||
} else {
|
||||
lineLength += getCharWidth(str[index]);
|
||||
}
|
||||
|
||||
if ((lineLength > width) || done || newLine) {
|
||||
if (end < 0) {
|
||||
done = true;
|
||||
}
|
||||
int startX = x;
|
||||
switch (align) {
|
||||
case TAL_CENTER:
|
||||
startX = x + (width - realLength) / 2;
|
||||
break;
|
||||
case TAL_RIGHT:
|
||||
startX = x + width - realLength;
|
||||
break;
|
||||
case TAL_LEFT:
|
||||
startX = x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (i = start; i < end + 1; i++) {
|
||||
if (draw) {
|
||||
drawChar(str[i], startX, y);
|
||||
}
|
||||
startX += getCharWidth(str[i]);
|
||||
}
|
||||
y += _tileHeight;
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
if (minimizeSpacing) {
|
||||
y -= 3;
|
||||
}
|
||||
#endif
|
||||
last_end = end;
|
||||
if (longLine) {
|
||||
end--;
|
||||
}
|
||||
start = end + 2;
|
||||
index = end + 1;
|
||||
lineLength = 0;
|
||||
newLine = false;
|
||||
longLine = false;
|
||||
numLines++;
|
||||
}
|
||||
}
|
||||
|
||||
if (draw) {
|
||||
_game->_renderer->endSpriteBatch();
|
||||
}
|
||||
|
||||
return numLines * _tileHeight;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void BaseFontBitmap::drawChar(byte c, int x, int y) {
|
||||
if (_fontextFix) {
|
||||
c--;
|
||||
}
|
||||
|
||||
int row, col;
|
||||
|
||||
row = c / _numColumns;
|
||||
col = c % _numColumns;
|
||||
|
||||
Common::Rect32 rect;
|
||||
/* l t r b */
|
||||
int tileWidth;
|
||||
if (_wholeCell) {
|
||||
tileWidth = _tileWidth;
|
||||
} else {
|
||||
tileWidth = _widths[c];
|
||||
}
|
||||
|
||||
BasePlatform::setRect(&rect, col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1) * _tileHeight);
|
||||
bool handled = false;
|
||||
if (_sprite) {
|
||||
_sprite->getCurrentFrame();
|
||||
if (_sprite->_currentFrame >= 0 && _sprite->_currentFrame < _sprite->_frames.getSize() && _sprite->_frames[_sprite->_currentFrame]) {
|
||||
if (_sprite->_frames[_sprite->_currentFrame]->_subframes.getSize() > 0) {
|
||||
_sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if (!handled && _subframe) {
|
||||
_subframe->_surface->displayTrans(x, y, rect, _subframe->_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontBitmap::loadFile(const char *filename) {
|
||||
char *buffer = (char *)_game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "BaseFontBitmap::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(ret = loadBuffer(buffer))) {
|
||||
_game->LOG(0, "Error parsing FONT file '%s'", filename);
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
TOKEN_DEF_START
|
||||
TOKEN_DEF(FONTEXT_FIX)
|
||||
TOKEN_DEF(FONT)
|
||||
TOKEN_DEF(IMAGE)
|
||||
TOKEN_DEF(TRANSPARENT)
|
||||
TOKEN_DEF(COLUMNS)
|
||||
TOKEN_DEF(TILE_WIDTH)
|
||||
TOKEN_DEF(TILE_HEIGHT)
|
||||
TOKEN_DEF(DEFAULT_WIDTH)
|
||||
TOKEN_DEF(WIDTHS)
|
||||
TOKEN_DEF(AUTO_WIDTH)
|
||||
TOKEN_DEF(SPACE_WIDTH)
|
||||
TOKEN_DEF(EXPAND_WIDTH)
|
||||
TOKEN_DEF(EDITOR_PROPERTY)
|
||||
TOKEN_DEF(SPRITE)
|
||||
TOKEN_DEF(WIDTHS_FRAME)
|
||||
TOKEN_DEF(PAINT_WHOLE_CELL)
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
TOKEN_DEF(COLOR)
|
||||
#endif
|
||||
TOKEN_DEF_END
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontBitmap::loadBuffer(char *buffer) {
|
||||
TOKEN_TABLE_START(commands)
|
||||
TOKEN_TABLE(FONTEXT_FIX)
|
||||
TOKEN_TABLE(FONT)
|
||||
TOKEN_TABLE(IMAGE)
|
||||
TOKEN_TABLE(TRANSPARENT)
|
||||
TOKEN_TABLE(COLUMNS)
|
||||
TOKEN_TABLE(TILE_WIDTH)
|
||||
TOKEN_TABLE(TILE_HEIGHT)
|
||||
TOKEN_TABLE(DEFAULT_WIDTH)
|
||||
TOKEN_TABLE(WIDTHS)
|
||||
TOKEN_TABLE(AUTO_WIDTH)
|
||||
TOKEN_TABLE(SPACE_WIDTH)
|
||||
TOKEN_TABLE(EXPAND_WIDTH)
|
||||
TOKEN_TABLE(EDITOR_PROPERTY)
|
||||
TOKEN_TABLE(SPRITE)
|
||||
TOKEN_TABLE(WIDTHS_FRAME)
|
||||
TOKEN_TABLE(PAINT_WHOLE_CELL)
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
TOKEN_TABLE(COLOR)
|
||||
#endif
|
||||
TOKEN_TABLE_END
|
||||
|
||||
char *params;
|
||||
int cmd;
|
||||
BaseParser parser(_game);
|
||||
|
||||
if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_FONT) {
|
||||
_game->LOG(0, "'FONT' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
|
||||
int widths[300];
|
||||
int num = 0, defaultWidth = 8;
|
||||
int lastWidth = 0;
|
||||
int i;
|
||||
int r = 255, g = 255, b = 255;
|
||||
bool customTrans = false;
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
int ar = 255, ag = 255, ab = 255;
|
||||
bool customAlpha = false;
|
||||
#endif
|
||||
char *surfaceFile = nullptr;
|
||||
char *spriteFile = nullptr;
|
||||
|
||||
bool autoWidth = false;
|
||||
int spaceWidth = 0;
|
||||
int expandWidth = 0;
|
||||
|
||||
while ((cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
|
||||
switch (cmd) {
|
||||
case TOKEN_IMAGE:
|
||||
surfaceFile = params;
|
||||
break;
|
||||
|
||||
case TOKEN_SPRITE:
|
||||
spriteFile = params;
|
||||
break;
|
||||
|
||||
case TOKEN_TRANSPARENT:
|
||||
parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
|
||||
customTrans = true;
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
case TOKEN_COLOR:
|
||||
parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
|
||||
customAlpha = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TOKEN_WIDTHS:
|
||||
parser.scanStr(params, "%D", widths, &num);
|
||||
for (i = 0; lastWidth < NUM_CHARACTERS && num > 0; lastWidth++, num--, i++) {
|
||||
_widths[lastWidth] = (byte)widths[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_DEFAULT_WIDTH:
|
||||
parser.scanStr(params, "%d", &defaultWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_WIDTHS_FRAME:
|
||||
parser.scanStr(params, "%d", &_widthsFrame);
|
||||
break;
|
||||
|
||||
case TOKEN_COLUMNS:
|
||||
parser.scanStr(params, "%d", &_numColumns);
|
||||
break;
|
||||
|
||||
case TOKEN_TILE_WIDTH:
|
||||
parser.scanStr(params, "%d", &_tileWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_TILE_HEIGHT:
|
||||
parser.scanStr(params, "%d", &_tileHeight);
|
||||
break;
|
||||
|
||||
case TOKEN_AUTO_WIDTH:
|
||||
parser.scanStr(params, "%b", &autoWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_FONTEXT_FIX:
|
||||
parser.scanStr(params, "%b", &_fontextFix);
|
||||
break;
|
||||
|
||||
case TOKEN_PAINT_WHOLE_CELL:
|
||||
parser.scanStr(params, "%b", &_wholeCell);
|
||||
break;
|
||||
|
||||
case TOKEN_SPACE_WIDTH:
|
||||
parser.scanStr(params, "%d", &spaceWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_EXPAND_WIDTH:
|
||||
parser.scanStr(params, "%d", &expandWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_EDITOR_PROPERTY:
|
||||
parseEditorProperty(params, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in FONT definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
if (spriteFile != nullptr) {
|
||||
SAFE_DELETE(_sprite);
|
||||
_sprite = new BaseSprite(_game, this);
|
||||
if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) {
|
||||
SAFE_DELETE(_sprite);
|
||||
}
|
||||
}
|
||||
|
||||
if (surfaceFile != nullptr && !_sprite) {
|
||||
_subframe = new BaseSubFrame(_game);
|
||||
if (customTrans) {
|
||||
_subframe->setSurface(surfaceFile, false, r, g, b);
|
||||
} else {
|
||||
_subframe->setSurface(surfaceFile);
|
||||
}
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
if (customAlpha) {
|
||||
_subframe->_alpha = BYTETORGBA(ar, ag, ab, 255);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (((_subframe == nullptr || _subframe->_surface == nullptr) && _sprite == nullptr) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) {
|
||||
_game->LOG(0, "Incomplete font definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
if (autoWidth) {
|
||||
// calculate characters width
|
||||
getWidths();
|
||||
|
||||
// do we need to modify widths?
|
||||
if (expandWidth != 0) {
|
||||
for (i = 0; i < NUM_CHARACTERS; i++) {
|
||||
int newWidth = (int)_widths[i] + expandWidth;
|
||||
if (newWidth < 0) {
|
||||
newWidth = 0;
|
||||
}
|
||||
|
||||
_widths[i] = (byte)newWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// handle space character
|
||||
uint32 spaceChar = ' ';
|
||||
if (_fontextFix) {
|
||||
spaceChar--;
|
||||
}
|
||||
|
||||
if (spaceWidth != 0) {
|
||||
_widths[spaceChar] = spaceWidth;
|
||||
} else {
|
||||
if (_widths[spaceChar] == expandWidth || _widths[spaceChar] == 0) {
|
||||
_widths[spaceChar] = (_widths[(uint32)'m'] + _widths[(uint32)'i']) / 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = lastWidth; i < NUM_CHARACTERS; i++) {
|
||||
_widths[i] = defaultWidth;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
if (BaseEngine::instance().isFoxTail()) {
|
||||
for (i = lastWidth; i < NUM_CHARACTERS; i++) {
|
||||
_widths[i]--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontBitmap::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseFont::persist(persistMgr);
|
||||
persistMgr->transferSint32(TMEMBER(_numColumns));
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_subframe));
|
||||
persistMgr->transferSint32(TMEMBER(_tileHeight));
|
||||
persistMgr->transferSint32(TMEMBER(_tileWidth));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_sprite));
|
||||
persistMgr->transferSint32(TMEMBER(_widthsFrame));
|
||||
|
||||
if (persistMgr->getIsSaving()) {
|
||||
persistMgr->putBytes(_widths, sizeof(_widths));
|
||||
} else {
|
||||
persistMgr->getBytes(_widths, sizeof(_widths));
|
||||
}
|
||||
|
||||
|
||||
persistMgr->transferBool(TMEMBER(_fontextFix));
|
||||
persistMgr->transferBool(TMEMBER(_wholeCell));
|
||||
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFontBitmap::getCharWidth(byte index) {
|
||||
if (_fontextFix) {
|
||||
index--;
|
||||
}
|
||||
return _widths[index];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontBitmap::getWidths() {
|
||||
BaseSurface *surf = nullptr;
|
||||
|
||||
if (_sprite) {
|
||||
if (_widthsFrame >= 0 && _widthsFrame < _sprite->_frames.getSize()) {
|
||||
if (_sprite->_frames[_widthsFrame] && _sprite->_frames[_widthsFrame]->_subframes.getSize() > 0) {
|
||||
surf = _sprite->_frames[_widthsFrame]->_subframes[0]->_surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surf == nullptr && _subframe) {
|
||||
surf = _subframe->_surface;
|
||||
}
|
||||
if (!surf || DID_FAIL(surf->startPixelOp())) {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < NUM_CHARACTERS; i++) {
|
||||
int xxx = (i % _numColumns) * _tileWidth;
|
||||
int yyy = (i / _numColumns) * _tileHeight;
|
||||
|
||||
|
||||
int minCol = -1;
|
||||
for (int row = 0; row < _tileHeight; row++) {
|
||||
for (int col = _tileWidth - 1; col >= minCol + 1; col--) {
|
||||
if (xxx + col < 0 || xxx + col >= surf->getWidth() || yyy + row < 0 || yyy + row >= surf->getHeight()) {
|
||||
continue;
|
||||
}
|
||||
if (!surf->isTransparentAtLite(xxx + col, yyy + row)) {
|
||||
//min_col = col;
|
||||
minCol = MAX(col, minCol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (minCol == _tileWidth - 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_widths[i] = minCol + 1;
|
||||
}
|
||||
surf->endPixelOp();
|
||||
/*
|
||||
_game->LOG(0, "----- %s ------", _filename);
|
||||
for(int j=0; j<16; j++)
|
||||
{
|
||||
_game->LOG(0, "%02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d", _widths[j*16+0], _widths[j*16+1], _widths[j*16+2], _widths[j*16+3], _widths[j*16+4], _widths[j*16+5], _widths[j*16+6], _widths[j*16+7], _widths[j*16+8], _widths[j*16+9], _widths[j*16+10], _widths[j*16+11], _widths[j*16+12], _widths[j*16+13], _widths[j*16+14], _widths[j*16+15]);
|
||||
}
|
||||
*/
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFontBitmap::getLetterHeight() {
|
||||
return _tileHeight;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
70
engines/wintermute/base/font/base_font_bitmap.h
Normal file
70
engines/wintermute/base/font/base_font_bitmap.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_BASE_FONTBITMAP_H
|
||||
#define WINTERMUTE_BASE_FONTBITMAP_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class BaseSubFrame;
|
||||
class BaseFontBitmap : public BaseFont {
|
||||
public:
|
||||
DECLARE_PERSISTENT(BaseFontBitmap, BaseFont)
|
||||
bool loadBuffer(char *buffer);
|
||||
bool loadFile(const char *filename);
|
||||
int getTextWidth(const byte *text, int maxLength = -1) override;
|
||||
int getTextHeight(const byte *text, int width) override;
|
||||
void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1) override;
|
||||
int getLetterHeight() override;
|
||||
|
||||
BaseFontBitmap(BaseGame *inGame);
|
||||
~BaseFontBitmap() override;
|
||||
|
||||
bool getWidths();
|
||||
BaseSprite *_sprite;
|
||||
int32 _widthsFrame;
|
||||
bool _fontextFix;
|
||||
int32 _numColumns;
|
||||
int32 _tileHeight;
|
||||
int32 _tileWidth;
|
||||
byte _widths[NUM_CHARACTERS];
|
||||
BaseSubFrame *_subframe;
|
||||
bool _wholeCell;
|
||||
|
||||
private:
|
||||
int getCharWidth(byte index);
|
||||
void drawChar(byte c, int x, int y);
|
||||
|
||||
int textHeightDraw(const byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int maxLength = -1);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
139
engines/wintermute/base/font/base_font_storage.cpp
Normal file
139
engines/wintermute/base/font/base_font_storage.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/font/base_font_storage.h"
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_PERSISTENT(BaseFontStorage, true)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFontStorage::BaseFontStorage(BaseGame *inGame) : BaseClass(inGame) {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFontStorage::~BaseFontStorage() {
|
||||
cleanup(true);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontStorage::cleanup(bool warn) {
|
||||
for (int32 i = 0; i < _fonts.getSize(); i++) {
|
||||
if (warn)
|
||||
_game->LOG(0, "Removing orphan font '%s'", _fonts[i]->_filename);
|
||||
delete _fonts[i];
|
||||
}
|
||||
_fonts.removeAll();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontStorage::initLoop() {
|
||||
for (int32 i = 0; i < _fonts.getSize(); i++) {
|
||||
_fonts[i]->initLoop();
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFont *BaseFontStorage::addFont(const char *filename) {
|
||||
if (!filename) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < _fonts.getSize(); i++) {
|
||||
if (scumm_stricmp(_fonts[i]->_filename, filename) == 0) {
|
||||
_fonts[i]->_refCount++;
|
||||
return _fonts[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BaseFont* font = new BaseFont(_game);
|
||||
if (!font) return nullptr;
|
||||
|
||||
if (DID_FAIL(font->loadFile(filename))) {
|
||||
delete font;
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
font->_refCount = 1;
|
||||
_fonts.add(font);
|
||||
return font;
|
||||
}
|
||||
*/
|
||||
BaseFont *font = BaseFont::createFromFile(_game, filename);
|
||||
if (font) {
|
||||
font->_refCount = 1;
|
||||
_fonts.add(font);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontStorage::removeFont(BaseFont *font) {
|
||||
if (!font) {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < _fonts.getSize(); i++) {
|
||||
if (_fonts[i] == font) {
|
||||
_fonts[i]->_refCount--;
|
||||
if (_fonts[i]->_refCount <= 0) {
|
||||
delete _fonts[i];
|
||||
_fonts.removeAt(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontStorage::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
cleanup(false);
|
||||
}
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_game));
|
||||
_fonts.persist(persistMgr);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
55
engines/wintermute/base/font/base_font_storage.h
Normal file
55
engines/wintermute/base/font/base_font_storage.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_BASE_FONTSTORAGE_H
|
||||
#define WINTERMUTE_BASE_FONTSTORAGE_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
#include "engines/wintermute/coll_templ.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class BaseFont;
|
||||
|
||||
class BaseFontStorage : public BaseClass {
|
||||
public:
|
||||
DECLARE_PERSISTENT(BaseFontStorage, BaseClass)
|
||||
bool cleanup(bool warn = false);
|
||||
bool removeFont(BaseFont *font);
|
||||
BaseFont *addFont(const char *filename);
|
||||
BaseFontStorage(BaseGame *inGame);
|
||||
~BaseFontStorage() override;
|
||||
BaseArray<BaseFont *> _fonts;
|
||||
|
||||
bool initLoop();
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
629
engines/wintermute/base/font/base_font_truetype.cpp
Normal file
629
engines/wintermute/base/font/base_font_truetype.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/font/base_font_truetype.h"
|
||||
#include "engines/wintermute/utils/string_util.h"
|
||||
#include "engines/wintermute/base/gfx/base_renderer.h"
|
||||
#include "engines/wintermute/base/gfx/base_surface.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/wintermute.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
#include "graphics/fonts/ttf.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
#include "common/compression/unzip.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(BaseFontTT, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFontTT::BaseFontTT(BaseGame *inGame) : BaseFont(inGame) {
|
||||
_fontHeight = 12;
|
||||
_isBold = _isItalic = _isUnderline = _isStriked = false;
|
||||
_charset = CHARSET_ANSI;
|
||||
|
||||
_fontFile = nullptr;
|
||||
_font = nullptr;
|
||||
_fallbackFont = nullptr;
|
||||
_deletableFont = nullptr;
|
||||
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
_cachedTexts[i] = nullptr;
|
||||
}
|
||||
|
||||
_lineHeight = 0;
|
||||
_maxCharWidth = _maxCharHeight = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseFontTT::~BaseFontTT() {
|
||||
clearCache();
|
||||
|
||||
for (int32 i = 0; i < _layers.getSize(); i++) {
|
||||
delete _layers[i];
|
||||
}
|
||||
_layers.removeAll();
|
||||
|
||||
SAFE_DELETE_ARRAY(_fontFile);
|
||||
|
||||
SAFE_DELETE(_deletableFont);
|
||||
|
||||
_font = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseFontTT::clearCache() {
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
if (_cachedTexts[i]) {
|
||||
delete _cachedTexts[i];
|
||||
}
|
||||
_cachedTexts[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseFontTT::initLoop() {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFontTT::getTextWidth(const byte *text, int maxLength) {
|
||||
WideString textStr;
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
textStr = StringUtil::utf8ToWide((const char *)text);
|
||||
} else {
|
||||
textStr = StringUtil::ansiToWide((const char *)text, _charset);
|
||||
}
|
||||
|
||||
if (maxLength >= 0 && (int)textStr.size() > maxLength) {
|
||||
textStr = textStr.substr(0, (uint32)maxLength);
|
||||
}
|
||||
//text = text.substr(0, MaxLength); // TODO: Remove
|
||||
|
||||
int textWidth, textHeight;
|
||||
measureText(textStr, -1, -1, textWidth, textHeight);
|
||||
|
||||
return textWidth;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFontTT::getTextHeight(const byte *text, int width) {
|
||||
WideString textStr;
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
textStr = StringUtil::utf8ToWide((const char *)text);
|
||||
} else {
|
||||
textStr = StringUtil::ansiToWide((const char *)text, _charset);
|
||||
}
|
||||
|
||||
|
||||
int textWidth, textHeight;
|
||||
measureText(textStr, width, -1, textWidth, textHeight);
|
||||
|
||||
return textHeight;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
|
||||
if (text == nullptr || strcmp((const char *)text, "") == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
WideString textStr;
|
||||
|
||||
// TODO: Why do we still insist on Widestrings everywhere?
|
||||
// HACK: J.U.L.I.A. uses CP1252, we need to fix that,
|
||||
// And we still don't have any UTF8-support.
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
textStr = StringUtil::utf8ToWide((const char *)text);
|
||||
} else {
|
||||
textStr = StringUtil::ansiToWide((const char *)text, _charset);
|
||||
}
|
||||
|
||||
if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
|
||||
textStr = textStr.substr(0, (uint32)maxLength);
|
||||
}
|
||||
//text = text.substr(0, MaxLength); // TODO: Remove
|
||||
|
||||
BaseRenderer *renderer = _game->_renderer;
|
||||
|
||||
// find cached surface, if exists
|
||||
uint32 minUseTime = INT_MAX_VALUE;
|
||||
int minIndex = -1;
|
||||
BaseSurface *surface = nullptr;
|
||||
int textOffset = 0;
|
||||
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
if (_cachedTexts[i] == nullptr) {
|
||||
minUseTime = 0;
|
||||
minIndex = i;
|
||||
} else {
|
||||
if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) {
|
||||
surface = _cachedTexts[i]->_surface;
|
||||
textOffset = _cachedTexts[i]->_textOffset;
|
||||
_cachedTexts[i]->_marked = true;
|
||||
_cachedTexts[i]->_lastUsed = BasePlatform::getTime();
|
||||
break;
|
||||
} else {
|
||||
if (_cachedTexts[i]->_lastUsed < minUseTime) {
|
||||
minUseTime = _cachedTexts[i]->_lastUsed;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found, create one
|
||||
if (!surface) {
|
||||
debugC(kWintermuteDebugFont, "Draw text: %s", text);
|
||||
surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset);
|
||||
if (surface) {
|
||||
// write surface to cache
|
||||
if (_cachedTexts[minIndex] != nullptr) {
|
||||
delete _cachedTexts[minIndex];
|
||||
}
|
||||
_cachedTexts[minIndex] = new BaseCachedTTFontText;
|
||||
|
||||
_cachedTexts[minIndex]->_surface = surface;
|
||||
_cachedTexts[minIndex]->_align = align;
|
||||
_cachedTexts[minIndex]->_width = width;
|
||||
_cachedTexts[minIndex]->_maxHeight = maxHeight;
|
||||
_cachedTexts[minIndex]->_maxLength = maxLength;
|
||||
_cachedTexts[minIndex]->_text = textStr;
|
||||
_cachedTexts[minIndex]->_textOffset = textOffset;
|
||||
_cachedTexts[minIndex]->_marked = true;
|
||||
_cachedTexts[minIndex]->_lastUsed = BasePlatform::getTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// and paint it
|
||||
if (surface) {
|
||||
Common::Rect32 rc;
|
||||
BasePlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight());
|
||||
for (int32 i = 0; i < _layers.getSize(); i++) {
|
||||
uint32 color = _layers[i]->_color;
|
||||
uint32 origForceAlpha = renderer->_forceAlphaColor;
|
||||
if (renderer->_forceAlphaColor != 0) {
|
||||
color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor));
|
||||
renderer->_forceAlphaColor = 0;
|
||||
}
|
||||
surface->displayTrans(x, y - textOffset, rc, color, Graphics::BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY);
|
||||
|
||||
renderer->_forceAlphaColor = origForceAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) {
|
||||
//TextLineList lines;
|
||||
// TODO: Use WideString-conversion here.
|
||||
//WrapText(text, width, maxHeight, lines);
|
||||
Common::Array<WideString> lines;
|
||||
_font->wordWrapText(text, width, lines);
|
||||
|
||||
while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) {
|
||||
lines.pop_back();
|
||||
}
|
||||
if (lines.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Graphics::TextAlign alignment = Graphics::kTextAlignInvalid;
|
||||
if (align == TAL_LEFT) {
|
||||
alignment = Graphics::kTextAlignLeft;
|
||||
} else if (align == TAL_CENTER) {
|
||||
alignment = Graphics::kTextAlignCenter;
|
||||
} else if (align == TAL_RIGHT) {
|
||||
alignment = Graphics::kTextAlignRight;
|
||||
}
|
||||
|
||||
// TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array.
|
||||
//debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
|
||||
// void drawAlphaString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
|
||||
Graphics::Surface *surface = new Graphics::Surface();
|
||||
surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _game->_renderer->getPixelFormat());
|
||||
uint32 useColor = 0xffffffff;
|
||||
Common::Array<WideString>::iterator it;
|
||||
int heightOffset = 0;
|
||||
for (it = lines.begin(); it != lines.end(); ++it) {
|
||||
WideString str;
|
||||
if (_game->_textRTL) {
|
||||
str = Common::convertBiDiU32String(*it, Common::BIDI_PAR_RTL);
|
||||
} else {
|
||||
str = Common::convertBiDiU32String(*it, Common::BIDI_PAR_LTR);
|
||||
}
|
||||
_font->drawAlphaString(surface, str, 0, heightOffset, width, useColor, alignment);
|
||||
heightOffset += (int)_lineHeight;
|
||||
}
|
||||
|
||||
BaseSurface *retSurface = _game->_renderer->createSurface();
|
||||
retSurface->create(surface->w, surface->h);
|
||||
retSurface->putSurface(*surface, true);
|
||||
surface->free();
|
||||
delete surface;
|
||||
return retSurface;
|
||||
// TODO: _isUnderline, _isBold, _isItalic, _isStriked
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseFontTT::getLetterHeight() {
|
||||
return (int)_lineHeight;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontTT::loadFile(const char *filename) {
|
||||
char *buffer = (char *)_game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "BaseFontTT::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(ret = loadBuffer(buffer))) {
|
||||
_game->LOG(0, "Error parsing TTFONT file '%s'", filename);
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
TOKEN_DEF_START
|
||||
TOKEN_DEF(TTFONT)
|
||||
TOKEN_DEF(SIZE)
|
||||
TOKEN_DEF(FACE)
|
||||
TOKEN_DEF(FILENAME)
|
||||
TOKEN_DEF(BOLD)
|
||||
TOKEN_DEF(ITALIC)
|
||||
TOKEN_DEF(UNDERLINE)
|
||||
TOKEN_DEF(STRIKE)
|
||||
TOKEN_DEF(CHARSET)
|
||||
TOKEN_DEF(COLOR)
|
||||
TOKEN_DEF(ALPHA)
|
||||
TOKEN_DEF(LAYER)
|
||||
TOKEN_DEF(OFFSET_X)
|
||||
TOKEN_DEF(OFFSET_Y)
|
||||
TOKEN_DEF_END
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontTT::loadBuffer(char *buffer) {
|
||||
TOKEN_TABLE_START(commands)
|
||||
TOKEN_TABLE(TTFONT)
|
||||
TOKEN_TABLE(SIZE)
|
||||
TOKEN_TABLE(FACE)
|
||||
TOKEN_TABLE(FILENAME)
|
||||
TOKEN_TABLE(BOLD)
|
||||
TOKEN_TABLE(ITALIC)
|
||||
TOKEN_TABLE(UNDERLINE)
|
||||
TOKEN_TABLE(STRIKE)
|
||||
TOKEN_TABLE(CHARSET)
|
||||
TOKEN_TABLE(COLOR)
|
||||
TOKEN_TABLE(ALPHA)
|
||||
TOKEN_TABLE(LAYER)
|
||||
TOKEN_TABLE_END
|
||||
|
||||
char *params;
|
||||
int cmd;
|
||||
BaseParser parser(_game);
|
||||
|
||||
if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_TTFONT) {
|
||||
_game->LOG(0, "'TTFONT' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
|
||||
uint32 baseColor = 0x00000000;
|
||||
|
||||
while ((cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_SIZE:
|
||||
parser.scanStr(params, "%d", &_fontHeight);
|
||||
break;
|
||||
|
||||
case TOKEN_FACE:
|
||||
// we don't need this anymore
|
||||
break;
|
||||
|
||||
case TOKEN_FILENAME:
|
||||
BaseUtils::setString(&_fontFile, params);
|
||||
break;
|
||||
|
||||
case TOKEN_BOLD:
|
||||
parser.scanStr(params, "%b", &_isBold);
|
||||
break;
|
||||
|
||||
case TOKEN_ITALIC:
|
||||
parser.scanStr(params, "%b", &_isItalic);
|
||||
break;
|
||||
|
||||
case TOKEN_UNDERLINE:
|
||||
parser.scanStr(params, "%b", &_isUnderline);
|
||||
break;
|
||||
|
||||
case TOKEN_STRIKE:
|
||||
parser.scanStr(params, "%b", &_isStriked);
|
||||
break;
|
||||
|
||||
case TOKEN_CHARSET:
|
||||
parser.scanStr(params, "%d", &_charset);
|
||||
break;
|
||||
|
||||
case TOKEN_COLOR: {
|
||||
int r, g, b;
|
||||
parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
|
||||
baseColor = BYTETORGBA(r, g, b, RGBCOLGetA(baseColor));
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_ALPHA: {
|
||||
int a;
|
||||
parser.scanStr(params, "%d", &a);
|
||||
baseColor = BYTETORGBA(RGBCOLGetR(baseColor), RGBCOLGetG(baseColor), RGBCOLGetB(baseColor), a);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_LAYER: {
|
||||
BaseTTFontLayer *layer = new BaseTTFontLayer;
|
||||
if (layer && DID_SUCCEED(parseLayer(layer, params))) {
|
||||
_layers.add(layer);
|
||||
} else {
|
||||
SAFE_DELETE(layer);
|
||||
cmd = PARSERR_TOKENNOTFOUND;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in TTFONT definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
// create at least one layer
|
||||
if (_layers.getSize() == 0) {
|
||||
BaseTTFontLayer *layer = new BaseTTFontLayer;
|
||||
layer->_color = baseColor;
|
||||
_layers.add(layer);
|
||||
}
|
||||
|
||||
if (!_fontFile) {
|
||||
BaseUtils::setString(&_fontFile, "arial.ttf");
|
||||
}
|
||||
|
||||
return initFont();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, char *buffer) {
|
||||
TOKEN_TABLE_START(commands)
|
||||
TOKEN_TABLE(OFFSET_X)
|
||||
TOKEN_TABLE(OFFSET_Y)
|
||||
TOKEN_TABLE(COLOR)
|
||||
TOKEN_TABLE(ALPHA)
|
||||
TOKEN_TABLE_END
|
||||
|
||||
char *params;
|
||||
int cmd;
|
||||
BaseParser parser(_game);
|
||||
|
||||
while ((cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_OFFSET_X:
|
||||
parser.scanStr(params, "%d", &layer->_offsetX);
|
||||
break;
|
||||
|
||||
case TOKEN_OFFSET_Y:
|
||||
parser.scanStr(params, "%d", &layer->_offsetY);
|
||||
break;
|
||||
|
||||
case TOKEN_COLOR: {
|
||||
int r, g, b;
|
||||
parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
|
||||
layer->_color = BYTETORGBA(r, g, b, RGBCOLGetA(layer->_color));
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_ALPHA: {
|
||||
int a;
|
||||
parser.scanStr(params, "%d", &a);
|
||||
layer->_color = BYTETORGBA(RGBCOLGetR(layer->_color), RGBCOLGetG(layer->_color), RGBCOLGetB(layer->_color), a);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd != PARSERR_EOF) {
|
||||
return STATUS_FAILED;
|
||||
} else {
|
||||
return STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontTT::persist(BasePersistenceManager *persistMgr) {
|
||||
BaseFont::persist(persistMgr);
|
||||
|
||||
persistMgr->transferBool(TMEMBER(_isBold));
|
||||
persistMgr->transferBool(TMEMBER(_isItalic));
|
||||
persistMgr->transferBool(TMEMBER(_isUnderline));
|
||||
persistMgr->transferBool(TMEMBER(_isStriked));
|
||||
persistMgr->transferSint32(TMEMBER(_fontHeight));
|
||||
persistMgr->transferCharPtr(TMEMBER(_fontFile));
|
||||
persistMgr->transferSint32(TMEMBER_INT(_charset));
|
||||
|
||||
|
||||
// persist layers
|
||||
int32 numLayers;
|
||||
if (persistMgr->getIsSaving()) {
|
||||
numLayers = _layers.getSize();
|
||||
persistMgr->transferSint32(TMEMBER(numLayers));
|
||||
for (int i = 0; i < numLayers; i++) {
|
||||
_layers[i]->persist(persistMgr);
|
||||
}
|
||||
} else {
|
||||
numLayers = _layers.getSize();
|
||||
persistMgr->transferSint32(TMEMBER(numLayers));
|
||||
for (int i = 0; i < numLayers; i++) {
|
||||
BaseTTFontLayer *layer = new BaseTTFontLayer;
|
||||
layer->persist(persistMgr);
|
||||
_layers.add(layer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
_cachedTexts[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// initialise to defaults
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
_fallbackFont = _font = _deletableFont = nullptr;
|
||||
_lineHeight = 0;
|
||||
_maxCharWidth = _maxCharHeight = 0;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseFontTT::afterLoad() {
|
||||
initFont();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseFontTT::initFont() {
|
||||
if (!_fontFile) {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
#ifdef USE_FREETYPE2
|
||||
const char *fallbackFilename;
|
||||
// Handle Bold atleast for the fallback-case.
|
||||
// TODO: Handle italic. (Needs a test-case)
|
||||
if (_isBold) {
|
||||
fallbackFilename = "LiberationSans-Bold.ttf";
|
||||
} else {
|
||||
fallbackFilename = "LiberationSans-Regular.ttf";
|
||||
}
|
||||
|
||||
// Load a file, but avoid having the File-manager handle the disposal of it.
|
||||
Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(_fontFile, true, false);
|
||||
if (!file) {
|
||||
if (Common::String(_fontFile) != "arial.ttf") {
|
||||
warning("%s has no replacement font yet, using %s for now (if available)", _fontFile, fallbackFilename);
|
||||
}
|
||||
// Fallback1: Try to find the LiberationSans font
|
||||
file = SearchMan.createReadStreamForMember(fallbackFilename);
|
||||
}
|
||||
|
||||
if (file) {
|
||||
_deletableFont = Graphics::loadTTFFont(file, DisposeAfterUse::YES, _fontHeight, Graphics::kTTFSizeModeCharacter, 96); // Use the same dpi as WME (96 vs 72).
|
||||
_font = _deletableFont;
|
||||
}
|
||||
|
||||
// Fallback2: Try load the font from the common fonts archive:
|
||||
if (!_font) {
|
||||
_deletableFont = Graphics::loadTTFFontFromArchive(fallbackFilename, _fontHeight, Graphics::kTTFSizeModeCharacter, 96); // Use the same dpi as WME (96 vs 72).
|
||||
_font = _deletableFont;
|
||||
}
|
||||
#else
|
||||
warning("BaseFontTT::InitFont - FreeType2-support not compiled in, TTF-fonts will not be loaded");
|
||||
#endif // USE_FREETYPE2
|
||||
|
||||
// Fallback3: Just use the Big GUI-font. (REALLY undesirable)
|
||||
if (!_font) {
|
||||
_font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
|
||||
warning("BaseFontTT::InitFont - Couldn't load font: %s", _fontFile);
|
||||
}
|
||||
_lineHeight = _font->getFontHeight();
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
if (BaseEngine::instance().isFoxTail(FOXTAIL_1_2_896, FOXTAIL_LATEST_VERSION)) {
|
||||
_lineHeight -= 1;
|
||||
}
|
||||
#endif
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) {
|
||||
//TextLineList lines;
|
||||
|
||||
if (maxWidth >= 0) {
|
||||
Common::Array<WideString> lines;
|
||||
_font->wordWrapText(text, maxWidth, lines);
|
||||
Common::Array<WideString>::iterator it;
|
||||
textWidth = 0;
|
||||
for (it = lines.begin(); it != lines.end(); ++it) {
|
||||
if (!it)
|
||||
continue;
|
||||
textWidth = MAX(textWidth, _font->getStringWidth(*it));
|
||||
}
|
||||
|
||||
//WrapText(text, maxWidth, maxHeight, lines);
|
||||
|
||||
textHeight = (int)(lines.size() * _lineHeight);
|
||||
} else {
|
||||
textWidth = _font->getStringWidth(text);
|
||||
textHeight = _fontHeight;
|
||||
}
|
||||
/*
|
||||
TextLineList::iterator it;
|
||||
for (it = lines.begin(); it != lines.end(); ++it) {
|
||||
TextLine *line = (*it);
|
||||
textWidth = MAX(textWidth, line->GetWidth());
|
||||
delete line;
|
||||
line = nullptr;
|
||||
}*/
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
148
engines/wintermute/base/font/base_font_truetype.h
Normal file
148
engines/wintermute/base/font/base_font_truetype.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_BASE_FONTTT_H
|
||||
#define WINTERMUTE_BASE_FONTTT_H
|
||||
|
||||
#include "engines/wintermute/base/font/base_font_storage.h"
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
#include "engines/wintermute/base/gfx/base_surface.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/font.h"
|
||||
|
||||
#define NUM_CACHED_TEXTS 30
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class BaseFontTT : public BaseFont {
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class BaseCachedTTFontText {
|
||||
public:
|
||||
WideString _text;
|
||||
int32 _width;
|
||||
TTextAlign _align;
|
||||
int32 _maxHeight;
|
||||
int32 _maxLength;
|
||||
BaseSurface *_surface;
|
||||
//int32 _priority;
|
||||
int32 _textOffset;
|
||||
bool _marked;
|
||||
uint32 _lastUsed;
|
||||
|
||||
BaseCachedTTFontText() : _text() {
|
||||
//_text = L"";
|
||||
_width = _maxHeight = _maxLength = -1;
|
||||
_align = TAL_LEFT;
|
||||
_surface = nullptr;
|
||||
//_priority = -1;
|
||||
_textOffset = 0;
|
||||
_lastUsed = 0;
|
||||
_marked = false;
|
||||
}
|
||||
|
||||
virtual ~BaseCachedTTFontText() {
|
||||
if (_surface) {
|
||||
delete _surface;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class BaseTTFontLayer {
|
||||
public:
|
||||
BaseTTFontLayer() {
|
||||
_offsetX = _offsetY = 0;
|
||||
_color = 0x00000000;
|
||||
}
|
||||
|
||||
bool persist(BasePersistenceManager *persistMgr) {
|
||||
persistMgr->transferSint32(TMEMBER(_offsetX));
|
||||
persistMgr->transferSint32(TMEMBER(_offsetY));
|
||||
persistMgr->transferUint32(TMEMBER(_color));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
int32 _offsetX;
|
||||
int32 _offsetY;
|
||||
uint32 _color;
|
||||
};
|
||||
|
||||
public:
|
||||
DECLARE_PERSISTENT(BaseFontTT, BaseFont)
|
||||
BaseFontTT(BaseGame *inGame);
|
||||
~BaseFontTT() override;
|
||||
|
||||
int getTextWidth(const byte *text, int maxLength = -1) override;
|
||||
int getTextHeight(const byte *text, int width) override;
|
||||
void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1) override;
|
||||
int getLetterHeight() override;
|
||||
|
||||
bool loadBuffer(char *buffer);
|
||||
bool loadFile(const char *filename);
|
||||
|
||||
void afterLoad() override;
|
||||
void initLoop() override;
|
||||
|
||||
private:
|
||||
bool parseLayer(BaseTTFontLayer *layer, char *buffer);
|
||||
|
||||
void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight);
|
||||
|
||||
BaseSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset);
|
||||
|
||||
BaseCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS];
|
||||
|
||||
bool initFont();
|
||||
|
||||
Graphics::Font *_deletableFont;
|
||||
const Graphics::Font *_font;
|
||||
const Graphics::Font *_fallbackFont;
|
||||
|
||||
float _lineHeight;
|
||||
|
||||
size_t _maxCharWidth;
|
||||
size_t _maxCharHeight;
|
||||
|
||||
private:
|
||||
bool _isBold;
|
||||
bool _isItalic;
|
||||
bool _isUnderline;
|
||||
bool _isStriked;
|
||||
int32 _fontHeight;
|
||||
char *_fontFile;
|
||||
TTextCharset _charset;
|
||||
|
||||
BaseArray<BaseTTFontLayer *> _layers;
|
||||
void clearCache();
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user