Skip to content

Commit e6a3c24

Browse files
committed
Define abstract PageSize
This allows for easy extensibility of custom page sizes as well as for defining more standard sizes.
1 parent b82d2a8 commit e6a3c24

File tree

10 files changed

+95
-39
lines changed

10 files changed

+95
-39
lines changed

Example/Sources/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ do {
1919
try PDFRenderer.render(
2020
document: document,
2121
to: destination,
22-
atPageSize: .a4
22+
atPageSize: DIN.a4
2323
)
2424

2525
print("PDF written to \(destination.absoluteString).")

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ do {
3131
try PDFRenderer.render(
3232
document: document,
3333
at: destination,
34-
atPageSize: .a4
34+
atPageSize: DIN.a4
3535
)
3636
} catch {
3737
...

Sources/PDFViewKit/EnvironmentKeys/PDFPageSizeKey.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import SwiftUI
1010

1111
struct PDFPageSizeKey: EnvironmentKey {
1212

13-
static var defaultValue: DIN = .a4
13+
static var defaultValue: PageSize = DIN.a4
1414

1515
}
1616

1717
// MARK: - EnvironmentValues shorthand extension
1818

1919
public extension EnvironmentValues {
2020

21-
var pdfPageSize: DIN {
21+
var pdfPageSize: PageSize {
2222
get { self[PDFPageSizeKey.self] }
2323
set { self[PDFPageSizeKey.self] = newValue }
2424
}
@@ -39,7 +39,7 @@ public extension View {
3939
/// - size: The page size for the view and its descendants.
4040
/// - force: Whether to apply the size to the view's frame.
4141
func pdfPageSize(
42-
_ size: DIN,
42+
_ size: PageSize,
4343
force: Bool = false
4444
) -> some View {
4545
environment(\.pdfPageSize, size)

Sources/PDFViewKit/Modifiers/ApplyPDFSizeFrameModifier.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import SwiftUI
1010

1111
private struct ApplyPDFSizeFrameModifier: ViewModifier {
1212

13-
public let size: DIN
13+
public let size: PageSize
1414

1515
@Environment(\.pdfRenderingDPI)
1616
private var pdfRenderingDPI
@@ -32,7 +32,7 @@ extension View {
3232
/// Applies the given PDF size to the view's frame, taking the current DPI setting into account.
3333
///
3434
/// - Seealso: ``PDFRenderingDPIEnvironmentKey``
35-
func applyPDFSizeFrame(size: DIN) -> some View {
35+
func applyPDFSizeFrame(size: PageSize) -> some View {
3636
modifier(ApplyPDFSizeFrameModifier(size: size))
3737
}
3838

Sources/PDFViewKit/PDFDocument.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ public struct PDFDocument {
2323

2424
}
2525

26+
// MARK: Default page size for result builders
27+
28+
private extension PDFDocument {
29+
30+
/// The default size used for pages implicitly created from views.
31+
static let defaultPageSize: PageSize = DIN.a4
32+
33+
}
34+
2635
// MARK: - PDFPagesBuilder
2736

2837
@resultBuilder
@@ -42,15 +51,21 @@ public enum PDFPagesBuilder {
4251
}
4352

4453
public static func buildPartialBlock(first: some View) -> [PDFPage<AnyView>] {
45-
[PDFPage(erasing: first)]
54+
[PDFPage(
55+
size: PDFDocument.defaultPageSize,
56+
erasing: first
57+
)]
4658
}
4759

4860
public static func buildPartialBlock(
4961
accumulated: [PDFPage<AnyView>],
5062
next: some View
5163
) -> [PDFPage<AnyView>] {
5264
var pages = accumulated
53-
pages.append(PDFPage(erasing: next))
65+
pages.append(PDFPage(
66+
size: PDFDocument.defaultPageSize,
67+
erasing: next
68+
))
5469
return pages
5570
}
5671

@@ -73,15 +88,18 @@ public enum PDFDocumentBuilder {
7388

7489
public static func buildPartialBlock(first: some View) -> PDFDocument {
7590
PDFDocument {
76-
PDFPage {
91+
PDFPage(size: PDFDocument.defaultPageSize) {
7792
first
7893
}
7994
}
8095
}
8196

8297
public static func buildPartialBlock(accumulated: PDFDocument, next: some View) -> PDFDocument {
8398
var pages = accumulated.pages
84-
pages.append(PDFPage(erasing: next))
99+
pages.append(PDFPage(
100+
size: PDFDocument.defaultPageSize,
101+
erasing: next
102+
))
85103
return PDFDocument(pages: pages)
86104
}
87105

Sources/PDFViewKit/PDFPage.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import SwiftUI
1414
/// The alignment of the page's content is top leading.
1515
public struct PDFPage<Content: View>: View {
1616

17-
public let size: DIN
17+
public let size: PageSize
1818

1919
public let content: Content
2020

2121
public init(
22-
size: DIN = .a4,
22+
size: PageSize,
2323
@ViewBuilder _ content: () -> Content
2424
) {
2525
self.size = size
@@ -53,16 +53,21 @@ public extension PDFPage where Content == AnyView {
5353
}
5454
}
5555

56-
init(erasing view: some View) {
57-
self.init(erasing: PDFPage({ AnyView(erasing: view) }))
56+
init(
57+
size: PageSize,
58+
erasing view: some View
59+
) {
60+
self.init(erasing: PDFPage(size: size) {
61+
AnyView(erasing: view)
62+
})
5863
}
5964

6065
}
6166

6267
// MARK: - Previews
6368

6469
#Preview {
65-
PDFPage {
70+
PDFPage(size: DIN.a4) {
6671
Text("Hello, World")
6772
}
6873
}

Sources/PDFViewKit/PDFRenderer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public enum PDFRenderer {
1313
public static func render(
1414
document: PDFDocument,
1515
to destination: URL,
16-
atPageSize pageSize: DIN
16+
atPageSize pageSize: some PageSize
1717
) throws {
1818
let pdfSize = pageSize.size(atDPI: .print)
1919
let viewRenderingDPI: DPI = .display
Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import Foundation
1010

11-
// Source: https://de.wikipedia.org/wiki/Papierformat#Internationale_Papierformate_(ISO/DIN)
11+
/// Defines standard page sizes in the german DIN system.
1212
public enum DIN {
1313

14+
// Source: https://de.wikipedia.org/wiki/Papierformat#Internationale_Papierformate_(ISO/DIN)
15+
1416
case a0
1517
case a1
1618
case a2
@@ -25,11 +27,11 @@ public enum DIN {
2527

2628
}
2729

28-
// MARK: Physical page sizes
30+
// MARK: PageSize
2931

30-
public extension DIN {
32+
extension DIN: PageSize {
3133

32-
var width: Measurement<UnitLength> {
34+
public var width: Measurement<UnitLength> {
3335
switch self {
3436
case .a0:
3537
Measurement(
@@ -99,7 +101,7 @@ public extension DIN {
99101
}
100102
}
101103

102-
var height: Measurement<UnitLength> {
104+
public var height: Measurement<UnitLength> {
103105
switch self {
104106
case .a0:
105107
Measurement(
@@ -169,20 +171,3 @@ public extension DIN {
169171
}
170172

171173
}
172-
173-
// MARK: Calculated properties based on physical sizes
174-
175-
public extension DIN {
176-
177-
var aspectRatio: CGFloat {
178-
width.converted(to: .millimeters).value / height.converted(to: .millimeters).value
179-
}
180-
181-
func size(atDPI dpi: DPI) -> CGSize {
182-
CGSize(
183-
width: width.converted(to: .inches).value * dpi.rawValue,
184-
height: height.converted(to: .inches).value * dpi.rawValue
185-
)
186-
}
187-
188-
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import Foundation
1010

11+
/// Defines specific dots per inch resolutions.
1112
public enum DPI: CGFloat {
1213

1314
// based on https://www.adobe.com/uk/creativecloud/photography/discover/dots-per-inch-dpi-resolution.html
15+
1416
case display = 96
1517
case displayHigh = 144 // 150%
1618

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// PageSize.swift
3+
// PDFViewKit
4+
//
5+
// Copyright (C) 2024 Sören Gade
6+
// See LICENSE for full license.
7+
//
8+
9+
import Foundation
10+
11+
/// A type that defines page sizes.
12+
public protocol PageSize {
13+
14+
/// The page's physical width.
15+
var width: Measurement<UnitLength> { get }
16+
17+
/// The page's physical height.
18+
var height: Measurement<UnitLength> { get }
19+
20+
/// The page's size aspect ratio.
21+
var aspectRatio: CGFloat { get }
22+
23+
/// Calculates the page's dot size at the given ``DPI`` rendering scale.
24+
///
25+
/// - Parameters:
26+
/// - dpi: The page resolution of dots per inch.
27+
func size(atDPI dpi: DPI) -> CGSize
28+
29+
}
30+
31+
// MARK: Default implementation
32+
33+
public extension PageSize {
34+
35+
var aspectRatio: CGFloat {
36+
width.converted(to: .millimeters).value / height.converted(to: .millimeters).value
37+
}
38+
39+
func size(atDPI dpi: DPI) -> CGSize {
40+
CGSize(
41+
width: width.converted(to: .inches).value * dpi.rawValue,
42+
height: height.converted(to: .inches).value * dpi.rawValue
43+
)
44+
}
45+
46+
}

0 commit comments

Comments
 (0)