[Scummvm-git-logs] scummvm master -> 19514bc2ad7602ce157abd6794d3a9a10c56657b

criezy noreply at scummvm.org
Mon Oct 10 22:42:47 UTC 2022


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

Summary:
26716156af AGS: added AudioChannel.SeekMs() to coplement PositionMs
f9e3580237 AGS: reimplemented clear division of clip position by sound type
69eeb18d36 AGS: Added GetGameInfo to plugin interface
98f4b82f36 AGS: added IAGSFontRenderer2 and NotifyFontUpdated
f380f418de AGS: implement IAGSFontRenderer2 and use NotifyFontUpdated for AGSSpriteFont
19514bc2ad AGS: Common: properly restore font metrics when setting an old font renderer


Commit: 26716156afe3312e18d9d14f299dff212c051369
    https://github.com/scummvm/scummvm/commit/26716156afe3312e18d9d14f299dff212c051369
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: added AudioChannel.SeekMs() to coplement PositionMs

>From upstream 59a5cacb8ed61e41dd8ef0641dd5de156caf8d32

Changed paths:
    engines/ags/engine/ac/audio_channel.cpp
    engines/ags/engine/ac/audio_channel.h
    engines/ags/engine/media/audio/clip_my_midi.cpp
    engines/ags/engine/media/audio/clip_my_midi.h
    engines/ags/engine/media/audio/sound_clip.cpp
    engines/ags/engine/media/audio/sound_clip.h


diff --git a/engines/ags/engine/ac/audio_channel.cpp b/engines/ags/engine/ac/audio_channel.cpp
index 2adafc4454b..6b8a8c4eb4c 100644
--- a/engines/ags/engine/ac/audio_channel.cpp
+++ b/engines/ags/engine/ac/audio_channel.cpp
@@ -178,10 +178,17 @@ void AudioChannel_Seek(ScriptAudioChannel *channel, int newPosition) {
 		quitprintf("!AudioChannel.Seek: invalid seek position %d", newPosition);
 
 	auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
-
-	if (ch) {
+	if (ch)
 		ch->seek(newPosition);
-	}
+}
+
+void AudioChannel_SeekMs(ScriptAudioChannel *channel, int newPosition) {
+	if (newPosition < 0)
+		quitprintf("!AudioChannel.SeekMs: invalid seek position %d", newPosition);
+
+	auto* ch = AudioChans::GetChannelIfPlaying(channel->id);
+	if (ch)
+		ch->seek_ms(newPosition);
 }
 
 void AudioChannel_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos) {
@@ -266,6 +273,10 @@ RuntimeScriptValue Sc_AudioChannel_Seek(void *self, const RuntimeScriptValue *pa
 	API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_Seek);
 }
 
