[Scummvm-git-logs] scummvm master -> 1cebc3f4db6fab3fe4a68b98c5c8333308d11fa9

sluicebox noreply at scummvm.org
Tue Feb 10 23:54:11 UTC 2026


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
2968f36c4b HUGO: Move intro font loading into function
1cebc3f4db GRAPHICS: FONTS: Cleanup WinFont, document versions


Commit: 2968f36c4b7c5f7dba4e5e537b73b79e59885026
    https://github.com/scummvm/scummvm/commit/2968f36c4b7c5f7dba4e5e537b73b79e59885026
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-02-10T15:52:43-08:00

Commit Message:
HUGO: Move intro font loading into function

Changed paths:
    engines/hugo/intro.cpp
    engines/hugo/intro.h


diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp
index 613bad0d68c..5dbcd188501 100644
--- a/engines/hugo/intro.cpp
+++ b/engines/hugo/intro.cpp
@@ -90,6 +90,16 @@ void IntroHandler::freeIntroData() {
 	_logo_v1d = nullptr;
 }
 
+/**
+ * Load a font from a Windows .FON file. Used only by DOS versions.
+ * Original DOS versions used the Microsoft QuickC runtime for this.
+ */
+void IntroHandler::loadFont(const char *fileName, const char *faceName, uint16 sizeInPoints) {
+	if (!_font.loadFromFON(fileName, Graphics::WinFontDirEntry(faceName, sizeInPoints))) {
+		error("Unable to load font %s, face '%s', size %d", fileName, faceName, sizeInPoints);
+	}
+}
+
 /**
  * Wait for a delay in milliseconds while processing events.
  * This keeps the program window responsive during long delays.
@@ -174,8 +184,7 @@ bool intro_v1d::introPlay() {
 			_vm->_screen->drawShape(250,92,_TLIGHTMAGENTA,_TMAGENTA);
 
 			// TROMAN, size 10-5
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 8)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
+			loadFont("TMSRB.FON", "Tms Rmn", 8);
 
 			char buffer[80];
 			if (_vm->_boot._registered == kRegRegistered)
@@ -214,8 +223,7 @@ bool intro_v1d::introPlay() {
 			drawLogo(119, 22, _TMAGENTA); // "Hugo's"
 
 			// TROMAN, size 30-24
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 24)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 24");
+			loadFont("TMSRB.FON", "Tms Rmn", 24);
 
 			Common::strcpy_s(buffer, "House of Horrors !");
 			_font.drawString(&_surf, buffer, 0, 50, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
@@ -224,8 +232,7 @@ bool intro_v1d::introPlay() {
 			_vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK);
 
 			// TROMAN, size 16-9
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 14)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 14");
+			loadFont("TMSRB.FON", "Tms Rmn", 14);
 
 			Common::strcpy_s(buffer, "S t a r r i n g :");
 			_font.drawString(&_surf, buffer, 0, 95, 320, _TMAGENTA, Graphics::kTextAlignCenter);
@@ -235,8 +242,7 @@ bool intro_v1d::introPlay() {
 			break;
 		case 3:
 			// TROMAN, size 20-9
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 18)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 18");
+			loadFont("TMSRB.FON", "Tms Rmn", 18);
 
 			Common::strcpy_s(buffer, "Hugo !");
 			_font.drawString(&_surf, buffer, 0, 115, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
@@ -248,8 +254,7 @@ bool intro_v1d::introPlay() {
 			_vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK);
 
 			// TROMAN, size 16-9
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 14)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 14");
+			loadFont("TMSRB.FON", "Tms Rmn", 14);
 
 			Common::strcpy_s(buffer, "P r o d u c e d  b y :");
 			_font.drawString(&_surf, buffer, 0, 95, 320, _TMAGENTA, Graphics::kTextAlignCenter);
@@ -305,8 +310,7 @@ bool intro_v1d::introPlay() {
 			_vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK);
 
 			// TROMAN, size 20-14
-			if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 18)))
-				error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 18");
+			loadFont("TMSRB.FON", "Tms Rmn", 18);
 
 			Common::strcpy_s(buffer, "E n j o y !");
 			_font.drawString(&_surf, buffer, 0, 100, 320, _TLIGHTMAGENTA, Graphics::kTextAlignCenter);
@@ -367,8 +371,7 @@ void intro_v2d::introInit() {
 	char buffer[128];
 
 	// TROMAN, size 10-5
-	if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 8)))
-		error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
+	loadFont("TMSRB.FON", "Tms Rmn", 8);
 
 	if (_vm->_boot._registered)
 		Common::sprintf_s(buffer, "%s %s  Registered Version", _vm->getCopyrightString1(), _vm->getCopyrightString2());
@@ -431,8 +434,7 @@ void intro_v3d::introInit() {
 		Common::sprintf_s(buffer,"%s %s  Shareware Version", _vm->getCopyrightString1(), _vm->getCopyrightString2());
 
 	// TROMAN, size 10-5
-	if (!_font.loadFromFON("TMSRB.FON", Graphics::WinFontDirEntry("Tms Rmn", 8)))
-		error("Unable to load font TMSRB.FON, face 'Tms Rmn', size 8");
+	loadFont("TMSRB.FON", "Tms Rmn", 8);
 
 	_font.drawString(&_surf, buffer, 0, 190, 320, _TBROWN, Graphics::kTextAlignCenter);
 
diff --git a/engines/hugo/intro.h b/engines/hugo/intro.h
index 5daeae219bd..77e2264253f 100644
--- a/engines/hugo/intro.h
+++ b/engines/hugo/intro.h
@@ -65,6 +65,7 @@ protected:
 	int16 _introTicks;                              // Count calls to introPlay()
 	byte *_logo_v1d;
 
+	void loadFont(const char *fileName, const char *faceName, uint16 sizeInPoints);
 	bool wait(uint32 delay);
 };
 


Commit: 1cebc3f4db6fab3fe4a68b98c5c8333308d11fa9
    https://github.com/scummvm/scummvm/commit/1cebc3f4db6fab3fe4a68b98c5c8333308d11fa9
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-02-10T15:52:43-08:00

Commit Message:
GRAPHICS: FONTS: Cleanup WinFont, document versions

While working on HUGO fonts, I learned about the old windows fonts and
found some inaccuracies in our code. Now we parse the headers correctly,
document which versions are supported and which aren't, and reject
Win 1.0 raster fonts because we do not really support them.

Changed paths:
    common/formats/winexe.h
    graphics/fonts/winfont.cpp
    graphics/fonts/winfont.h


diff --git a/common/formats/winexe.h b/common/formats/winexe.h
index 0ca57d58319..e7b6a8c8580 100644
--- a/common/formats/winexe.h
+++ b/common/formats/winexe.h
@@ -69,7 +69,7 @@ enum WinResourceType {
 class WinResourceID {
 public:
 	WinResourceID() { _idType = kIDTypeNull; _id = 0; }
-	WinResourceID(String x) { _idType = kIDTypeString; _name = x; }
+	WinResourceID(const String &x) { _idType = kIDTypeString; _name = x; }
 	WinResourceID(uint32 x) { _idType = kIDTypeNumerical; _id = x; }
 
 	WinResourceID &operator=(const String &x);
diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp
index 2411f66fa8c..c042c676114 100644
--- a/graphics/fonts/winfont.cpp
+++ b/graphics/fonts/winfont.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "common/file.h"
+#include "common/ptr.h"
 #include "common/str.h"
 #include "common/stream.h"
 #include "common/textconsole.h"
@@ -78,55 +79,48 @@ static WinFontDirEntry readDirEntry(Common::SeekableReadStream &stream) {
 }
 
 bool WinFont::loadFromFON(const Common::Path &fileName, const WinFontDirEntry &dirEntry) {
-	Common::WinResources *exe = Common::WinResources::createFromEXE(fileName);
-	if (!exe)
+	Common::ScopedPtr<Common::WinResources> exe(Common::WinResources::createFromEXE(fileName));
+	if (!exe) {
 		return false;
+	}
 
-	bool ok = loadFromEXE(exe, fileName, dirEntry);
-	delete exe;
-	return ok;
+	return loadFromEXE(exe.get(), fileName, dirEntry);
 }
 
 bool WinFont::loadFromFON(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry) {
-	Common::WinResources *exe = Common::WinResources::createFromEXE(&stream);
-	if (!exe)
+	Common::ScopedPtr<Common::WinResources> exe(Common::WinResources::createFromEXE(&stream));
+	if (!exe) {
 		return false;
+	}
 
-	bool ok = loadFromEXE(exe, Common::Path("stream"), dirEntry);
-	delete exe;
-	return ok;
+	return loadFromEXE(exe.get(), "stream", dirEntry);
 }
 
 bool WinFont::loadFromEXE(Common::WinResources *exe, const Common::Path &fileName, const WinFontDirEntry &dirEntry) {
 	// Let's pull out the font directory
-	Common::SeekableReadStream *fontDirectory = exe->getResource(Common::kWinFontDir, Common::String("FONTDIR"));
+	Common::ScopedPtr<Common::SeekableReadStream> fontDirectory(exe->getResource(Common::kWinFontDir, Common::WinResourceID("FONTDIR")));
 	if (!fontDirectory) {
 		warning("No font directory in '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	uint32 fontId = getFontIndex(*fontDirectory, dirEntry);
-
-	delete fontDirectory;
-
-	// Couldn't match the face name
+	// Match the face name
+	uint32 fontId = getFontIndex(*fontDirectory.get(), dirEntry);
 	if (fontId == 0xffffffff) {
 		warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(),
 				fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	// Actually go get our font now...
-	Common::SeekableReadStream *fontStream = exe->getResource(Common::kWinFont, fontId);
+	// Get the font
+	Common::ScopedPtr<Common::SeekableReadStream> fontStream(exe->getResource(Common::kWinFont, fontId));
 	if (!fontStream) {
 		warning("Could not find font %d in %s", fontId,
 				fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	bool ok = loadFromFNT(*fontStream);
-	delete fontStream;
-	return ok;
+	return loadFromFNT(*fontStream.get());
 }
 
 /**
@@ -152,7 +146,7 @@ uint32 WinFont::getFontIndex(Common::SeekableReadStream &stream, const WinFontDi
 		return 0xffffffff;
 	}
 
-	// Scour the directory for our matching name
+	// Search the directory for our matching name
 	for (uint16 i = 0; i < numFonts; i++) {
 		uint16 id = stream.readUint16LE();
 
@@ -182,8 +176,10 @@ Common::String WinFont::getFONFontName(Common::SeekableReadStream& stream) {
 
 bool WinFont::loadFromFNT(const Common::Path &fileName) {
 	Common::File file;
-
-	return file.open(fileName) && loadFromFNT(file);
+	if (!file.open(fileName)) {
+		return false;
+	}
+	return loadFromFNT(file);
 }
 
 char WinFont::indexToCharacter(uint16 index) const {
@@ -207,15 +203,22 @@ int WinFont::getCharWidth(uint32 chr) const {
 }
 
 bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
+	uint32 fontPos = stream.pos();
+
+	// Font versions:
+	// 1.0 Raster: Unsupported. Different bitmap format. Win 1.0 included these.
+	// 2.0 Raster: Supported. Most common format.
+	// 3.0 Raster: Supported. More header fields, 32-bit offsets.
+	// 1.0 Vector: Unsupported. Windows only has three: Modern, Roman, Script
+	// 2.0 Vector: Unsupported. None are known to exist.
+	// 3.0 Vector: Unsupported. None are known to exist.
 	uint16 version = stream.readUint16LE();
-
-	// We'll accept Win1, Win2, and Win3 fonts
 	if (version != 0x100 && version != 0x200 && version != 0x300) {
 		warning("Bad FNT version %04x", version);
 		return false;
 	}
 
-	/* uint32 sizeOfGlyphTableInBytes = */ stream.readUint32LE();
+	/* uint32 fontSize = */ stream.readUint32LE();
 	stream.skip(60); // Copyright info
 	uint16 fontType = stream.readUint16LE();
 	_sizeInPoints = stream.readUint16LE();
