From f4893a39e959f9b43ba1ef3fda45017cb76768cb Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Tue, 17 Feb 2026 20:51:35 +0100 Subject: [PATCH] Improve multi-line text, logo, and version display - Enhance ImageCreatorAlternate to support multi-line text rendering with correct sizing, spacing, and shadow for each line. - Only draw logos on non-thumbnail images to match GDI behavior. - Add a status bar to MainWindow showing the app version at runtime. - Upgrade MinVer to 7.0.0 and adjust versioning to avoid WPF/XAML assembly identity issues. - Refactor XAML layout to accommodate the new status bar. --- MaddoShared/ImageCreatorAlternate.cs | 33 +++++++++++++++++++++------- imagecatalog/ImageCatalog 2.csproj | 20 ++++++----------- imagecatalog/MainWindow.xaml | 18 +++++++++++++-- imagecatalog/MainWindow.xaml.cs | 22 +++++++++++++++++++ 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/MaddoShared/ImageCreatorAlternate.cs b/MaddoShared/ImageCreatorAlternate.cs index 8ddfbec..80f42d3 100644 --- a/MaddoShared/ImageCreatorAlternate.cs +++ b/MaddoShared/ImageCreatorAlternate.cs @@ -171,15 +171,22 @@ public class ImageCreatorAlternate : IImageCreator var maxTextWidth = working.Width * 0.95f; var maxTextHeight = working.Height * 0.15f; - var chosenSize = FindBestFontSize(text, font.Name, Math.Max(6, baseSize), maxTextWidth, maxTextHeight); + // Support multi-line text: measure using the longest line when choosing font size + var normalizedText = text.Replace("\r", string.Empty); + var lines = normalizedText.Split(new[] { '\n' }, StringSplitOptions.None); + var longestLine = lines.OrderByDescending(l => l.Length).FirstOrDefault() ?? string.Empty; + + var chosenSize = FindBestFontSize(longestLine, font.Name, Math.Max(6, baseSize), maxTextWidth, maxTextHeight); // Use final font var finalFont = SixLabors.Fonts.SystemFonts.CreateFont(font.Name, chosenSize); if (!isThumbnail) imgState.DimensioneStandard = (int)Math.Round(chosenSize); // Approximate measured size since TextMeasurer/RendererOptions may not be available in this Fonts version - var approxWidth = finalFont.Size * text.Length * 0.6f; - var approxHeight = finalFont.Size * 1.0f; + var approxWidth = finalFont.Size * longestLine.Length * 0.6f; + // Account for multiple lines: height = font size * lineCount * lineSpacing + var lineSpacing = 1.1f; // small extra spacing between lines + var approxHeight = finalFont.Size * lines.Length * lineSpacing; // Compute horizontal position based on alignment float xCenterOfImg; @@ -228,16 +235,26 @@ public class ImageCreatorAlternate : IImageCreator originX = Math.Max(0, Math.Min(originX, working.Width - approxWidth)); originY = Math.Max(0, Math.Min(originY, working.Height - approxHeight)); - // Draw shadow then text + // Draw shadow then text; handle multiple lines + var lineHeight = finalFont.Size * lineSpacing; working.Mutate(ctx => { - ctx.DrawText(text, finalFont, shadowColor, new SixLabors.ImageSharp.PointF(originX + 1, originY + 1)); - ctx.DrawText(text, finalFont, textColor, new SixLabors.ImageSharp.PointF(originX, originY)); + for (int i = 0; i < lines.Length; i++) + { + var line = lines[i]; + var y = originY + i * lineHeight; + // Ensure we're drawing inside the canvas vertically + if (y + finalFont.Size < 0 || y > working.Height) continue; + + ctx.DrawText(line, finalFont, shadowColor, new SixLabors.ImageSharp.PointF(originX + 1, y + 1)); + ctx.DrawText(line, finalFont, textColor, new SixLabors.ImageSharp.PointF(originX, y)); + } }); } - // Draw logo if provided - if (logo != null && _picSettings.LogoAggiungi) + // Draw logo if provided. For compatibility with the original GDI implementation, + // do not draw the logo on thumbnails (ImageCreatorSharp only draws logos on big images). + if (logo != null && _picSettings.LogoAggiungi && !isThumbnail) { try { diff --git a/imagecatalog/ImageCatalog 2.csproj b/imagecatalog/ImageCatalog 2.csproj index 3744a5c..b6b77b9 100644 --- a/imagecatalog/ImageCatalog 2.csproj +++ b/imagecatalog/ImageCatalog 2.csproj @@ -7,10 +7,6 @@ true true False - 3.1.2.0 - 3.1.2.0 - 3.1.2 - 3.1.2 ImageCatalog default @@ -20,6 +16,9 @@ win-x64 + true @@ -46,20 +45,15 @@ - + all - - - - $(Version) - $(Version) - $(Version) - + True diff --git a/imagecatalog/MainWindow.xaml b/imagecatalog/MainWindow.xaml index 17bda4f..7e23dae 100644 --- a/imagecatalog/MainWindow.xaml +++ b/imagecatalog/MainWindow.xaml @@ -31,8 +31,14 @@ - - + + + + + + + + @@ -318,5 +324,13 @@ + + + + + + + + \ No newline at end of file diff --git a/imagecatalog/MainWindow.xaml.cs b/imagecatalog/MainWindow.xaml.cs index b7cb1be..5d07dd9 100644 --- a/imagecatalog/MainWindow.xaml.cs +++ b/imagecatalog/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.IO; using System.Windows.Media.Imaging; +using System.Diagnostics; using Microsoft.Win32; using System.Windows.Forms; @@ -16,6 +17,27 @@ namespace ImageCatalog_2 InitializeComponent(); _model = model; DataContext = _model; + // Set product version in status bar (use ProductVersion rather than AssemblyVersion) + try + { + var entry = System.Reflection.Assembly.GetEntryAssembly(); + string version = string.Empty; + if (entry is not null && !string.IsNullOrEmpty(entry.Location)) + { + try + { + version = FileVersionInfo.GetVersionInfo(entry.Location).ProductVersion ?? string.Empty; + } + catch { } + } + if (string.IsNullOrWhiteSpace(version)) + { + // fallback to assembly version + version = entry?.GetName().Version?.ToString() ?? string.Empty; + } + VersionTextBlock.Text = string.IsNullOrWhiteSpace(version) ? string.Empty : $"v{version}"; + } + catch { } // Apply theme based on user preference or system setting (default to light) ApplyTheme(isDark: false); // Subscribe to DataModel events that require UI dialogs