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
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@

**Implemented enhancements:**

- Added optional table cell splicing disabling

**Fixed bugs:**

**Closed issues:**

- Issue #205
- Issue #222
- Issue #243
- Issue #249

**Merged pull requests:**

- PR #223

## [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
27 changes: 6 additions & 21 deletions Shared/Examples/ExperimentFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ExperimentFactory: ExampleFactory {
table.margin = 10
table.padding = 10
table.showHeadersOnEveryPage = false
table.shouldSplitCellsOnPageBreak = false
table.style.columnHeaderCount = 3

for row in 0..<table.size.rows {
Expand All @@ -28,29 +29,13 @@ class ExperimentFactory: ExampleFactory {
}
}

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)

let singleCellTable = PDFTable(rows: 1, columns: 1)
singleCellTable[0,0].content = (0...100).map(String.init)
.joined(separator: "\n")
.asTableContent
document.add(table: singleCellTable)
// 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]
}
Expand Down
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
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
4 changes: 4 additions & 0 deletions TPPDF.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
D4803D3A24703E5300DDA039 /* PDFAttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4803C9F24703E5300DDA039 /* PDFAttributedText.swift */; };
D4803D3B24703E5300DDA039 /* PDFText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4803CA024703E5300DDA039 /* PDFText.swift */; };
D4803D3C24703E5300DDA039 /* PDFTextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4803CA124703E5300DDA039 /* PDFTextStyle.swift */; };
D4839C39253706950005BB87 /* PDFTableCalculatedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4839C38253706950005BB87 /* PDFTableCalculatedCell.swift */; };
D4EE2F9724A34C990004E3B9 /* PDFContextGraphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE2F9624A34C990004E3B9 /* PDFContextGraphics.swift */; };
D4EE2F9924A34CBF0004E3B9 /* CrossPlattformGraphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE2F9824A34CBF0004E3B9 /* CrossPlattformGraphics.swift */; };
OBJ_419 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_331 /* AdapterProtocols.swift */; };
Expand Down Expand Up @@ -621,6 +622,7 @@
D4803C9F24703E5300DDA039 /* PDFAttributedText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFAttributedText.swift; sourceTree = "<group>"; };
D4803CA024703E5300DDA039 /* PDFText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFText.swift; sourceTree = "<group>"; };
D4803CA124703E5300DDA039 /* PDFTextStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFTextStyle.swift; sourceTree = "<group>"; };
D4839C38253706950005BB87 /* PDFTableCalculatedCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFTableCalculatedCell.swift; sourceTree = "<group>"; };
D4EE2F9624A34C990004E3B9 /* PDFContextGraphics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFContextGraphics.swift; sourceTree = "<group>"; };
D4EE2F9824A34CBF0004E3B9 /* CrossPlattformGraphics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossPlattformGraphics.swift; sourceTree = "<group>"; };
"Nimble::Nimble::Product" /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -1054,6 +1056,7 @@
D4803C3724703E5300DDA039 /* Table */ = {
isa = PBXGroup;
children = (
D4839C38253706950005BB87 /* PDFTableCalculatedCell.swift */,
D4803C3824703E5300DDA039 /* PDFTableMergeUtil.swift */,
D4803C3924703E5300DDA039 /* PDFTableNode.swift */,
D4803C3A24703E5300DDA039 /* PDFTableObject.swift */,
Expand Down Expand Up @@ -2265,6 +2268,7 @@
D4803D1124703E5300DDA039 /* PDFBezierPath.swift in Sources */,
D4803D3A24703E5300DDA039 /* PDFAttributedText.swift in Sources */,
D4803D2224703E5300DDA039 /* PDFTable+RowSubscripts.swift in Sources */,
D4839C39253706950005BB87 /* PDFTableCalculatedCell.swift in Sources */,
D4803CF924703E5300DDA039 /* PDFSection.swift in Sources */,
D4803CB924703E5300DDA039 /* PDFPaginationStyle+Equatable.swift in Sources */,
D4803CD124703E5300DDA039 /* PDFRectangleObject.swift in Sources */,
Expand Down
Loading