IvanS
IvanS

Reputation: 61

ttf font loads, but comes out garbled (somewhat like barcodes)

I originally created my app with ImGuiNET and ClickableTransparentOverlay. However, since I need to send keystrokes to the foreground window I need to port it to plain ImGuiNet. That's because CTO is always the foreground window.

In CTO I use ttf fonts and all works well, but with ImGuiNET (1.91.0) the fonts seem to load fine, but the output is garbled. It looks like the textures aren't built correctly or there's a problem loading them into the GPU.

I'm using the ImGui.NET.SampleProgram (ImGuiNET + Veldrid) as a base for testing my font implementation. Can anyone help out or point me to a working example? I couldn't find one online (or not complete enough to solve the problem) nor could ChatGPT find a solution.

enter image description here

This is part of the code:

       static void Main(string[] args)
   {
       bool keepRunning = true;
       // Create window, GraphicsDevice, and all resources necessary for the demo.
       VeldridStartup.CreateWindowAndGraphicsDevice(
           //                new WindowCreateInfo(50, 50, 1280, 720, WindowState.Normal, "icaVoice"),
           new WindowCreateInfo(50, 50, 800, 600, WindowState.Normal, "icaVoice"),
           new GraphicsDeviceOptions(true, null, true, ResourceBindingModel.Improved, true, true),
           out _window,
           out _gd);
       _window.Resized += () =>
       {
           _gd.MainSwapchain.Resize((uint)_window.Width, (uint)_window.Height);
           _controller.WindowResized(_window.Width, _window.Height);
       };
       _cl = _gd.ResourceFactory.CreateCommandList();
       _controller = new ImGuiController(_gd, _gd.MainSwapchain.Framebuffer.OutputDescription, _window.Width, _window.Height);

       //hwnd = WindowHelper.GetForegroundWindow(); // Get your actual HWND
       WindowHelper.SetHWND();   // Initialize window handle

        // Load fonts
        FontLoader fontLoader = new FontLoader(_gd, _controller);
        fontLoader.LoadFonts();

        var gui = new GUI(settings, commandQueue, _controller, _gd);

        while (keepRunning)
        {
            InputSnapshot snapshot = _window.PumpEvents();
            _controller.Update(deltaTime, snapshot); // Feed the input events to our ImGui controller, which passes them through to ImGui.
            _showGUI = WindowHelper.SetWindowState(settings.GuiMode, settings.GuiDelay, deltaTime);   // TODO : make bool, so it determines whether to render GUI
            if (_showGUI)
            {
                // Only process if window visible
                if (!_window.Exists)
                {
                    keepRunning = false;
                    break;
                }

                // Lock ImGui window to main (Veldrid/SDL2) window size and position
                ImGui.SetNextWindowSize(new Vector2(_window.Width, _window.Height));
                ImGui.SetNextWindowPos(Vector2.Zero);

                // Render GUI
                //gui.Render(); 
                FontTest();
                //GlyphList();

                // Show in window
                _cl.Begin();
                _cl.SetFramebuffer(_gd.MainSwapchain.Framebuffer);
                _cl.ClearColorTarget(0, new RgbaFloat(_clearColor.X, _clearColor.Y, _clearColor.Z, 0.1f));
                _controller.Render(_gd, _cl);
                _cl.End();
                _gd.SubmitCommands(_cl);
                _gd.SwapBuffers(_gd.MainSwapchain);
            }
            Thread.Sleep(40);
        }

        // Clean up Veldrid resources
        _gd.WaitForIdle();
        _controller.Dispose();
        _cl.Dispose();
        _gd.Dispose();

        Console.WriteLine("Finished");
    }

    public class FontLoader
    {
        private GraphicsDevice _gd;
        private ImGuiController _controller;

        public FontLoader(GraphicsDevice gd, ImGuiController controller)
        {
            _gd = gd;
            _controller = controller;
        }

        public unsafe void LoadFonts()
        {
            // Access ImGui's IO structure
            var io = ImGui.GetIO();

            // Define font file paths (ensure the paths are correct!)
            string fontFilePath = "C:/Users/ivan/AppData/Local/Icarus/fonts/dejavu-sans-mono.book.ttf";
            string boldFontFilePath = @"C:\Users\Ivan\AppData\Local\Icarus\fonts\dejavu-sans-mono.bold.ttf";

            if (!File.Exists(fontFilePath))
            {
                Console.WriteLine($"Font file {fontFilePath} not found.");
                return;
            }

            if (!File.Exists(boldFontFilePath))
            {
                Console.WriteLine($"Font file {boldFontFilePath} not found.");
                return;
            }


            // Clear existing fonts (optional, if reloading fonts)
            io.Fonts.Clear();

            // create the object on the native side
            var nativeConfig = ImGuiNative.ImFontConfig_ImFontConfig();

            // fill with data
            (*nativeConfig).OversampleH = 3;
            (*nativeConfig).OversampleV = 3;
            (*nativeConfig).RasterizerMultiply = 1f;
            (*nativeConfig).GlyphExtraSpacing = new System.Numerics.Vector2(0, 0);
            (*nativeConfig).MergeMode = 0;

            // Load a basic font 
            regularFont = io.Fonts.AddFontFromFileTTF(fontFilePath, 22.0f, nativeConfig);
            if (regularFont.NativePtr == null) Console.WriteLine("Failed to load regular font.");

            //// Load a bold font
            boldFont = io.Fonts.AddFontFromFileTTF(boldFontFilePath, 34.0f, nativeConfig);
            if (boldFont.NativePtr == null) Console.WriteLine("Failed to load bold font.");

            ImGuiNative.igGetIO()->FontDefault = null; // Use the new font

            // Build the font atlas
            io.Fonts.Build();

            // Update ImGui's font texture with the graphics device
            _controller.RecreateFontDeviceTexture(_gd);
        }
    }

    private static unsafe void FontTest()
    {
        // ImGui rendering logic
        ImGui.Begin("Hello, World!");
        ImGui.PushFont(regularFont);
        ImGui.Text("This is a sample window with a custom font!");
        ImGui.End();
    }

