[Scummvm-git-logs] scummvm master -> 1072856f89d9b4dc0144db1cb2ea19e496f86814

mduggan noreply at scummvm.org
Thu May 4 01:43:47 UTC 2023


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

Summary:
7248c55ed1 TETRAEDGE: Simplify rotation calculations
c011652f8a TETRAEDGE: Fix Amerzone inventory updates
1072856f89 TETRAEDGE: Add loading support for tef font format


Commit: 7248c55ed1fe3f44637ddfcc9c409eb211622e95
    https://github.com/scummvm/scummvm/commit/7248c55ed1fe3f44637ddfcc9c409eb211622e95
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-05-04T10:28:47+09:00

Commit Message:
TETRAEDGE: Simplify rotation calculations

This should also fix a tiny bug in Syberia 2 where the clock hands rotate too
fast and to the wrong spot.

Changed paths:
    engines/tetraedge/game/amerzone_game.cpp
    engines/tetraedge/game/character.cpp
    engines/tetraedge/game/in_game_scene.cpp
    engines/tetraedge/game/lua_binds.cpp
    engines/tetraedge/game/object3d.h
    engines/tetraedge/te/te_particle.cpp
    engines/tetraedge/te/te_quaternion.h
    engines/tetraedge/te/te_warp.cpp


