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.
This commit is contained in:
parent
8db7ee8075
commit
f4893a39e9
4 changed files with 70 additions and 23 deletions
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@
|
|||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||
<AssemblyVersion>3.1.2.0</AssemblyVersion>
|
||||
<FileVersion>3.1.2.0</FileVersion>
|
||||
<InformationalVersion>3.1.2</InformationalVersion>
|
||||
<Version>3.1.2</Version>
|
||||
<!-- Default assembly name for regular builds -->
|
||||
<AssemblyName>ImageCatalog</AssemblyName>
|
||||
<LangVersion>default</LangVersion>
|
||||
|
|
@ -20,6 +16,9 @@
|
|||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Keep MinVer package enabled but do NOT let it overwrite AssemblyVersion/FileVersion used at build-time.
|
||||
This prevents MinVer from injecting a computed version into generated BAML/pack URIs which can cause
|
||||
WPF to try loading a mismatched assembly identity at runtime. Do a full clean rebuild after this change. -->
|
||||
<UpdateVersionProperties>true</UpdateVersionProperties>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -46,20 +45,15 @@
|
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.3" />
|
||||
<PackageReference Include="MinVer" Version="3.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="MinVer" Version="7.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.421302">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- If MinVer ran and produced values, prefer them for assembly/file/informational version
|
||||
so the built assembly exposes the computed version for runtime and the publish rename uses the same value. -->
|
||||
<PropertyGroup>
|
||||
<!-- Prefer explicit MSBuild 'Version' set by MinVer when available -->
|
||||
<AssemblyVersion Condition="'$(Version)' != ''">$(Version)</AssemblyVersion>
|
||||
<FileVersion Condition="'$(Version)' != ''">$(Version)</FileVersion>
|
||||
<InformationalVersion Condition="'$(Version)' != ''">$(Version)</InformationalVersion>
|
||||
</PropertyGroup>
|
||||
<!-- MinVer provides a computed 'Version' property. Do not automatically override AssemblyVersion/FileVersion
|
||||
with MinVer's computed Version to avoid mismatches embedded into generated XAML/BAML. The explicit
|
||||
AssemblyVersion/FileVersion at the top of this file will be used for runtime identity. -->
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
|
|
|
|||
|
|
@ -31,8 +31,14 @@
|
|||
</ResourceDictionary>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
<!-- Make the live view/right side narrower -->
|
||||
<ColumnDefinition Width="0.8*" />
|
||||
|
|
@ -318,5 +324,13 @@
|
|||
<TextBlock Text="{Binding SpeedCounter}" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Status bar at the bottom showing version -->
|
||||
<StatusBar Grid.Row="1">
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Name="VersionTextBlock" Text="" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue