一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
124 行
3.9 KiB
TypeScript
124 行
3.9 KiB
TypeScript
// cspell:ignore isnot Pbgra
|
|
|
|
const xpsToPngPowerShellScript = String.raw`
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Load the WPF assemblies that expose XpsDocument and bitmap rendering APIs.
|
|
$assemblies = @(
|
|
'PresentationCore',
|
|
'PresentationFramework',
|
|
'ReachFramework',
|
|
'System.Xaml',
|
|
'WindowsBase'
|
|
)
|
|
|
|
foreach ($assembly in $assemblies) {
|
|
Add-Type -AssemblyName $assembly
|
|
}
|
|
|
|
# Compile the C# renderer once for this PowerShell process.
|
|
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition @"
|
|
using System;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Xps.Packaging;
|
|
|
|
namespace Joplin {
|
|
public static class XpsConverter {
|
|
private const double MaxRenderedPixels = 16000000;
|
|
|
|
public static void RenderPages(string inputPath, int[] pageNumbers, string[] outputPaths, double scale) {
|
|
if (String.IsNullOrEmpty(inputPath)) {
|
|
throw new ArgumentException("Missing input path.", "inputPath");
|
|
}
|
|
|
|
if (pageNumbers == null) {
|
|
throw new ArgumentNullException("pageNumbers");
|
|
}
|
|
|
|
if (outputPaths == null) {
|
|
throw new ArgumentNullException("outputPaths");
|
|
}
|
|
|
|
if (pageNumbers.Length != outputPaths.Length) {
|
|
throw new ArgumentException("Page numbers and output paths must have the same length.");
|
|
}
|
|
|
|
using (XpsDocument document = new XpsDocument(inputPath, FileAccess.Read)) {
|
|
FixedDocumentSequence sequence = document.GetFixedDocumentSequence();
|
|
DocumentPaginator paginator = sequence.DocumentPaginator;
|
|
|
|
for (int i = 0; i < pageNumbers.Length; i++) {
|
|
RenderPage(paginator, pageNumbers[i], outputPaths[i], scale);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RenderPage(DocumentPaginator paginator, int pageNumber, string outputPath, double scale) {
|
|
if (String.IsNullOrEmpty(outputPath)) {
|
|
throw new ArgumentException("Missing output path.", "outputPath");
|
|
}
|
|
|
|
if (pageNumber < 1) {
|
|
throw new ArgumentOutOfRangeException("pageNumber");
|
|
}
|
|
|
|
int pageIndex = pageNumber - 1;
|
|
DocumentPage page = paginator.GetPage(pageIndex);
|
|
try {
|
|
Size pageSize = page.Size;
|
|
double renderScale = scale;
|
|
double unscaledPixels = pageSize.Width * pageSize.Height;
|
|
if (unscaledPixels * renderScale * renderScale > MaxRenderedPixels) {
|
|
renderScale = Math.Sqrt(MaxRenderedPixels / unscaledPixels);
|
|
}
|
|
int pixelWidth = Math.Max(1, (int)Math.Ceiling(pageSize.Width * renderScale));
|
|
int pixelHeight = Math.Max(1, (int)Math.Ceiling(pageSize.Height * renderScale));
|
|
|
|
DrawingVisual visual = new DrawingVisual();
|
|
using (DrawingContext context = visual.RenderOpen()) {
|
|
context.DrawRectangle(Brushes.White, null, new Rect(new Point(0, 0), pageSize));
|
|
context.PushTransform(new ScaleTransform(renderScale, renderScale));
|
|
context.DrawRectangle(new VisualBrush(page.Visual), null, new Rect(new Point(0, 0), pageSize));
|
|
context.Pop();
|
|
}
|
|
|
|
RenderTargetBitmap bitmap = new RenderTargetBitmap(pixelWidth, pixelHeight, 96, 96, PixelFormats.Pbgra32);
|
|
bitmap.Render(visual);
|
|
|
|
PngBitmapEncoder encoder = new PngBitmapEncoder();
|
|
encoder.Frames.Add(BitmapFrame.Create(bitmap));
|
|
|
|
using (FileStream stream = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) {
|
|
encoder.Save(stream);
|
|
}
|
|
} finally {
|
|
page.Dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"@
|
|
|
|
# The TypeScript side passes page/output pairs as JSON in a file. This avoids
|
|
# environment variable size limits for large printouts with many pages.
|
|
$pages = Get-Content -LiteralPath $env:JOPLIN_XPS_PAGES_FILE -Raw | ConvertFrom-Json
|
|
if ($pages -isnot [array]) {
|
|
$pages = @($pages)
|
|
}
|
|
|
|
$pageNumbers = New-Object 'int[]' $pages.Count
|
|
$outputPaths = New-Object 'string[]' $pages.Count
|
|
for ($i = 0; $i -lt $pages.Count; $i++) {
|
|
$pageNumbers[$i] = [int]$pages[$i].PageNumber
|
|
$outputPaths[$i] = [string]$pages[$i].OutputPath
|
|
}
|
|
|
|
[Joplin.XpsConverter]::RenderPages($env:JOPLIN_XPS_INPUT, $pageNumbers, $outputPaths, 2.0)
|
|
`;
|
|
|
|
export default xpsToPngPowerShellScript;
|