mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 01:08:25 +00:00
ZVISION: Create class for rendering TrueType fonts
This commit is contained in:
parent
af94158723
commit
c7358ed4f7
@ -23,6 +23,7 @@ MODULE_OBJS := \
|
||||
scripts.o \
|
||||
single_value_container.o \
|
||||
timer_node.o \
|
||||
truetype_font.o \
|
||||
utility.o \
|
||||
video.o \
|
||||
zvision.o \
|
||||
|
191
engines/zvision/truetype_font.cpp
Normal file
191
engines/zvision/truetype_font.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "graphics/fonts/ttf.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "zvision/truetype_font.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/render_manager.h"
|
||||
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
TruetypeFont::TruetypeFont(ZVision *engine, int32 fontHeight, const Graphics::PixelFormat pixelFormat)
|
||||
: _engine(engine),
|
||||
_pixelFormat(pixelFormat),
|
||||
_isBold(false),
|
||||
_isItalic(false),
|
||||
_isStriked(false),
|
||||
_isUnderline(false),
|
||||
_fontHeight(fontHeight),
|
||||
_font(0),
|
||||
_lineHeight(0),
|
||||
_maxCharWidth(0),
|
||||
_maxCharHeight(0) {
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
_cachedTexts[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TruetypeFont::~TruetypeFont(void) {
|
||||
clearCache();
|
||||
|
||||
delete _font;
|
||||
}
|
||||
|
||||
void TruetypeFont::clearCache() {
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
if (_cachedTexts[i]) {
|
||||
delete _cachedTexts[i];
|
||||
}
|
||||
_cachedTexts[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool TruetypeFont::loadFile(const Common::String &filename) {
|
||||
Common::File file;
|
||||
if (file.open(filename)) {
|
||||
debug("TTF font file %s could not be opened", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
_font = Graphics::loadTTFFont(file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72).
|
||||
_lineHeight = _font->getFontHeight();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TruetypeFont::drawText(const Common::String &text, int x, int y, int width, TextAlign align, int maxHeight) {
|
||||
if (text.equals("")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the cached surface, if it exists
|
||||
uint32 minUseTime = UINT_MAX;
|
||||
int minIndex = -1;
|
||||
Graphics::Surface *surface = nullptr;
|
||||
|
||||
for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
|
||||
if (_cachedTexts[i] == nullptr) {
|
||||
minUseTime = 0;
|
||||
minIndex = i;
|
||||
} else {
|
||||
if (_cachedTexts[i]->_text == text && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight) {
|
||||
surface = _cachedTexts[i]->_surface;
|
||||
_cachedTexts[i]->_marked = true;
|
||||
_cachedTexts[i]->_lastUsed = g_system->getMillis();
|
||||
break;
|
||||
} else {
|
||||
if (_cachedTexts[i]->_lastUsed < minUseTime) {
|
||||
minUseTime = _cachedTexts[i]->_lastUsed;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It's not cached, so create one
|
||||
if (!surface) {
|
||||
surface = renderTextToTexture(text, width, align, maxHeight);
|
||||
if (surface) {
|
||||
// Write the new surface to cache
|
||||
if (_cachedTexts[minIndex] != nullptr) {
|
||||
delete _cachedTexts[minIndex];
|
||||
}
|
||||
_cachedTexts[minIndex] = new CachedText;
|
||||
|
||||
_cachedTexts[minIndex]->_surface = surface;
|
||||
_cachedTexts[minIndex]->_align = align;
|
||||
_cachedTexts[minIndex]->_width = width;
|
||||
_cachedTexts[minIndex]->_maxHeight = maxHeight;
|
||||
_cachedTexts[minIndex]->_text = text;
|
||||
_cachedTexts[minIndex]->_marked = true;
|
||||
_cachedTexts[minIndex]->_lastUsed = _engine->_system->getMillis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render it to the working window
|
||||
if (surface) {
|
||||
_engine->getRenderManager()->copyRectToWorkingWindow((uint16 *)surface->getPixels(), x, y, surface->w, surface->w, surface->h);
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Surface *TruetypeFont::renderTextToTexture(const Common::String &text, int width, TextAlign align, int maxHeight) {
|
||||
Common::Array<Common::String> 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 == ALIGN_LEFT) {
|
||||
alignment = Graphics::kTextAlignLeft;
|
||||
} else if (align == ALIGN_CENTER) {
|
||||
alignment = Graphics::kTextAlignCenter;
|
||||
} else if (align == ALIGN_RIGHT) {
|
||||
alignment = Graphics::kTextAlignRight;
|
||||
}
|
||||
|
||||
Graphics::Surface *surface = new Graphics::Surface();
|
||||
surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _pixelFormat);
|
||||
|
||||
uint32 alphaColor = 0xffffffff;
|
||||
int heightOffset = 0;
|
||||
for (Common::Array<Common::String>::iterator it = lines.begin(); it != lines.end(); it++) {
|
||||
_font->drawString(surface, *it, 0, heightOffset, width, alphaColor, alignment);
|
||||
heightOffset += (int)_lineHeight;
|
||||
}
|
||||
|
||||
return surface;
|
||||
// TODO: _isUnderline, _isBold, _isItalic, _isStriked
|
||||
}
|
||||
|
||||
void TruetypeFont::measureText(const Common::String &text, int maxWidth, int maxHeight, int &textWidthOut, int &textHeightOut) {
|
||||
if (maxWidth >= 0) {
|
||||
Common::Array<Common::String> lines;
|
||||
_font->wordWrapText(text, maxWidth, lines);
|
||||
Common::Array<Common::String>::iterator it;
|
||||
textWidthOut = 0;
|
||||
for (it = lines.begin(); it != lines.end(); ++it) {
|
||||
textWidthOut = MAX(textWidthOut, _font->getStringWidth(*it));
|
||||
}
|
||||
|
||||
textHeightOut = (int)(lines.size() * getLineHeight());
|
||||
} else {
|
||||
textWidthOut = _font->getStringWidth(text);
|
||||
textHeightOut = _fontHeight;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
129
engines/zvision/truetype_font.h
Normal file
129
engines/zvision/truetype_font.h
Normal file
@ -0,0 +1,129 @@
|
||||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file is based on engines/wintermute/base/fonts/base_font_truetype.h/.cpp
|
||||
|
||||
#ifndef ZVISION_TRUETYPE_FONT_H
|
||||
#define ZVISION_TRUETYPE_FONT_H
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
#include "graphics/font.h"
|
||||
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
class TruetypeFont {
|
||||
public:
|
||||
TruetypeFont(ZVision *engine, int32 fontHeight, const Graphics::PixelFormat pixelFormat);
|
||||
~TruetypeFont();
|
||||
|
||||
public:
|
||||
enum {
|
||||
NUM_CACHED_TEXTS = 30
|
||||
};
|
||||
|
||||
enum TextAlign {
|
||||
ALIGN_LEFT = 0,
|
||||
ALIGN_RIGHT,
|
||||
ALIGN_CENTER
|
||||
};
|
||||
|
||||
class CachedText {
|
||||
public:
|
||||
Common::String _text;
|
||||
int32 _width;
|
||||
TextAlign _align;
|
||||
int32 _maxHeight;
|
||||
Graphics::Surface *_surface;
|
||||
int32 _textOffset;
|
||||
bool _marked;
|
||||
uint32 _lastUsed;
|
||||
|
||||
CachedText() {
|
||||
_width = _maxHeight = -1;
|
||||
_align = ALIGN_LEFT;
|
||||
_surface = 0;
|
||||
_lastUsed = 0;
|
||||
_marked = false;
|
||||
}
|
||||
|
||||
virtual ~CachedText() {
|
||||
delete _surface;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
ZVision *_engine;
|
||||
const Graphics::PixelFormat _pixelFormat;
|
||||
|
||||
Graphics::Font *_font;
|
||||
|
||||
float _lineHeight;
|
||||
|
||||
size_t _maxCharWidth;
|
||||
size_t _maxCharHeight;
|
||||
|
||||
CachedText *_cachedTexts[NUM_CACHED_TEXTS];
|
||||
|
||||
public:
|
||||
bool _isBold;
|
||||
bool _isItalic;
|
||||
bool _isUnderline;
|
||||
bool _isStriked;
|
||||
int32 _fontHeight;
|
||||
|
||||
//BaseArray<BaseTTFontLayer *> _layers;
|
||||
|
||||
public:
|
||||
int getTextWidth(const byte *text, int maxLength = -1);
|
||||
int getTextHeight(const byte *text, int width);
|
||||
void drawText(const Common::String &text, int x, int y, int width, TextAlign align = ALIGN_LEFT, int max_height = -1);
|
||||
int getLetterHeight();
|
||||
|
||||
void initLoop() {}
|
||||
void afterLoad() {}
|
||||
|
||||
bool loadBuffer(byte *buffer);
|
||||
bool loadFile(const Common::String &filename);
|
||||
|
||||
float getLineHeight() const { return _lineHeight; }
|
||||
|
||||
void clearCache();
|
||||
|
||||
static TruetypeFont *createFromFile(ZVision *game, const Common::String &filename);
|
||||
|
||||
private:
|
||||
void measureText(const Common::String &text, int maxWidth, int maxHeight, int &textWidthOut, int &textHeightOut);
|
||||
Graphics::Surface *renderTextToTexture(const Common::String &text, int width, TextAlign align, int maxHeight);
|
||||
bool initFont();
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user