Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ jobs:
- uses: swift-actions/setup-swift@v2
with:
swift-version: "6.2"
- name: Test
run: swift test --configuration release -v
- name: Build
run: swift build --configuration release -v
6 changes: 5 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ let package = Package(
)
],
targets: [
.target(name: "PDFViewKit")
.target(name: "PDFViewKit"),
.testTarget(
name: "PDFViewKitTests",
dependencies: ["PDFViewKit"]
)
]
)
11 changes: 6 additions & 5 deletions Sources/PDFViewKit/PDFRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ public enum PDFRenderer {
to destination: URL,
atPageSize pageSize: some PageSize
) throws {
let pdfSize = pageSize.size(atDPI: .print)
let pdfSize = pageSize.size(atDPI: .pdf)
let viewRenderingDPI: DPI = .display
let viewSize = pageSize.size(atDPI: viewRenderingDPI)

let scaleFactor = pdfSize.width / viewSize.width
let viewToPDFScaleFactor = pdfSize.width / viewSize.width
let rasterizationScaleFactor = DPI.print.rawValue / viewRenderingDPI.rawValue
var box = CGRect(
origin: .zero,
size: pdfSize
Expand All @@ -38,12 +39,12 @@ public enum PDFRenderer {
let renderer = ImageRenderer(content: renderedView)
renderer.proposedSize = ProposedViewSize(viewSize)

renderer.render(rasterizationScale: scaleFactor) { _, renderer in
renderer.render(rasterizationScale: rasterizationScaleFactor) { _, renderer in
context.beginPDFPage(nil)

context.scaleBy(
x: scaleFactor,
y: scaleFactor
x: viewToPDFScaleFactor,
y: viewToPDFScaleFactor
)

renderer(context)
Expand Down
2 changes: 2 additions & 0 deletions Sources/PDFViewKit/PageSizes/DPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum DPI: CGFloat {

// based on https://www.adobe.com/uk/creativecloud/photography/discover/dots-per-inch-dpi-resolution.html

case pdf = 72 // PDF user-space points (1/72 inch)

case display = 96
case displayHigh = 144 // 150%

Expand Down
54 changes: 54 additions & 0 deletions Tests/PDFViewKitTests/PDFRendererTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// PDFRendererTests.swift
// PDFViewKit
//
// Copyright (C) 2026 Sören Gade
// See LICENSE for full license.
//

import Foundation
import PDFKit
@testable import PDFViewKit
import SwiftUI
import Testing

@MainActor
struct PDFRendererTests {

@Test
func renderedA4PageUsesPDFPointDimensions() throws {
let destination = FileManager.default.temporaryDirectory
.appendingPathComponent("PDFViewKit-A4-\(UUID().uuidString).pdf")
defer { try? FileManager.default.removeItem(at: destination) }

let document = PDFViewKit.PDFDocument {
Text("Hello, A4")
}

try PDFRenderer.render(
document: document,
to: destination,
atPageSize: DIN.a4
)

let pdfDocument = try #require(PDFDocument(url: destination))
let page = try #require(pdfDocument.page(at: 0))

let mediaBoxSize = page.bounds(for: .mediaBox).size

#expect(abs(mediaBoxSize.width - a4SizeInPDFPoints.width) < pointTolerance)
#expect(abs(mediaBoxSize.height - a4SizeInPDFPoints.height) < pointTolerance)
}

private var a4SizeInPDFPoints: CGSize {
CGSize(
width: 210 / 25.4 * DPI.pdf.rawValue,
height: 297 / 25.4 * DPI.pdf.rawValue
)
}

private var pointTolerance: CGFloat {
0.001
}

}
Loading