Private/New-VellumTextStyle.ps1
|
function New-VellumTextStyle { <# .SYNOPSIS Builds a VellumPdf.Layout.Core.TextStyle from simple scalar parameters. .DESCRIPTION Internal helper shared by the public Add-* functions so that font, size, color, and alignment handling stays in one place. Returns $null when no styling was requested, letting callers fall back to the document's default font. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Returns a new in-memory TextStyle object; performs no external/system state change.')] [CmdletBinding()] [OutputType([VellumPdf.Layout.Core.TextStyle])] param( [string]$Font, [double]$FontSize, [VellumPdf.Fonts.EmbeddedFontHandle]$FontHandle, [ValidateCount(3, 3)] [ValidateRange(0.0, 1.0)] [double[]]$Color, [string]$LinkUri, # Line leading (extra vertical space between lines), in points. [ValidateRange(0, 1000)] [double]$Leading, # The flow document the style is for. In a conformant document (PDF/A, PDF/UA-1) a base-14 # -Font is replaced by the embedded Liberation substitute (see Get-VellumPdfEmbeddedStandard14). [VellumPdf.Layout.Document]$Document, # Names the cmdlet in the error raised when a base-14 font has no embeddable substitute. [string]$CommandName = 'New-VellumTextStyle' ) if ($Font -and -not $FontHandle -and $Document -and (Get-VellumPdfConformanceRequirement -Document $Document).NeedsEmbeddedFonts) { $FontHandle = Get-VellumPdfEmbeddedStandard14 -Document $Document -Font $Font -CommandName $CommandName } $wantsColor = $PSBoundParameters.ContainsKey('Color') $wantsLeading = $PSBoundParameters.ContainsKey('Leading') # Link hygiene: whitespace-only URIs become no-link (a literal '/URI ( )' # annotation otherwise lands in the PDF), and the URI scheme is allowlisted # to http/https/mailto. An allowlist (not a blocklist) is used so a NEW # dangerous scheme - a future protocol handler, vbscript:, file:, data:, or a # scheme-relative '//host' that a reader resolves as https - cannot reach the # PDF just because it is not on a list of known-bad names. A generated /URI # action should only ever be an outbound web or mail link. # # The scheme is read from a copy with ALL whitespace and control characters # removed, not just leading ones, because lenient readers strip that noise # before dispatching the scheme. Reading the scheme from the raw value would # let 'java<TAB>script:', a mid-keyword no-break space, or a leading 0x01 # byte present a different scheme to the reader than the one we validated. $LinkUri = if ($PSBoundParameters.ContainsKey('LinkUri')) { $LinkUri.Trim() } else { '' } $wantsLink = $LinkUri -ne '' if ($wantsLink) { $LinkUri = Test-VellumPdfLinkUri -Uri $LinkUri } if (-not $Font -and -not $PSBoundParameters.ContainsKey('FontSize') -and -not $FontHandle ` -and -not $wantsColor -and -not $wantsLink -and -not $wantsLeading) { return $null } $style = [VellumPdf.Layout.Core.TextStyle]::new() if ($FontHandle) { # Embedded TrueType font wins; do NOT also set Standard14 Font. $style.FontRef = [VellumPdf.Layout.Core.FontReference]::new($FontHandle) } elseif ($Font) { # Standard14 exposes one static field per base-14 font (Helvetica, etc.). $style.Font = [VellumPdf.Fonts.Standard14]::$Font } if ($PSBoundParameters.ContainsKey('FontSize')) { $style.FontSize = $FontSize } if ($wantsColor) { $style.Color = [VellumPdf.Layout.Core.ColorRgb]::new($Color[0], $Color[1], $Color[2]) } if ($wantsLink) { $style.LinkUri = $LinkUri } if ($wantsLeading) { $style.Leading = $Leading } return $style } |