Upvotes: 1

Views: 129

Answers (2)

bh_earth0
bh_earth0

Reputation: 2834

edit-Final: found the real solution with pure imguiNet.. see my other answer below.. here_the_Link

i will keep this here for people who wants to use Easier Library Called clickableTransparentOverlay


edit: i realized, i offer the solution you trying to escape.

clickableTransparentOverlay is easyToUse.


don't use example from website.. it's difficult if you are newComer.

luckily some people manage to run it.

be sure all libs are installed. nuget fails silently... no dialog when it fails.. read the output at the bottom window..


Get started with imGuiNET:( + ClickableTransparentOverlay)

  1. create New DotNet 8 console App

  2. install these 4 package here..

    • use this specific versions. new ones have weird bugs..
    • everything works good with this specific versions. related-github-issue
       * inputText works. can type into it.
       * viewport is not cropped to 800x600 .. good...
       * i added runOnce function. now i can resize Window.. (resize grip at bottomRight)
          * not sure if its related to this runOnce or not. 
    
    
    <PackageReference Include="ClickableTransparentOverlay" Version="9.1.0" />
    <PackageReference Include="ImGui.NET" Version="1.90.8.1" />
    <PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
    <PackageReference Include="Veldrid.ImGui" Version="5.72.0" />
    <PackageReference Include="Vortice.Mathematics" Version="1.9.3" />
  1. the minimal Example code.

program.cs // new style

using console_Imgui;


Console.WriteLine("Welcome To **ImGuiNET  ** ");
var v1 = new myView1();
v1.Start().Wait();

myview1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using ImGuiNET;
using ClickableTransparentOverlay;
using System.Numerics;

namespace console_Imgui
{
    internal class myView1 : Overlay
    {
        //--on 1080p  dpi:125% --
        //fontSize:22, barely matches the Win11 Fancy UI Font size.. 
        string FontPath = @"C:\Windows\Fonts\arial.ttf";
        bool runOnce=false;
        protected override void Render()
        {
            if(runOnce) {
                ReplaceFont(FontPath, 22, FontGlyphRangeType.English);
                runOnce=true;
            }   
       
            ImGui.Begin("window1", ImGuiWindowFlags.None);
            ImGui.Text("hello Imgui.");
            ImGui.End();
        }


    }
}

References:

Both of these guys install the same 4 libs

Upvotes: 1

bh_earth0
bh_earth0

Reputation: 2834

okay, i got the REAL solution. running the pure imguiNET example ------ no Overlay thingy..

How to Change Font in imguiNET:

  1. download the 1.90.1 source code.

    https://github.com/ImGuiNET/ImGui.NET/releases/tag/v1.91.0.1

  2. open csharp project with vs2022.

  3. in VS2022 -> Solution Explorer Window -> goto project: ImGui.NET.SampleProgram

  4. open imguiController.cs

  5. find the function below modify it like this... dont forget to add the function AddFont_viaGH460_build()

ImGuiController.cs


  ///-------------->>>>find this Method....
  /// <summary>
  /// Constructs a new ImGuiController.
  /// </summary>
  public ImGuiController(GraphicsDevice gd, OutputDescription outputDescription, int width, int height)
  {
      _gd = gd;
      _windowWidth = width;
      _windowHeight = height;

      ImGui.CreateContext();
      var io = ImGui.GetIO();
      io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
      io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard |
          ImGuiConfigFlags.DockingEnable;
      io.Fonts.Flags |= ImFontAtlasFlags.NoBakedLines;

      //------inject MY Font here-----
      string FontPath = @"C:\Windows\Fonts\arial.ttf";
      AddFont_viaGH460_build(FontPath, 22);


      CreateDeviceResources(gd, outputDescription);
      SetPerFrameImGuiData(1f / 60f);
      ImGui.NewFrame();
      _frameBegun = true;
  }

  ///-------------->>>>copy paste this method into to same file , right below.
  /// <summary>
  /// https://github.com/ImGuiNET/ImGui.NET/issues/460
  /// this function work on both. v1.89.4  and 1.91.0.1
  /// </summary>
  public static void AddFont_viaGH460_build(string fontFilePath, float fontSize)
  {
      var io = ImGui.GetIO();
      unsafe
      {
          // Add the default fonts for the App
          io.Fonts.AddFontFromFileTTF(fontFilePath, 22.0f);
      }

      io.ConfigFlags |= ImGuiConfigFlags.DockingEnable | ImGuiConfigFlags.ViewportsEnable | ImGuiConfigFlags.NavEnableKeyboard;
      io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset | ImGuiBackendFlags.PlatformHasViewports;
      io.Fonts.Build();
  }


Upvotes: 0

Related Questions