Public/Invoke-VellumPdfCanvas.ps1
|
function Invoke-VellumPdfCanvas { <# .SYNOPSIS Draws on a page of a page-based document with a script block that receives the canvas. .DESCRIPTION Gives full access to the VellumPdf PdfCanvas of one page - paths, colours (RGB, grey, CMYK), transparency, gradients, clipping, dashes, text, images - for anything the Add-VellumPdfShape/Text/... cmdlets do not cover. The script block receives: $canvas the VellumPdf.Canvas.PdfCanvas of the page $page the VellumPdf.Document.PdfPage $document the VellumPdf.Document.PdfDocument All drawing on a page shares one canvas, so calls accumulate in order. The graphics state is saved before and restored after your script. Operators that take spans (dash patterns, raw colour components, glyph ids) cannot be called from PowerShell directly; use [PSVellumPDF.Interop.CanvasHelpers]. In a tagged page document the drawing is wrapped in an artifact (decorative graphics) unless you pass -NoMarkedContent and mark the content yourself. .PARAMETER Document A document from New-VellumPdfPageDocument. .PARAMETER Page The 1-based page number. Default 1. .PARAMETER ScriptBlock The drawing code: param($canvas, $page, $document). .PARAMETER NoMarkedContent Do not wrap the drawing as an artifact in a tagged document. .EXAMPLE $doc | Invoke-VellumPdfCanvas -Page 1 -ScriptBlock { param($canvas) $canvas.SetFillAlpha(0.4).SetFillColorRgb(0, 0, 1).Rectangle(100, 100, 200, 120).Fill() | Out-Null } .OUTPUTS VellumPdf.Document.PdfDocument (the same instance, for chaining) #> [CmdletBinding()] [OutputType([VellumPdf.Document.PdfDocument])] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Canvas is a singular noun (the PDF drawing surface); the rule mistakes the trailing s.')] param( [Parameter(Mandatory, ValueFromPipeline)] [VellumPdf.Document.PdfDocument]$Document, [ValidateRange(1, 1000000)] [int]$Page = 1, [Parameter(Mandatory, Position = 0)] [scriptblock]$ScriptBlock, # In a tagged document your drawing is wrapped as an artifact (decorative graphics). # Pass this to take over: bracket real content yourself with BeginMarkedContent / # RegisterStructElem, or the page will contain unmarked content. [switch]$NoMarkedContent ) process { try { Assert-VellumPdfDocumentOpen -Document $Document -CommandName 'Invoke-VellumPdfCanvas' $Page = Resolve-VellumPdfPageNumber -Document $Document -Page $(if ($PSBoundParameters.ContainsKey('Page')) { $PSBoundParameters['Page'] } else { 1 }) -Bound $PSBoundParameters.ContainsKey('Page') -CommandName 'Invoke-VellumPdfCanvas' $canvas = Get-VellumPdfPageCanvas -Document $Document -Page $Page -CommandName 'Invoke-VellumPdfCanvas' $pdfPage = $Document.Pages[$Page - 1] if (-not $Document.PSObject.Properties['PSVellumRawCanvas']) { $Document.PSObject.Properties.Add([psnoteproperty]::new('PSVellumRawCanvas', $true)) } [void]$canvas.SaveState() try { if ($NoMarkedContent) { & $ScriptBlock $canvas $pdfPage $Document | Out-Null } else { Invoke-VellumPdfTagged -Document $Document -Canvas $canvas -PdfPage $pdfPage -Kind Artifact -Draw { & $ScriptBlock $canvas $pdfPage $Document | Out-Null } } } finally { [void]$canvas.RestoreState() } $Document } catch { $PSCmdlet.ThrowTerminatingError((Resolve-VellumPdfErrorRecord -ErrorRecord $_ -CommandName 'Invoke-VellumPdfCanvas')) } } } |