diff --git a/engines/tetraedge/game/amerzone_game.cpp b/engines/tetraedge/game/amerzone_game.cpp
index 15483eba128..ddffe5d3398 100644
--- a/engines/tetraedge/game/amerzone_game.cpp
+++ b/engines/tetraedge/game/amerzone_game.cpp
@@ -115,8 +115,9 @@ bool AmerzoneGame::changeWarp(const Common::String &rawZone, const Common::Strin
 	TeSceneWarp sceneWarp;
 	sceneWarp.load(sceneXml, _warpY, false);
 
-	_xAngleMin = FLT_MAX;
-	_xAngleMax = FLT_MAX;
+	// NOTE: Original uses FLT_MAX here but that can cause overflows, just use a big number.
+	_xAngleMin = 1e8;
+	_xAngleMax = 1e8;
 	_yAngleMin = 45.0f - _orientationY;
 	_yAngleMax = _orientationY + 55.0f;
 
@@ -525,8 +526,10 @@ void AmerzoneGame::update() {
 				changeSpeedToMouseDirection();
 			}
 			float dragtime = (float)(_dragTimer.timeElapsed() / 1000000.0);
-			setAngleX(_orientationX - _speedX * dragtime);
-			setAngleY(_orientationY + _speedY * dragtime);
+			if (_speedX)
+				setAngleX(_orientationX - _speedX * dragtime);
+			if (_speedY)
+				setAngleY(_orientationY + _speedY * dragtime);
 		}
 	} else {
 		// Compass stuff happens here in the game, but it's
@@ -542,19 +545,12 @@ void AmerzoneGame::update() {
 			_warpY->setMouseLeftUpForMakers();
 	}
 
-	// Rotate x around the Y axis (spinning left/right on the spot)
-	TeQuaternion xRot = TeQuaternion::fromAxisAndAngle(TeVector3f32(0, 1, 0), (float)(_orientationX * M_PI) / 180.0f);
-	// Rotate y around the axis perpendicular to the x rotation
-	// Note: slightly different from original because of the way
-	// rotation works in the Amerzone Tetraedge engine.
-	TeVector3f32 yRotAxis = TeVector3f32(1, 0, 0);
-	xRot.inverse().transform(yRotAxis);
-	TeQuaternion yRot = TeQuaternion::fromAxisAndAngle(yRotAxis, (float)(_orientationY * M_PI) / 180.0f);
+	const TeQuaternion rot = TeQuaternion::fromEulerDegrees(TeVector3f32(_orientationX, _orientationY, 0));
 
 	if (_warpX)
-		_warpX->rotateCamera(xRot * yRot);
+		_warpX->rotateCamera(rot);
 	if (_warpY)
-		_warpY->rotateCamera(xRot * yRot);
+		_warpY->rotateCamera(rot);
 	if (_warpX)
 		_warpX->update();
 	if (_warpY)
diff --git a/engines/tetraedge/game/character.cpp b/engines/tetraedge/game/character.cpp
index 43d6a4abb26..ccfff6fa3da 100644
--- a/engines/tetraedge/game/character.cpp
+++ b/engines/tetraedge/game/character.cpp
@@ -1119,11 +1119,11 @@ Character::Water::Water() {
 	quad[1] = camMatrix.mult3x3(TeVector3f32( 0.1f, 0.0f,  0.1f));
 	quad[2] = camMatrix.mult3x3(TeVector3f32(-0.1f, 0.0f, -0.1f));
 	quad[3] = camMatrix.mult3x3(TeVector3f32( 0.1f, 0.0f, -0.1f));
-	TeQuaternion rot = TeQuaternion::fromEuler(TeVector3f32(0, 0, 0));
+	const TeQuaternion noRot = TeQuaternion::fromEuler(TeVector3f32(0, 0, 0));
 	TeIntrusivePtr<Te3DTexture> tex = Te3DTexture::makeInstance();
 	tex->load(g_engine->getCore()->findFile("texturesIngame/EauOndine1.tga"));
 	_model->setQuad(tex, quad, TeColor(255, 0, 0, 0));
-	_model->setRotation(rot);
+	_model->setRotation(noRot);
 	_model->setScale(TeVector3f32(0.5, 0.5, 0.5));
 	_colorAnim._duration = 2000.0f;
 	TeColor col = _model->color();
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index 9c5eb5e5f7e..cdce5a89cf7 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -175,7 +175,7 @@ bool InGameScene::addMarker(const Common::String &markerName, const Common::Stri
 float InGameScene::angularDistance(float a1, float a2) {
 	float result = a2 - a1;
 	if (result >= -M_PI && result > M_PI) {
-		result = result + -(M_PI * 2);
+		result = result - (M_PI * 2);
 	} else {
 		result = result + (M_PI * 2);
 	}
@@ -1764,7 +1764,7 @@ void InGameScene::update() {
 		if (obj->_rotateTime >= 0) {
 			float time = MIN((float)(obj->_rotateTimer.getTimeFromStart() / 1000000.0), obj->_rotateTime);
 			TeVector3f32 rot = (obj->_rotateAmount * (time / obj->_rotateTime));
-			TeQuaternion rotq = TeQuaternion::fromEuler(rot);
+			TeQuaternion rotq = TeQuaternion::fromEulerDegrees(rot);
 			obj->model()->setRotation(obj->_rotateStart * rotq);
 		}
 	}
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index ae76e8ddfb0..565f71f2ce9 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -917,7 +917,7 @@ static int tolua_ExportedFunctions_PlaceCharacterOnDummy00(lua_State *L) {
 }
 
 static void SetCharacterRotation(const Common::String &charname, float rx, float ry, float rz) {
-	TeQuaternion quat = TeQuaternion::fromEuler(TeVector3f32(rx * M_PI / 180.0, ry * M_PI / 180.0, rz * M_PI / 180.0));
+	const TeQuaternion quat = TeQuaternion::fromEulerDegrees(TeVector3f32(rx, ry, rz));
 	Game *game = g_engine->getGame();
 	Character *c = game->scene().character(charname);
 	if (c) {
@@ -1139,8 +1139,7 @@ static void SetGroundObjectRotation(const Common::String &objname, float x, floa
 		return;
 	}
 
-	TeVector3f32 rotvec(x * M_PI / 180.0, y * M_PI / 180.0, z * M_PI / 180.0);
-	obj->model()->setRotation(TeQuaternion::fromEuler(rotvec));
+	obj->model()->setRotation(TeQuaternion::fromEulerDegrees(TeVector3f32(x, y, z)));
 	obj->model()->setVisible(true);
 }
 
@@ -2055,8 +2054,7 @@ static void SetObjectRotation(const Common::String &obj, float xr, float yr, flo
 		warning("[SetObjectRotation] Object not found %s", obj.c_str());
 		return;
 	}
-	const TeVector3f32 rot(xr * M_PI / 180.0, yr * M_PI / 180.0, zr * M_PI / 180.0);
-	obj3d->_objRotation = TeQuaternion::fromEuler(rot);
+	obj3d->_objRotation = TeQuaternion::fromEulerDegrees(TeVector3f32(xr, yr, zr));
 }
 
 static int tolua_ExportedFunctions_SetObjectRotation00(lua_State *L) {
@@ -2964,7 +2962,7 @@ static void LookAt(int x, int y) {
 	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
 	assert(game);
 	game->setAngleX(-x);
-	int yval = y + -360;
+	int yval = y - 360;
 	if (y < 90)
 		yval = y;
 	game->setAngleY(-yval);
diff --git a/engines/tetraedge/game/object3d.h b/engines/tetraedge/game/object3d.h
index 2ce86bb1a87..a2ebd954a41 100644
--- a/engines/tetraedge/game/object3d.h
+++ b/engines/tetraedge/game/object3d.h
@@ -61,7 +61,7 @@ public:
 	float _rotateTime;
 	TeTimer _rotateTimer;
 	TeQuaternion _rotateStart;
-	TeVector3f32 _rotateAmount;
+	TeVector3f32 _rotateAmount; // Rotate vector in degrees
 
 	float _translateTime;
 	TeTimer _translateTimer;
diff --git a/engines/tetraedge/te/te_particle.cpp b/engines/tetraedge/te/te_particle.cpp
index e818596a879..8b954766d62 100644
--- a/engines/tetraedge/te/te_particle.cpp
+++ b/engines/tetraedge/te/te_particle.cpp
@@ -60,6 +60,7 @@ bool TeParticle::loadTexture(const Common::String &filename) {
 void TeParticle::setOrientation(const TeVector3f32 &orientation) {
 	// Divergence from original.. orientation is only ever used
 	// to calculate this matrix during update(), so just do it now.
+	// TODO: isn't this equivalent to using fromEuler?
 	_orientMatrix = TeMatrix4x4();
 	_orientMatrix.rotate(TeQuaternion::fromAxisAndAngle(TeVector3f32(1,  0, 0),
 							orientation.x() * M_PI / 180));
diff --git a/engines/tetraedge/te/te_quaternion.h b/engines/tetraedge/te/te_quaternion.h
index 26ef8e5103a..8eeced106ea 100644
--- a/engines/tetraedge/te/te_quaternion.h
+++ b/engines/tetraedge/te/te_quaternion.h
@@ -69,6 +69,13 @@ public:
 		return retval;
 	}
 
+	static TeQuaternion fromEulerDegrees(const TeVector3f32 &euler) {
+		const float xdeg = (float)(euler.x() * M_PI / 180.0);
+		const float ydeg = (float)(euler.y() * M_PI / 180.0);
+		const float zdeg = (float)(euler.z() * M_PI / 180.0);
+		return fromEuler(TeVector3f32(xdeg, ydeg, zdeg));
+	}
+
 	TeMatrix4x4 toTeMatrix() const {
 		const TeMatrix4x4 retval = toMatrix();
 		return retval.transpose();
diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp
index 31797c9f5ff..af5d83d1d77 100644
--- a/engines/tetraedge/te/te_warp.cpp
+++ b/engines/tetraedge/te/te_warp.cpp
@@ -165,7 +165,7 @@ void TeWarp::configMarker(const Common::String &objname, int markerImgNo, long m
 		}
 		foundId = anim->_markerIds[0];
 	}
-	assert(foundId >= 0 && foundId < _warpMarkers.size());
+	assert(foundId >= 0 && foundId < (long)_warpMarkers.size());
 
 	TeWarpMarker *warpMarker = _warpMarkers[foundId];
 	// The game uses TeSprite, but we use the layout system instead.


Commit: c011652f8a20aba691be981f92249bce6f64f870
    https://github.com/scummvm/scummvm/commit/c011652f8a20aba691be981f92249bce6f64f870
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-05-04T10:28:47+09:00

Commit Message:
TETRAEDGE: Fix Amerzone inventory updates

Changed paths:
    engines/tetraedge/game/amerzone_game.cpp
    engines/tetraedge/game/game.cpp
    engines/tetraedge/game/inventory.cpp
    engines/tetraedge/game/lua_binds.cpp
    engines/tetraedge/game/notifier.cpp
    engines/tetraedge/game/puzzle_disjoncteur.cpp
    engines/tetraedge/game/puzzle_disjoncteur.h
    engines/tetraedge/game/puzzle_hanjie.cpp
    engines/tetraedge/game/puzzle_hanjie.h
    engines/tetraedge/game/puzzle_liquides.cpp
    engines/tetraedge/game/puzzle_liquides.h


diff --git a/engines/tetraedge/game/amerzone_game.cpp b/engines/tetraedge/game/amerzone_game.cpp
index ddffe5d3398..b29ba0c947f 100644
--- a/engines/tetraedge/game/amerzone_game.cpp
+++ b/engines/tetraedge/game/amerzone_game.cpp
@@ -545,7 +545,7 @@ void AmerzoneGame::update() {
 			_warpY->setMouseLeftUpForMakers();
 	}
 
-	const TeQuaternion rot = TeQuaternion::fromEulerDegrees(TeVector3f32(_orientationX, _orientationY, 0));
+	const TeQuaternion rot = TeQuaternion::fromEulerDegrees(TeVector3f32(_orientationY, _orientationX, 0));
 
 	if (_warpX)
 		_warpX->rotateCamera(rot);
diff --git a/engines/tetraedge/game/game.cpp b/engines/tetraedge/game/game.cpp
index 3826d9c0338..64820bc1007 100644
--- a/engines/tetraedge/game/game.cpp
+++ b/engines/tetraedge/game/game.cpp
@@ -68,8 +68,16 @@ Game::~Game() {
 };
 
 void Game::addNoScale2Child(TeLayout *layout) {
-	if (_noScaleLayout2 && layout) {
-		_noScaleLayout2->addChild(layout);
+	if (!layout)
+		return;
+
+	if (!g_engine->gameIsAmerzone()) {
+		if (_noScaleLayout2) {
+			_noScaleLayout2->addChild(layout);
+		}
+	} else {
+		// No _noScaleLayout in Amerzone, just use front
+		g_engine->getApplication()->frontLayout().addChild(layout);
 	}
 }
 
@@ -377,9 +385,16 @@ void Game::playSound(const Common::String &name, int repeats, float volume) {
 }
 
 void Game::removeNoScale2Child(TeLayout *layout) {
-	if (!_noScaleLayout2 || !layout)
+	if (!layout)
 		return;
-	_noScaleLayout2->removeChild(layout);
+
+	if (!g_engine->gameIsAmerzone()) {
+		if (_noScaleLayout2)
+			_noScaleLayout2->removeChild(layout);
+	} else {
+		// No _noScaleLayout in Amerzone, just use front
+		g_engine->getApplication()->frontLayout().removeChild(layout);
+	}
 }
 
 void Game::resumeMovie() {
diff --git a/engines/tetraedge/game/inventory.cpp b/engines/tetraedge/game/inventory.cpp
index 52253dd53d9..314a9ae1cbc 100644
--- a/engines/tetraedge/game/inventory.cpp
+++ b/engines/tetraedge/game/inventory.cpp
@@ -262,18 +262,21 @@ bool Inventory::addObject(InventoryObject *obj) {
 				break;
 			}
 
-			TeTextLayout *newText = new TeTextLayout();
-			newText->setSizeType(CoordinatesType::RELATIVE_TO_PARENT);
-			newText->setPosition(TeVector3f32(1.0, 1.0, 0.0));
-			newText->setSize(TeVector3f32(1.0, 1.0, 0.0));
-			newText->setTextSizeType(1);
-			newText->setTextSizeProportionalToWidth(200);
-			newText->setText(_gui.value("textAttributs").toString() + objectName((*invObjIter)->name()));
-			newText->setName((*invObjIter)->name());
-			newText->setVisible(false);
-
-			TeLayout *layout = _gui.layout("textObject");
-			layout->addChild(newText);
+			if (!g_engine->gameIsAmerzone()) {
+				TeTextLayout *newText = new TeTextLayout();
+				newText->setSizeType(CoordinatesType::RELATIVE_TO_PARENT);
+				newText->setPosition(TeVector3f32(1.0, 1.0, 0.0));
+				newText->setSize(TeVector3f32(1.0, 1.0, 0.0));
+				newText->setTextSizeType(1);
+				newText->setTextSizeProportionalToWidth(200);
+				newText->setText(_gui.value("textAttributs").toString() + objectName((*invObjIter)->name()));
+				newText->setName((*invObjIter)->name());
+				newText->setVisible(false);
+
+				TeLayout *layout = _gui.layout("textObject");
+				layout->addChild(newText);
+			}
+
 			slot->addChild(*invObjIter);
 
 			totalSlots++;
@@ -351,7 +354,8 @@ bool Inventory::onMainMenuButton() {
 bool Inventory::onObjectSelected(InventoryObject &obj) {
 	selectedObject(&obj);
 	if (_selectedTimer.running()) {
-		if (_selectedTimer.timeElapsed() < 300000)
+		uint64 timeout = g_engine->gameIsAmerzone() ? 250000 : 300000;
+		if (_selectedTimer.timeElapsed() < timeout)
 			g_engine->getGame()->inventoryMenu().leave();
 	} else {
 		_selectedTimer.start();
@@ -489,13 +493,18 @@ void Inventory::selectedObject(const Common::String &objname) {
 void Inventory::selectedObject(InventoryObject *obj) {
 	Game *game = g_engine->getGame();
 	game->setCurrentObjectSprite("");
-	_gui.layoutChecked("prendre")->setVisible(false);
-	_gui.layoutChecked("textObject")->setVisible(false);
+
+	if (!g_engine->gameIsAmerzone()) {
+		_gui.layoutChecked("prendre")->setVisible(false);
+		_gui.layoutChecked("textObject")->setVisible(false);
+	}
 	_selectedObject = obj;
 	if (!obj) {
 		_gui.spriteLayoutChecked("selectionSprite")->setVisible(false);
-		_gui.textLayout("text")->setText("");
-		game->inGameGui().spriteLayoutChecked("selectedObject")->unload();
+		if (!g_engine->gameIsAmerzone()) {
+			_gui.textLayout("text")->setText("");
+			game->inGameGui().spriteLayoutChecked("selectedObject")->unload();
+		}
 	} else {
 		TeSpriteLayout *selection = _gui.spriteLayoutChecked("selectionSprite");
 		selection->setVisible(obj->worldVisible());
@@ -505,25 +514,30 @@ void Inventory::selectedObject(InventoryObject *obj) {
 		TeVector3f32 pos = parentLayout->position();
 		pos.z() = selection->position().z();
 		selection->setPosition(pos);
-		const Common::String &objId = obj->name();
-		static const char *textStyle = "<section style=\"center\" /><color r=\"200\" g=\"200\" b=\"200\"/><font file=\"Common/Fonts/Colaborate-Regular.otf\" size=\"24\" />";
-		Common::String text = Common::String::format("%s%s<br/>%s", textStyle,
-					objectName(objId).c_str(),
-					objectDescription(objId).c_str());
-		_gui.textLayout("text")->setText(text);
-		_gui.buttonLayoutChecked("lire")->setEnable(isDocument(objId));
+
 		const Common::String spritePathStr = obj->spritePath();
 		game->setCurrentObjectSprite(spritePathStr);
-		TeLayout *textObj = _gui.layout("textObject");
-		for (int i = 0; i < textObj->childCount(); i++) {
-			if (textObj->child(i)->name() == obj->name()) {
-				textObj->setVisible(true);
-				textObj->child(i)->setVisible(true);
-			} else {
-				textObj->child(i)->setVisible(false);
+
+		if (!g_engine->gameIsAmerzone()) {
+			const Common::String &objId = obj->name();
+			static const char *textStyle = "<section style=\"center\" /><color r=\"200\" g=\"200\" b=\"200\"/><font file=\"Common/Fonts/Colaborate-Regular.otf\" size=\"24\" />";
+			Common::String text = Common::String::format("%s%s<br/>%s", textStyle,
+						objectName(objId).c_str(),
+						objectDescription(objId).c_str());
+			_gui.textLayout("text")->setText(text);
+
+			_gui.buttonLayoutChecked("lire")->setEnable(isDocument(objId));
+			TeLayout *textObj = _gui.layout("textObject");
+			for (int i = 0; i < textObj->childCount(); i++) {
+				if (textObj->child(i)->name() == obj->name()) {
+					textObj->setVisible(true);
+					textObj->child(i)->setVisible(true);
+				} else {
+					textObj->child(i)->setVisible(false);
+				}
 			}
+			game->inGameGui().spriteLayoutChecked("selectedObject")->load(spritePathStr);
 		}
-		game->inGameGui().spriteLayoutChecked("selectedObject")->load(spritePathStr);
 	}
 }
 
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index 565f71f2ce9..eb3a7d4cb74 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -207,7 +207,8 @@ static int tolua_ExportedFunctions_Selected00(lua_State *L) {
 
 static void TakeObject_Amerzone(const Common::String &obj) {
 	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
-	assert(game);
+	assert(game && game->warpY());
+	debug("TakeObject: lastObj %s, obj %s", game->lastHitObjectName().c_str(), obj.c_str());
 	game->luaContext().setGlobal(game->lastHitObjectName(), true);
 	game->warpY()->takeObject(game->lastHitObjectName());
 	if (!obj.empty()) {
@@ -2915,14 +2916,21 @@ static int tolua_ExportedFunctions_RemoveObject00_Amerzone(lua_State *L) {
 	error("#ferror in function 'RemoveObject': %d %d %s", err.index, err.array, err.type);
 }
 
+static void AddToBag(const Common::String &name) {
+	Game *game = g_engine->getGame();
+	game->addToBag(name);
+	TeSoundManager *sndMgr = g_engine->getSoundManager();
+	sndMgr->playFreeSound("Sounds/SFX/N_prendre.ogg");
+}
+
 static int tolua_ExportedFunctions_AddToBag00(lua_State *L) {
 	tolua_Error err;
 	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
 		Common::String s1(tolua_tostring(L, 1, nullptr));
-		debug("%s", s1.c_str());
+		AddToBag(s1);
 		return 0;
 	}
-	error("#ferror in function 'PrintDebugMessage': %d %d %s", err.index, err.array, err.type);
+	error("#ferror in function 'AddToBag': %d %d %s", err.index, err.array, err.type);
 }
 
 void SaveGame(const Common::String &name) {
@@ -2961,11 +2969,13 @@ static int tolua_ExportedFunctions_SetMarker00(lua_State *L) {
 static void LookAt(int x, int y) {
 	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
 	assert(game);
-	game->setAngleX(-x);
+	// Note: Reverse the angles to what the game does, because we apply them
+	// using fromEuler.
+	game->setAngleX(x);
 	int yval = y - 360;
 	if (y < 90)
 		yval = y;
-	game->setAngleY(-yval);
+	game->setAngleY(yval);
 }
 
 static int tolua_ExportedFunctions_LookAt00(lua_State *L) {
diff --git a/engines/tetraedge/game/notifier.cpp b/engines/tetraedge/game/notifier.cpp
index 1e652f3c6cd..dd1cfcaa5c8 100644
--- a/engines/tetraedge/game/notifier.cpp
+++ b/engines/tetraedge/game/notifier.cpp
@@ -29,6 +29,10 @@ namespace Tetraedge {
 Notifier::Notifier() {
 }
 
+static const char *notifyLayoutName() {
+	return g_engine->gameIsAmerzone() ? "notify" : "notifier";
+}
+
 void Notifier::launchNextnotifier() {
 	TeCurveAnim2<Te3DObject2, TeColor> *colorAnim = _gui.colorLinearAnimation("fadeIn");
 	assert(colorAnim);
@@ -58,19 +62,21 @@ void Notifier::launchNextnotifier() {
 	TeITextLayout *text = _gui.textLayout("text");
 	text->setText(formattedName);
 
-	if (!_notifierDataArray[0]._imgpath.empty()) {
+	if (!_notifierDataArray[0]._imgpath.empty() && !g_engine->gameIsAmerzone()) {
 		_gui.spriteLayoutChecked("image")->load(_notifierDataArray[0]._imgpath);
 	}
 
-	_gui.layoutChecked("notifier")->setVisible(true);
+	_gui.layoutChecked(notifyLayoutName())->setVisible(true);
 
 	colorAnim = _gui.colorLinearAnimation("fadeIn");
 	colorAnim->_callbackObj = _gui.layoutChecked("sprite");
 	colorAnim->play();
 
-	colorAnim = _gui.colorLinearAnimation("fadeInImage");
-	colorAnim->_callbackObj = _gui.layoutChecked("image");
-	colorAnim->play();
+	if (!g_engine->gameIsAmerzone()) {
+		colorAnim = _gui.colorLinearAnimation("fadeInImage");
+		colorAnim->_callbackObj = _gui.layoutChecked("image");
+		colorAnim->play();
+	}
 
 	_notifierDataArray.remove_at(0);
 }
@@ -78,10 +84,8 @@ void Notifier::launchNextnotifier() {
 void Notifier::load() {
 	const char *luaPath = g_engine->gameIsAmerzone() ? "GUI/Notify.lua" : "menus/Notifier.lua";
 	_gui.load(luaPath);
-	const char *layoutName = g_engine->gameIsAmerzone() ? "notify" : "notifier";
-	TeLayout *notifierLayout = _gui.layoutChecked(layoutName);
-	Game *game = g_engine->getGame();
-	game->addNoScale2Child(notifierLayout);
+	TeLayout *notifierLayout = _gui.layoutChecked(notifyLayoutName());
+	g_engine->getGame()->addNoScale2Child(notifierLayout);
 	notifierLayout->setVisible(false);
 
 	TeCurveAnim2<Te3DObject2, TeColor> *fadeIn = _gui.colorLinearAnimation("fadeIn");
@@ -99,15 +103,17 @@ bool Notifier::onFadeInFinished() {
 	colorAnim->_callbackObj = _gui.layout("sprite");
 	colorAnim->play();
 
-	colorAnim = _gui.colorLinearAnimation("visibleImage");
-	colorAnim->_callbackObj = _gui.layout("image");
-	colorAnim->play();
+	if (!g_engine->gameIsAmerzone()) {
+		colorAnim = _gui.colorLinearAnimation("visibleImage");
+		colorAnim->_callbackObj = _gui.layout("image");
+		colorAnim->play();
+	}
 
 	return false;
 }
 
 bool Notifier::onFadeOutFinished() {
-	TeLayout *notifierLayout = _gui.layout("notifier");
+	TeLayout *notifierLayout = _gui.layoutChecked(notifyLayoutName());
 	notifierLayout->setVisible(false);
 	launchNextnotifier();
 	return false;
@@ -118,9 +124,11 @@ bool Notifier::onVisibleFinished() {
 	colorAnim->_callbackObj = _gui.layout("sprite");
 	colorAnim->play();
 
-	colorAnim = _gui.colorLinearAnimation("fadeOutImage");
-	colorAnim->_callbackObj = _gui.layout("image");
-	colorAnim->play();
+	if (!g_engine->gameIsAmerzone()) {
+		colorAnim = _gui.colorLinearAnimation("fadeOutImage");
+		colorAnim->_callbackObj = _gui.layout("image");
+		colorAnim->play();
+	}
 	return false;
 }
 
@@ -131,7 +139,7 @@ void Notifier::push(const Common::String &name, const Common::String &imgpath) {
 }
 
 void Notifier::unload() {
-	TeLayout *layout = _gui.layout("notifier");
+	TeLayout *layout = _gui.layoutChecked(notifyLayoutName());
 	g_engine->getGame()->removeNoScale2Child(layout);
 	_gui.unload();
 }
diff --git a/engines/tetraedge/game/puzzle_disjoncteur.cpp b/engines/tetraedge/game/puzzle_disjoncteur.cpp
index 8d61c74a80a..726bbe99558 100644
--- a/engines/tetraedge/game/puzzle_disjoncteur.cpp
+++ b/engines/tetraedge/game/puzzle_disjoncteur.cpp
@@ -23,13 +23,60 @@
 
 namespace Tetraedge {
 
-PuzzleDisjoncteur::PuzzleDisjoncteur() {
+PuzzleDisjoncteur::PuzzleDisjoncteur() : _state(0) {
 }
 
 void PuzzleDisjoncteur::wakeUp() {
 	error("TODO: Implement PuzzleDisjoncteur::wakeUp");
 }
 
-// TODO: Add more functions here.
+void PuzzleDisjoncteur::sleep() {
+	error("TODO: Implement PuzzleDisjoncteur::sleep");
+}
+
+void PuzzleDisjoncteur::addState(uint32 flags) {
+	if (!(_state & flags))
+		_state += flags;
+}
+
+void PuzzleDisjoncteur::removeState(uint32 flags) {
+	if (_state & flags)
+		_state -= flags;
+}
+
+void PuzzleDisjoncteur::setDraggedSprite(TeSpriteLayout *sprite) {
+	error("TODO: Implement PuzzleDisjoncteur::setDraggedSprite");
+}
+
+void PuzzleDisjoncteur::setDraggedSpriteBack() {
+	error("TODO: Implement PuzzleDisjoncteur::setDraggedSpriteBack");
+}
+
+bool PuzzleDisjoncteur::onExitButton() {
+	sleep();
+	return false;
+}
+
+bool PuzzleDisjoncteur::onLevierAnimFinished() {
+	error("TODO: Implement PuzzleDisjoncteur::onLevierAnimFinished");
+}
+
+bool PuzzleDisjoncteur::onMouseDown(const Common::Point &pt) {
+	error("TODO: Implement PuzzleDisjoncteur::onMouseDown");
+}
+
+bool PuzzleDisjoncteur::onMouseMove(const Common::Point &pt) {
+	error("TODO: Implement PuzzleDisjoncteur::onMouseMove");
+}
+
+bool PuzzleDisjoncteur::onMouseUp(const Common::Point &pt) {
+	error("TODO: Implement PuzzleDisjoncteur::onMouseUp");
+}
+
+bool PuzzleDisjoncteur::onWinTimer() {
+	sleep();
+	return false;
+}
+
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/game/puzzle_disjoncteur.h b/engines/tetraedge/game/puzzle_disjoncteur.h
index d539631f954..4c71cda7564 100644
--- a/engines/tetraedge/game/puzzle_disjoncteur.h
+++ b/engines/tetraedge/game/puzzle_disjoncteur.h
@@ -23,6 +23,8 @@
 #define TETRAEDGE_GAME_PUZZLE_DISJONCTEUR_H
 
 #include "tetraedge/te/te_3d_object2.h"
+#include "tetraedge/te/te_sprite_layout.h"
+#include "tetraedge/te/te_xml_gui.h"
 
 namespace Tetraedge {
 
@@ -31,12 +33,24 @@ public:
 	PuzzleDisjoncteur();
 
 	void wakeUp();
-
-	// TODO add public members
+	void sleep();
 
 private:
-	// TODO add private members
-
+	void addState(uint32 flags);
+	void removeState(uint32 flags);
+	void setDraggedSprite(TeSpriteLayout *sprite);
+	void setDraggedSpriteBack();
+	void setState(uint32 flags) { _state = flags; }
+
+	bool onExitButton();
+	bool onLevierAnimFinished();
+	bool onMouseDown(const Common::Point &pt);
+	bool onMouseMove(const Common::Point &pt);
+	bool onMouseUp(const Common::Point &pt);
+	bool onWinTimer();
+
+	TeXmlGui _gui;
+	uint32 _state;
 };
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/game/puzzle_hanjie.cpp b/engines/tetraedge/game/puzzle_hanjie.cpp
index 4759af79beb..45d42b5ca2c 100644
--- a/engines/tetraedge/game/puzzle_hanjie.cpp
+++ b/engines/tetraedge/game/puzzle_hanjie.cpp
@@ -31,7 +31,7 @@ static const char *BG_NAMES[] = {"Amenta", "Croix", "Echelle", "Sang", "Trident"
 
 PuzzleHanjie::PuzzleHanjie() : _exitButton(nullptr), _entered(false), _foregroundSprite(nullptr), _backgroundNo(0) {
 	ARRAYCLEAR(_sprites);
-	ARRAYCLEAR(_expectedVals, 0);
+	ARRAYCLEAR(_expectedVals, false);
 }
 
 void PuzzleHanjie::wakeUp() {
@@ -72,7 +72,7 @@ void PuzzleHanjie::wakeUp() {
 		if (splitData.size() != 7)
 			error("Invalid puzzle data for %s: %s", key.c_str(), data.c_str());
 		for (uint col = 0; col < 7; col++) {
-			_expectedVals[row * 7 + col] = (splitData[col] == "1" ? 1 : 0);
+			_expectedVals[row * 7 + col] = (splitData[col] == "1");
 		}
 	}
 
@@ -98,6 +98,14 @@ void PuzzleHanjie::sleep() {
 	game->warpY()->setVisible(true, false);
 }
 
+bool PuzzleHanjie::isSolved() {
+	for (uint i = 0; i < ARRAYSIZE(_expectedVals); i++) {
+		if (_expectedVals[i] != _sprites[i]->visible())
+			return false;
+	}
+	return true;
+}
+
 bool PuzzleHanjie::onExitButton() {
 	sleep();
 	return false;
diff --git a/engines/tetraedge/game/puzzle_hanjie.h b/engines/tetraedge/game/puzzle_hanjie.h
index 26c6e447789..e8e09484bec 100644
--- a/engines/tetraedge/game/puzzle_hanjie.h
+++ b/engines/tetraedge/game/puzzle_hanjie.h
@@ -38,6 +38,7 @@ public:
 	void sleep();
 
 private:
+	bool isSolved();
 	bool onExitButton();
 	bool onWinTimer();
 	bool onMouseUp(const Common::Point &pt);
@@ -53,8 +54,7 @@ private:
 	Common::String _bgImg;
 	Common::String _soundBegin;
 	TeSpriteLayout _bgSprite;
-	int _expectedVals[49];
-	// TODO add private members
+	bool _expectedVals[49];
 
 };
 
diff --git a/engines/tetraedge/game/puzzle_liquides.cpp b/engines/tetraedge/game/puzzle_liquides.cpp
index 463e07e87e9..19b797efefe 100644
--- a/engines/tetraedge/game/puzzle_liquides.cpp
+++ b/engines/tetraedge/game/puzzle_liquides.cpp
@@ -30,6 +30,10 @@ void PuzzleLiquides::wakeUp() {
 	error("TODO: Implement PuzzleLiquides::wakeUp");
 }
 
+void PuzzleLiquides::sleep() {
+	error("TODO: Implement PuzzleLiquides::sleep");
+}
+
 // TODO: Add more functions here.
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/game/puzzle_liquides.h b/engines/tetraedge/game/puzzle_liquides.h
index 518ddc9761a..58b4e1f4e05 100644
--- a/engines/tetraedge/game/puzzle_liquides.h
+++ b/engines/tetraedge/game/puzzle_liquides.h
@@ -31,11 +31,18 @@ public:
 	PuzzleLiquides();
 
 	void wakeUp();
-
-	// TODO add public members
+	void sleep();
 
 private:
-	// TODO add private members
+	void initCase();
+	bool isAdjacent(int x, int y);
+	bool isSolved();
+
+	bool onExitButton();
+	bool onMouseDown(const Common::Point &pt);
+	bool onMouseMove(const Common::Point &pt);
+	bool onMouseUp(const Common::Point &pt);
+	bool onWinTimer();
 
 };
 


Commit: 1072856f89d9b4dc0144db1cb2ea19e496f86814
    https://github.com/scummvm/scummvm/commit/1072856f89d9b4dc0144db1cb2ea19e496f86814
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-05-04T10:28:47+09:00

Commit Message:
TETRAEDGE: Add loading support for tef font format

Still needs some fixes on the rendering side, but loading is working.

Changed paths:
  A engines/tetraedge/te/te_font2.cpp
  A engines/tetraedge/te/te_font2.h
  A engines/tetraedge/te/te_i_font.cpp
  A engines/tetraedge/te/te_i_font.h
    engines/tetraedge/game/application.cpp
    engines/tetraedge/game/notifier.cpp
    engines/tetraedge/module.mk
    engines/tetraedge/te/te_font3.cpp
    engines/tetraedge/te/te_font3.h
    engines/tetraedge/te/te_png.cpp
    engines/tetraedge/te/te_text_base2.cpp
    engines/tetraedge/te/te_text_base2.h
    engines/tetraedge/te/te_text_layout.cpp
    engines/tetraedge/te/te_text_layout_xml_parser.cpp
    engines/tetraedge/te/te_text_layout_xml_parser.h
    engines/tetraedge/te/te_warp.cpp


diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp
index 2c6203ba1d6..a94275ba54f 100644
--- a/engines/tetraedge/game/application.cpp
+++ b/engines/tetraedge/game/application.cpp
@@ -36,6 +36,7 @@
 #include "tetraedge/te/te_core.h"
 #include "tetraedge/te/te_resource_manager.h"
 #include "tetraedge/te/te_renderer.h"
+#include "tetraedge/te/te_font2.h"
 #include "tetraedge/te/te_font3.h"
 #include "tetraedge/te/te_input_mgr.h"
 #include "tetraedge/te/te_sound_manager.h"
@@ -119,12 +120,23 @@ void Application::create() {
 
 	TeResourceManager *resmgr = g_engine->getResourceManager();
 	TeCore *core = g_engine->getCore();
-	_fontComic = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/ComicRelief.ttf"));
-	_fontArgh = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/Argh.ttf"));
-	_fontArial = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/arial.ttf"));
-	_fontChaucer = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/CHAUCER.TTF"));
-	_fontColaborate = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/Colaborate-Regular.otf"));
-	_fontProDisplay = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/ProDisplay.ttf"));
+	// Cache some fonts
+	if (g_engine->gameIsAmerzone()) {
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Arial_r_10.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Arial_r_12.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Arial_r_16.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Colaborate-Regular_r_16.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Colaborate-Regular_r_24.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/Credits.tef"));
+		resmgr->getResource<TeFont2>(core->findFile("Common/Fonts/FontLoadingMenu.tef"));
+	} else {
+		_fontComic = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/ComicRelief.ttf"));
+		_fontArgh = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/Argh.ttf"));
+		_fontArial = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/arial.ttf"));
+		_fontChaucer = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/CHAUCER.TTF"));
+		_fontColaborate = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/Colaborate-Regular.otf"));
+		_fontProDisplay = resmgr->getResource<TeFont3>(core->findFile("Common/Fonts/ProDisplay.ttf"));
+	}
 
 	// The app prebuilds some fonts.. cover letters, numbers, a few accented chars, and punctuation.
 	// Skip that here.
diff --git a/engines/tetraedge/game/notifier.cpp b/engines/tetraedge/game/notifier.cpp
index dd1cfcaa5c8..c4e3b6eafe2 100644
--- a/engines/tetraedge/game/notifier.cpp
+++ b/engines/tetraedge/game/notifier.cpp
@@ -56,13 +56,18 @@ void Notifier::launchNextnotifier() {
 	if (_notifierDataArray.empty())
 		return;
 
-	TeVariant textformat = _gui.value("textFormat");
-	Common::String formattedName = Common::String::format(textformat.toString().c_str(), _notifierDataArray[0]._name.c_str());
+	Common::String textformat = _gui.value("textFormat").toString();
+	Common::String formattedName;
+	if (!textformat.empty())
+		formattedName = Common::String::format(textformat.c_str(), _notifierDataArray[0]._name.c_str());
+	else
+		formattedName = _notifierDataArray[0]._name;
 
 	TeITextLayout *text = _gui.textLayout("text");
 	text->setText(formattedName);
 
-	if (!_notifierDataArray[0]._imgpath.empty() && !g_engine->gameIsAmerzone()) {
+	if (!_notifierDataArray[0]._imgpath.empty()) {
+		assert(!g_engine->gameIsAmerzone());
 		_gui.spriteLayoutChecked("image")->load(_notifierDataArray[0]._imgpath);
 	}
 
diff --git a/engines/tetraedge/module.mk b/engines/tetraedge/module.mk
index 6fe6f25a128..30ac79e4496 100644
--- a/engines/tetraedge/module.mk
+++ b/engines/tetraedge/module.mk
@@ -69,11 +69,13 @@ MODULE_OBJS := \
 	te/te_color.o \
 	te/te_core.o \
 	te/te_extended_text_layout.o \
+	te/te_font2.o \
 	te/te_font3.o \
 	te/te_frame_anim.o \
 	te/te_free_move_zone.o \
 	te/te_frustum.o \
 	te/te_i_3d_object2.o \
+	te/te_i_font.o \
 	te/te_i_layout.o \
 	te/te_i_loc.o \
 	te/te_i_text_layout.o \
diff --git a/engines/tetraedge/te/te_font2.cpp b/engines/tetraedge/te/te_font2.cpp
new file mode 100644
index 00000000000..c390c836ba3
--- /dev/null
+++ b/engines/tetraedge/te/te_font2.cpp
@@ -0,0 +1,206 @@
+/* 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 "tetraedge/te/te_font2.h"
+
+#include "tetraedge/tetraedge.h"
+#include "tetraedge/te/te_3d_object2.h"
+#include "tetraedge/te/te_core.h"
+
+namespace Tetraedge {
+
+bool operator==(const KernChars &l, const KernChars &r) {
+	return l._c1 == r._c1 && l._c2 == r._c2;
+}
+
+TeFont2::TeFont2() : _numChars(0), _hasKernData(false), _maxHeight(0) {
+}
+
+TeFont2::~TeFont2() {
+}
+
+bool TeFont2::load(const Common::String &path) {
+	if (_loadedPath == path)
+		return true; // already open
+
+	TeCore *core = g_engine->getCore();
+	Common::FSNode node = core->findFile(path);
+	return load(node);
+}
+
+bool TeFont2::load(const Common::FSNode &node) {
+	const Common::String path = node.getPath();
+
+	unload();
+	setAccessName(path);
+	_loadedPath = path;
+
+	if (!node.isReadable()) {
+		warning("TeFont2::load: Can't read from %s", path.c_str());
+		return false;
+	}
+
+	Common::File file;
+	file.open(node);
+
+	if (!Te3DObject2::loadAndCheckFourCC(file, "TESF")) {
+		warning("TeFont2::load: Invalid magic in %s", path.c_str());
+		return false;
+	}
+
+	_numChars = file.readUint32LE();
+	if (_numChars > 65535)
+		error("TeFont2::load: improbable number of char points %d", _numChars);
+	TeVector2s32::deserialize(file, _somePt);
+	TeVector3f32::deserialize(file, _someVec);
+	_hasKernData = (file.readByte() != 0);
+	if (_hasKernData) {
+		uint32 numKernData = file.readUint32LE();
+		if (numKernData > 10000)
+			error("TeFont2::load: improbable number of kerning points %d", numKernData);
+		for (uint32 i = 0; i < numKernData; i++) {
+			KernChars kc;
+			TeVector3f32 vec;
+			kc._c1 = file.readUint32LE();
+			kc._c2 = file.readUint32LE();
+			vec.x() = file.readFloatLE();
+			vec.y() = file.readFloatLE();
+			_kernData[kc] = vec;
+			//debug("KernChars: '%c'-'%c' (%.2f, %.2f)", (char)kc._c1, (char)kc._c2, vec.x(), vec.y());
+		}
+	}
+
+	for (uint32 i = 0; i < _numChars; i++) {
+		GlyphData2 g;
+		g._xSz = file.readFloatLE();
+		g._ySz = file.readFloatLE();
+		_maxHeight = MAX(_maxHeight, g._ySz);
+		g._xOff = file.readFloatLE();
+		g._yOff = file.readFloatLE();
+		g._xAdvance = file.readFloatLE();
+		// TODO: What are these other floats?
+		for (uint j = 0; j < 3; j++)
+			g._floats[j] = file.readFloatLE();
+		g._vec.x() = file.readFloatLE();
+		g._vec.y() = file.readFloatLE();
+		_glyphs.push_back(g);
+		uint32 charNo = file.readUint32LE();
+		_uintArray.push_back(charNo);
+		/*
+		if (i >= 35 && i <= 127)
+			debug("Char data %c: sz (%.1f %.1f) off (%.1f %.1f) xadv %.1f %.1f %.1f %.1f texloc (%.1f, %.1f) %d", (char)i,
+				g._xSz, g._ySz, g._xOff, g._yOff, g._xAdvance, g._floats[0], g._floats[1], g._floats[2],
+				g._vec.x(), g._vec.y(), charNo);
+		*/
+	}
+
+	if (!_texture.load(file, "png")) {
+		warning("Invalid png data in %s", path.c_str());
+		return false;
+	}
+
+	return true;
+}
+
+void TeFont2::unload() {
+	_texture.free();
+	_uintArray.clear();
+	_glyphs.clear();
+	_kernData.clear();
+	_numChars = 0;
+}
+
+int TeFont2::getFontHeight() const {
+	return _maxHeight;
+}
+
+int TeFont2::getMaxCharWidth() const {
+	int maxWidth = 0;
+	for (auto &glyph : _glyphs) {
+		maxWidth = MAX(maxWidth, (int)glyph._xAdvance);
+	}
+	return maxWidth;
+}
+
+int TeFont2::getCharWidth(uint32 chr) const {
+	if (chr >= _glyphs.size())
+		return 0;
+	return (int)_glyphs[chr]._xAdvance;
+}
+
+void TeFont2::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+	if (chr >= _glyphs.size())
+		return;
+
+	if (_texture.empty())
+		error("Call to TeFont2::drawChar but no texture loaded");
+	const GlyphData2 g = _glyphs[chr];
+
+	Common::Rect srcRect;
+	srcRect.left = (int)g._vec.x();
+	srcRect.top = _texture.h - (int)g._vec.y();
+	srcRect.right = srcRect.left + g._xSz;
+	srcRect.bottom = srcRect.top + g._ySz;
+
+	int dstX = x + g._xOff;
+	int dstY = _maxHeight - g._yOff;
+
+	dst->copyRectToSurface(_texture, dstX, dstY, srcRect);
+}
+
+int TeFont2::getKerningOffset(uint32 left, uint32 right) const {
+	KernChars kc { left, right };
+	if (_kernData.contains(kc))
+		return (int)_kernData[kc].x();
+	return 0;
+}
+
+TeVector3f32 TeFont2::kerning(uint pxSize, uint isocode1, uint isocode2) {
+	KernChars kc { isocode1, isocode2 };
+	if (_kernData.contains(kc))
+		return _kernData[kc];
+	return TeVector3f32();
+}
+
+Common::Rect TeFont2::getBoundingBox(const Common::String &str, int fontSize) {
+	Common::Rect rect;
+	for (uint i = 0; i < str.size(); i++) {
+		uint c = str[i];
+		if (c >= _glyphs.size())
+			continue;
+		const GlyphData2 &g = _glyphs[c];
+		rect.top = MIN(rect.top, (int16)-g._yOff);
+		rect.bottom = MAX(rect.bottom, (int16)(-g._yOff + g._ySz));
+		rect.right += g._xAdvance;
+	}
+	return rect;
+}
+
+float TeFont2::height(uint pxSize) {
+	return _maxHeight;
+}
+
+Graphics::Font *TeFont2::getAtSize(uint size) {
+	return this;
+}
+
+
+} // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_font2.h b/engines/tetraedge/te/te_font2.h
new file mode 100644
index 00000000000..4b9147806d6
--- /dev/null
+++ b/engines/tetraedge/te/te_font2.h
@@ -0,0 +1,106 @@
+/* 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 TETRAEDGE_TE_TE_FONT2_H
+#define TETRAEDGE_TE_TE_FONT2_H
+
+#include "common/str.h"
+#include "common/file.h"
+#include "common/hashmap.h"
+#include "graphics/font.h"
+
+#include "tetraedge/te/te_resource.h"
+#include "tetraedge/te/te_vector2s32.h"
+#include "tetraedge/te/te_vector3f32.h"
+#include "tetraedge/te/te_3d_texture.h"
+#include "tetraedge/te/te_intrusive_ptr.h"
+#include "tetraedge/te/te_i_font.h"
+
+namespace Tetraedge {
+	struct KernChars {
+		uint32 _c1;
+		uint32 _c2;
+	};
+	bool operator==(const KernChars &l, const KernChars &r);
+}
+
+namespace Common {
+	template<> struct Hash<Tetraedge::KernChars> : public UnaryFunction<Tetraedge::KernChars, uint> {
+		uint operator()(Tetraedge::KernChars val) const { return val._c1 * 7333 + val._c2; }
+	};
+}
+
+namespace Tetraedge {
+
+/**
+ * A pre-rendered font format with positioning data used in Amerzone
+ * ('tef' format)
+ */
+class TeFont2 : public TeIFont, public Graphics::Font {
+public:
+
+	struct GlyphData2 {
+		float _xSz;
+		float _ySz;
+		float _xOff; // from nominal location
+		float _yOff; // top location, from baseline
+		float _xAdvance;
+		float _floats[3];
+		TeVector3f32 _vec; // location in texture - offset from bottom left
+	};
+
+	TeFont2();
+	virtual ~TeFont2();
+
+	bool load(const Common::String &path);
+	bool load(const Common::FSNode &node);
+	void unload();
+
+	Graphics::Font *getAtSize(uint size) override;
+
+	virtual int getFontHeight() const override;
+	virtual int getMaxCharWidth() const override;
+	virtual int getCharWidth(uint32 chr) const override;
+	virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+	virtual int getKerningOffset(uint32 left, uint32 right) const override;
+	virtual Common::Rect getBoundingBox(const Common::String &str, int fontSize) override;
+	virtual TeVector3f32 kerning(uint pxSize, uint isocode1, uint isocode2) override;
+
+	virtual float height(uint pxSize) override;
+
+private:
+	Common::String _loadedPath;
+
+	uint32 _numChars;
+	TeVector2s32 _somePt;
+	TeVector3f32 _someVec;
+	bool _hasKernData;
+	float _maxHeight;
+	// Records a map of character pairs to kerning offsets
+	Common::HashMap<KernChars, TeVector3f32> _kernData;
+	Common::Array<uint32> _uintArray;
+	Common::Array<GlyphData2> _glyphs;
+	TeImage _texture;
+};
+
+} // end namespace Tetraedge
+
+#endif // TETRAEDGE_TE_TE_FONT2_H
diff --git a/engines/tetraedge/te/te_font3.cpp b/engines/tetraedge/te/te_font3.cpp
index 289a95ab41b..b4edfe4e1c9 100644
--- a/engines/tetraedge/te/te_font3.cpp
+++ b/engines/tetraedge/te/te_font3.cpp
@@ -32,44 +32,7 @@
 
 namespace Tetraedge {
 
-
-static uint getUnicodeFromISO(uint chr)
-{
-	uint retval;
-
-	TeCore *core = g_engine->getCore();
-	bool isrus = (core->fileFlagSystemFlag("language") == "ru");
-
-	if (!isrus) {
-		uint uVar1 = 0x152;
-		if (chr != 0xbc) {
-			uVar1 = chr;
-		}
-		retval = 0x153;
-		if (uVar1 != 0xbd) {
-			retval = uVar1;
-		}
-	} else {
-		retval = 0xad;
-		if (chr != 0xad) {
-			if (chr == 0xf0) {
-				retval = 0x2116;
-			}
-			else if (chr == 0xfd) {
-				retval = 0xa7;
-			} else {
-				retval = chr + 0x360;
-				if (0x5e < chr - 0xa1) {
-					retval = chr;
-				}
-			}
-		}
-	}
-	return retval;
-}
-
 TeFont3::TeFont3() {
-	init();
 }
 
 TeFont3::~TeFont3() {
@@ -95,77 +58,6 @@ Graphics::Font *TeFont3::getAtSize(uint size) {
 	return newFont;
 }
 
-TeFont3::GlyphData TeFont3::glyph(uint pxSize, uint charcode) {
-	Graphics::Font *font = getAtSize(pxSize);
-	Common::Rect bbox = font->getBoundingBox(charcode);
-	TeImage *img = new TeImage();
-	Common::SharedPtr<TePalette> nullpal;
-	img->createImg(bbox.width(), bbox.height(), nullpal, TeImage::RGBA8);
-	font->drawChar(img, charcode, 0, 0, 0xffffffff);
-	GlyphData retval;
-	retval._charcode = charcode;
-	retval._bitmapSize = bbox;
-	retval._img = img;
-	return retval;
-}
-
-Common::CodePage TeFont3::codePage() const {
-	Common::String lang = g_engine->getCore()->language();
-	if (lang == "he")
-		return Common::kWindows1255; 
-	if (lang == "ru")
-		return Common::kISO8859_5;
-	return Common::kLatin1;
-}
-
-
-int TeFont3::wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines) {
-	Graphics::Font *font = getAtSize(fontSize);
-	Common::Array<Common::U32String> u32lines;
-	int retval = font->wordWrapText(str.decode(_codePage), maxWidth, u32lines);
-	for (auto &line: u32lines) {
-		lines.push_back(line.encode(_codePage));
-	}
-	return retval;
-}
-
-Common::Rect TeFont3::getBoundingBox(const Common::String &str, int fontSize) {
-	Graphics::Font *font = getAtSize(fontSize);
-	return font->getBoundingBox(str.decode(_codePage));
-}
-
-int TeFont3::getHeight(int fontSize) {
-	Graphics::Font *font = getAtSize(fontSize);
-	return font->getFontHeight();
-}
-
-void TeFont3::draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, TeFont3::AlignStyle align) {
-	Graphics::Font *font = getAtSize(fontSize);
-	Graphics::TextAlign talign;
-	switch (align) {
-		case AlignLeft:
-			talign = Graphics::kTextAlignLeft;
-			break;
-		case AlignRight:
-			talign = Graphics::kTextAlignRight;
-			break;
-		// Note: we don't support justify.. just center. (justify is not used anyway)
-		case AlignJustify:
-		case AlignCenter:
-		default:
-			talign = Graphics::kTextAlignCenter;
-			break;
-	}
-	const Graphics::PixelFormat &fmt = destImage.format;
-
-	uint32 uintcol = ((uint32)col.a() << fmt.aShift) | ((uint32)(col.r()) << fmt.rShift)
-						| ((uint32)(col.g()) << fmt.gShift) | ((uint32)(col.b()) << fmt.bShift);
-	Common::U32String line = str.decode(_codePage);
-	if (g_engine->getCore()->language() == "he")
-		line = Common::convertBiDiU32String(line).visual;
-	font->drawString(&destImage, line, 0, yoff, destImage.w, uintcol, talign);
-}
-
 bool TeFont3::load(const Common::String &path) {
 	if (_loadedPath == path && _fontFile.isOpen())
 		return true; // already open
@@ -183,8 +75,8 @@ bool TeFont3::load(const Common::FSNode &node) {
 	setAccessName(path);
 	_loadedPath = path;
 
-	if (!node.exists()) {
-		warning("TeFont3::load: File %s doesn't exist", path.c_str());
+	if (!node.isReadable()) {
+		warning("TeFont3::load: Can't read from %s", path.c_str());
 		return false;
 	}
 
@@ -206,32 +98,4 @@ void TeFont3::unload() {
 	_fontFile.close();
 }
 
-void TeFont3::init() {
-	_codePage = codePage();
-}
-
-float TeFont3::ascender(uint pxSize) {
-	Graphics::Font *font = getAtSize(pxSize);
-	return font->getFontAscent();
-}
-
-float TeFont3::descender(uint pxSize) {
-	error("TODO: Implement TeFont3::descender");
-}
-
-float TeFont3::height(uint pxSize) {
-	Graphics::Font *font = getAtSize(pxSize);
-	return font->getFontHeight();
-}
-
-TeVector3f32 TeFont3::kerning(uint pxSize, uint isocode1, uint isocode2) {
-	uint32 uni1 = getUnicodeFromISO(isocode1);
-	uint32 uni2 = getUnicodeFromISO(isocode2);
-	Graphics::Font *font = getAtSize(pxSize);
-	int offset = font->getKerningOffset(uni1, uni2);
-	// note: not perfect because we have no Y, but it's ok..
-	return TeVector3f32(offset, 0.0f, 0.0f);
-}
-
-
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_font3.h b/engines/tetraedge/te/te_font3.h
index 1bc7a69cffc..14e72d16b90 100644
--- a/engines/tetraedge/te/te_font3.h
+++ b/engines/tetraedge/te/te_font3.h
@@ -34,6 +34,7 @@
 #include "tetraedge/te/te_image.h"
 #include "tetraedge/te/te_intrusive_ptr.h"
 #include "tetraedge/te/te_3d_texture.h"
+#include "tetraedge/te/te_i_font.h"
 
 struct FT_FaceRec_;
 struct FT_LibraryRec_;
@@ -44,51 +45,26 @@ class Font;
 
 namespace Tetraedge {
 
-class TeFont3 : public TeResource {
+/**
+ * TeFont3 is a minimal wrapper on Graphics::Font for TTF files, supporting
+ * multiple sizes and matching the original TeFont api a bit closer.
+ */
+class TeFont3 : public TeIFont {
 public:
 	TeFont3();
-	~TeFont3();
-
-	enum AlignStyle {
-		AlignLeft,
-		AlignRight,
-		AlignJustify,
-		AlignCenter
-	};
-
-	struct GlyphData {
-		uint32 _charcode;
-		Common::Rect _bitmapSize;
-		TeIntrusivePtr<TeImage> _img;
-	};
+	virtual ~TeFont3();
 
 	bool load(const Common::String &path);
 	bool load(const Common::FSNode &node);
 	void unload();
 
-	GlyphData glyph(uint size, uint charcode);
+private:
 
-	float ascender(uint pxSize);
-	float descender(uint pxSize);
-	float height(uint pxSize);
-	TeVector3f32 kerning(uint pxSize, uint isocode1, uint isocode2);
 	TeIntrusivePtr<Te3DTexture> getFontSizeData(int size) const {
 		return _fontSizeData[size];
 	}
 
-	Common::Rect getBoundingBox(const Common::String &str, int fontSize);
-	int getHeight(int fontSize);
-
-	void draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, AlignStyle alignMode);
-
-	int wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines);
-
-private:
-	void init();
-	Graphics::Font *getAtSize(uint size);
-	Common::CodePage codePage() const;
-
-	Common::CodePage _codePage;
+	Graphics::Font *getAtSize(uint size) override;
 	Common::File _fontFile;
 	Common::HashMap<uint, Graphics::Font *> _fonts;
 	Common::String _loadedPath;
diff --git a/engines/tetraedge/te/te_i_font.cpp b/engines/tetraedge/te/te_i_font.cpp
new file mode 100644
index 00000000000..11927e908d5
--- /dev/null
+++ b/engines/tetraedge/te/te_i_font.cpp
@@ -0,0 +1,133 @@
+/* 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/>.
+ *
+ */
+
+// Since FreeType2 includes files, which contain forbidden symbols, we need to
+// allow all symbols here.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "tetraedge/tetraedge.h"
+#include "tetraedge/te/te_font3.h"
+#include "tetraedge/te/te_core.h"
+#include "graphics/font.h"
+#include "graphics/fonts/ttf.h"
+#include "common/unicode-bidi.h"
+
+namespace Tetraedge {
+
+TeIFont::TeIFont() {
+	_codePage = codePage();
+}
+
+TeIFont::~TeIFont() {
+}
+
+TeIFont::GlyphData TeIFont::glyph(uint pxSize, uint charcode) {
+	Graphics::Font *font = getAtSize(pxSize);
+	Common::Rect bbox = font->getBoundingBox(charcode);
+	TeImage *img = new TeImage();
+	Common::SharedPtr<TePalette> nullpal;
+	img->createImg(bbox.width(), bbox.height(), nullpal, TeImage::RGBA8);
+	font->drawChar(img, charcode, 0, 0, 0xffffffff);
+	GlyphData retval;
+	retval._charcode = charcode;
+	retval._bitmapSize = bbox;
+	retval._img = img;
+	return retval;
+}
+
+Common::CodePage TeIFont::codePage() const {
+	Common::String lang = g_engine->getCore()->language();
+	if (lang == "he")
+		return Common::kWindows1255;
+	if (lang == "ru")
+		return Common::kISO8859_5;
+	return Common::kLatin1;
+}
+
+int TeIFont::wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines) {
+	Graphics::Font *font = getAtSize(fontSize);
+	Common::Array<Common::U32String> u32lines;
+	int retval = font->wordWrapText(str.decode(_codePage), maxWidth, u32lines);
+	for (auto &line: u32lines) {
+		lines.push_back(line.encode(_codePage));
+	}
+	return retval;
+}
+
+Common::Rect TeIFont::getBoundingBox(const Common::String &str, int fontSize) {
+	Graphics::Font *font = getAtSize(fontSize);
+	return font->getBoundingBox(str.decode(_codePage));
+}
+
+int TeIFont::getHeight(int fontSize) {
+	Graphics::Font *font = getAtSize(fontSize);
+	return font->getFontHeight();
+}
+
+void TeIFont::draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, TeIFont::AlignStyle align) {
+	Graphics::Font *font = getAtSize(fontSize);
+	Graphics::TextAlign talign;
+	switch (align) {
+		case AlignLeft:
+			talign = Graphics::kTextAlignLeft;
+			break;
+		case AlignRight:
+			talign = Graphics::kTextAlignRight;
+			break;
+		// Note: we don't support justify.. just center. (justify is not used anyway)
+		case AlignJustify:
+		case AlignCenter:
+		default:
+			talign = Graphics::kTextAlignCenter;
+			break;
+	}
+	const Graphics::PixelFormat &fmt = destImage.format;
+
+	uint32 uintcol = ((uint32)col.a() << fmt.aShift) | ((uint32)(col.r()) << fmt.rShift)
+						| ((uint32)(col.g()) << fmt.gShift) | ((uint32)(col.b()) << fmt.bShift);
+	Common::U32String line = str.decode(_codePage);
+	if (g_engine->getCore()->language() == "he")
+		line = Common::convertBiDiU32String(line).visual;
+	font->drawString(&destImage, line, 0, yoff, destImage.w, uintcol, talign);
+}
+
+float TeIFont::ascender(uint pxSize) {
+	Graphics::Font *font = getAtSize(pxSize);
+	return font->getFontAscent();
+}
+
+float TeIFont::descender(uint pxSize) {
+	error("TODO: Implement TeFont3::descender");
+}
+
+float TeIFont::height(uint pxSize) {
+	Graphics::Font *font = getAtSize(pxSize);
+	return font->getFontHeight();
+}
+
+TeVector3f32 TeIFont::kerning(uint pxSize, uint charcode1, uint charcode2) {
+	Graphics::Font *font = getAtSize(pxSize);
+	int offset = font->getKerningOffset(charcode1, charcode2);
+	// note: not perfect because we have no Y, but it's ok..
+	return TeVector3f32(offset, 0.0f, 0.0f);
+}
+
+} // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_i_font.h b/engines/tetraedge/te/te_i_font.h
new file mode 100644
index 00000000000..05f62ca7bd0
--- /dev/null
+++ b/engines/tetraedge/te/te_i_font.h
@@ -0,0 +1,78 @@
+/* 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 TETRAEDGE_TE_TE_I_FONT_H
+#define TETRAEDGE_TE_TE_I_FONT_H
+
+#include "common/str.h"
+#include "graphics/font.h"
+#include "tetraedge/te/te_color.h"
+#include "tetraedge/te/te_image.h"
+#include "tetraedge/te/te_resource.h"
+#include "tetraedge/te/te_vector3f32.h"
+
+namespace Tetraedge {
+
+/**
+ * A wrapper to provide a TeFont-like interface using ScummVM'S font class.
+ */
+class TeIFont : public TeResource {
+public:
+	enum AlignStyle {
+		AlignLeft,
+		AlignRight,
+		AlignJustify,
+		AlignCenter
+	};
+
+	struct GlyphData {
+		uint32 _charcode;
+		Common::Rect _bitmapSize;
+		TeIntrusivePtr<TeImage> _img;
+	};
+
+	TeIFont();
+	virtual ~TeIFont();
+	virtual Graphics::Font *getAtSize(uint size) = 0;
+
+	virtual float ascender(uint pxSize);
+	virtual float descender(uint pxSize);
+	virtual float height(uint pxSize);
+	virtual TeVector3f32 kerning(uint pxSize, uint isocode1, uint isocode2);
+
+	virtual void draw(TeImage &destImage, const Common::String &str, int fontSize, int yoff, const TeColor &col, AlignStyle alignMode);
+	virtual Common::Rect getBoundingBox(const Common::String &str, int fontSize);
+	virtual int getHeight(int fontSize);
+	virtual int wordWrapText(const Common::String &str, int fontSize, int maxWidth, Common::Array<Common::String> &lines);
+
+	virtual TeIFont::GlyphData glyph(uint pxSize, uint charcode);
+
+protected:
+	Common::CodePage _codePage;
+
+private:
+	Common::CodePage codePage() const;
+
+};
+
+} // end namespace Tetraedge
+
+#endif // TETRAEDGE_TE_TE_I_FONT_H
diff --git a/engines/tetraedge/te/te_png.cpp b/engines/tetraedge/te/te_png.cpp
index 6c57837e1e2..e754ba3e4f6 100644
--- a/engines/tetraedge/te/te_png.cpp
+++ b/engines/tetraedge/te/te_png.cpp
@@ -27,7 +27,7 @@
 
 namespace Tetraedge {
 
-TePng::TePng(const Common::String &extn) {
+TePng::TePng(const Common::String &extn) : _height(0) {
 	if (extn == "png#anim") {
 		_nbFrames = 8;
 		_frameRate = 8.0f;
@@ -63,6 +63,9 @@ bool TePng::load(Common::SeekableReadStream &stream) {
 		return false;
 
 	_loadedSurface = png.getSurface()->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
+
+	_height = _loadedSurface->h;
+
 	return true;
 }
 
diff --git a/engines/tetraedge/te/te_text_base2.cpp b/engines/tetraedge/te/te_text_base2.cpp
index a290b40772a..c33b3660086 100644
--- a/engines/tetraedge/te/te_text_base2.cpp
+++ b/engines/tetraedge/te/te_text_base2.cpp
@@ -30,7 +30,7 @@
 namespace Tetraedge {
 
 TeTextBase2::TeTextBase2() : _drawRect(0, 0), _size(0, 0),
-_alignStyle(TeFont3::AlignLeft), _interLine(0.0f), _globalColor(0xff, 0xff, 0xff, 0xff),
+_alignStyle(TeIFont::AlignLeft), _interLine(0.0f), _globalColor(0xff, 0xff, 0xff, 0xff),
 _wrapMode(WrapModeFixed), _strikethrough(false), _fontSize(10), _valueWasSet(true) {
 	_mesh = TeMesh::makeInstance();
 	_mesh->setglTexEnvBlend();
@@ -49,7 +49,7 @@ void TeTextBase2::build() {
 	if (!_text.size() || !_fontSize)
 		return;
 
-	TeIntrusivePtr<TeFont3> font = _fonts[0];
+	TeIntrusivePtr<TeIFont> font = _fonts[0];
 	if (!font.get()) {
 		warning("[TeTextBase2::build()] Warning : font missing");
 		return;
@@ -78,7 +78,7 @@ void TeTextBase2::build() {
 	float lineHeight = font->getHeight(_fontSize);
 	float height = 0;
 	for (const Common::String &line : _wrappedLines) {
-		if (_alignStyle == TeFont3::AlignJustify) {
+		if (_alignStyle == TeIFont::AlignJustify) {
 			warning("TODO: Implement TeTextBase2::computeNbSpaces for Justify");
 			//computeNbSpaces(&line, offset, line.endOffset);
 		}
@@ -185,11 +185,11 @@ TeColor TeTextBase2::currentColor(uint offset) const {
 	return result;
 }
 
-TeIntrusivePtr<TeFont3> TeTextBase2::currentFont(uint offset) {
+TeIntrusivePtr<TeIFont> TeTextBase2::currentFont(uint offset) {
 	if (_fonts.size() == 0)
-		return TeIntrusivePtr<TeFont3>();
+		return TeIntrusivePtr<TeIFont>();
 	int closest_off = -1;
-	TeIntrusivePtr<TeFont3> result;
+	TeIntrusivePtr<TeIFont> result;
 	// Find closest without going over.
 	for (auto &pair : _fonts) {
 		if ((int)pair._key > closest_off && pair._key <= offset) {
@@ -198,7 +198,7 @@ TeIntrusivePtr<TeFont3> TeTextBase2::currentFont(uint offset) {
 		}
 	}
 	if (closest_off == -1)
-		return TeIntrusivePtr<TeFont3>();
+		return TeIntrusivePtr<TeIFont>();
 	return result;
 }
 
@@ -220,7 +220,7 @@ void TeTextBase2::drawEmptyChar(uint offset) {
 }
 
 void TeTextBase2::drawLine(TeImage &img, const Common::String &str, int yoffset) {
-	TeIntrusivePtr<TeFont3> font = _fonts[0];
+	TeIntrusivePtr<TeIFont> font = _fonts[0];
 
 	// Note: We draw this with black because the global color will be applied on
 	// the mesh.
@@ -257,7 +257,7 @@ int TeTextBase2::nextNonSpaceChar(uint offset) {
 	return offset; // TODO: or offset - 1?
 }
 
-void TeTextBase2::setAlignStyle(TeFont3::AlignStyle style) {
+void TeTextBase2::setAlignStyle(TeIFont::AlignStyle style) {
 	_alignStyle = style;
 	_valueWasSet = true;
 }
@@ -267,7 +267,7 @@ void TeTextBase2::setColor(uint offset, const TeColor &color) {
 	_valueWasSet = true;
 }
 
-void TeTextBase2::setFont(uint offset, const TeIntrusivePtr<TeFont3> &newfont) {
+void TeTextBase2::setFont(uint offset, const TeIntrusivePtr<TeIFont> &newfont) {
 	_fonts.setVal(offset, newfont);
 	_valueWasSet = true;
 }
diff --git a/engines/tetraedge/te/te_text_base2.h b/engines/tetraedge/te/te_text_base2.h
index 8c6936f2ede..d98089fe10b 100644
--- a/engines/tetraedge/te/te_text_base2.h
+++ b/engines/tetraedge/te/te_text_base2.h
@@ -26,8 +26,8 @@
 #include "common/hashmap.h"
 
 #include "tetraedge/te/te_color.h"
-#include "tetraedge/te/te_font3.h"
 #include "tetraedge/te/te_intrusive_ptr.h"
+#include "tetraedge/te/te_i_font.h"
 #include "tetraedge/te/te_mesh.h"
 #include "tetraedge/te/te_vector2s32.h"
 
@@ -56,16 +56,16 @@ public:
 	void clearText();
 
 	TeColor currentColor(uint offset) const;
-	TeIntrusivePtr<TeFont3> currentFont(uint offset);
+	TeIntrusivePtr<TeIFont> currentFont(uint offset);
 	void draw();
 	uint endOfWord(uint i) const;
 	void insertNewLine(uint offset);
 	bool isASpace(uint offset) const;
 	int newLines(uint offset) const;
 	int nextNonSpaceChar(uint start);
-	void setAlignStyle(TeFont3::AlignStyle style);
+	void setAlignStyle(TeIFont::AlignStyle style);
 	void setColor(uint offset, const TeColor &color);
-	void setFont(uint offset, const TeIntrusivePtr<TeFont3> &newfont);
+	void setFont(uint offset, const TeIntrusivePtr<TeIFont> &newfont);
 	void setFontSize(int fontSz);
 	void setGlobalColor(const TeColor &color);
 	void setInterLine(float val);
@@ -84,7 +84,7 @@ private:
 	void drawEmptyChar(uint offset);
 	void drawLine(TeImage &img, const Common::String &str, int yoffset);
 
-	TeFont3::AlignStyle _alignStyle;
+	TeIFont::AlignStyle _alignStyle;
 	WrapMode _wrapMode;
 	int _fontSize;
 	bool _valueWasSet;
@@ -101,7 +101,7 @@ private:
 
 	Common::Array<uint32> _lineBreaks;
 	Common::HashMap<uint, TeColor> _colors;
-	Common::HashMap<uint, TeIntrusivePtr<TeFont3>> _fonts;
+	Common::HashMap<uint, TeIntrusivePtr<TeIFont>> _fonts;
 };
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_text_layout.cpp b/engines/tetraedge/te/te_text_layout.cpp
index 981db3c83d4..596318e0708 100644
--- a/engines/tetraedge/te/te_text_layout.cpp
+++ b/engines/tetraedge/te/te_text_layout.cpp
@@ -26,6 +26,8 @@
 #include "tetraedge/te/te_renderer.h"
 #include "tetraedge/te/te_text_layout.h"
 #include "tetraedge/te/te_text_layout_xml_parser.h"
+#include "tetraedge/te/te_font3.h"
+#include "tetraedge/te/te_font2.h"
 
 namespace Tetraedge {
 
@@ -55,17 +57,17 @@ void TeTextLayout::draw() {
 
 }
 
-static TeFont3::AlignStyle _alignNameToEnum(const Common::String &name) {
+static TeIFont::AlignStyle _alignNameToEnum(const Common::String &name) {
 	if (name == "left")
-		return TeFont3::AlignLeft;
+		return TeIFont::AlignLeft;
 	else if (name == "right")
-		return TeFont3::AlignRight;
+		return TeIFont::AlignRight;
 	else if (name == "justify")
-		return TeFont3::AlignJustify;
+		return TeIFont::AlignJustify;
 	else if (name =="center")
-		return TeFont3::AlignCenter;
+		return TeIFont::AlignCenter;
 	warning("Unknown text align style: %s", name.c_str());
-	return TeFont3::AlignLeft;
+	return TeIFont::AlignLeft;
 }
 
 void TeTextLayout::setText(const Common::String &val) {
@@ -116,10 +118,14 @@ void TeTextLayout::setText(const Common::String &val) {
 	if (parser.fontSize())
 		_baseFontSize = parser.fontSize();
 
-	if (parser.fontFile().size()) {
+	if (!parser.fontFile().empty()) {
 		Common::Path fontPath(parser.fontFile());
 		Common::FSNode fontNode = g_engine->getCore()->findFile(fontPath);
-		TeIntrusivePtr<TeFont3> font = g_engine->getResourceManager()->getResource<TeFont3>(fontNode);
+		TeIntrusivePtr<TeIFont> font;
+		if (parser.fontFile().hasSuffixIgnoreCase(".ttf"))
+			font = g_engine->getResourceManager()->getResource<TeFont3>(fontNode).get();
+		else
+			font = g_engine->getResourceManager()->getResource<TeFont2>(fontNode).get();
 		//font->load(fontPath); // lazy load this later.
 		_base.setFont(0, font);
 	}
diff --git a/engines/tetraedge/te/te_text_layout_xml_parser.cpp b/engines/tetraedge/te/te_text_layout_xml_parser.cpp
index 25a0478e550..f754932e04a 100644
--- a/engines/tetraedge/te/te_text_layout_xml_parser.cpp
+++ b/engines/tetraedge/te/te_text_layout_xml_parser.cpp
@@ -34,7 +34,12 @@ bool TeTextLayoutXmlParser::parserCallback_color(ParserNode *node) {
 
 bool TeTextLayoutXmlParser::parserCallback_font(ParserNode *node) {
 	_fontFile = node->values["file"];
-	_fontSize = node->values["size"].asUint64();
+	if (node->values.contains("size"))
+		_fontSize = node->values["size"].asUint64();
+	else {
+		warning("default font size to 16");
+		_fontSize = 16;
+	}
 	return true;
 }
 
diff --git a/engines/tetraedge/te/te_text_layout_xml_parser.h b/engines/tetraedge/te/te_text_layout_xml_parser.h
index dcd14085be1..c5d5379c43c 100644
--- a/engines/tetraedge/te/te_text_layout_xml_parser.h
+++ b/engines/tetraedge/te/te_text_layout_xml_parser.h
@@ -46,7 +46,7 @@ public:
 			KEY_END()
 			XML_KEY(font)
 				XML_PROP(file, true)
-				XML_PROP(size, true)
+				XML_PROP(size, false)
 			KEY_END()
 			XML_KEY(br)
 			KEY_END()
diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp
index af5d83d1d77..6fbdf3887d5 100644
--- a/engines/tetraedge/te/te_warp.cpp
+++ b/engines/tetraedge/te/te_warp.cpp
@@ -612,6 +612,8 @@ void TeWarp::takeObject(const Common::String &name) {
 }
 
 void TeWarp::unload() {
+	// Not done in original but can happen if user clicks really fast.
+	g_engine->getInputMgr()->_mouseLDownSignal.remove(this, &TeWarp::onMouseLeftDown);
 	unloadTextures();
 	_xCount = 0;
 	_yCount = 0;




More information about the Scummvm-git-logs mailing list