Private/Measure-VellumPdfTextWidth.ps1
|
function Measure-VellumPdfTextWidth { <# .SYNOPSIS Width in points of a string in a resolved page font, including text-state spacing. .DESCRIPTION $Resolved comes from Get-VellumPdfPageFont (an object with Handle for an embedded font or Resource for a base-14 font). The engine measures plain text; this adds character spacing (per character), word spacing (per space) and horizontal scaling, exactly as a PDF viewer applies them: width = (glyph widths + Tc * characters + Tw * spaces) * Th / 100. That is the PDF advance width: a viewer adds Tc after every character, the last one included, so the text cursor ends Tc * Th / 100 past the last glyph. -VisibleExtent leaves that trailing Tc out and returns the width of what is actually inked, which is what right and centre alignment need. #> [CmdletBinding()] [OutputType([double])] param( [Parameter(Mandatory)] $Resolved, [AllowEmptyString()] [Parameter(Mandatory)] [string]$Text, [Parameter(Mandatory)] [double]$FontSize, [double]$CharSpacing = 0, [double]$WordSpacing = 0, [double]$HorizontalScale = 100, [switch]$VisibleExtent ) if ($Text.Length -eq 0) { return 0.0 } $base = if ($Resolved.Handle) { $Resolved.Handle.MeasureString($Text, $FontSize) } else { $Resolved.Resource.MeasureString($Text, $FontSize) } $characters = 0 foreach ($rune in $Text.EnumerateRunes()) { $characters++ } $spaces = 0 foreach ($ch in $Text.ToCharArray()) { if ($ch -eq ' ') { $spaces++ } } $trailing = if ($VisibleExtent) { $CharSpacing } else { 0.0 } ($base + $CharSpacing * $characters - $trailing + $WordSpacing * $spaces) * $HorizontalScale / 100 } |