Update text truncation logic to use rendered width

Replaced character-based truncation with pixel-accurate truncation based on rendered width in inches. Updated `TruncateText` in `PDFBurner.vb` to use `Graphics.MeasureString` for width calculation and introduced a binary search for efficient truncation. Renamed `egName` to `fieldEgName` for clarity.

Replaced `TextMaxLengths` with `TextMaxWidths` in `PDFBurnerParams.vb`, specifying maximum render widths in inches. Updated default values for `position`, `city`, and `date`. Revised XML documentation to reflect the new truncation logic.
This commit is contained in:
2026-08-25 09:47:22 +02:00
parent feaea1626b
commit 35c1374b9c
2 changed files with 39 additions and 14 deletions

View File

@@ -311,20 +311,44 @@ Namespace Jobs.FinalizeDocument
#Region "Helpers"
''' <summary>
''' Truncates a field value to the configured max length for that egName.
''' Truncates a field value so its rendered width fits within the configured max width (inches).
''' Uses Graphics.MeasureString with the configured font for pixel-accurate measurement.
''' Appends TruncationSuffix when the value is cut.
''' </summary>
Private Function TruncateText(value As String, egName As String) As String
Private Function TruncateText(value As String, fieldEgName As String) As String
If String.IsNullOrEmpty(value) Then Return value
If _pdfBurnerParams.TextMaxLengths Is Nothing Then Return value
If _pdfBurnerParams.TextMaxWidths Is Nothing Then Return value
Dim maxLen As Integer = 0
If Not _pdfBurnerParams.TextMaxLengths.TryGetValue(egName, maxLen) Then Return value
If maxLen <= 0 OrElse value.Length <= maxLen Then Return value
Dim maxWidthInches As Single = 0
If Not _pdfBurnerParams.TextMaxWidths.TryGetValue(fieldEgName, maxWidthInches) Then Return value
If maxWidthInches <= 0 Then Return value
Dim suffix As String = If(_pdfBurnerParams.TruncationSuffix, "")
Dim cutAt As Integer = Math.Max(0, maxLen - suffix.Length)
Return value.Substring(0, cutAt) & suffix
Using bmp As New Bitmap(1, 1)
Using g As Graphics = Graphics.FromImage(bmp)
Dim font As New Font(_pdfBurnerParams.FontName, _pdfBurnerParams.FontSize, _pdfBurnerParams.FontStyle, GraphicsUnit.Point)
Dim maxWidthPx As Single = maxWidthInches * g.DpiX
' Already fits — no truncation needed
If g.MeasureString(value, font).Width <= maxWidthPx Then Return value
' Binary search for the longest prefix that fits (with suffix)
Dim lo As Integer = 0
Dim hi As Integer = value.Length
While lo < hi
Dim mid As Integer = (lo + hi + 1) \ 2
Dim candidate As String = value.Substring(0, mid) & suffix
If g.MeasureString(candidate, font).Width <= maxWidthPx Then
lo = mid
Else
hi = mid - 1
End If
End While
Return value.Substring(0, lo) & suffix
End Using
End Using
End Function