Skip to content

Commit

Permalink
#254: Release 2.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip Niedertscheider authored Dec 5, 2020
2 parents 0ebf966 + 46ff9ec commit 8f55b0a
Show file tree
Hide file tree
Showing 16 changed files with 454 additions and 112 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
- bundle exec pod install --project-directory="${ROOT_FOLDER}"
- cd "${ROOT_FOLDER}"
script:
- set -o pipefail
- set -o pipefail
- xcodebuild -workspace "$WORKSPACE"
-scheme "$EXAMPLE_SCHEME"
-sdk iphonesimulator
Expand Down Expand Up @@ -122,7 +122,7 @@ jobs:
-clonedSourcePackagesDirPath .
-derivedDataPath ${TRAVIS_BUILD_DIR}/derived_data
-configuration Debug | xcpretty
- set -o pipefail
- set -o pipefail
- xcodebuild -project ${PROJECT}
-scheme ${EXAMPLE_SCHEME}
-clonedSourcePackagesDirPath .
Expand All @@ -146,7 +146,7 @@ jobs:
-clonedSourcePackagesDirPath .
-derivedDataPath ${TRAVIS_BUILD_DIR}/derived_data
-configuration Debug | xcpretty
- set -o pipefail
- set -o pipefail
- xcodebuild -project ${PROJECT}
-scheme ${EXAMPLE_SCHEME}
-clonedSourcePackagesDirPath .
Expand Down
28 changes: 27 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Change Log

## [Unreleased](https://github.com/techprimate/TPPDF/tree/HEAD) (2020-??-??)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/2.3.1...HEAD)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/2.3.2...HEAD)

**Implemented enhancements:**

Expand All @@ -11,6 +11,32 @@

**Merged pull requests:**

## [2.3.2](https://github.com/techprimate/TPPDF/tree/2.3.2) (2020-12-05)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/2.3.1...2.3.2)

**Implemented enhancements:**

