From e8c957a7a8068e3d4b46c6a163d461c8265e67eb Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Fri, 7 Jun 2024 23:00:07 -0700 Subject: [PATCH] Scale OSD text according to display scale fixes #2605 --- .../Renderers/StringRenderer.cs | 57 ++++++++++-------- .../DisplayManager/DisplayManagerBase.cs | 4 ++ .../DisplayManager/FilterManager.cs | 4 ++ .../DisplayManager/Filters/Gui.cs | 14 +++-- .../DisplayManager/IBlitter.cs | 2 + .../DisplayManager/OSDManager.cs | 58 ++++++++----------- .../DisplayManager/DisplayManager.cs | 2 + 7 files changed, 79 insertions(+), 62 deletions(-) diff --git a/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs index 2dc3da8640..d551fda995 100644 --- a/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs +++ b/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs @@ -1,5 +1,5 @@ -//http://www.angelcode.com/products/bmfont/ -//http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp +// https://www.angelcode.com/products/bmfont/ +// https://devblog.cyotek.com/post/angelcode-bitmap-font-parsing-using-csharp using System; using System.Collections.Generic; @@ -19,10 +19,24 @@ namespace BizHawk.Bizware.Graphics FontInfo.LoadXml(xml); // load textures - for (var i=0; i<FontInfo.Pages.Length; i++) + for (var i = 0; i < FontInfo.Pages.Length; i++) { TexturePages.Add(owner.LoadTexture(textures[i])); } + + // precalc texcoords + foreach (var bfc in FontInfo) + { + var tex = TexturePages[bfc.TexturePage]; + var w = (float)tex.Width; + var h = (float)tex.Height; + var bounds = new Rectangle(bfc.X, bfc.Y, bfc.Width, bfc.Height); + var u0 = bounds.Left / w; + var v0 = bounds.Top / h; + var u1 = bounds.Right / w; + var v1 = bounds.Bottom / h; + CharTexCoords.Add(bfc.Char, new(u0, v0, u1, v1)); + } } public void Dispose() @@ -35,10 +49,10 @@ namespace BizHawk.Bizware.Graphics TexturePages = null; } - public SizeF Measure(string str) + public SizeF Measure(string str, int scale) { float x = 0; - float y = FontInfo.LineHeight; + float y = FontInfo.LineHeight * scale; var ox = x; var len = str.Length; @@ -67,18 +81,18 @@ namespace BizHawk.Bizware.Graphics } x = 0; - y += FontInfo.LineHeight; + y += FontInfo.LineHeight * scale; continue; } var bfc = FontInfo[c]; - x += bfc.XAdvance; + x += bfc.XAdvance * scale; } return new(Math.Max(x, ox), y); } - public void RenderString(IGuiRenderer renderer, float x, float y, string str) + public void RenderString(IGuiRenderer renderer, float x, float y, string str, int scale) { if (Owner != renderer.Owner) { @@ -108,33 +122,28 @@ namespace BizHawk.Bizware.Graphics if (c == '\n') { x = ox; - y += FontInfo.LineHeight; + y += FontInfo.LineHeight * scale; continue; } var bfc = FontInfo[c]; - - // calculate texcoords (we shouldve already had this cached, but im speedcoding now) var tex = TexturePages[bfc.TexturePage]; - var w = (float)tex.Width; - var h = (float)tex.Height; - var bounds = new Rectangle(bfc.X, bfc.Y, bfc.Width, bfc.Height); - var u0 = bounds.Left / w; - var v0 = bounds.Top / h; - var u1 = bounds.Right / w; - var v1 = bounds.Bottom / h; + var gx = x + bfc.XOffset * scale; + var gy = y + bfc.YOffset * scale; + var charTexCoords = CharTexCoords[bfc.Char]; + renderer.DrawSubrect(tex, gx, gy, bfc.Width * scale, bfc.Height * scale, + charTexCoords.U0, charTexCoords.V0, charTexCoords.U1, charTexCoords.V1); - var gx = x + bfc.XOffset; - var gy = y + bfc.YOffset; - renderer.DrawSubrect(tex, gx, gy, bfc.Width, bfc.Height, u0, v0, u1, v1); - - x += bfc.XAdvance; + x += bfc.XAdvance * scale; } } public IGL Owner { get; } private readonly BitmapFont FontInfo; - private List<ITexture2D> TexturePages = new(); + private List<ITexture2D> TexturePages = [ ]; + private readonly Dictionary<char, TexCoords> CharTexCoords = [ ]; + + private record TexCoords(float U0, float V0, float U1, float V1); } } \ No newline at end of file diff --git a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs index 566a6fdd93..b559c489ad 100644 --- a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs +++ b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs @@ -440,6 +440,8 @@ namespace BizHawk.Client.Common protected abstract Size GetGraphicsControlSize(); + protected abstract int GetGraphicsControlDpi(); + /// <summary> /// This will receive an emulated output frame from an IVideoProvider and run it through the complete frame processing pipeline /// Then it will stuff it into the bound PresentationPanel. @@ -811,6 +813,8 @@ namespace BizHawk.Client.Common filterProgram.GuiRenderer = _renderer; filterProgram.GL = _gl; + filterProgram.ControlDpi = GetGraphicsControlDpi(); + //setup the source image filter var fInput = (SourceImage)filterProgram["input"]; fInput.Texture = videoTexture; diff --git a/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs b/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs index a045ea2ee0..16ff743269 100644 --- a/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs +++ b/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs @@ -71,6 +71,10 @@ namespace BizHawk.Client.Common.FilterManager public IRenderTarget CurrRenderTarget; + // DPI / 96.0 indicates the display scaling + // this is mainly relevant for OSD + public int ControlDpi; + public IRenderTarget GetTempTarget(int width, int height) { return RenderTargetProvider.Get(new(width, height)); diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs index 0941f33ac3..70cee5cc32 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs @@ -613,9 +613,10 @@ namespace BizHawk.Client.Common.Filters } var size = FindInput().SurfaceFormat.Size; - + FilterProgram.GuiRenderer.Begin(size.Width, size.Height); - var blitter = new OSDBlitter(_font, FilterProgram.GuiRenderer, new(0, 0, size.Width, size.Height)); + var scale = (int)Math.Round(FilterProgram.ControlDpi / 96.0f); + var blitter = new OSDBlitter(_font, FilterProgram.GuiRenderer, new(0, 0, size.Width, size.Height), scale); FilterProgram.GuiRenderer.EnableBlending(); _manager.DrawScreenInfo(blitter); _manager.DrawMessages(blitter); @@ -627,24 +628,27 @@ namespace BizHawk.Client.Common.Filters private readonly StringRenderer _font; private readonly IGuiRenderer _renderer; - public OSDBlitter(StringRenderer font, IGuiRenderer renderer, Rectangle clipBounds) + public OSDBlitter(StringRenderer font, IGuiRenderer renderer, Rectangle clipBounds, int scale) { _font = font; _renderer = renderer; ClipBounds = clipBounds; + Scale = scale; } public void DrawString(string s, Color color, float x, float y) { _renderer.SetModulateColor(color); - _font.RenderString(_renderer, x, y, s); + _font.RenderString(_renderer, x, y, s, Scale); _renderer.SetModulateColorWhite(); } public SizeF MeasureString(string s) - => _font.Measure(s); + => _font.Measure(s, Scale); public Rectangle ClipBounds { get; } + + public int Scale { get; } } } } \ No newline at end of file diff --git a/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs b/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs index 47db7c2f5e..8bb9bde7f8 100644 --- a/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs +++ b/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs @@ -14,5 +14,7 @@ namespace BizHawk.Client.Common SizeF MeasureString(string s); Rectangle ClipBounds { get; } + + public int Scale { get; } } } diff --git a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs index 11d930cd4e..a6bacafc92 100644 --- a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs +++ b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Drawing; using System.Collections.Generic; + using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -36,17 +37,18 @@ namespace BizHawk.Client.Common public Color FixedMessagesColor => Color.FromArgb(_config.MessagesColor); public Color FixedAlertMessageColor => Color.FromArgb(_config.AlertMessageColor); - private PointF GetCoordinates(IBlitter g, MessagePosition position, string message) + + + private static PointF GetCoordinates(IBlitter g, MessagePosition position, string message) { var size = g.MeasureString(message); - float x = position.Anchor.IsLeft() + var x = position.Anchor.IsLeft() ? position.X : g.ClipBounds.Width - position.X - size.Width; - float y = position.Anchor.IsTop() + var y = position.Anchor.IsTop() ? position.Y : g.ClipBounds.Height - position.Y - size.Height; - return new PointF(x, y); } @@ -78,9 +80,9 @@ namespace BizHawk.Client.Common return _emulator.Frame.ToString(); } - private readonly List<UIMessage> _messages = new List<UIMessage>(5); - private readonly List<UIDisplay> _guiTextList = new List<UIDisplay>(); - private readonly List<UIDisplay> _ramWatchList = new List<UIDisplay>(); + private readonly List<UIMessage> _messages = new(5); + private readonly List<UIDisplay> _guiTextList = [ ]; + private readonly List<UIDisplay> _ramWatchList = [ ]; public void AddMessage(string message, int? duration = null) => _messages.Add(new() { @@ -89,9 +91,7 @@ namespace BizHawk.Client.Common }); public void ClearRamWatches() - { - _ramWatchList.Clear(); - } + => _ramWatchList.Clear(); public void AddRamWatch(string message, MessagePosition pos, Color backGround, Color foreColor) { @@ -116,9 +116,7 @@ namespace BizHawk.Client.Common } public void ClearGuiText() - { - _guiTextList.Clear(); - } + => _guiTextList.Clear(); private void DrawMessage(IBlitter g, UIMessage message, int yOffset) { @@ -140,10 +138,10 @@ namespace BizHawk.Client.Common { if (_config.StackOSDMessages) { - int line = 1; - for (int i = _messages.Count - 1; i >= 0; i--, line++) + var line = 1; + for (var i = _messages.Count - 1; i >= 0; i--, line++) { - int yOffset = (line - 1) * 18; + var yOffset = (line - 1) * 18 * g.Scale; if (!_config.Messages.Anchor.IsTop()) { yOffset = 0 - yOffset; @@ -154,7 +152,7 @@ namespace BizHawk.Client.Common } else { - var message = _messages[_messages.Count - 1]; + var message = _messages[^1]; DrawMessage(g, message, 0); } } @@ -175,14 +173,10 @@ namespace BizHawk.Client.Common } public string InputStrMovie() - { - return MakeStringFor(_movieSession.MovieController, cache: true); - } + => MakeStringFor(_movieSession.MovieController, cache: true); public string InputStrImmediate() - { - return MakeStringFor(_inputManager.AutofireStickyXorAdapter, cache: true); - } + => MakeStringFor(_inputManager.AutofireStickyXorAdapter, cache: true); public string InputPrevious() { @@ -235,10 +229,8 @@ namespace BizHawk.Client.Common : ""; } - private void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y) - { - g.DrawString(message, color, x, y); - } + private static void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y) + => g.DrawString(message, color, x, y); /// <summary> /// Display all screen info objects like fps, frame counter, lag counter, and input display @@ -247,7 +239,7 @@ namespace BizHawk.Client.Common { if (_config.DisplayFrameCounter && !_emulator.IsNull()) { - string message = MakeFrameCounter(); + var message = MakeFrameCounter(); var point = GetCoordinates(g, _config.FrameCounter, message); DrawOsdMessage(g, message, Color.FromArgb(_config.MessagesColor), point.X, point.Y); @@ -266,14 +258,14 @@ namespace BizHawk.Client.Common { var input = InputStrMovie(); var point = GetCoordinates(g, _config.InputDisplay, input); - Color c = Color.FromArgb(_config.MovieInput); + var c = Color.FromArgb(_config.MovieInput); g.DrawString(input, c, point.X, point.Y); } if (!moviePlaying) // TODO: message config -- allow setting of "mixed", and "auto" { var previousColor = Color.FromArgb(_config.LastInputColor); - Color immediateColor = Color.FromArgb(_config.MessagesColor); + var immediateColor = Color.FromArgb(_config.MessagesColor); var autoColor = Color.Pink; var changedColor = Color.PeachPuff; @@ -325,7 +317,7 @@ namespace BizHawk.Client.Common if (_config.DisplayRerecordCount) { - string rerecordCount = MakeRerecordCount(); + var rerecordCount = MakeRerecordCount(); var point = GetCoordinates(g, _config.ReRecordCounter, rerecordCount); DrawOsdMessage(g, rerecordCount, FixedMessagesColor, point.X, point.Y); } @@ -334,12 +326,12 @@ namespace BizHawk.Client.Common { var sb = new StringBuilder("Held: "); - foreach (string sticky in _inputManager.StickyXorAdapter.CurrentStickies) + foreach (var sticky in _inputManager.StickyXorAdapter.CurrentStickies) { sb.Append(sticky).Append(' '); } - foreach (string autoSticky in _inputManager.AutofireStickyXorAdapter.CurrentStickies) + foreach (var autoSticky in _inputManager.AutofireStickyXorAdapter.CurrentStickies) { sb .Append("Auto-") diff --git a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs index 690d167fd3..bccd565dc5 100644 --- a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs +++ b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs @@ -51,6 +51,8 @@ namespace BizHawk.Client.EmuHawk public override Size GetPanelNativeSize() => _presentationPanel.NativeSize; + protected override int GetGraphicsControlDpi() => _graphicsControl.DeviceDpi; + protected override Point GraphicsControlPointToClient(Point p) => _graphicsControl.PointToClient(p); protected override void SwapBuffersOfGraphicsControl() => _graphicsControl.SwapBuffers();