@@ -248,22 +251,38 @@ bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
 	/* uint32 device = */ stream.readUint32LE();
 	/* uint32 face = */ stream.readUint32LE();
 	/* uint32 bitsPointer = */ stream.readUint32LE();
-	uint32 bitsOffset = stream.readUint32LE();
-	/* byte reserved = */ stream.readByte();
+	/* uint32 bitsOffset = */ stream.readUint32LE();
 
-	if (version == 0x100) {
-		// Seems Win1 has an extra byte?
-		stream.readByte();
+	if (version == 0x200) {
+		/* byte reserved = */ stream.readByte();
 	} else if (version == 0x300) {
-		// For Windows 3.0, Microsoft added 6 new fields. All of which are
-		// guaranteed to be 0. Which leads to the question: Why add these at all?
+		/* byte reserved = */ stream.readByte();
 
+		// Windows 3.0 added fields for future versions that were never used.
+		// These fields are always zero. True Type replaced this font format.
 		/* uint32 flags = */ stream.readUint32LE();
 		/* uint16 aSpace = */ stream.readUint16LE();
 		/* uint16 bSpace = */ stream.readUint16LE();
 		/* uint16 cSpace = */ stream.readUint16LE();
 		/* uint32 colorPointer = */ stream.readUint32LE();
-		stream.skip(16); // Reserved
+		stream.skip(16); // reserved [ dfReserved1 ]
+	}
+
+	// TODO: Add support for the three vector fonts: Modern, Roman, and Script.
+	// Note that the Windows font spec defines how vector points are stored, but not
+	// the line drawing or resizing algorithms; these were implementation specific.
+	// The three vector fonts only appear in the 1.0 format. The Script font has
+	// characters that draw beyond their widths to achieve the connected effect.
+	if (fontType & 1) {
+		warning("WinFont: vector fonts not supported");
+		return false;
+	}
+	// Windows 1.0 raster fonts have significantly different formats for the glyph
+	// entries and the font bitmap. The glyph entry table may not even be present.
+	// 1.0 raster fonts appeared in Windows 1.0 and were upgraded to 2.0 afterwards.
+	if (version == 0x100) {
+		warning("WinFont: 1.0 raster fonts not supported");
+		return false;
 	}
 
 	// Begin loading in the glyphs
@@ -279,21 +298,11 @@ bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
 			_glyphs[i].charWidth = pixWidth;
 
 		_glyphs[i].offset = (version == 0x300) ? stream.readUint32LE() : stream.readUint16LE();
-
-		// Seems the offsets in the Win1 font format are based on bitsOffset
-		if (version == 0x100)
-			_glyphs[i].offset += bitsOffset;
-	}
-
-	// TODO: Currently only raster fonts are supported!
-	if (fontType & 1) {
-		warning("Vector FNT files not supported yet");
-		return false;
 	}
 
 	// Read in the bitmaps for the raster images
 	for (uint16 i = 0; i < _glyphCount - 1; i++) {
-		stream.seek(_glyphs[i].offset);
+		stream.seek(fontPos + _glyphs[i].offset);
 
 		_glyphs[i].bitmap = new byte[_pixHeight * _glyphs[i].charWidth];
 
diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h
index 732e5a8c557..e43a5779bb6 100644
--- a/graphics/fonts/winfont.h
+++ b/graphics/fonts/winfont.h
@@ -106,7 +106,7 @@ private:
 
 	uint16 _glyphCount;
 	struct GlyphEntry {
-		GlyphEntry() { bitmap = 0; charWidth = 0; offset = 0; }
+		GlyphEntry() : charWidth(0), offset(0), bitmap(nullptr) {}
 		~GlyphEntry() { delete[] bitmap; }
 
 		uint16 charWidth;




More information about the Scummvm-git-logs mailing list