Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added macOS compatibility to tests #224

Merged
merged 15 commits into from
Jul 19, 2020
21 changes: 20 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ stages:
jobs:
include:
- stage: Tests
name: "Unit Tests"
name: "iOS Unit Tests"
language: objective-c
env:
- TEST_FRAMEWORK_SCHEME="TPPDF-Package"
Expand All @@ -43,6 +43,25 @@ jobs:
after_success:
- bundle exec slather coverage -t --build-directory ${TRAVIS_BUILD_DIR}/derived_data
- bash <(curl -s https://codecov.io/bash) -f cobertura.xml -X coveragepy -X gco
- stage: Tests
name: "macOS Unit Tests"
language: objective-c
env:
- TEST_FRAMEWORK_SCHEME="TPPDF-Package"
- PROJECT="TPPDF.xcodeproj"
script:
- set -o pipefail
- swift package resolve
- set -o pipefail
- xcodebuild -project ${PROJECT}
-scheme ${TEST_FRAMEWORK_SCHEME}
-clonedSourcePackagesDirPath .
-derivedDataPath ${TRAVIS_BUILD_DIR}/derived_data
-sdk macosx
-destination "platform=macOS"
-configuration Debug
ONLY_ACTIVE_ARCH=YES
test | xcpretty

- stage: Examples
name: "Example iOS - Cocoapods"
Expand Down
4 changes: 3 additions & 1 deletion Example macOS/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1150;
LastUpgradeCheck = 1150;
LastUpgradeCheck = 1160;
ORGANIZATIONNAME = "techprimate GmbH & Co. KG";
TargetAttributes = {
D48C538424A269F400D7A3DD = {
Expand Down Expand Up @@ -478,6 +478,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\"";
Expand All @@ -502,6 +503,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\"";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
LastUpgradeVersion = "1160"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
1 change: 1 addition & 0 deletions Example macOS/Example/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
window.setFrameAutosaveName("main")
}

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
Expand Down
4 changes: 2 additions & 2 deletions Example macOS/Example/UI/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import TPPDF
class ContentViewModel: ObservableObject {

@Published var url: URL?
@State var selectedFactory = Examples.factories.first?.examples.first
@State var selectedFactory = Examples.defaultFactory

}

Expand All @@ -37,7 +37,7 @@ struct ContentView: View {
alignment: .topLeading)
.listStyle(SidebarListStyle())

DetailView(example: viewModel.selectedFactory!)
DetailView(example: viewModel.selectedFactory)
.frame(minWidth: 0, maxWidth: .infinity,
minHeight: 0, maxHeight: .infinity,
alignment: .topLeading)
Expand Down
4 changes: 4 additions & 0 deletions Shared/Examples/Examples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,9 @@ enum Examples {
])
]
}

static var defaultFactory: Example {
return factories[1].examples[0]
}
}

