[Scummvm-git-logs] scummvm master -> afc55543cccecd6eebe3ff6cf7dc2c017dc76de5
AndywinXp
noreply at scummvm.org
Wed Jan 28 11:57:55 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
afc55543cc SCUMM: HE: Add TTF font support
Commit: afc55543cccecd6eebe3ff6cf7dc2c017dc76de5
https://github.com/scummvm/scummvm/commit/afc55543cccecd6eebe3ff6cf7dc2c017dc76de5
Author: AndywinXp (andywinxp at gmail.com)
Date: 2026-01-28T12:57:48+01:00
Commit Message:
SCUMM: HE: Add TTF font support
This is a port of the original Font module, which was using
Windows syscalls for TTF font rendering.
I don't know if it's pixel accurate, but since it was originally
OS driven, I'd rather not care too much about it and let our
library do its own thing. ;-)
Fixes #16474 and #16473
"SCUMM: PUTTSFUNSHOP: Loading any pre-filled project fails"
"SCUMM: PUTTSFUNSHOP: Text input is not working"
Changed paths:
A engines/scumm/he/font_he.cpp
A engines/scumm/he/font_he.h
engines/scumm/he/intern_he.h
engines/scumm/he/script_v100he.cpp
engines/scumm/he/script_v72he.cpp
engines/scumm/he/script_v90he.cpp
engines/scumm/he/wiz_he.cpp
engines/scumm/module.mk
engines/scumm/scumm.cpp
diff --git a/engines/scumm/he/font_he.cpp b/engines/scumm/he/font_he.cpp
new file mode 100644
index 00000000000..010d795d855
--- /dev/null
+++ b/engines/scumm/he/font_he.cpp
@@ -0,0 +1,394 @@
+/* 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/>.
+ *
+ */
+
+#include "scumm/he/font_he.h"
+#include "scumm/he/intern_he.h"
+#include "scumm/he/wiz_he.h"
+
+#include "common/archive.h"
+#include "common/compression/unzip.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/fs.h"
+
+#include "graphics/surface.h"
+
+#ifdef USE_FREETYPE2
+#include "graphics/fonts/ttf.h"
+#endif
+
+namespace Scumm {
+
+HEFont::HEFont(ScummEngine_v99he *vm) : _vm(vm), _fontsEnumerated(false) {
+ _fontContextList.size();
+}
+
+HEFont::~HEFont() {
+ for (Common::List<HEFontContextElement *>::iterator it = _fontContextList.begin();
+ it != _fontContextList.end(); ++it) {
+ delete *it;
+ }
+
+ _fontContextList.clear();
+ _fontEntries.clear();
+}
+
+HEFontContextElement *HEFont::findFontContext(int imageNum) {
+ for (Common::List<HEFontContextElement *>::iterator it = _fontContextList.begin();
+ it != _fontContextList.end(); ++it) {
+
+ if ((*it)->imageNumber == imageNum) {
+ return *it;
+ }
+ }
+
+ return nullptr;
+}
+
+bool HEFont::startFont(int imageNum) {
+ // Check if a context already exists for this image...
+ HEFontContextElement *existing = findFontContext(imageNum);
+ if (existing) {
+ debug(1, "HEFont::startFont(): Warning - font system exists for image %d. Destroying existing.", imageNum);
+ endFont(imageNum);
+ }
+
+ // Verify the image is suitable...
+ WizSimpleBitmap bitmap;
+ if (!_vm->_wiz->dwSetSimpleBitmapStructFromImage(imageNum, 0, &bitmap)) {
+ debug(1, "HEFont::startFont(): Image %d is not suitable for rendering (must not be compressed)", imageNum);
+ return false;
+ }
+
+ // Create new font context...
+ HEFontContextElement *newContext = new HEFontContextElement();
+ newContext->imageNumber = imageNum;
+
+ _fontContextList.push_back(newContext);
+
+ return true;
+}
+
+bool HEFont::endFont(int imageNum) {
+ for (Common::List<HEFontContextElement *>::iterator it = _fontContextList.begin();
+ it != _fontContextList.end(); ++it) {
+
+ if ((*it)->imageNumber == imageNum) {
+ delete *it;
+ _fontContextList.erase(it);
+ return true;
+ }
+ }
+
+ debug(1, "HEFont::endFont(): Font system not started for image %d", imageNum);
+ return false;
+}
+
+bool HEFont::createFont(int imageNum, const char *fontName, int fgColor, int bgColor, int style, int size) {
+ HEFontContextElement *ctx = findFontContext(imageNum);
+ if (!ctx) {
+ debug(1, "HEFont::createFont(): Font system not created for image %d", imageNum);
+ return false;
+ }
+
+ // Destroy any previously created font...
+ if (ctx->font) {
+ delete ctx->font;
+ ctx->font = nullptr;
+ }
+
+#ifdef USE_FREETYPE2
+ // Find the filename for this font name...
+ Common::String fontFileName;
+ for (uint i = 0; i < _fontEntries.size(); i++) {
+ if (_fontEntries[i].fontName.equalsIgnoreCase(fontName)) {
+ fontFileName = _fontEntries[i].fileName + ".ttf";
+ break;
+ }
+ }
+
+ // Fallback: try using fontName directly as filename...
+ if (fontFileName.empty()) {
+ fontFileName = Common::String(fontName) + ".ttf";
+ }
+
+ // Try loading from fonts.dat...
+ ctx->font = Graphics::loadTTFFontFromArchive(fontFileName,
+ size,
+ Graphics::kTTFSizeModeCell,
+ 0, 0,
+ Graphics::kTTFRenderModeLight,
+ nullptr);
+
+ // If not in archive, we're probably searching for a game-specific font, so try via SearchMan...
+ if (!ctx->font) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(Common::Path(fontFileName));
+
+ if (stream) {
+ ctx->font = Graphics::loadTTFFont(stream,
+ DisposeAfterUse::YES,
+ size,
+ Graphics::kTTFSizeModeCell,
+ 0, 0,
+ Graphics::kTTFRenderModeLight,
+ nullptr);
+ }
+ }
+#endif
+
+ if (!ctx->font) {
+ debug(1, "HEFont::createFont(): Could not create font '%s'", fontName);
+ return false;
+ }
+
+ // Store colors
+ ctx->fgColor = fgColor;
+ ctx->bgColor = bgColor;
+ ctx->transparentBg = (bgColor == _vm->VAR(_vm->VAR_WIZ_TRANSPARENT_COLOR));
+
+ // Set alignment
+ ctx->align = Graphics::kTextAlignCenter; // Default
+ if (style & kHEFontStyleLeft) {
+ ctx->align = Graphics::kTextAlignLeft;
+ } else if (style & kHEFontStyleRight) {
+ ctx->align = Graphics::kTextAlignRight;
+ }
+
+ return true;
+}
+
+bool HEFont::renderString(int imageNum, int imageState, int xPos, int yPos, const char *string) {
+ HEFontContextElement *ctx = findFontContext(imageNum);
+ if (!ctx) {
+ debug(1, "HEFont::renderString(): Font system not created for image %d", imageNum);
+ return false;
+ }
+
+ if (!ctx->font) {
+ debug(1, "HEFont::renderString(): No font selected for image %d", imageNum);
+ return false;
+ }
+
+ // Get the bitmap from the current image...
+ WizSimpleBitmap bitmap;
+ if (!_vm->_wiz->dwSetSimpleBitmapStructFromImage(imageNum, imageState, &bitmap)) {
+ debug(1, "HEFont::renderString(): Could not get bitmap from image %d", imageNum);
+ return false;
+ }
+
+ // Wrap it in a Surface, which we can assume is a 8-bit paletted one for our use case...
+ Graphics::Surface surface;
+ surface.init(bitmap.bitmapWidth, bitmap.bitmapHeight,
+ bitmap.bitmapWidth,
+ bitmap.bufferPtr(),
+ Graphics::PixelFormat::createFormatCLUT8());
+
+ int stringWidth = ctx->font->getStringWidth(string);
+ int stringHeight = ctx->font->getFontHeight();
+
+ // If background is not transparent, fill the background rectangle first...
+ if (!ctx->transparentBg) {
+ Common::Rect bgRect(xPos, yPos, xPos + stringWidth, yPos + stringHeight);
+ surface.fillRect(bgRect, ctx->bgColor);
+ }
+
+ // Draw the string!
+ ctx->font->drawString(&surface, string, xPos, yPos, stringWidth, ctx->fgColor, ctx->align);
+
+ return true;
+}
+
+int HEFont::getStringWidth(int imageNum, const char *string) {
+ HEFontContextElement *ctx = findFontContext(imageNum);
+ if (!ctx) {
+ debug(1, "HEFont::getStringWidth(): Font system not created for image %d", imageNum);
+ return 0;
+ }
+
+ if (!ctx->font) {
+ debug(1, "HEFont::getStringWidth(): No font selected for image %d", imageNum);
+ return 0;
+ }
+
+ return ctx->font->getStringWidth(string);
+}
+
+int HEFont::getStringHeight(int imageNum, const char *string) {
+ HEFontContextElement *ctx = findFontContext(imageNum);
+ if (!ctx) {
+ debug(1, "HEFont::getStringHeight(): Font system not created for image %d", imageNum);
+ return 0;
+ }
+
+ if (!ctx->font) {
+ debug(1, "HEFont::getStringHeight(): No font selected for image %d", imageNum);
+ return 0;
+ }
+
+ return ctx->font->getFontHeight();
+}
+
+void HEFont::enumerateFonts() {
+ if (_fontsEnumerated) {
+ return;
+ }
+
+ _fontEntries.clear();
+
+#ifdef USE_FREETYPE2
+ Common::Array<Common::String> candidateFonts;
+
+ // Open fonts.dat...
+ Common::SeekableReadStream *archiveStream = nullptr;
+
+ if (ConfMan.hasKey("extrapath")) {
+ Common::FSDirectory extrapath(ConfMan.getPath("extrapath"));
+ archiveStream = extrapath.createReadStreamForMember("fonts.dat");
+ }
+
+ if (!archiveStream) {
+ archiveStream = SearchMan.createReadStreamForMember("fonts.dat");
+ }
+
+ if (archiveStream) {
+ Common::Archive *archive = Common::makeZipArchive(archiveStream);
+ if (archive) {
+ Common::ArchiveMemberList members;
+ archive->listMembers(members);
+
+ for (Common::ArchiveMemberList::const_iterator it = members.begin();
+ it != members.end(); ++it) {
+ Common::String name = (*it)->getName();
+ if (name.hasSuffixIgnoreCase(".ttf")) {
+ Common::String fontName = name.substr(0, name.size() - 4);
+ candidateFonts.push_back(fontName);
+ }
+ }
+
+ delete archive;
+ }
+ }
+
+ // If not in archive, we're probably searching for a game-specific font, so try via SearchMan...
+ Common::ArchiveMemberList fontFiles;
+ SearchMan.listMatchingMembers(fontFiles, "*.ttf");
+
+ // Use filenames for fonts.dat fonts...
+ for (uint i = 0; i < candidateFonts.size(); i++) {
+ Common::String fontFileName = candidateFonts[i] + ".ttf";
+
+ Graphics::Font *testFont = Graphics::loadTTFFontFromArchive(
+ fontFileName,
+ 12,
+ Graphics::kTTFSizeModeCharacter
+ );
+
+ if (testFont) {
+ HEFontEntry entry;
+ entry.fileName = candidateFonts[i];
+ entry.fontName = candidateFonts[i];
+ _fontEntries.push_back(entry);
+ delete testFont;
+ }
+ }
+
+ // Use actual font name from metadata for game fonts...
+ for (Common::ArchiveMemberList::const_iterator it = fontFiles.begin();
+ it != fontFiles.end(); ++it) {
+ Common::String name = (*it)->getName();
+ Common::String fileBaseName = name.substr(0, name.size() - 4);
+
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(Common::Path(name));
+ if (stream) {
+ Graphics::Font *testFont = Graphics::loadTTFFont(stream,
+ DisposeAfterUse::YES,
+ 12,
+ Graphics::kTTFSizeModeCharacter
+ );
+
+ if (testFont) {
+ HEFontEntry entry;
+ entry.fileName = fileBaseName;
+ entry.fontName = testFont->getFontName();
+
+ // If there's no metadata name, just fallback to the filename...
+ if (entry.fontName.empty()) {
+ entry.fontName = fileBaseName;
+ }
+
+ _fontEntries.push_back(entry);
+ delete testFont;
+ }
+ }
+ }
+#endif
+
+ // Sort alphabetically...
+ Common::sort(_fontEntries.begin(), _fontEntries.end(),
+ [](const HEFontEntry &a, const HEFontEntry &b) {
+ return a.fontName.compareToIgnoreCase(b.fontName) < 0;
+ }
+ );
+
+ _fontsEnumerated = true;
+}
+
+int HEFont::enumInit() {
+ enumerateFonts();
+ return _fontEntries.size();
+}
+
+void HEFont::enumDestroy() {
+ _fontEntries.clear();
+ _fontsEnumerated = false;
+}
+
+const char *HEFont::enumGet(int index) {
+ if (!_fontsEnumerated) {
+ debug(1, "HEFont::enumGet(): Font enumeration not initialized");
+ return nullptr;
+ }
+
+ if (index < 0 || index >= (int)_fontEntries.size()) {
+ debug(1, "HEFont::enumGet(): Index %d out of range (0-%d)", index, (int)_fontEntries.size() - 1);
+ return nullptr;
+ }
+
+ return _fontEntries[index].fontName.c_str();
+}
+
+int HEFont::enumFind(const char *fontName) {
+ if (!_fontsEnumerated) {
+ debug(1, "HEFont::enumFind(): Font enumeration not initialized");
+ return -1;
+ }
+
+ for (uint i = 0; i < _fontEntries.size(); i++) {
+ if (_fontEntries[i].fontName.equalsIgnoreCase(fontName)) {
+ return i;
+ }
+ }
+
+ debug(1, "HEFont::enumFind(): Could not find font '%s'", fontName);
+ return -1;
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/font_he.h b/engines/scumm/he/font_he.h
new file mode 100644
index 00000000000..c8c4021e215
--- /dev/null
+++ b/engines/scumm/he/font_he.h
@@ -0,0 +1,102 @@
+/* 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/>.
+ *
+ */
+
+#ifndef SCUMM_HE_FONT_HE_H
+#define SCUMM_HE_FONT_HE_H
+
+#include "common/array.h"
+#include "common/list.h"
+#include "common/scummsys.h"
+#include "common/str.h"
+
+#include "graphics/font.h"
+
+namespace Scumm {
+
+class ScummEngine_v99he;
+
+// Font style flags, taken from the original
+enum HEFontStyle {
+ kHEFontStyleItalic = 0x01,
+ kHEFontStyleUnderline = 0x02,
+ kHEFontStyleBold = 0x04,
+ kHEFontStyleCenter = 0x08,
+ kHEFontStyleLeft = 0x10,
+ kHEFontStyleRight = 0x20
+};
+
+struct HEFontContextElement {
+ HEFontContextElement() : imageNumber(0),
+ font(nullptr),
+ fgColor(0),
+ bgColor(0),
+ transparentBg(false),
+ align(Graphics::kTextAlignCenter) {}
+
+ ~HEFontContextElement() {
+ delete font;
+ font = nullptr;
+ }
+
+ int imageNumber;
+ Graphics::Font *font;
+ int fgColor;
+ int bgColor;
+ bool transparentBg;
+ Graphics::TextAlign align;
+};
+
+struct HEFontEntry {
+ Common::String fileName; // Filename without extension (e.g., "LiberationSans-Bold")
+ Common::String fontName; // Actual font name from metadata (e.g., "Liberation Sans")
+};
+
+class HEFont {
+public:
+ HEFont(ScummEngine_v99he *vm);
+ ~HEFont();
+
+ bool startFont(int imageNum);
+ bool endFont(int imageNum);
+ bool createFont(int imageNum, const char *fontName, int fgColor, int bgColor, int style, int size);
+ bool renderString(int imageNum, int imageState, int xPos, int yPos, const char *string);
+ int getStringWidth(int imageNum, const char *string);
+ int getStringHeight(int imageNum, const char *string);
+ int enumInit();
+ void enumDestroy();
+ const char *enumGet(int index);
+ int enumFind(const char *fontName);
+
+private:
+ ScummEngine_v99he *_vm;
+
+ Common::List<HEFontContextElement *> _fontContextList;
+
+ Common::Array<HEFontEntry> _fontEntries;
+ bool _fontsEnumerated;
+
+ HEFontContextElement *findFontContext(int imageNum);
+ void enumerateFonts();
+};
+
+} // End of namespace Scumm
+
+#endif // SCUMM_HE_FONT_HE_H
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 94f94b31ae7..3a0cff1c383 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -286,6 +286,7 @@ class Lobby;
class ScummEngine_v71he : public ScummEngine_v70he {
friend class Wiz;
friend class Gdi;
+ friend class HEFont;
protected:
enum SubOpType {
@@ -826,8 +827,13 @@ protected:
};
class ScummEngine_v99he : public ScummEngine_v95he {
+friend class ScummEngine_v72he;
+friend class ScummEngine_v90he;
+friend class Wiz;
+
public:
- ScummEngine_v99he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v95he(syst, dr) {}
+ ScummEngine_v99he(OSystem *syst, const DetectorResult &dr);
+ ~ScummEngine_v99he() override;
void resetScumm() override;
@@ -843,6 +849,8 @@ protected:
void setPaletteFromPtr(const byte *ptr, int numcolor = -1) override;
void setPalColor(int index, int r, int g, int b) override;
void updatePalette() override;
+
+ HEFont *_heFont = nullptr;
};
class ScummEngine_v100he : public ScummEngine_v99he {
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index b054f313f7d..40adf438b7e 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -27,6 +27,7 @@
#include "scumm/charset.h"
#include "scumm/dialogs.h"
#include "scumm/he/animation_he.h"
+#include "scumm/he/font_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
@@ -2628,6 +2629,7 @@ void ScummEngine_v100he::o100_getSpriteGroupInfo() {
void ScummEngine_v100he::o100_getWizData() {
byte filename[4096];
int resId, state, type;
+ int fontImageNum, fontProperty;
Common::Rect clipRect;
int32 w, h;
int32 x, y;
@@ -2687,11 +2689,28 @@ void ScummEngine_v100he::o100_getWizData() {
push(y);
break;
case SO_FONT_START:
- pop();
+ // I don't think any HE100 games use this, since all FunShop games are HE99, but still...
+ fontProperty = pop();
copyScriptString(filename, sizeof(filename));
- pop();
- push(0);
- debug(0, "o100_getWizData() case 111 unhandled");
+ fontImageNum = pop();
+
+ if (fontImageNum) {
+ switch (fontProperty) {
+ case 2: // PFONT_EXTENT_X
+ push(_heFont->getStringWidth(fontImageNum, Common::String((char *)filename).c_str()));
+ break;
+
+ case 3: // PFONT_EXTENT_Y
+ push(_heFont->getStringHeight(fontImageNum, Common::String((char *)filename).c_str()));
+ break;
+ default:
+ // No default case in the original...
+ break;
+ }
+ } else {
+ push(0);
+ }
+
break;
case SO_HISTOGRAM:
clipRect.bottom = pop();
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index b2ea13ef1e8..37b388178db 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -29,6 +29,7 @@
#include "scumm/charset.h"
#include "scumm/dialogs.h"
#include "scumm/file.h"
+#include "scumm/he/font_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/localizer.h"
#include "scumm/object.h"
@@ -2167,6 +2168,44 @@ void ScummEngine_v72he::o72_readINI() {
push(4);
else
push(2);
+ } else if (_game.heversion >= 99 && !strcmp((char *)option, "NoFontsInstalled")) {
+ // The three FunShop came with these six exact optional TrueType fonts:
+ // Augie, Dot2Dot, Frosty, Goo Puff, Smilage and Zodiastic.
+ //
+ // These fonts are an optional choice from the installer, and if not installed,
+ // this NoFontsInstalled flag will be set to 1.
+ //
+ // In our case, some users might not have a suitable Windows OS to run the
+ // InstallShield installers, and they might just take the plain data files
+ // from the CD. So let's check for exactly those fonts in our HEFont class
+ // and set this flag accordingly.
+ //
+ // The perceived effect of this is that without these fonts, premade printing
+ // models won't be available, instead of crashing the engine. ;-)
+#ifdef USE_FREETYPE2
+ static const char *funShopFonts[] = {
+ "Augie",
+ "Dot2Dot",
+ "Frosty",
+ "Goo Puff",
+ "Smilage",
+ "Zodiastic"
+ };
+
+ ((ScummEngine_v99he *)this)->_heFont->enumInit();
+
+ bool allFontsFound = true;
+ for (int i = 0; i < ARRAYSIZE(funShopFonts); i++) {
+ if (((ScummEngine_v99he *)this)->_heFont->enumFind(funShopFonts[i]) == -1) {
+ allFontsFound = false;
+ break;
+ }
+ }
+
+ push(allFontsFound ? 0 : 1);
+#else
+ push(0);
+#endif
} else {
push(ConfMan.getInt((char *)option));
}
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index 5b0b96bd722..a2297730f15 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -24,6 +24,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
#include "scumm/he/animation_he.h"
+#include "scumm/he/font_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/object.h"
@@ -1332,8 +1333,6 @@ void ScummEngine_v90he::o90_getWizData() {
push(_wiz->dwGetImageGeneralProperty(resId, state, type));
break;
case SO_FONT_START: // 141
- // TODO: Implement...
-
fontProperty = pop();
copyScriptString(filename, sizeof(filename));
fontImageNum = pop();
@@ -1341,13 +1340,11 @@ void ScummEngine_v90he::o90_getWizData() {
if (fontImageNum) {
switch (fontProperty) {
case 2: // PFONT_EXTENT_X
- //push(PFONT_GetStringWidth(iImage, szResultString));
- push(0);
+ push(((ScummEngine_v99he *)this)->_heFont->getStringWidth(fontImageNum, Common::String((char *)filename).c_str()));
break;
case 3: // PFONT_EXTENT_Y
- //push(PFONT_GetStringHeight(iImage, szResultString));
- push(0);
+ push(((ScummEngine_v99he *)this)->_heFont->getStringHeight(fontImageNum, Common::String((char *)filename).c_str()));
break;
default:
// No default case in the original...
@@ -1357,7 +1354,6 @@ void ScummEngine_v90he::o90_getWizData() {
push(0);
}
- debug(0, "o90_getWizData() case SO_FONT_START unhandled");
break;
default:
error("o90_getWizData: Unknown case %d", subOp);
@@ -2347,28 +2343,38 @@ void ScummEngine_v90he::o90_paletteOps() {
}
void ScummEngine_v90he::o90_fontEnum() {
- byte string[80];
+ byte resultString[80];
byte subOp = fetchScriptByte();
switch (subOp) {
case ScummEngine_v100he::SO_INIT: // HE100
case SO_INIT:
- push(1);
+ push(((ScummEngine_v99he *)this)->_heFont->enumInit());
break;
case ScummEngine_v100he::SO_PROPERTY: // HE100
case SO_PROPERTY:
switch (pop()) {
case 1: // FONT_ENUM_GET
- pop();
- writeVar(0, 0);
- defineArray(0, kStringArray, 0, 0, 0, 0);
- writeArray(0, 0, 0, 0);
- push(readVar(0));
+ {
+ _scummVars[0] = 0;
+ const char *fontName = ((ScummEngine_v99he *)this)->_heFont->enumGet(pop());
+ if (!fontName) {
+ fontName = "";
+ }
+
+ int len = strlen(fontName);
+ byte *ptr = defineArray(0, kStringArray, 0, 0, 0, len);
+ if (ptr) {
+ memcpy(ptr, fontName, len);
+ }
+
+ push(_scummVars[0]);
break;
+ }
case 2: // FONT_ENUM_FIND
- copyScriptString(string, sizeof(string));
- push(-1);
+ copyScriptString(resultString, sizeof(resultString));
+ push(((ScummEngine_v99he *)this)->_heFont->enumFind((char *)resultString));
break;
}
@@ -2376,8 +2382,6 @@ void ScummEngine_v90he::o90_fontEnum() {
default:
error("o90_fontEnum: Unknown case %d", subOp);
}
-
- debug(1, "o90_fontEnum stub (%d)", subOp);
}
void ScummEngine_v90he::o90_getActorAnimProgress() {
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index c416c0884b9..b03bf45d94a 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -26,6 +26,7 @@
#include "common/system.h"
#include "graphics/cursorman.h"
#include "graphics/primitives.h"
+#include "scumm/he/font_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/resource.h"
@@ -2399,23 +2400,40 @@ void Wiz::processWizImageRenderEllipseCmd(const WizImageCommand *params) {
}
void Wiz::processWizImageFontStartCmd(const WizImageCommand *params) {
- // Used for text in FreddisFunShop/PuttsFunShop/SamsFunShop
- // TODO: Start Font
+ // Used for TTF text in FreddisFunShop/PuttsFunShop/SamsFunShop
+ if (!(((ScummEngine_v99he *)_vm)->_heFont->startFont(params->image))) {
+ warning("Wiz::processWizImageFontStartCmd(): Couldn't start font");
+ }
}
void Wiz::processWizImageFontEndCmd(const WizImageCommand *params) {
- // Used for text in FreddisFunShop/PuttsFunShop/SamsFunShop
- // TODO: End Font
+ // Used for TTF text in FreddisFunShop/PuttsFunShop/SamsFunShop
+ if (!(((ScummEngine_v99he *)_vm)->_heFont->endFont(params->image))) {
+ warning("Wiz::processWizImageFontEndCmd(): Couldn't end font");
+ }
}
void Wiz::processWizImageFontCreateCmd(const WizImageCommand *params) {
- // Used for text in FreddisFunShop/PuttsFunShop/SamsFunShop
- // TODO: Create Font
+ // Used for TTF text in FreddisFunShop/PuttsFunShop/SamsFunShop
+ if (!(((ScummEngine_v99he *)_vm)->_heFont->createFont(params->image,
+ (char *)params->fontProperties.fontName,
+ params->fontProperties.fgColor,
+ params->fontProperties.bgColor,
+ params->fontProperties.style,
+ params->fontProperties.size))) {
+ warning("Wiz::processWizImageFontCreateCmd(): Couldn't create font");
+ }
}
void Wiz::processWizImageFontRenderCmd(const WizImageCommand *params) {
- // TODO: Render Font String
- error("Wiz::processWizImageFontRenderCmd(): Render Font String");
+ // Used for TTF text in FreddisFunShop/PuttsFunShop/SamsFunShop
+ if (!(((ScummEngine_v99he *)_vm)->_heFont->renderString(params->image,
+ params->state,
+ params->fontProperties.xPos,
+ params->fontProperties.yPos,
+ (char *)params->fontProperties.string))) {
+ warning("Wiz::processWizImageFontRenderCmd(): Couldn't render font");
+ }
}
void Wiz::processWizImageRenderFloodFillCmd(const WizImageCommand *params) {
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index a2cc2b66021..de3c730f912 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -169,6 +169,7 @@ MODULE_OBJS += \
he/basketball/shooting.o \
he/basketball/trajectory.o \
he/cup_player_he.o \
+ he/font_he.o \
he/gfx_comp/aux_comp.o \
he/gfx_comp/mrle_comp.o \
he/gfx_comp/trle_comp.o \
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 1da7f083858..d8b20048a11 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -53,6 +53,7 @@
#include "scumm/players/player_towns.h"
#include "scumm/insane/insane.h"
#include "scumm/he/animation_he.h"
+#include "scumm/he/font_he.h"
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/sound_he.h"
@@ -843,6 +844,15 @@ ScummEngine_v90he::~ScummEngine_v90he() {
}
}
+ScummEngine_v99he::ScummEngine_v99he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v95he(syst, dr) {
+ _heFont = new HEFont(this);
+}
+
+ScummEngine_v99he::~ScummEngine_v99he() {
+ delete _heFont;
+ _heFont = nullptr;
+}
+
ScummEngine_v100he::ScummEngine_v100he(OSystem *syst, const DetectorResult &dr) : ScummEngine_v99he(syst, dr) {
/* Moonbase stuff */
if (_game.id == GID_MOONBASE)
@@ -1553,6 +1563,16 @@ Common::Error ScummEngine::init() {
_internalGUIControls[i].doubleLinesFlag = false;
}
+#ifndef USE_FREETYPE2
+ if (_game.id == GID_FUNSHOP) {
+ GUI::MessageDialog dialog(_(
+ "It appears your ScummVM version was not built with TrueType Fonts support.\n\n"
+ "Since the One-Stop Fun Shop series makes extensive use of TTF fonts,\n"
+ "some of the graphics on screen will be missing."));
+ dialog.runModal();
+ }
+#endif
+
_setupIsComplete = true;
syncSoundSettings();
More information about the Scummvm-git-logs
mailing list