- Added optional table cell splicing disabling (#205)

**Fixed bugs:**

- Fixed carthage version missing (#236)

**Closed issues:**

- Issue #205
- Issue #222
- Issue #236
- Issue #243
- Issue #249
- Issue #233

**Merged pull requests:**

- PR #223
- PR #252 [by lpeancovschi]
- PR #255

## [2.3.1](https://github.com/techprimate/TPPDF/tree/2.3.1) (2020-09-23)
[Full Changelog](https://github.com/techprimate/TPPDF/compare/2.3.0...2.3.1)

Expand Down
25 changes: 25 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"object": {
"pins": [
{
"package": "Nimble",
"repositoryURL": "https://github.com/Quick/Nimble",
"state": {
"branch": null,
"revision": "7a46a5fc86cb917f69e3daf79fcb045283d8f008",
"version": "8.1.2"
}
},
{
"package": "Quick",
"repositoryURL": "https://github.com/Quick/Quick",
"state": {
"branch": null,
"revision": "09b3becb37cb2163919a3842a4c5fa6ec7130792",
"version": "2.2.1"
}
}
]
},
"version": 1
}
44 changes: 7 additions & 37 deletions Shared/Examples/ExperimentFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,15 @@ class ExperimentFactory: ExampleFactory {
func generateDocument() -> [PDFDocument] {
let document = PDFDocument(format: .a4)

document.add(space: 100)
let 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()

let table = PDFTable(rows: 3, columns: 4)
table.content = [
["0,0", "0,1", "0,2", "0,3"],
["1,0", "1,1", "1,2", "1,3"],
["2,0", "2,1", "2,2", "2,3"],
]
table.rows.allRowsAlignment = [.left, .left, .right, .right]
document.add(table: table)

let singleCellTable = PDFTable(rows: 1, columns: 1)
singleCellTable[0,0].content = (0...100).map(String.init)
.joined(separator: "\n")
.asTableContent
document.add(table: singleCellTable)

return [document]
}
}
2 changes: 1 addition & 1 deletion Source/API/Table/PDFTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class PDFTable: PDFDocumentObject {
/**
Cells should split when overlapping page
*/
public var shouldSplitCellsOnPageBeak = false
public var shouldSplitCellsOnPageBreak = false

/**
Count of rows and columns in this table
Expand Down
4 changes: 2 additions & 2 deletions Source/API/Table/Sections/PDFTableRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class PDFTableRow {
}
set {
assert(newValue.count <= cells.count, "Can not access more cells than available")
for (idx, cell) in cells.enumerated() {
for (idx, cell) in cells.enumerated() where idx <= newValue.count - 1 {
cell.style = newValue[idx]
}
}
Expand Down Expand Up @@ -97,7 +97,7 @@ public class PDFTableRow {
}
set {
assert(newValue.count <= cells.count, "Can not access more cells than available")
for (idx, cell) in cells.enumerated() {
for (idx, cell) in cells.enumerated() where idx <= newValue.count - 1 {
cell.alignment = newValue[idx]
}
}
Expand Down
6 changes: 4 additions & 2 deletions Source/API/Table/Sections/PDFTableRows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ public class PDFTableRows {
fatalError("You cannot read from this object.")
}
set {
assert(newValue.count <= rows.count, "Can not access more rows than available")
rows.forEach { $0.alignment = newValue }
rows.forEach {
assert(newValue.count <= $0.cells.count, "Can not access more columns than available")
$0.alignment = newValue
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions Source/Internal/Table/PDFTableCalculatedCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// PDFTableCalculatedCell.swift
// TPPDF
//
// Created by Philip Niedertscheider on 19.07.20.
//

import CoreGraphics

internal struct PDFTableCalculatedCell {
var cell: PDFTableCell
var type: PDFTableObject.CellType
var style: PDFTableCellStyle
var frames: (cell: CGRect, content: CGRect)
}
117 changes: 74 additions & 43 deletions Source/Internal/Table/PDFTableObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ import AppKit

// swiftlint:disable function_parameter_count

internal typealias PDFTableCalculatedCell = (cell: PDFTableCell,
type: PDFTableObject.CellType,
style: PDFTableCellStyle,
frames: (cell: CGRect, content: CGRect))

/**
Internal object, used for calculating a `PDFTable`
*/
Expand Down Expand Up @@ -144,7 +139,7 @@ internal class PDFTableObject: PDFRenderObject {
type: CellType,
origin: CGPoint,
width: CGFloat) -> PDFTableCalculatedCell {
var frame: PDFTableCalculatedCell = (
var frame = PDFTableCalculatedCell(
cell: cell,
type: type,
style: style,
Expand Down Expand Up @@ -335,8 +330,18 @@ internal class PDFTableObject: PDFRenderObject {
minOffset += headerHeight
}

var onPageCells: [PDFTableCalculatedCell]
(onPageCells, nextPageCells) = filterCellsOnPage(for: generator, items: nextPageCells, minOffset: minOffset, maxOffset: maxOffset)
let filterResult = filterCellsOnPage(for: generator,
items: nextPageCells,
minOffset: minOffset,
maxOffset: maxOffset,
shouldSplitCellsOnPageBeak: table.shouldSplitCellsOnPageBreak)
let onPageCells = filterResult.cells
nextPageCells = filterResult.remainder
// If none of the cells fit on the current page, the algorithm will try again on the next page and if it occurs again, an error should be thrown
if onPageCells.isEmpty && !firstPage, let firstInvalidCell = nextPageCells.first {
throw PDFError.tableCellTooBig(cell: firstInvalidCell.cell)
}


for (idx, item) in onPageCells.enumerated() {
let cellFrame = item.frames.cell
Expand Down Expand Up @@ -392,29 +397,60 @@ internal class PDFTableObject: PDFRenderObject {
return (objects: result, offset: pageEnd.y)
}

internal typealias FilteredCells = (cells: [PDFTableCalculatedCell], rest: [PDFTableCalculatedCell])
/// Holds two lists of cells, used during table calculations
internal struct FilteredCells {
/// List of calculated cells on the active page
var cells: [PDFTableCalculatedCell]
/// List of remaining cells on further pages
var remainder: [PDFTableCalculatedCell]
}


internal func filterCellsOnPage(for generator: PDFGenerator, items: [PDFTableCalculatedCell], minOffset: CGFloat, maxOffset: CGFloat) -> FilteredCells {
/// Filters the given list of cells into the ones that fit on the current page, and all remainding cells, repositioned for the next page.
///
/// - Parameters:
/// - generator: Active instance of `PDFGenerator`
/// - items: List of cells to filter
/// - minOffset: Minimum `y`-position on the page
/// - maxOffset: Maximum `y`-position on the page
/// - shouldSplitCellsOnPageBreak: If `true`, cells won't be sliced and shown on both pages, instead moved entirely to the next page
/// - Returns: Two lists of cells, see `FilteredCells`
internal func filterCellsOnPage(for generator: PDFGenerator, items: [PDFTableCalculatedCell], minOffset: CGFloat, maxOffset: CGFloat, shouldSplitCellsOnPageBeak: Bool) -> FilteredCells {
// Maximum height available
let contentHeight = maxOffset - minOffset
var result = FilteredCells(cells: [], remainder: [])

var cells: [PDFTableCalculatedCell] = []
var rest: [PDFTableCalculatedCell] = []
var offsetFix: CGFloat!

for item in items {
// Iterate each cell and decide if it fits on current page or if it needs to be moved to the further pages
for item in items {
let cellFrame = item.frames.cell
if cellFrame.maxY < maxOffset {
cells.append(item)

// Cells needs to fit the current available space entirely
if cellFrame.maxY < maxOffset { // TODO: is the row padding relevant here?
result.cells.append(item)
} else {
if cellFrame.minY < maxOffset {
cells.append(item)
// If cells should be split and cell is partially on current page, add it to the cells, the cell will be sliced afterwards
if shouldSplitCellsOnPageBeak && cellFrame.minY < maxOffset {
result.cells.append(item)
}
// In any case, if the cell does not fit on the active page entirely, it must be repositioned for further pages
var nextPageCell = item
nextPageCell.frames.cell.origin.y -= contentHeight
nextPageCell.frames.content.origin.y -= contentHeight
rest.append(nextPageCell)
if shouldSplitCellsOnPageBeak {
nextPageCell.frames.cell.origin.y -= contentHeight
nextPageCell.frames.content.origin.y -= contentHeight
} else {
let cellContentOffset = nextPageCell.frames.content.minY - nextPageCell.frames.cell.minY
if offsetFix == nil {
offsetFix = nextPageCell.frames.cell.minY - minOffset
}
nextPageCell.frames.cell.origin.y -= offsetFix
nextPageCell.frames.content.origin.y = nextPageCell.frames.cell.minY + cellContentOffset
}
result.remainder.append(nextPageCell)
}
}
return (cells: cells, rest: rest)
return result
}

internal func createSliceObject(frame: CGRect, elements: [PDFRenderObject], minOffset: CGFloat, maxOffset: CGFloat) -> PDFSlicedObject {
Expand All @@ -430,9 +466,12 @@ internal class PDFTableObject: PDFRenderObject {
return sliceObject
}

/**
Creates a render object for the cell background
*/
/// Creates a render object for the cell background
///
/// - Parameters:
/// - style: Style of table cell
/// - frame: Frame of cell
/// - Returns: Calculated `PDFRectangleObject`
internal func createCellBackgroundObject(style: PDFTableCellStyle, frame: CGRect) -> PDFRenderObject {
let object = PDFRectangleObject(lineStyle: .none, size: frame.size, fillColor: style.colors.fill)
object.frame = frame
Expand Down Expand Up @@ -500,14 +539,11 @@ internal class PDFTableObject: PDFRenderObject {
return .content
}

/**
Returns the style of a given cell, depending on the type.

- parameters tableStyle: Style configuration of table
- parameters type: Type of cell

- returns: Style of cell
*/
/// Returns the style of a given cell, depending on the type.
/// - Parameters:
/// - tableStyle: Style configuration of table
/// - type: Type of cell
/// - Returns: Style of cell
internal func getStyle(tableStyle: PDFTableStyle, type: CellType) -> PDFTableCellStyle {
switch type {
case .header:
Expand All @@ -525,14 +561,11 @@ internal class PDFTableObject: PDFRenderObject {
}
}

/**
Creates four outline line objects around a given frame using the given style.

- parameter borders: Style of each border direction
- parameter frame: Frame of rectangle

- returns: Array of `PDFLineObject`
*/
/// Creates four outline line objects around a given frame using the given style.
/// - Parameters:
/// - borders: Style of each border edge
/// - frame: Frame of rectangle
/// - Returns: Array of `PDFLineObject`
internal func createCellOutlineObjects(borders: PDFTableCellBorders, frame: CGRect) -> [PDFLineObject] {
[
PDFLineObject(style: borders.top,
Expand All @@ -550,9 +583,7 @@ internal class PDFTableObject: PDFRenderObject {
]
}

/**
Creates a new `PDFTableObject` with the same properties
*/
/// Creates a new `PDFTableObject` with the same properties
override internal var copy: PDFRenderObject {
PDFTableObject(table: table.copy)
}
Expand Down
Loading

0 comments on commit 8f55b0a

Please sign in to comment.