diff options
Diffstat (limited to 'engines/zvision/text')
-rw-r--r-- | engines/zvision/text/string_manager.cpp | 11 | ||||
-rw-r--r-- | engines/zvision/text/string_manager.h | 2 | ||||
-rw-r--r-- | engines/zvision/text/subtitles.cpp | 108 | ||||
-rw-r--r-- | engines/zvision/text/subtitles.h | 54 | ||||
-rw-r--r-- | engines/zvision/text/text.cpp | 155 | ||||
-rw-r--r-- | engines/zvision/text/text.h | 36 | ||||
-rw-r--r-- | engines/zvision/text/truetype_font.cpp | 228 | ||||
-rw-r--r-- | engines/zvision/text/truetype_font.h | 84 |
8 files changed, 583 insertions, 95 deletions
diff --git a/engines/zvision/text/string_manager.cpp b/engines/zvision/text/string_manager.cpp index ec10b6220c..6b870d0b8d 100644 --- a/engines/zvision/text/string_manager.cpp +++ b/engines/zvision/text/string_manager.cpp @@ -43,21 +43,18 @@ StringManager::~StringManager() { } void StringManager::initialize(ZVisionGameId gameId) { - if (gameId == GID_NEMESIS) { - // TODO: Check this hardcoded filename against all versions of Nemesis + if (gameId == GID_NEMESIS) loadStrFile("nemesis.str"); - } else if (gameId == GID_GRANDINQUISITOR) { - // TODO: Check this hardcoded filename against all versions of Grand Inquisitor + else if (gameId == GID_GRANDINQUISITOR) loadStrFile("inquis.str"); - } } void StringManager::loadStrFile(const Common::String &fileName) { Common::File file; if (!_engine->getSearchManager()->openFile(file, fileName)) { - warning("%s does not exist. String parsing failed", fileName.c_str()); - return; + error("%s does not exist. String parsing failed", fileName.c_str()); } + uint lineNumber = 0; while (!file.eos()) { _lines[lineNumber] = readWideLine(file); diff --git a/engines/zvision/text/string_manager.h b/engines/zvision/text/string_manager.h index b77ad65040..f4564ee1ec 100644 --- a/engines/zvision/text/string_manager.h +++ b/engines/zvision/text/string_manager.h @@ -24,7 +24,7 @@ #define ZVISION_STRING_MANAGER_H #include "zvision/detection.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" namespace Graphics { class FontManager; diff --git a/engines/zvision/text/subtitles.cpp b/engines/zvision/text/subtitles.cpp new file mode 100644 index 0000000000..acf4c37c2f --- /dev/null +++ b/engines/zvision/text/subtitles.cpp @@ -0,0 +1,108 @@ +/* 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 "zvision/graphics/render_manager.h" +#include "zvision/text/subtitles.h" +#include "zvision/file/search_manager.h" +#include "zvision/text/text.h" + +namespace ZVision { + +Subtitle::Subtitle(ZVision *engine, const Common::String &subname) : + _engine(engine), + _areaId(-1), + _subId(-1) { + Common::File file; + if (_engine->getSearchManager()->openFile(file, subname)) { + while (!file.eos()) { + Common::String str = file.readLine(); + if (str.lastChar() == '~') + str.deleteLastChar(); + + if (str.matchString("*Initialization*", true)) { + // Not used + } else if (str.matchString("*Rectangle*", true)) { + int32 x1, y1, x2, y2; + sscanf(str.c_str(), "%*[^:]:%d %d %d %d", &x1, &y1, &x2, &y2); + Common::Rect rct = Common::Rect(x1, y1, x2, y2); + _areaId = _engine->getRenderManager()->createSubArea(rct); + } else if (str.matchString("*TextFile*", true)) { + char filename[64]; + sscanf(str.c_str(), "%*[^:]:%s", filename); + Common::File txt; + if (_engine->getSearchManager()->openFile(txt, filename)) { + while (!txt.eos()) { + Common::String txtline = readWideLine(txt); + sub curSubtitle; + curSubtitle.start = -1; + curSubtitle.stop = -1; + curSubtitle.subStr = txtline; + + _subs.push_back(curSubtitle); + } + txt.close(); + } + } else { + int32 st; + int32 en; + int32 sb; + if (sscanf(str.c_str(), "%*[^:]:(%d,%d)=%d", &st, &en, &sb) == 3) { + if (sb <= (int32)_subs.size()) { + _subs[sb].start = st; + _subs[sb].stop = en; + } + } + } + } + } +} + +Subtitle::~Subtitle() { + if (_areaId != -1) + _engine->getRenderManager()->deleteSubArea(_areaId); + + _subs.clear(); +} + +void Subtitle::process(int32 time) { + int16 j = -1; + for (uint16 i = 0; i < _subs.size(); i++) + if (time >= _subs[i].start && time <= _subs[i].stop) { + j = i; + break; + } + + if (j == -1 && _subId != -1) { + if (_areaId != -1) + _engine->getRenderManager()->updateSubArea(_areaId, ""); + _subId = -1; + } + + if (j != -1 && j != _subId) { + if (_subs[j].subStr.size()) + if (_areaId != -1) + _engine->getRenderManager()->updateSubArea(_areaId, _subs[j].subStr); + _subId = j; + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/text/subtitles.h b/engines/zvision/text/subtitles.h new file mode 100644 index 0000000000..c3da6583a4 --- /dev/null +++ b/engines/zvision/text/subtitles.h @@ -0,0 +1,54 @@ +/* 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. + * + */ + +#ifndef ZVISION_SUBTITLES_H +#define ZVISION_SUBTITLES_H + +#include "zvision/zvision.h" + +namespace ZVision { + +class ZVision; + +class Subtitle { +public: + Subtitle(ZVision *engine, const Common::String &subname); + ~Subtitle(); + + void process(int32 time); +private: + ZVision *_engine; + int32 _areaId; + int16 _subId; + + struct sub { + int start; + int stop; + Common::String subStr; + }; + + Common::Array<sub> _subs; +}; + +} + +#endif diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp index 406c36e5b0..a5ed044424 100644 --- a/engines/zvision/text/text.cpp +++ b/engines/zvision/text/text.cpp @@ -33,27 +33,31 @@ #include "zvision/text/text.h" #include "zvision/graphics/render_manager.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "zvision/scripting/script_manager.h" namespace ZVision { cTxtStyle::cTxtStyle() { - fontname = "Arial"; - blue = 255; - green = 255; - red = 255; - bold = false; - escapement = 0; - italic = false; - justify = TXT_JUSTIFY_LEFT; - newline = false; - size = 12; - skipcolor = false; - strikeout = false; - underline = false; - statebox = 0; - sharp = false; + _fontname = "Arial"; + _blue = 255; + _green = 255; + _red = 255; + _bold = false; +#if 0 + _newline = false; + _escapement = 0; +#endif + _italic = false; + _justify = TXT_JUSTIFY_LEFT; + _size = 12; +#if 0 + _skipcolor = false; +#endif + _strikeout = false; + _underline = false; + _statebox = 0; + _sharp = false; } txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { @@ -80,10 +84,10 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (_tmp.lastChar() == '"') _tmp.deleteLastChar(); - fontname = _tmp; + _fontname = _tmp; } else { if (!tokenizer.empty()) - fontname = token; + _fontname = token; } retval |= TXT_RET_FNTCHG; @@ -91,8 +95,8 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (blue != tmp) { - blue = tmp; + if (_blue != tmp) { + _blue = tmp; retval |= TXT_RET_FNTSTL; } } @@ -100,8 +104,8 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (red != tmp) { - red = tmp; + if (_red != tmp) { + _red = tmp; retval |= TXT_RET_FNTSTL; } } @@ -109,43 +113,47 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (green != tmp) { - green = tmp; + if (_green != tmp) { + _green = tmp; retval |= TXT_RET_FNTSTL; } } } else if (token.matchString("newline", true)) { +#if 0 if ((retval & TXT_RET_NEWLN) == 0) - newline = 0; + _newline = 0; - newline++; + _newline++; +#endif retval |= TXT_RET_NEWLN; } else if (token.matchString("point", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); int32 tmp = atoi(token.c_str()); - if (size != tmp) { - size = tmp; + if (_size != tmp) { + _size = tmp; retval |= TXT_RET_FNTCHG; } } } else if (token.matchString("escapement", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); +#if 0 int32 tmp = atoi(token.c_str()); - escapement = tmp; + _escapement = tmp; +#endif } } else if (token.matchString("italic", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (italic != true) { - italic = true; + if (_italic != true) { + _italic = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (italic != false) { - italic = false; + if (_italic != false) { + _italic = false; retval |= TXT_RET_FNTSTL; } } @@ -154,13 +162,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (underline != true) { - underline = true; + if (_underline != true) { + _underline = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (underline != false) { - underline = false; + if (_underline != false) { + _underline = false; retval |= TXT_RET_FNTSTL; } } @@ -169,13 +177,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (strikeout != true) { - strikeout = true; + if (_strikeout != true) { + _strikeout = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (strikeout != false) { - strikeout = false; + if (_strikeout != false) { + _strikeout = false; retval |= TXT_RET_FNTSTL; } } @@ -184,13 +192,13 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("on", true)) { - if (bold != true) { - bold = true; + if (_bold != true) { + _bold = true; retval |= TXT_RET_FNTSTL; } } else if (token.matchString("off", true)) { - if (bold != false) { - bold = false; + if (_bold != false) { + _bold = false; retval |= TXT_RET_FNTSTL; } } @@ -198,29 +206,31 @@ txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) { } else if (token.matchString("skipcolor", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); +#if 0 if (token.matchString("on", true)) { - skipcolor = true; + _skipcolor = true; } else if (token.matchString("off", true)) { - skipcolor = false; + _skipcolor = false; } +#endif } } else if (token.matchString("image", true)) { // Not used } else if (token.matchString("statebox", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); - statebox = atoi(token.c_str()); + _statebox = atoi(token.c_str()); retval |= TXT_RET_HASSTBOX; } } else if (token.matchString("justify", true)) { if (!tokenizer.empty()) { token = tokenizer.nextToken(); if (token.matchString("center", true)) - justify = TXT_JUSTIFY_CENTER; + _justify = TXT_JUSTIFY_CENTER; else if (token.matchString("left", true)) - justify = TXT_JUSTIFY_LEFT; + _justify = TXT_JUSTIFY_LEFT; else if (token.matchString("right", true)) - justify = TXT_JUSTIFY_RIGHT; + _justify = TXT_JUSTIFY_RIGHT; } } } @@ -247,19 +257,19 @@ void cTxtStyle::readAllStyle(const Common::String &txt) { void cTxtStyle::setFontStyle(StyledTTFont &font) { uint tempStyle = 0; - if (bold) + if (_bold) tempStyle |= StyledTTFont::STTF_BOLD; - if (italic) + if (_italic) tempStyle |= StyledTTFont::STTF_ITALIC; - if (underline) + if (_underline) tempStyle |= StyledTTFont::STTF_UNDERLINE; - if (strikeout) + if (_strikeout) tempStyle |= StyledTTFont::STTF_STRIKEOUT; - if (sharp) + if (_sharp) tempStyle |= StyledTTFont::STTF_SHARP; font.setStyle(tempStyle); @@ -268,27 +278,27 @@ void cTxtStyle::setFontStyle(StyledTTFont &font) { void cTxtStyle::setFont(StyledTTFont &font) { uint tempStyle = 0; - if (bold) + if (_bold) tempStyle |= StyledTTFont::STTF_BOLD; - if (italic) + if (_italic) tempStyle |= StyledTTFont::STTF_ITALIC; - if (underline) + if (_underline) tempStyle |= StyledTTFont::STTF_UNDERLINE; - if (strikeout) + if (_strikeout) tempStyle |= StyledTTFont::STTF_STRIKEOUT; - if (sharp) + if (_sharp) tempStyle |= StyledTTFont::STTF_SHARP; - font.loadFont(fontname, size, tempStyle); + font.loadFont(_fontname, _size, tempStyle); } Graphics::Surface *TextRenderer::render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style) { style.setFontStyle(fnt); - uint32 clr = _engine->_pixelFormat.RGBToColor(style.red, style.green, style.blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(style._red, style._green, style._blue); return fnt.renderSolidText(txt, clr); } @@ -307,13 +317,13 @@ int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Gra dst.fillRect(Common::Rect(dst.w, dst.h), 0); - uint32 clr = _engine->_pixelFormat.RGBToColor(fontStyle.red, fontStyle.green, fontStyle.blue); + uint32 clr = _engine->_resourcePixelFormat.RGBToColor(fontStyle._red, fontStyle._green, fontStyle._blue); int16 w; w = font.getStringWidth(txt); - drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle.justify); + drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle._justify); return w; } @@ -352,7 +362,7 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac int16 prevbufspace = 0, prevtxtspace = 0; while (i < stringlen) { - TxtJustify[currentline] = style.justify; + TxtJustify[currentline] = style._justify; if (text[i] == '<') { int16 ret = 0; @@ -396,7 +406,7 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac if (ret & TXT_RET_HASSTBOX) { Common::String buf3; - buf3 = Common::String::format("%d", _engine->getScriptManager()->getStateValue(style.statebox)); + buf3 = Common::String::format("%d", _engine->getScriptManager()->getStateValue(style._statebox)); buf += buf3; textPosition += buf3.size(); } @@ -452,15 +462,16 @@ void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surfac j++; } dx = 0; + Common::Rect empty; for (int32 jj = 0; jj < j; jj++) { if (TxtJustify[i] == TXT_JUSTIFY_LEFT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); else if (TxtJustify[i] == TXT_JUSTIFY_CENTER) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); else if (TxtJustify[i] == TXT_JUSTIFY_RIGHT) - _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); + _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], empty, dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0); dx += TxtSurfaces[i][jj]->w; } @@ -495,10 +506,12 @@ Common::String readWideLine(Common::SeekableReadStream &stream) { } else if (value >= 0x80 && value < 0x800) { asciiString += (char)(0xC0 | ((value >> 6) & 0x1F)); asciiString += (char)(0x80 | (value & 0x3F)); - } else if (value >= 0x800 && value < 0x10000) { + } else if (value >= 0x800 && value < 0x10000 && value != 0xCCCC) { asciiString += (char)(0xE0 | ((value >> 12) & 0xF)); asciiString += (char)(0x80 | ((value >> 6) & 0x3F)); asciiString += (char)(0x80 | (value & 0x3F)); + } else if (value == 0xCCCC) { + // Ignore, this character is used as newline sometimes } else if (value >= 0x10000 && value < 0x200000) { asciiString += (char)(0xF0); asciiString += (char)(0x80 | ((value >> 12) & 0x3F)); diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h index ecec3ccde6..c942b8141a 100644 --- a/engines/zvision/text/text.h +++ b/engines/zvision/text/text.h @@ -25,7 +25,7 @@ #define ZVISION_TEXT_H #include "zvision/detection.h" -#include "zvision/graphics/truetype_font.h" +#include "zvision/text/truetype_font.h" #include "zvision/zvision.h" namespace ZVision { @@ -55,21 +55,25 @@ public: void setFont(StyledTTFont &font); public: - Common::String fontname; - txtJustify justify; // 0 - center, 1-left, 2-right - int16 size; - uint8 red; // 0-255 - uint8 green; // 0-255 - uint8 blue; // 0-255 - int8 newline; - int8 escapement; - bool italic; - bool bold; - bool underline; - bool strikeout; - bool skipcolor; - int32 statebox; - bool sharp; + Common::String _fontname; + txtJustify _justify; // 0 - center, 1-left, 2-right + int16 _size; + uint8 _red; // 0-255 + uint8 _green; // 0-255 + uint8 _blue; // 0-255 +#if 0 + int8 _newline; + int8 _escapement; +#endif + bool _italic; + bool _bold; + bool _underline; + bool _strikeout; +#if 0 + bool _skipcolor; +#endif + int32 _statebox; + bool _sharp; // char image ?? }; diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp new file mode 100644 index 0000000000..622a02a6a8 --- /dev/null +++ b/engines/zvision/text/truetype_font.cpp @@ -0,0 +1,228 @@ +/* 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/config-manager.h" +#include "common/debug.h" +#include "common/file.h" +#include "common/system.h" +#include "common/unzip.h" +#include "graphics/font.h" +#include "graphics/fonts/ttf.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/text/truetype_font.h" + +namespace ZVision { + +StyledTTFont::StyledTTFont(ZVision *engine) { + _engine = engine; + _style = 0; + _font = NULL; + _lineHeight = 0; +} + +StyledTTFont::~StyledTTFont() { + if (_font) + delete _font; +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) { + _style = style; + return loadFont(fontName, point); +} + +bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) { + struct FontStyle { + const char *zorkFont; + const char *fontBase; + const char *freeFontBase; + const char *freeFontItalicName; + }; + + const FontStyle systemFonts[] = { + { "*times new roman*", "times", "FreeSerif", "Italic" }, + { "*times*", "times", "FreeSerif", "Italic" }, + { "*century schoolbook*", "censcbk", "FreeSerif", "Italic" }, + { "*garamond*", "gara", "FreeSerif", "Italic" }, + { "*courier new*", "cour", "FreeMono", "Oblique" }, + { "*courier*", "cour", "FreeMono", "Oblique" }, + { "*ZorkDeath*", "cour", "FreeMono", "Oblique" }, + { "*arial*", "arial", "FreeSans", "Oblique" }, + { "*ZorkNormal*", "arial", "FreeSans", "Oblique" }, + }; + + Common::String newFontName; + Common::String freeFontName; + + for (int i = 0; i < ARRAYSIZE(systemFonts); i++) { + if (fontName.matchString(systemFonts[i].zorkFont, true)) { + newFontName = systemFonts[i].fontBase; + freeFontName = systemFonts[i].freeFontBase; + + if ((_style & STTF_BOLD) && (_style & STTF_ITALIC)) { + newFontName += "bi"; + freeFontName += "Bold"; + freeFontName += systemFonts[i].freeFontItalicName; + } else if (_style & STTF_BOLD) { + newFontName += "bd"; + freeFontName += "Bold"; + } else if (_style & STTF_ITALIC) { + newFontName += "i"; + freeFontName += systemFonts[i].freeFontItalicName; + } + + newFontName += ".ttf"; + freeFontName += ".ttf"; + break; + } + } + + if (newFontName.empty()) { + debug("Could not identify font: %s. Reverting to Arial", fontName.c_str()); + newFontName = "arial.ttf"; + freeFontName = "FreeSans.ttf"; + } + + bool sharp = (_style & STTF_SHARP) == STTF_SHARP; + + Common::File file; + if (!file.open(newFontName) && !file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, newFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) + error("Unable to open font file %s (free alternative: %s)", newFontName.c_str(), freeFontName.c_str()); + + Graphics::Font *_newFont = Graphics::loadTTFFont(file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display + if (_newFont) { + if (!_font) + delete _font; + _font = _newFont; + } + + _fntName = fontName; + _lineHeight = point; + + if (_font) + return true; + return false; +} + +void StyledTTFont::setStyle(uint newStyle) { + if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) { + _style = newStyle; + loadFont(_fntName, _lineHeight); + } else { + _style = newStyle; + } +} + +int StyledTTFont::getFontHeight() { + if (_font) + return _font->getFontHeight(); + return 0; +} + +int StyledTTFont::getMaxCharWidth() { + if (_font) + return _font->getMaxCharWidth(); + return 0; +} + +int StyledTTFont::getCharWidth(byte chr) { + if (_font) + return _font->getCharWidth(chr); + return 0; +} + +int StyledTTFont::getKerningOffset(byte left, byte right) { + if (_font) + return _font->getKerningOffset(left, right); + return 0; +} + +void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) { + if (_font) { + _font->drawChar(dst, chr, x, y, color); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color); + } + } +} + +void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) { + if (_font) { + _font->drawString(dst, str, x, y, w, color, align); + if (_style & STTF_UNDERLINE) { + int16 pos = floor(_font->getFontHeight() * 0.87); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + if (_style & STTF_STRIKEOUT) { + int16 pos = floor(_font->getFontHeight() * 0.60); + int16 wd = MIN(_font->getStringWidth(str), w); + int16 stX = x; + if (align == Graphics::kTextAlignCenter) + stX += (w - wd) / 2; + else if (align == Graphics::kTextAlignRight) + stX += (w - wd); + + int thk = MAX((int)(_font->getFontHeight() * 0.05), 1); + + dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color); + } + } +} + +int StyledTTFont::getStringWidth(const Common::String &str) { + if (_font) + return _font->getStringWidth(str); + return 0; +} + +Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) { + Graphics::Surface *tmp = new Graphics::Surface; + if (_font) { + int16 w = _font->getStringWidth(str); + if (w && w < 1024) { + tmp->create(w, _font->getFontHeight(), _engine->_resourcePixelFormat); + drawString(tmp, str, 0, 0, w, color); + } + } + return tmp; +} + +} // End of namespace ZVision diff --git a/engines/zvision/text/truetype_font.h b/engines/zvision/text/truetype_font.h new file mode 100644 index 0000000000..b5fac4af8a --- /dev/null +++ b/engines/zvision/text/truetype_font.h @@ -0,0 +1,84 @@ +/* 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 "graphics/font.h" +#include "graphics/pixelformat.h" + +namespace Graphics { +struct Surface; +} + +namespace ZVision { + +class ZVision; + +// Styled TTF +class StyledTTFont { +public: + StyledTTFont(ZVision *engine); + ~StyledTTFont(); + + enum { + STTF_BOLD = 1, + STTF_ITALIC = 2, + STTF_UNDERLINE = 4, + STTF_STRIKEOUT = 8, + STTF_SHARP = 16 + }; + +private: + ZVision *_engine; + Graphics::Font *_font; + int _lineHeight; + uint _style; + Common::String _fntName; + +public: + bool loadFont(const Common::String &fontName, int32 point); + bool loadFont(const Common::String &fontName, int32 point, uint style); + void setStyle(uint newStyle); + + int getFontHeight(); + int getMaxCharWidth(); + int getCharWidth(byte chr); + int getKerningOffset(byte left, byte right); + + void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color); + + void drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft); + int getStringWidth(const Common::String &str); + + Graphics::Surface *renderSolidText(const Common::String &str, uint32 color); + + bool isLoaded() { + return _font != NULL; + }; +}; + +} // End of namespace ZVision + +#endif |