+RuntimeScriptValue Sc_AudioChannel_SeekMs(void *self, const RuntimeScriptValue *params, int32_t param_count) {
+	API_OBJCALL_VOID_PINT(ScriptAudioChannel, AudioChannel_SeekMs);
+}
+
 // void | ScriptAudioChannel *channel, int xPos, int yPos
 RuntimeScriptValue Sc_AudioChannel_SetRoomLocation(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_VOID_PINT2(ScriptAudioChannel, AudioChannel_SetRoomLocation);
@@ -295,6 +306,7 @@ void RegisterAudioChannelAPI() {
 	ccAddExternalObjectFunction("AudioChannel::Pause^0", Sc_AudioChannel_Pause);
 	ccAddExternalObjectFunction("AudioChannel::Resume^0", Sc_AudioChannel_Resume);
 	ccAddExternalObjectFunction("AudioChannel::Seek^1", Sc_AudioChannel_Seek);
+	ccAddExternalObjectFunction("AudioChannel::SeekMs^1", Sc_AudioChannel_SeekMs);
 	ccAddExternalObjectFunction("AudioChannel::SetRoomLocation^2", Sc_AudioChannel_SetRoomLocation);
 	ccAddExternalObjectFunction("AudioChannel::Stop^0", Sc_AudioChannel_Stop);
 	ccAddExternalObjectFunction("AudioChannel::get_ID", Sc_AudioChannel_GetID);
diff --git a/engines/ags/engine/ac/audio_channel.h b/engines/ags/engine/ac/audio_channel.h
index 3290a463fc6..a5ea6f8fa36 100644
--- a/engines/ags/engine/ac/audio_channel.h
+++ b/engines/ags/engine/ac/audio_channel.h
@@ -39,6 +39,7 @@ int     AudioChannel_GetVolume(ScriptAudioChannel *channel);
 int     AudioChannel_SetVolume(ScriptAudioChannel *channel, int newVolume);
 void    AudioChannel_Stop(ScriptAudioChannel *channel);
 void    AudioChannel_Seek(ScriptAudioChannel *channel, int newPosition);
+void    AudioChannel_SeekMs(ScriptAudioChannel *channel, int newPosition);
 void    AudioChannel_SetRoomLocation(ScriptAudioChannel *channel, int xPos, int yPos);
 
 } // namespace AGS3
diff --git a/engines/ags/engine/media/audio/clip_my_midi.cpp b/engines/ags/engine/media/audio/clip_my_midi.cpp
index b5240de4666..22504f4d557 100644
--- a/engines/ags/engine/media/audio/clip_my_midi.cpp
+++ b/engines/ags/engine/media/audio/clip_my_midi.cpp
@@ -47,9 +47,14 @@ void MYMIDI::poll() {
 }
 
 void MYMIDI::seek(int pos) {
+	// pos is the beat number
 	warning("TODO: MYMIDI::seek");
 }
 
+void MYMIDI::seek_ms(int pos_ms) {
+	warning("TODO: MYMIDI::seek_ms");
+}
+
 int MYMIDI::get_pos() {
 	// We don't know ms with midi
 	return 0;
diff --git a/engines/ags/engine/media/audio/clip_my_midi.h b/engines/ags/engine/media/audio/clip_my_midi.h
index 0d646e60c3f..4b8b36d3f99 100644
--- a/engines/ags/engine/media/audio/clip_my_midi.h
+++ b/engines/ags/engine/media/audio/clip_my_midi.h
@@ -40,6 +40,7 @@ struct MYMIDI : public SOUNDCLIP {
 	void poll() override;
 
 	void seek(int pos) override;
+	void seek_ms(int pos_ms) override;
 
 	int get_pos() override;
 
diff --git a/engines/ags/engine/media/audio/sound_clip.cpp b/engines/ags/engine/media/audio/sound_clip.cpp
index 2ad80703d2e..d669f766aed 100644
--- a/engines/ags/engine/media/audio/sound_clip.cpp
+++ b/engines/ags/engine/media/audio/sound_clip.cpp
@@ -194,11 +194,19 @@ bool SoundClipWaveBase::is_paused() {
 }
 
 void SoundClipWaveBase::seek(int offset) {
+	// TODO: for backward compatibility we need to reimplement seeking
+	// to a position which units are defined according to the sound type:
+	// - WAV / VOC - the sample number
+	// - OGG / MP3 - milliseconds
+	seek_ms(offset);
+}
+
+void SoundClipWaveBase::seek_ms(int pos_ms) {
 	Audio::SeekableAudioStream *stream =
 		dynamic_cast<Audio::SeekableAudioStream *>(_stream);
 
 	if (stream) {
-		stream->seek(Audio::Timestamp(offset));
+		stream->seek(Audio::Timestamp(pos_ms));
 	} else {
 		warning("Audio stream did not support seeking");
 	}
diff --git a/engines/ags/engine/media/audio/sound_clip.h b/engines/ags/engine/media/audio/sound_clip.h
index e02dbb4567f..e752f587a39 100644
--- a/engines/ags/engine/media/audio/sound_clip.h
+++ b/engines/ags/engine/media/audio/sound_clip.h
@@ -34,6 +34,12 @@
 
 namespace AGS3 {
 
+// SOUNDCLIP's state and parameter updates sync with the audio core in
+// batches, only when the engine updates the game, never while the user script
+// is being executed. The sync is performed by calling update().
+// This is to ensure that the clip reference, state and properties don't change
+// in the middle of the script's command sequence.
+
 // TODO: one of the biggest problems with sound clips currently is that it
 // provides several methods of applying volume, which may ignore or override
 // each other, and does not shape a consistent interface.
@@ -66,7 +72,21 @@ struct SOUNDCLIP {
 	virtual int play() = 0;
 	virtual void pause() = 0;
 	virtual void resume() = 0;
+
+	/**
+	 * Seeks to the position, where pos units depend on the audio type:
+	 *  - MIDI - the beat number
+	 *  - MOD / XM / S3M - the pattern number
+	 *  - WAV / VOC - the sample number
+	 *  - OGG / MP3 - milliseconds
+	 */
 	virtual void seek(int offset) = 0;
+
+	/**
+	 * Seeks to the position in milliseconds
+	 */
+	virtual void seek_ms(int pos_ms) = 0;
+
 	virtual int play_from(int position) = 0;
 	virtual bool is_playing() = 0; // true if playing or paused. false if never played or stopped.
 	virtual bool is_paused() = 0; // true if paused
@@ -208,6 +228,7 @@ public:
 	bool is_playing() override;
 	bool is_paused() override;
 	void seek(int offset) override;
+	void seek_ms(int pos_ms) override;
 	int get_pos() override;
 	int get_pos_ms() override;
 	int get_length_ms() override;


Commit: f9e358023776b9bfe153adf3f69cc79188822a60
    https://github.com/scummvm/scummvm/commit/f9e358023776b9bfe153adf3f69cc79188822a60
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: reimplemented clear division of clip position by sound type

Currently only MP3/OGG and WAVs are reporting correct sound type dependent pos.

Adapted from upstream 19bdee979c80f339d0ada0bee99b7517c8b595c5

Changed paths:
    engines/ags/engine/media/audio/sound_clip.cpp
    engines/ags/engine/media/audio/sound_clip.h


diff --git a/engines/ags/engine/media/audio/sound_clip.cpp b/engines/ags/engine/media/audio/sound_clip.cpp
index d669f766aed..53fdc7022cf 100644
--- a/engines/ags/engine/media/audio/sound_clip.cpp
+++ b/engines/ags/engine/media/audio/sound_clip.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "ags/engine/media/audio/sound_clip.h"
+#include "ags/engine/media/audio/audio_defines.h"
 #include "ags/ags.h"
 
 namespace AGS3 {
@@ -193,12 +194,26 @@ bool SoundClipWaveBase::is_paused() {
 	return _state == SoundClipPaused;
 }
 
-void SoundClipWaveBase::seek(int offset) {
-	// TODO: for backward compatibility we need to reimplement seeking
-	// to a position which units are defined according to the sound type:
+int SoundClipWaveBase::pos_to_posms(int pos) const {
+	// The pos meaning depends on the sound type:
 	// - WAV / VOC - the sample number
 	// - OGG / MP3 - milliseconds
-	seek_ms(offset);
+	// - MOD - the pattern number
+	switch (get_sound_type()) {
+	case MUS_WAVE: // Pos is in samples
+		if (!_stream)
+			return 0;
+		return static_cast<int>((static_cast<int64_t>(pos) * 1000) / _stream->getRate());
+	case MUS_MOD:  /* TODO: reimplement */
+		// better say that it does not work than return wrong value
+		return 0;
+	default:
+		return pos;
+	}
+}
+
+void SoundClipWaveBase::seek(int pos) {
+	seek_ms(pos_to_posms(pos));
 }
 
 void SoundClipWaveBase::seek_ms(int pos_ms) {
diff --git a/engines/ags/engine/media/audio/sound_clip.h b/engines/ags/engine/media/audio/sound_clip.h
index e752f587a39..815eaee5721 100644
--- a/engines/ags/engine/media/audio/sound_clip.h
+++ b/engines/ags/engine/media/audio/sound_clip.h
@@ -208,6 +208,9 @@ protected:
 struct SoundClipWaveBase : public SOUNDCLIP {
 private:
 	Audio::Mixer::SoundType _soundType = Audio::Mixer::kPlainSoundType;
+
+	int pos_to_posms(int pos) const;
+
 public:
 	Audio::Mixer *_mixer;
 	Audio::AudioStream *_stream;


Commit: 69eeb18d36e2651b868d2d691766049ea43fb2a0
    https://github.com/scummvm/scummvm/commit/69eeb18d36e2651b868d2d691766049ea43fb2a0
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: Added GetGameInfo to plugin interface

>From upstream 97d02b47babb0cdd0e82e8815f3f5dbf8e7b2e1b

Changed paths:
    engines/ags/plugins/ags_plugin.cpp
    engines/ags/plugins/ags_plugin.h


diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 19afd4a8f0b..cdb4395c8e7 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -80,7 +80,7 @@ using namespace AGS::Shared;
 using namespace AGS::Shared::Memory;
 using namespace AGS::Engine;
 
-const int PLUGIN_API_VERSION = 25;
+const int PLUGIN_API_VERSION = 26;
 
 // On save/restore, the Engine will provide the plugin with a handle. Because we only ever save to one file at a time,
 // we can reuse the same handle.
@@ -754,6 +754,13 @@ void IAGSEngine::GetRenderStageDesc(AGSRenderStageDesc *desc) {
 	}
 }
 
+void IAGSEngine::GetGameInfo(AGSGameInfo* ginfo) {
+	if (ginfo->Version >= 26) {
+		snprintf(ginfo->GameName, sizeof(ginfo->GameName), "%s", _GP(game).gamename);
+		snprintf(ginfo->guid, sizeof(ginfo->guid), "%s", _GP(game).guid);
+		ginfo->uniqueid = _GP(game).uniqueid;
+	}
+}
 
 // *********** General plugin implementation **********
 
diff --git a/engines/ags/plugins/ags_plugin.h b/engines/ags/plugins/ags_plugin.h
index a71b473649e..3f2dba09ca1 100644
--- a/engines/ags/plugins/ags_plugin.h
+++ b/engines/ags/plugins/ags_plugin.h
@@ -311,6 +311,18 @@ struct AGSRenderStageDesc {
 	AGSRenderMatrixes Matrixes;
 };
 
+// Game info
+struct AGSGameInfo {
+	// Which version of the plugin interface the struct corresponds to;
+	// this field must be filled by a plugin before passing the struct into the engine!
+	int Version;
+	// Game name
+	char GameName[50];
+	// guid
+	char guid[40];
+	// Random key identifying the game
+	int uniqueid;
+};
 
 // The plugin-to-engine interface
 class IAGSEngine {
@@ -564,6 +576,11 @@ public:
 	// fills the provided AGSRenderStageDesc struct with current render stage description;
 	// please note that plugin MUST fill the struct's Version field before passing it into the function!
 	AGSIFUNC(void)  GetRenderStageDesc(AGSRenderStageDesc *desc);
+
+	// *** BELOW ARE INTERFACE VERSION 26 AND ABOVE ONLY
+	// fills the provided AGSGameInfo struct
+	// please note that plugin MUST fill the struct's Version field before passing it into the function!
+	AGSIFUNC(void)  GetGameInfo(AGSGameInfo* ginfo);
 };
 
 struct EnginePlugin {


Commit: 98f4b82f364660b6f4df22df7abdfa1795586736
    https://github.com/scummvm/scummvm/commit/98f4b82f364660b6f4df22df7abdfa1795586736
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: added IAGSFontRenderer2 and NotifyFontUpdated

>From upstream e42b1371a8258ddd47c79af04a6f78fab2a136f4

Changed paths:
    engines/ags/plugins/ags_plugin.cpp
    engines/ags/plugins/ags_plugin.h
    engines/ags/shared/font/ags_font_renderer.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/fonts.h
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/font/ttf_font_renderer.h
    engines/ags/shared/font/wfn_font_renderer.h


diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index cdb4395c8e7..b8b584fa039 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -762,6 +762,17 @@ void IAGSEngine::GetGameInfo(AGSGameInfo* ginfo) {
 	}
 }
 
+IAGSFontRenderer2* IAGSEngine::ReplaceFontRenderer2(int fontNumber, IAGSFontRenderer2 *newRenderer) {
+	auto *old_render = font_replace_renderer(fontNumber, newRenderer);
+	GUI::MarkForFontUpdate(fontNumber);
+	return old_render;
+}
+
+void IAGSEngine::NotifyFontUpdated(int fontNumber) {
+	font_recalc_metrics(fontNumber);
+	GUI::MarkForFontUpdate(fontNumber);
+}
+
 // *********** General plugin implementation **********
 
 void pl_stop_plugins() {
diff --git a/engines/ags/plugins/ags_plugin.h b/engines/ags/plugins/ags_plugin.h
index 3f2dba09ca1..5f9555f6db6 100644
--- a/engines/ags/plugins/ags_plugin.h
+++ b/engines/ags/plugins/ags_plugin.h
@@ -581,6 +581,10 @@ public:
 	// fills the provided AGSGameInfo struct
 	// please note that plugin MUST fill the struct's Version field before passing it into the function!
 	AGSIFUNC(void)  GetGameInfo(AGSGameInfo* ginfo);
+	// install a replacement renderer (extended interface) for the specified font number
+	AGSIFUNC(IAGSFontRenderer2*) ReplaceFontRenderer2(int fontNumber, IAGSFontRenderer2* newRenderer);
+	// notify the engine that certain custom font has been updated
+	AGSIFUNC(void)  NotifyFontUpdated(int fontNumber);
 };
 
 struct EnginePlugin {
diff --git a/engines/ags/shared/font/ags_font_renderer.h b/engines/ags/shared/font/ags_font_renderer.h
index 5c6eb06c85f..2d36808adda 100644
--- a/engines/ags/shared/font/ags_font_renderer.h
+++ b/engines/ags/shared/font/ags_font_renderer.h
@@ -42,6 +42,31 @@ protected:
 	~IAGSFontRenderer() {}
 };
 
+// Extended font renderer interface.
+// WARNING: this interface is exposed for plugins and declared for the second time in agsplugin.h
+class IAGSFontRenderer2 : public IAGSFontRenderer {
+public:
+	// Returns engine API version this font renderer complies to.
+	// Must not be lower than 26 (this interface was added at API v26).
+	virtual int GetVersion() = 0;
+	// Returns an arbitrary renderer name; this is for informational
+	// purposes only.
+	virtual const char *GetRendererName() = 0;
+	// Returns given font's name (if available).
+	virtual const char *GetFontName(int fontNumber) = 0;
+	// Returns the given font's height: that is the maximal vertical size
+	// that the font glyphs may occupy.
+	virtual int GetFontHeight(int fontNumber) = 0;
+	// Returns the given font's linespacing;
+	// is allowed to return 0, telling that no specific linespacing
+	// is assigned for this font.
+	virtual int GetLineSpacing(int fontNumber) = 0;
+
+protected:
+	IAGSFontRenderer2() {}
+	~IAGSFontRenderer2() {}
+};
+
 // Font render params, mainly for dealing with various compatibility issues.
 struct FontRenderParams {
 	// Font's render multiplier
@@ -57,7 +82,7 @@ struct FontMetrics {
 };
 
 // The strictly internal font renderer interface, not to use in plugin API.
- // Contains methods necessary for built-in font renderers.
+// Contains methods necessary for built-in font renderers.
 class IAGSFontRendererInternal {
 public:
 	// Tells if this is a bitmap font (otherwise it's a vector font)
@@ -65,8 +90,6 @@ public:
 	// Load font, applying extended font rendering parameters
 	virtual bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
 		FontMetrics *metrics) = 0;
-	// Gets font's name; must return an empty string if no name is available
-	virtual const char *GetName(int fontNumber) = 0;
 	// Perform any necessary adjustments when the AA mode is toggled
 	virtual void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) = 0;
 protected:
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index e86e065b85b..61ade153336 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -75,15 +75,23 @@ bool is_font_loaded(size_t fontNumber) {
 // Finish font's initialization
 static void font_post_init(size_t fontNumber) {
 	Font &font = _GP(fonts)[fontNumber];
+	// If no font height property was provided, then try several methods,
+	// depending on which interface is available
 	if (font.Metrics.Height == 0) {
-		// There is no explicit method for getting maximal possible height of any
-		// random font renderer at the moment; the implementations of GetTextHeight
-		// are allowed to return varied results depending on the text parameter.
-		// We use special line of text to get more or less reliable font height.
-		const char *height_test_string = "ZHwypgfjqhkilIK";
-		int height = font.Renderer->GetTextHeight(height_test_string, fontNumber);
-		font.Metrics.Height = height;
-		font.Metrics.RealHeight = height;
+		int height = 0;
+		if (font.Renderer2)
+			height = font.Renderer2->GetFontHeight(fontNumber);
+		if (height <= 0) {
+			// With the old renderer we have to rely on GetTextHeight;
+			// the implementations of GetTextHeight are allowed to return varied
+			// results depending on the text parameter.
+			// We use special line of text to get more or less reliable font height.
+			const char *height_test_string = "ZHwypgfjqhkilIK";
+			height = font.Renderer->GetTextHeight(height_test_string, fontNumber);
+		}
+
+		font.Metrics.Height = std::max(0, height);
+		font.Metrics.RealHeight = font.Metrics.Height;
 	}
 	// Use either nominal or real pixel height to define font's logical height
 	// and default linespacing; logical height = nominal height is compatible with the old games
@@ -94,11 +102,20 @@ static void font_post_init(size_t fontNumber) {
 		font.Info.AutoOutlineThickness = 0;
 	}
 
-	// If there's no explicit linespacing property set, then calculate
-	// default linespacing from the font height + outline thickness.
+	// If no linespacing property was provided, then try several methods,
+	// depending on which interface is available
 	font.LineSpacingCalc = font.Info.LineSpacing;
 	if (font.Info.LineSpacing == 0) {
-		font.LineSpacingCalc = font.Metrics.CompatHeight + 2 * font.Info.AutoOutlineThickness;
+		int linespacing = 0;
+		if (font.Renderer2)
+			linespacing = font.Renderer2->GetLineSpacing(fontNumber);
+		if (linespacing > 0) {
+			font.LineSpacingCalc = linespacing;
+		} else {
+			// Calculate default linespacing from the font height + outline thickness.
+			font.Info.Flags |= FFLG_DEFLINESPACING;
+			font.LineSpacingCalc = font.Metrics.CompatHeight + 2 * font.Info.AutoOutlineThickness;
+		}
 	}
 }
 
@@ -107,11 +124,32 @@ IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *ren
 		return nullptr;
 	IAGSFontRenderer *oldRender = _GP(fonts)[fontNumber].Renderer;
 	_GP(fonts)[fontNumber].Renderer = renderer;
+	_GP(fonts)[fontNumber].Renderer2 = nullptr;
+	_GP(fonts)[fontNumber].RendererInt = nullptr;
+	_GP(fonts)[fontNumber].Metrics = FontMetrics();
+	font_post_init(fontNumber);
+	return oldRender;
+}
+
+IAGSFontRenderer2* font_replace_renderer(size_t fontNumber, IAGSFontRenderer2 *renderer) {
+	if (fontNumber >= _GP(fonts).size())
+		return nullptr;
+	IAGSFontRenderer2* oldRender = _GP(fonts)[fontNumber].Renderer2;
+	_GP(fonts)[fontNumber].Renderer = renderer;
+	_GP(fonts)[fontNumber].Renderer2 = renderer;
 	_GP(fonts)[fontNumber].RendererInt = nullptr;
+	_GP(fonts)[fontNumber].Metrics = FontMetrics();
 	font_post_init(fontNumber);
 	return oldRender;
 }
 
+void font_recalc_metrics(size_t fontNumber) {
+	if (fontNumber >= _GP(fonts).size())
+		return;
+	_GP(fonts)[fontNumber].Metrics = FontMetrics();
+	font_post_init(fontNumber);
+}
+
 bool is_bitmap_font(size_t fontNumber) {
 	if (fontNumber >= _GP(fonts).size() || !_GP(fonts)[fontNumber].RendererInt)
 		return false;
@@ -125,9 +163,9 @@ bool font_supports_extended_characters(size_t fontNumber) {
 }
 
 const char *get_font_name(size_t fontNumber) {
-	if (fontNumber >= _GP(fonts).size() || !_GP(fonts)[fontNumber].RendererInt)
+	if (fontNumber >= _GP(fonts).size() || !_GP(fonts)[fontNumber].Renderer2)
 		return "";
-	const char *name = _GP(fonts)[fontNumber].RendererInt->GetName(fontNumber);
+	const char *name = _GP(fonts)[fontNumber].Renderer2->GetFontName(fontNumber);
 	return name ? name : "";
 }
 
@@ -404,9 +442,11 @@ bool load_font_size(size_t fontNumber, const FontInfo &font_info) {
 
 	if (_GP(ttfRenderer).LoadFromDiskEx(fontNumber, font_info.Size, &params, &metrics)) {
 		_GP(fonts)[fontNumber].Renderer = &_GP(ttfRenderer);
+		_GP(fonts)[fontNumber].Renderer2 = &_GP(ttfRenderer);
 		_GP(fonts)[fontNumber].RendererInt = &_GP(ttfRenderer);
 	} else if (_GP(wfnRenderer).LoadFromDiskEx(fontNumber, font_info.Size, &params, &metrics)) {
 		_GP(fonts)[fontNumber].Renderer = &_GP(wfnRenderer);
+		_GP(fonts)[fontNumber].Renderer2 = &_GP(wfnRenderer);
 		_GP(fonts)[fontNumber].RendererInt = &_GP(wfnRenderer);
 	}
 
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index 51163b51888..3b1ee0a34eb 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -32,6 +32,7 @@
 namespace AGS3 {
 
 class IAGSFontRenderer;
+class IAGSFontRenderer2;
 class IAGSFontRendererInternal;
 struct FontInfo;
 struct FontRenderParams;
@@ -40,7 +41,11 @@ namespace AGS {
 namespace Shared {
 
 struct Font {
+	// Classic font renderer interface
 	IAGSFontRenderer *Renderer = nullptr;
+	// Extended font renderer interface (optional)
+	IAGSFontRenderer2 *Renderer2 = nullptr;
+	// Internal interface (only for built-in renderers)
 	IAGSFontRendererInternal *RendererInt = nullptr;
 	FontInfo            Info;
 	// Values received from the renderer and saved for the reference
@@ -60,15 +65,12 @@ struct Font {
 
 using namespace AGS;
 
-class IAGSFontRenderer;
-class IAGSFontRendererInternal;
-struct FontInfo;
-struct FontRenderParams;
-
 void init_font_renderer();
 void shutdown_font_renderer();
 void adjust_y_coordinate_for_text(int *ypos, size_t fontnum);
 IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer);
+IAGSFontRenderer2* font_replace_renderer(size_t fontNumber, IAGSFontRenderer2 *renderer);
+ void font_recalc_metrics(size_t fontNumber);
 bool font_first_renderer_loaded();
 bool is_font_loaded(size_t fontNumber);
 bool is_bitmap_font(size_t fontNumber);
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index a2ca87c5042..675bbffc76f 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -126,10 +126,14 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	return true;
 }
 
-const char *TTFFontRenderer::GetName(int fontNumber) {
+const char *TTFFontRenderer::GetFontName(int fontNumber) {
 	return alfont_get_name(_fontData[fontNumber].AlFont);
 }
 
+int TTFFontRenderer::GetFontHeight(int fontNumber) {
+	return alfont_get_font_real_height(_fontData[fontNumber].AlFont);
+}
+
 void TTFFontRenderer::AdjustFontForAntiAlias(int fontNumber, bool /*aa_mode*/) {
 	if (_G(loaded_game_file_version) < kGameVersion_341) {
 		ALFONT_FONT *alfptr = _fontData[fontNumber].AlFont;
diff --git a/engines/ags/shared/font/ttf_font_renderer.h b/engines/ags/shared/font/ttf_font_renderer.h
index 8f01ecdb198..7e0c38578b9 100644
--- a/engines/ags/shared/font/ttf_font_renderer.h
+++ b/engines/ags/shared/font/ttf_font_renderer.h
@@ -30,7 +30,7 @@ namespace AGS3 {
 
 struct ALFONT_FONT;
 
-class TTFFontRenderer : public IAGSFontRenderer, public IAGSFontRendererInternal {
+class TTFFontRenderer : public IAGSFontRenderer2, public IAGSFontRendererInternal {
 public:
 	virtual ~TTFFontRenderer() {}
 
@@ -46,11 +46,17 @@ public:
 	void AdjustYCoordinateForFont(int *ycoord, int fontNumber) override;
 	void EnsureTextValidForFont(char *text, int fontNumber) override;
 
+	// IAGSFontRenderer2 implementation
+	int GetVersion() override { return 26; /* first compatible engine API version */ }
+	const char *GetRendererName() override { return "TTFFontRenderer"; }
+	const char *GetFontName(int fontNumber) override;
+	int GetFontHeight(int fontNumber) override;
+	int GetLineSpacing(int fontNumber) override { return 0; /* no specific spacing */ }
+
 	// IAGSFontRendererInternal implementation
 	bool IsBitmapFont() override;
 	bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
 		FontMetrics *metrics) override;
-	const char *GetName(int fontNumber) override;
 	void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) override;
 
 	//
diff --git a/engines/ags/shared/font/wfn_font_renderer.h b/engines/ags/shared/font/wfn_font_renderer.h
index d944284d0cd..f2e44b09873 100644
--- a/engines/ags/shared/font/wfn_font_renderer.h
+++ b/engines/ags/shared/font/wfn_font_renderer.h
@@ -29,7 +29,7 @@ namespace AGS3 {
 
 class WFNFont;
 
-class WFNFontRenderer : public IAGSFontRenderer, public IAGSFontRendererInternal {
+class WFNFontRenderer : public IAGSFontRenderer2, public IAGSFontRendererInternal {
 public:
 	// IAGSFontRenderer implementation
 	virtual ~WFNFontRenderer() {}
@@ -43,11 +43,17 @@ public:
 	void AdjustYCoordinateForFont(int *ycoord, int fontNumber) override;
 	void EnsureTextValidForFont(char *text, int fontNumber) override;
 
+	// IAGSFontRenderer2 implementation
+	int GetVersion() override { return 26; /* first compatible engine API version */ }
+	const char *GetRendererName() override { return "WFNFontRenderer"; }
+	const char *GetFontName(int /*fontNumber*/) override { return ""; }
+	int GetFontHeight(int fontNumber) override { return 0; /* TODO? */ }
+	int GetLineSpacing(int fontNumber) override { return 0; /* no specific spacing */ }
+
 	// IAGSFontRendererInternal implementation
 	bool IsBitmapFont() override;
 	bool LoadFromDiskEx(int fontNumber, int fontSize,
 		const FontRenderParams *params, FontMetrics *metrics) override;
-	const char *GetName(int /*fontNumber*/) override { return ""; }
 	void AdjustFontForAntiAlias(int /*fontNumber*/, bool /*aa_mode*/) override { /* do nothing */ }
 
 private:


Commit: f380f418de2b6d9955583bc4cc77586a3dd6337d
    https://github.com/scummvm/scummvm/commit/f380f418de2b6d9955583bc4cc77586a3dd6337d
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: implement IAGSFontRenderer2 and use NotifyFontUpdated for AGSSpriteFont

>From upstream 63304da8ad002549930c3b894b56f4babec25902

Changed paths:
    engines/ags/plugins/ags_sprite_font/ags_sprite_font.cpp
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h


diff --git a/engines/ags/plugins/ags_sprite_font/ags_sprite_font.cpp b/engines/ags/plugins/ags_sprite_font/ags_sprite_font.cpp
index 5a3d7a5a498..00d611eb151 100644
--- a/engines/ags/plugins/ags_sprite_font/ags_sprite_font.cpp
+++ b/engines/ags/plugins/ags_sprite_font/ags_sprite_font.cpp
@@ -108,14 +108,14 @@ void AGSSpriteFont::SetSpriteFont(ScriptMethodParams &params) {
 	PARAMS9(int, fontNum, int, sprite, int, rows, int, columns, int, charWidth, int, charHeight, int, charMin, int, charMax, bool, use32bit);
 	_engine->PrintDebugConsole("AGSSpriteFont: SetSpriteFont");
 	_fontRenderer->SetSpriteFont(fontNum, sprite, rows, columns, charWidth, charHeight, charMin, charMax, use32bit);
-	_engine->ReplaceFontRenderer(fontNum, _fontRenderer);
+	_engine->ReplaceFontRenderer2(fontNum, _fontRenderer);
 }
 
 void AGSSpriteFont::SetVariableSpriteFont(ScriptMethodParams &params) {
 	PARAMS2(int, fontNum, int, sprite);
 	_engine->PrintDebugConsole("AGSSpriteFont: SetVariableFont");
 	_vWidthRenderer->SetSprite(fontNum, sprite);
-	_engine->ReplaceFontRenderer(fontNum, _vWidthRenderer);
+	_engine->ReplaceFontRenderer2(fontNum, _vWidthRenderer);
 }
 
 void AGSSpriteFont::SetGlyph(ScriptMethodParams &params) {
diff --git a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
index 2fe72110a37..8e26382fdb9 100644
--- a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
+++ b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
@@ -85,6 +85,11 @@ int SpriteFontRenderer::GetTextHeight(const char *text, int fontNumber) {
 	return font->CharHeight;
 }
 
+int SpriteFontRenderer::GetFontHeight(int fontNumber) {
+	SpriteFont *font = getFontFor(fontNumber);
+	return font->CharHeight;
+}
+
 SpriteFont *SpriteFontRenderer::getFontFor(int fontNum) {
 	SpriteFont *font;
 	for (int i = 0; i < (int)_fonts.size(); i ++) {
diff --git a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h
index 8aa9b954752..848450f02f2 100644
--- a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h
+++ b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h
@@ -30,7 +30,7 @@ namespace AGS3 {
 namespace Plugins {
 namespace AGSSpriteFont {
 
-class SpriteFontRenderer : public IAGSFontRenderer {
+class SpriteFontRenderer : public IAGSFontRenderer2 {
 protected:
 	IAGSEngine *_engine;
 	SpriteFont *getFontFor(int fontNum);
@@ -41,6 +41,9 @@ public:
 	SpriteFontRenderer(IAGSEngine *engine);
 	virtual ~SpriteFontRenderer();
 
+	void SetSpriteFont(int fontNum, int sprite, int rows, int columns, int charWidth, int charHeight, int charMin, int charMax, bool use32bit);
+
+	// IAGSFontRenderer implementation
 	bool LoadFromDisk(int fontNumber, int fontSize) override {
 		return true;
 	}
@@ -51,7 +54,13 @@ public:
 	void RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) override;
 	void AdjustYCoordinateForFont(int *ycoord, int fontNumber) override { }
 	void EnsureTextValidForFont(char *text, int fontNumber) override;
-	void SetSpriteFont(int fontNum, int sprite, int rows, int columns, int charWidth, int charHeight, int charMin, int charMax, bool use32bit);
+
+	// IAGSFontRenderer2 implementation
+	int GetVersion() override { return 26; /* compatible engine API ver */ }
+	const char *GetRendererName() override { return "SpriteFontRenderer"; }
+	const char *GetFontName(int fontNumber) override { return ""; /* not supported */ }
+	int GetFontHeight(int fontNumber) override;
+	int GetLineSpacing(int fontNumber) override { return 0; /* not specified */ }
 };
 
 } // namespace AGSSpriteFont
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
index 26ad15d335a..95456248cb2 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
@@ -70,6 +70,19 @@ int VariableWidthSpriteFontRenderer::GetTextHeight(const char *text, int fontNum
 	return 0;
 }
 
+int VariableWidthSpriteFontRenderer::GetFontHeight(int fontNumber) {
+	VariableWidthFont *font = getFontFor(fontNumber);
+	if (font->characters.size() > 0) {
+		return font->characters.begin()->_value.Height + font->LineHeightAdjust;
+	}
+	return 0;
+ }
+
+int VariableWidthSpriteFontRenderer::GetLineSpacing(int fontNumber) {
+	VariableWidthFont *font = getFontFor(fontNumber);
+	return font->LineSpacingOverride;
+}
+
 void VariableWidthSpriteFontRenderer::SetSpacing(int fontNum, int spacing) {
 	VariableWidthFont *font = getFontFor(fontNum);
 	font->Spacing = spacing;
@@ -82,6 +95,9 @@ void VariableWidthSpriteFontRenderer::SetLineHeightAdjust(int fontNum, int LineH
 	font->LineHeightAdjust = LineHeight;
 	font->LineSpacingAdjust = SpacingHeight;
 	font->LineSpacingOverride = SpacingOverride;
+
+	if (_engine->version >= 26)
+		_engine->NotifyFontUpdated(fontNum);
 }
 
 void VariableWidthSpriteFontRenderer::EnsureTextValidForFont(char *text, int fontNumber) {
@@ -100,6 +116,12 @@ void VariableWidthSpriteFontRenderer::EnsureTextValidForFont(char *text, int fon
 void VariableWidthSpriteFontRenderer::SetGlyph(int fontNum, int charNum, int x, int y, int width, int height) {
 	VariableWidthFont *font = getFontFor(fontNum);
 	font->SetGlyph(charNum, x, y, width, height);
+
+	// Only notify engine at the first engine glyph,
+	// that should be enough for calculating font height metrics,
+	// and will reduce work load (sadly there's no Begin/EndUpdate functions).
+	if ((_engine->version >= 26) && (font->characters.size() == 1))
+		_engine->NotifyFontUpdated(fontNum);
 }
 
 
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h
index a3026838391..7c34d511dc6 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h
@@ -30,7 +30,7 @@ namespace AGS3 {
 namespace Plugins {
 namespace AGSSpriteFont {
 
-class VariableWidthSpriteFontRenderer : public IAGSFontRenderer {
+class VariableWidthSpriteFontRenderer : public IAGSFontRenderer2 {
 protected:
 	IAGSEngine *_engine;
 	std::vector<VariableWidthFont *> _fonts;
@@ -41,6 +41,12 @@ public:
 	VariableWidthSpriteFontRenderer(IAGSEngine *engine);
 	virtual ~VariableWidthSpriteFontRenderer();
 
+	void SetGlyph(int fontNum, int charNum, int x, int y, int width, int height);
+	void SetSprite(int fontNum, int spriteNum);
+	void SetSpacing(int fontNum, int spacing);
+	void SetLineHeightAdjust(int fontNum, int LineHeight, int SpacingHeight, int SpacingOverride);
+
+	// IAGSFontRenderer implementation
 	bool LoadFromDisk(int fontNumber, int fontSize) override {
 		return true;
 	}
@@ -52,10 +58,13 @@ public:
 	void RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) override;
 	void AdjustYCoordinateForFont(int *ycoord, int fontNumber) override { }
 	void EnsureTextValidForFont(char *text, int fontNumber) override;
-	void SetGlyph(int fontNum, int charNum, int x, int y, int width, int height);
-	void SetSprite(int fontNum, int spriteNum);
-	void SetSpacing(int fontNum, int spacing);
-	void SetLineHeightAdjust(int fontNum, int LineHeight, int SpacingHeight, int SpacingOverride);
+
+	// IAGSFontRenderer2 implementation
+	int GetVersion() override { return 26; /* compatible engine API ver */ }
+	const char *GetRendererName() override { return "VariableWidthSpriteFontRenderer"; }
+	const char *GetFontName(int fontNumber) override { return ""; /* not supported */ }
+	int GetFontHeight(int fontNumber) override;
+	int GetLineSpacing(int fontNumber) override;
 };
 
 } // namespace AGSSpriteFont
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
index 233811f191a..df5607cf1f1 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
@@ -32,26 +32,6 @@ VariableWidthSpriteFontRendererClifftop::VariableWidthSpriteFontRendererClifftop
 VariableWidthSpriteFontRendererClifftop::~VariableWidthSpriteFontRendererClifftop(void) {
 }
 
-int VariableWidthSpriteFontRendererClifftop::GetTextHeight(const char *text, int fontNumber) {
-	VariableWidthFont *font = getFontFor(fontNumber);
-	if (strcmp("<LINE_SPACING>", text) == 0)
-		return font->LineSpacingOverride;
-
-	for (int i = 0; i < (int)strlen(text); i++) {
-		if (font->characters.count(text[i]) > 0) {
-			int height = font->characters[text[i]].Height;
-
-			if (strcmp("ZHwypgfjqhkilIK", text) == 0 || strcmp("ZhypjIHQFb", text) == 0 || strcmp("YpyjIHgMNWQ", text) == 0 || strcmp("BigyjTEXT", text) == 0)
-				height += font->LineSpacingAdjust;
-			else
-				height += font->LineHeightAdjust;
-
-			return height;
-		}
-	}
-	return 0;
-}
-
 void VariableWidthSpriteFontRendererClifftop::RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) {
 	VariableWidthFont *font = getFontFor(fontNumber);
 	int totalWidth = 0;
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h
index 88136c84ad5..a03d78cf20d 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h
@@ -37,7 +37,6 @@ public:
 	VariableWidthSpriteFontRendererClifftop(IAGSEngine *engine);
 	~VariableWidthSpriteFontRendererClifftop(void) override;
 
-	int GetTextHeight(const char *text, int fontNumber) override;
 	void RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) override;
 };
 


Commit: 19514bc2ad7602ce157abd6794d3a9a10c56657b
    https://github.com/scummvm/scummvm/commit/19514bc2ad7602ce157abd6794d3a9a10c56657b
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-10-10T23:42:34+01:00

Commit Message:
AGS: Common: properly restore font metrics when setting an old font renderer

>From upstream f07e8e20ddf715511012aa20861b9e8cecf7aa4f

Changed paths:
    engines/ags/shared/font/ags_font_renderer.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/font/ttf_font_renderer.h
    engines/ags/shared/font/wfn_font_renderer.cpp
    engines/ags/shared/font/wfn_font_renderer.h


diff --git a/engines/ags/shared/font/ags_font_renderer.h b/engines/ags/shared/font/ags_font_renderer.h
index 2d36808adda..3ee7a1f4c58 100644
--- a/engines/ags/shared/font/ags_font_renderer.h
+++ b/engines/ags/shared/font/ags_font_renderer.h
@@ -83,15 +83,18 @@ struct FontMetrics {
 
 // The strictly internal font renderer interface, not to use in plugin API.
 // Contains methods necessary for built-in font renderers.
-class IAGSFontRendererInternal {
+class IAGSFontRendererInternal : public IAGSFontRenderer2 {
 public:
 	// Tells if this is a bitmap font (otherwise it's a vector font)
 	virtual bool IsBitmapFont() = 0;
 	// Load font, applying extended font rendering parameters
 	virtual bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
 		FontMetrics *metrics) = 0;
+	// Fill FontMetrics struct; note that it may be left cleared if this is not supported
+	virtual void GetFontMetrics(int fontNumber, FontMetrics *metrics) = 0;
 	// Perform any necessary adjustments when the AA mode is toggled
 	virtual void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) = 0;
+
 protected:
 	IAGSFontRendererInternal() {}
 	~IAGSFontRendererInternal() {}
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index 61ade153336..3ab78847f32 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -77,7 +77,7 @@ static void font_post_init(size_t fontNumber) {
 	Font &font = _GP(fonts)[fontNumber];
 	// If no font height property was provided, then try several methods,
 	// depending on which interface is available
-	if (font.Metrics.Height == 0) {
+	if (font.Metrics.Height == 0 && font.Renderer) {
 		int height = 0;
 		if (font.Renderer2)
 			height = font.Renderer2->GetFontHeight(fontNumber);
@@ -119,28 +119,37 @@ static void font_post_init(size_t fontNumber) {
 	}
 }
 
+static void font_replace_renderer(size_t fontNumber, IAGSFontRenderer* renderer, IAGSFontRenderer2* renderer2) {
+	_GP(fonts)[fontNumber].Renderer = renderer;
+	_GP(fonts)[fontNumber].Renderer2 = renderer2;
+	// If this is one of our built-in font renderers, then correctly
+	// reinitialize interfaces and font metrics
+	if ((renderer == &_GP(ttfRenderer)) || (renderer == &_GP(wfnRenderer))) {
+		_GP(fonts)[fontNumber].RendererInt = static_cast<IAGSFontRendererInternal*>(renderer);
+		_GP(fonts)[fontNumber].RendererInt->GetFontMetrics(fontNumber, &_GP(fonts)[fontNumber].Metrics);
+	} else {
+		// Otherwise, this is probably coming from plugin
+		_GP(fonts)[fontNumber].RendererInt = nullptr;
+		_GP(fonts)[fontNumber].Metrics = FontMetrics(); // reset to defaults
+	}
+	font_post_init(fontNumber);
+}
+
+
 IAGSFontRenderer *font_replace_renderer(size_t fontNumber, IAGSFontRenderer *renderer) {
 	if (fontNumber >= _GP(fonts).size())
 		return nullptr;
-	IAGSFontRenderer *oldRender = _GP(fonts)[fontNumber].Renderer;
-	_GP(fonts)[fontNumber].Renderer = renderer;
-	_GP(fonts)[fontNumber].Renderer2 = nullptr;
-	_GP(fonts)[fontNumber].RendererInt = nullptr;
-	_GP(fonts)[fontNumber].Metrics = FontMetrics();
-	font_post_init(fontNumber);
-	return oldRender;
+	IAGSFontRenderer* old_render = _GP(fonts)[fontNumber].Renderer;
+	font_replace_renderer(fontNumber, renderer, nullptr);
+	return old_render;
 }
 
 IAGSFontRenderer2* font_replace_renderer(size_t fontNumber, IAGSFontRenderer2 *renderer) {
 	if (fontNumber >= _GP(fonts).size())
 		return nullptr;
-	IAGSFontRenderer2* oldRender = _GP(fonts)[fontNumber].Renderer2;
-	_GP(fonts)[fontNumber].Renderer = renderer;
-	_GP(fonts)[fontNumber].Renderer2 = renderer;
-	_GP(fonts)[fontNumber].RendererInt = nullptr;
-	_GP(fonts)[fontNumber].Metrics = FontMetrics();
-	font_post_init(fontNumber);
-	return oldRender;
+	IAGSFontRenderer2* old_render = _GP(fonts)[fontNumber].Renderer2;
+	font_replace_renderer(fontNumber, renderer, renderer);
+	return old_render;
 }
 
 void font_recalc_metrics(size_t fontNumber) {
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index 675bbffc76f..4ece2d2e0be 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -85,9 +85,8 @@ static int GetAlfontFlags(int load_mode) {
 	return flags;
 }
 
-// Loads a TTF font of a certain size, optionally fill the FontMetrics struct
-static ALFONT_FONT *LoadTTF(const String &filename, int fontSize,
-	int alfont_flags, FontMetrics *metrics) {
+// Loads a TTF font of a certain size
+static ALFONT_FONT *LoadTTF(const String &filename, int fontSize, int alfont_flags) {
 	std::unique_ptr<Stream> reader(_GP(AssetMgr)->OpenAsset(filename));
 	if (!reader)
 		return nullptr;
@@ -101,13 +100,16 @@ static ALFONT_FONT *LoadTTF(const String &filename, int fontSize,
 	if (!alfptr)
 		return nullptr;
 	alfont_set_font_size_ex(alfptr, fontSize, alfont_flags);
-	if (metrics) {
-		metrics->Height = alfont_get_font_height(alfptr);
-		metrics->RealHeight = alfont_get_font_real_height(alfptr);
-	}
 	return alfptr;
 }
 
+// Fill the FontMetrics struct from the given ALFONT
+static void FillMetrics(ALFONT_FONT *alfptr, FontMetrics *metrics) {
+	metrics->Height = alfont_get_font_height(alfptr);
+	metrics->RealHeight = alfont_get_font_real_height(alfptr);
+	metrics->CompatHeight = metrics->Height; // just set to default here
+}
+
 bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	const FontRenderParams *params, FontMetrics *metrics) {
 	String filename = String::FromFormat("agsfnt%d.ttf", fontNumber);
@@ -117,12 +119,14 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 		fontSize *= params->SizeMultiplier;
 
 	ALFONT_FONT *alfptr = LoadTTF(filename, fontSize,
-		GetAlfontFlags(params->LoadMode), metrics);
+		GetAlfontFlags(params->LoadMode));
 	if (!alfptr)
 		return false;
 
 	_fontData[fontNumber].AlFont = alfptr;
 	_fontData[fontNumber].Params = params ? *params : FontRenderParams();
+	if (metrics)
+		FillMetrics(alfptr, metrics);
 	return true;
 }
 
@@ -134,6 +138,10 @@ int TTFFontRenderer::GetFontHeight(int fontNumber) {
 	return alfont_get_font_real_height(_fontData[fontNumber].AlFont);
 }
 
+void TTFFontRenderer::GetFontMetrics(int fontNumber, FontMetrics *metrics) {
+	FillMetrics(_fontData[fontNumber].AlFont, metrics);
+}
+
 void TTFFontRenderer::AdjustFontForAntiAlias(int fontNumber, bool /*aa_mode*/) {
 	if (_G(loaded_game_file_version) < kGameVersion_341) {
 		ALFONT_FONT *alfptr = _fontData[fontNumber].AlFont;
@@ -149,17 +157,19 @@ void TTFFontRenderer::FreeMemory(int fontNumber) {
 }
 
 bool TTFFontRenderer::MeasureFontOfPointSize(const String &filename, int size_pt, FontMetrics *metrics) {
-	ALFONT_FONT *alfptr = LoadTTF(filename, size_pt, ALFONT_FLG_FORCE_RESIZE | ALFONT_FLG_SELECT_NOMINAL_SZ, metrics);
+	ALFONT_FONT *alfptr = LoadTTF(filename, size_pt, ALFONT_FLG_FORCE_RESIZE | ALFONT_FLG_SELECT_NOMINAL_SZ);
 	if (!alfptr)
 		return false;
+	FillMetrics(alfptr, metrics);
 	alfont_destroy_font(alfptr);
 	return true;
 }
 
 bool TTFFontRenderer::MeasureFontOfPixelHeight(const String &filename, int pixel_height, FontMetrics *metrics) {
-	ALFONT_FONT *alfptr = LoadTTF(filename, pixel_height, ALFONT_FLG_FORCE_RESIZE, metrics);
+	ALFONT_FONT *alfptr = LoadTTF(filename, pixel_height, ALFONT_FLG_FORCE_RESIZE);
 	if (!alfptr)
 		return false;
+	FillMetrics(alfptr, metrics);
 	alfont_destroy_font(alfptr);
 	return true;
 }
diff --git a/engines/ags/shared/font/ttf_font_renderer.h b/engines/ags/shared/font/ttf_font_renderer.h
index 7e0c38578b9..12e37b8810c 100644
--- a/engines/ags/shared/font/ttf_font_renderer.h
+++ b/engines/ags/shared/font/ttf_font_renderer.h
@@ -30,7 +30,7 @@ namespace AGS3 {
 
 struct ALFONT_FONT;
 
-class TTFFontRenderer : public IAGSFontRenderer2, public IAGSFontRendererInternal {
+class TTFFontRenderer : public IAGSFontRendererInternal {
 public:
 	virtual ~TTFFontRenderer() {}
 
@@ -57,6 +57,7 @@ public:
 	bool IsBitmapFont() override;
 	bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
 		FontMetrics *metrics) override;
+	void GetFontMetrics(int fontNumber, FontMetrics *metrics) override;
 	void AdjustFontForAntiAlias(int fontNumber, bool aa_mode) override;
 
 	//
diff --git a/engines/ags/shared/font/wfn_font_renderer.cpp b/engines/ags/shared/font/wfn_font_renderer.cpp
index 1cca2fc4763..802219c02fe 100644
--- a/engines/ags/shared/font/wfn_font_renderer.cpp
+++ b/engines/ags/shared/font/wfn_font_renderer.cpp
@@ -155,6 +155,8 @@ bool WFNFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
 	}
 	_fontData[fontNumber].Font = font;
 	_fontData[fontNumber].Params = params ? *params : FontRenderParams();
+	if (metrics)
+		*metrics = FontMetrics();
 	return true;
 }
 
diff --git a/engines/ags/shared/font/wfn_font_renderer.h b/engines/ags/shared/font/wfn_font_renderer.h
index f2e44b09873..87bde8d30c0 100644
--- a/engines/ags/shared/font/wfn_font_renderer.h
+++ b/engines/ags/shared/font/wfn_font_renderer.h
@@ -29,7 +29,7 @@ namespace AGS3 {
 
 class WFNFont;
 
-class WFNFontRenderer : public IAGSFontRenderer2, public IAGSFontRendererInternal {
+class WFNFontRenderer : public IAGSFontRendererInternal {
 public:
 	// IAGSFontRenderer implementation
 	virtual ~WFNFontRenderer() {}
@@ -54,6 +54,7 @@ public:
 	bool IsBitmapFont() override;
 	bool LoadFromDiskEx(int fontNumber, int fontSize,
 		const FontRenderParams *params, FontMetrics *metrics) override;
+	void GetFontMetrics(int fontNumber, FontMetrics *metrics) override { *metrics = FontMetrics(); }
 	void AdjustFontForAntiAlias(int /*fontNumber*/, bool /*aa_mode*/) override { /* do nothing */ }
 
 private:




More information about the Scummvm-git-logs mailing list