36 changes: 35 additions & 1 deletion Shared/Examples/TableExampleFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class TableExampleFactory: ExampleFactory {
let document = PDFDocument(format: .a4)

// Create a table
let table = PDFTable(rows: 10, columns: 4)
var table = PDFTable(rows: 10, columns: 4)

// Tables can contain Strings, Numbers, Images or nil, in case you need an empty cell.
// If you add a unknown content type, an assertion will be thrown and the rendering will stop.
Expand Down Expand Up @@ -85,6 +85,40 @@ class TableExampleFactory: ExampleFactory {

document.add(table: table)

// Another table:

table = PDFTable(rows: 50, columns: 4)
table.widths = [0.1, 0.3, 0.3, 0.3]
table.margin = 10
table.padding = 10
table.showHeadersOnEveryPage = false
table.style.columnHeaderCount = 3

for row in 0..<table.size.rows {
table[row, 0].content = "\(row)".asTableContent
for column in 1..<table.size.columns {
table[row, column].content = "\(row),\(column)".asTableContent
}
}

for i in stride(from: 3, to: 48, by: 3) {
table[rows: i...(i + 2), column: 1].merge(with: PDFTableCell(content: Array(repeating: "\(i),1", count: 3).joined(separator: "\n").asTableContent,
alignment: .center))
}
for i in stride(from: 4, to: 47, by: 3) {
table[rows: i...(i + 2), column: 2].merge(with: PDFTableCell(content: Array(repeating: "\(i),2", count: 3).joined(separator: "\n").asTableContent,
alignment: .center))
}
for i in stride(from: 5, to: 48, by: 3) {
table[rows: i...(i + 2), column: 3].merge(with: PDFTableCell(content: Array(repeating: "\(i),3", count: 3).joined(separator: "\n").asTableContent,
alignment: .center))
}

table[rows: 0..<2, column: 2].merge()
table[rows: 1..<3, column: 3].merge()

document.add(table: table)

return [document]
}
}
2 changes: 1 addition & 1 deletion Source/API/Groups/PDFGroup+Objects.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public extension PDFGroup {
- parameter container: Container whose text color will be reset, defaults to `PDFGroupContainer.left`
*/
func resetFont(_ container: PDFGroupContainer = PDFGroupContainer.left) {
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: Font.systemFontSize)))]
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: PDFConstants.defaultFontSize)))]
}

/**
Expand Down
2 changes: 1 addition & 1 deletion Source/API/PDFDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public class PDFDocument: CustomStringConvertible {
- parameter container: Container whose text color will be reset, defaults to `PDFContainer.contentLeft`
*/
public func resetFont(_ container: PDFContainer = PDFContainer.contentLeft) {
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: Font.systemFontSize)))]
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: PDFConstants.defaultFontSize)))]
}

/**
Expand Down
4 changes: 2 additions & 2 deletions Source/API/PDFGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class PDFGenerator: PDFGeneratorProtocol, CustomStringConvertible {
These values are used for simple text objects
*/
internal lazy var fonts: [PDFContainer: Font] = .init(uniqueKeysWithValues: PDFContainer.allCases.map({ container in
(container, Font.systemFont(ofSize: Font.systemFontSize))
(container, Font.systemFont(ofSize: PDFConstants.defaultFontSize))
}))

/**
Expand Down Expand Up @@ -107,7 +107,7 @@ public class PDFGenerator: PDFGeneratorProtocol, CustomStringConvertible {
columnState.reset()
currentPage = 1
fonts = fonts.mapValues { _ in
Font.systemFont(ofSize: Font.systemFontSize)
Font.systemFont(ofSize: PDFConstants.defaultFontSize)
}
textColor = textColor.mapValues { _ in
Color.black
Expand Down
2 changes: 1 addition & 1 deletion Source/API/Section/PDFSectionColumn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public class PDFSectionColumn: PDFDocumentObject {
- parameter container: Container whose text color will be reset, defaults to `PDFSectionColumnContainer.left`
*/
public func resetFont(_ container: PDFSectionColumnContainer = PDFSectionColumnContainer.left) {
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: Font.systemFontSize)))]
objects += [(container, PDFFontObject(font: Font.systemFont(ofSize: PDFConstants.defaultFontSize)))]
}

/**
Expand Down
2 changes: 1 addition & 1 deletion Source/API/Table/Content/PDFTableContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import AppKit
/**
TODO: Documentation
*/
public class PDFTableContent {
public class PDFTableContent: CustomStringConvertible {

/**
TODO: Documentation
Expand Down
5 changes: 5 additions & 0 deletions Source/API/Table/PDFTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public class PDFTable: PDFDocumentObject {
*/
public var showHeadersOnEveryPage: Bool = false

/**
Cells should split when overlapping page
*/
public var shouldSplitCellsOnPageBeak = false

/**
Count of rows and columns in this table
*/
Expand Down
4 changes: 2 additions & 2 deletions Source/API/Table/Style/PDFTableCellStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct PDFTableCellStyle {
*/
public init(colors: (fill: Color, text: Color) = (Color.clear, Color.black),
borders: PDFTableCellBorders = PDFTableCellBorders(),
font: Font = Font.systemFont(ofSize: Font.systemFontSize)) {
font: Font = Font.systemFont(ofSize: PDFConstants.defaultFontSize)) {
self.colors = colors
self.borders = borders
self.font = font
Expand All @@ -47,5 +47,5 @@ extension PDFTableCellStyle {

public static let none = PDFTableCellStyle(colors: (fill: Color.clear, text: Color.black),
borders: .none,
font: Font.systemFont(ofSize: Font.systemFontSize))
font: Font.systemFont(ofSize: PDFConstants.defaultFontSize))
}
10 changes: 10 additions & 0 deletions Source/API/Utils/PDFConstants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CoreGraphics

/// Constants used throught the framework
public class PDFConstants {

/// Default font size for objects
///
/// In earlier versions the default `UIFont.systemFontSize` was used, but during implementation of macOS support, findings showed that it `NSFont.systemFontSize` differs. Therefore the new default fontSize is declared here
public static let defaultFontSize: CGFloat = 17
}
5 changes: 5 additions & 0 deletions Source/API/Utils/PDFError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public enum PDFError: Error {
*/
case tableCellWeakReferenceBroken

/// Indicates that the cell is too big to be rendered onto a single page
case tableCellTooBig(cell: PDFTableCell)

/**
TODO: Documentation
*/
Expand Down Expand Up @@ -87,6 +90,8 @@ public enum PDFError: Error {
return "Table index out of bounds: <index: \(index), length: \(length)>"
case .tableCellWeakReferenceBroken:
return "Weak reference in table cell is broken"
case .tableCellTooBig(let cell):
return "Table cell is too big to be rendered: \(cell)"
case .textObjectIsNil:
return "No text object has been set"
case .textObjectNotCalculated:
Expand Down
26 changes: 26 additions & 0 deletions Source/Internal/Graphics/PDFContextGraphics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ import CoreGraphics

internal enum PDFContextGraphics {

internal static func createBitmapContext(size: CGSize) -> CGContext? {
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bytesPerPixel = 4
let bytesPerRow = bytesPerPixel * Int(size.width)
let rawData = malloc(Int(size.height) * bytesPerRow)
let bitsPerComponent = 8
return CGContext(data: rawData,
width: Int(size.width),
height: Int(size.height),
bitsPerComponent: bitsPerComponent,
bytesPerRow: bytesPerRow,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
}

internal static func getImage(from context: CGContext, size: CGSize) -> Image? {
guard let cgImage = context.makeImage() else {
return nil
}
#if os(macOS)
return Image(cgImage: cgImage, size: size)
#elseif os(iOS)
return Image(cgImage: cgImage)
#endif
}

internal static func createPDFContext(url: URL, bounds: CGRect, info: PDFInfo) -> CGContext {
var mediaBox = bounds
guard let context = CGContext(url as CFURL, mediaBox: &mediaBox, info.generate() as CFDictionary) else {
Expand Down
5 changes: 3 additions & 2 deletions Source/Internal/Graphics/PDFGraphics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ internal enum PDFGraphics {
let factor: CGFloat = min(3 * quality, 1)
let resizeFactor = factor.isZero ? 0.2 : factor

let size = CGSize(width: frame.width * resizeFactor,
height: frame.height * resizeFactor)
// If there is a floating point error, e.g. 24.000000000000004, then UIKit will use the next higher integer value, but AppKit does not
let size = CGSize(width: floor(frame.width * resizeFactor),
height: floor(frame.height * resizeFactor))

#if os(iOS)
UIGraphicsBeginImageContext(size)
Expand Down
2 changes: 1 addition & 1 deletion Source/Internal/Table/PDFTableObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ internal class PDFTableObject: PDFRenderObject {
.reduce([], +)
.map(\.1)
cellElements += outline

let sliceObject = createSliceObject(frame: cellFrame,
elements: cellElements,
minOffset: minOffset,
Expand Down
Loading