Skip to content

Commit

Permalink
Merge pull request #7 from dkyowell/dev
Browse files Browse the repository at this point in the history
v0.2.3 merge
  • Loading branch information
dkyowell authored Apr 25, 2024
2 parents 40a21ed + 8ec592e commit 96e1601
Show file tree
Hide file tree
Showing 91 changed files with 2,156 additions and 874 deletions.
14 changes: 14 additions & 0 deletions Documentation/Changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog


## v0.2.3
* Added .scaleEffect modifier
* Added .textStroke modifier
* Added .textFill modifier
* Added more Shape drawing functions
* Early look at Columns layout. Not complete
* Early look at page or column wrapable Text
* Changed default layout to center instead of top leading
* Changed name of Size to Dimension and allow points to be expressed as literals
* Change Text to use CoreText rendering

31 changes: 0 additions & 31 deletions Documentation/Design.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,3 @@ type which is shared by the entire tree. EnvironmentValues is a value type. Chil
EnvironmentValues, but can ammend them. So, it is possible for every node in the block tree to have a different
EnvironmentValues value.

...



## Future

Offset
Clip
PageWrap Text
Stroked Text
StrokeStyle
Rotation
Text along Path?
https://medium.com/swlh/add-curved-text-in-your-app-3d41d4463c24



Elliptical Gradient: Easy


## Issues

* Text Gradient Fill: I had this working with a couple of caveats. Multiline text would not render. This seems to be a
limitation of CoreGraphics.



# SO, INSTEAD OF THAT...

Run a page...when a

55 changes: 4 additions & 51 deletions Documentation/ToDo.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# To Do List

## Version 1.0 Roadmap
### PageWrap Text

### Column Layout
### VGrid

### Offset

### Rotation
## Partialy Implmented
### PageWrap Text

### VGrid
### Column Layout

## Partialy Implmented
### Grids
There should be more layout options.

Expand All @@ -20,51 +18,6 @@ There are many intersection, union, etc functions that I have not yet implemente
on top of MutablePath. I could just get rid of all of it and operate directly upon a MutablePath. Or, I could
expose MutablePath.

## Fixes

### Overlays
Need to review overlay rendering deferal. It seems that overlays are not being rendered in many cases.



## Reevaluate

### Default Positioning
TopLeading or Center?


### Expose Renderable
Is there a way to make a CustomBlock that uses .sizeFor(), but that does not expose the full Renderable protocol?
Exposing Renderer would not be a big deal.
Offer a PDFBlocksAdvanced import with Renderable?

### Layout


## Version > 1.0
### Leading to Trailing Page Wrap
Currently page wrap only works with elements that flow from top to bottom.

### Gradient fill for text
I have attempted this, but ran into a couple of dead ends. 1) When the Text was in a stack with other elements, the
gradient would randomly decide to spill over the entire page. 2) The gradient would not work at all with multi line
text.

### Text along a path




## Version 2.0
If library gains widespready adoption, the following could be considered for a 2.0 release.

### Secondary Page Wrap Blocks
Allow Borders, Backgrounds, Overlays, etc

### Custom Layouts
This will wait for a use case and more widespready adoption of PDFBlocks. Any users who are held up would be able
to fork and implement their own.

### Text around a path
This would require CoreText,

29 changes: 14 additions & 15 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ PDFBlocks uses a declarative language for describing document layout and appeara
draw(), or newPage(). Here is the "code" used to generate the PDFBlocks logo used at the top of this document:

```swift
struct Document: Block {
private struct Document: Block {
var body: some Block {
VStack(spacing: .pt(2)) {
HStack(spacing: .pt(2)) {
VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 2) {
ForEach(["P", "D", "F"]) { item in
LetterBlock(letter: item, color: .red)
}
}
HStack(spacing: .pt(2)) {
HStack(spacing: 2) {
ForEach(["B", "L", "O", "C", "K", "S"]) { item in
LetterBlock(letter: item, color: .cyan)
}
Expand All @@ -31,13 +31,13 @@ struct Document: Block {
}
}

struct LetterBlock: Block {
private struct LetterBlock: Block {
let letter: String
let color: Color
var body: some Block {
Text(letter)
.foregroundColor(.white)
.frame(width: .pt(48), height: .pt(48), alignment: .center)
.frame(width: 48, height: 48, alignment: .center)
.background { color }
.font(name: "American Typewriter", size: 36)
.bold()
Expand Down Expand Up @@ -88,17 +88,17 @@ PDFBlocks is inspired by SwiftUI and follows its syntax closely, however, there
### Blocks
Everything in SwiftUI that is a View is a Block in PDFBlocks.

* Components such as Text, Image, Color, Divider, VStack, HStack, ZStack, Page, and Table are all blocks.
* Modifiers like .font, .foregroundColor, .opacity, .padding, ,border, .frame, .background, and .overlay are blocks as well.
* Documents you write are blocks.
* Re-usable components you compose are blocks.

### Units
Sizes must be specified in points (.pt), inches (.in), or milimeters (.mm).
Dimensions can be specified in points (.pt), inches (.in), or milimeters (.mm).
```swift
Color.blue
.frame(width: .in(1), height: .pt(72))
```
Dimensions can also be expressed integer or float literals, in which case the unit is points.
```swift
Color.blue
.frame(width: 36, height: 36)
```
### Frames
There is no minWidth, maxWidth, minHeight, maxHeight for frames. Instead, a width or height can be set as .max.
So, instead of this SwiftUI code for positioning an element in the bottom trailing corner of a view:
Expand Down Expand Up @@ -128,9 +128,6 @@ HStack(spacing: .flex) {
Text("Blue Fish")
}
```
### Alignment
Default alignment in SwiftUI is centered. In PDFBlocks it is top leading.
### Pages
A document with multiple pages can be defined like this:
```swift
Expand Down Expand Up @@ -177,6 +174,8 @@ Then import PDFBlocks wherever you’d like to use it:
import PDFBlocks
```
## For a Quick "Preview"
The best way to explore this package to see what it can do is with XCode Previews.

1. Download the PDFBlocks project.
2. Open Package.swift in XCode.
3. Navigate to Sources/PDFBlocks/Examples
Expand Down
21 changes: 21 additions & 0 deletions Sources/PDFBlocks/API/Blocks/Columns.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* PDF Blocks
* Copyright (c) David Yowell 2024
* MIT license, see LICENSE file for details
*/

import Foundation

public struct Columns<Content>: Block where Content: Block {
let count: Int
let spacing: Dimension
let allowWrap: Bool
let content: Content

public init(count: Int, spacing: Dimension, allowWrap: Bool = false, @BlockBuilder content: () -> Content) {
self.count = max(1, count)
self.spacing = spacing
self.allowWrap = allowWrap
self.content = content()
}
}
6 changes: 3 additions & 3 deletions Sources/PDFBlocks/API/Blocks/Divider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import Foundation
/// When contained in a stack, the divider extends across the minor axis of the stack,
/// or horizontally when not in a stack.
public struct Divider: Block {
let thickness: Size
let padding: Size
let thickness: Dimension
let padding: Dimension

public init(thickness: Size = .pt(0.75), padding: Size = .pt(1)) {
public init(thickness: Dimension = .pt(0.75), padding: Dimension = .pt(1)) {
self.thickness = thickness
self.padding = padding
}
Expand Down
14 changes: 7 additions & 7 deletions Sources/PDFBlocks/API/Blocks/HGrid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import Foundation
/// A grid can span multiple pages.
public struct HGrid<Content>: Block where Content: Block {
let columnCount: Int
let columnSpacing: Size
let rowSpacing: Size
let allowPageWrap: Bool
let columnSpacing: Dimension
let rowSpacing: Dimension
let allowWrap: Bool
let content: Content

public init(columnCount: Int,
columnSpacing: Size,
rowSpacing: Size,
allowPageWrap: Bool = false,
columnSpacing: Dimension,
rowSpacing: Dimension,
allowWrap: Bool = false,
@BlockBuilder content: () -> Content)
{
self.columnCount = max(1, columnCount)
self.columnSpacing = columnSpacing
self.rowSpacing = rowSpacing
self.allowPageWrap = allowPageWrap
self.allowWrap = allowWrap
self.content = content()
}
}
2 changes: 1 addition & 1 deletion Sources/PDFBlocks/API/Blocks/HStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public struct HStack<Content: Block>: Block {
/// - alignment: The vertical alignment for the contents of the stack.
/// - spacing: The distance between elements of the stack.
/// - content: A block builder that creates the content of this stack.
public init(alignment: VerticalAlignment = .top, spacing: StackSpacing = .none, @BlockBuilder content: () -> Content) {
public init(alignment: VerticalAlignment = .center, spacing: StackSpacing = .none, @BlockBuilder content: () -> Content) {
self.alignment = alignment
self.spacing = spacing
self.content = content()
Expand Down
4 changes: 2 additions & 2 deletions Sources/PDFBlocks/API/Blocks/Line.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import Foundation

/// A horizontal line.
public struct Line: Block {
let thickness: Size
let thickness: Dimension
let dash: [CGFloat]

public init(thickness: Size = .pt(1), dash: [CGFloat] = []) {
public init(thickness: Dimension = .pt(1), dash: [CGFloat] = []) {
self.thickness = thickness
self.dash = dash
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/PDFBlocks/API/Blocks/Spacer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import Foundation
/// LAYOUTPRIORITY OF LESS THAN 0. LAYOUT PRIORITY
/// SUPPORT HAS NOT BEEN ADDED.
public struct Spacer: Block {
let minLength: Size
let minLength: Dimension

public init(minLength: Size = .pt(0)) {
public init(minLength: Dimension = .pt(0)) {
self.minLength = minLength
}
}
6 changes: 3 additions & 3 deletions Sources/PDFBlocks/API/Blocks/Table.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public protocol TableGroupContent<Row> where Value: Equatable, Value: Comparable
var value: KeyPath<Row, Value> { get }
var header: ([Row], Value) -> any Block { get }
var footer: ([Row], Value) -> any Block { get }
var spacing: Size { get }
var spacing: Dimension { get }
var nextGroup: (any TableGroupContent<Row>)? { get set }
}

Expand All @@ -213,7 +213,7 @@ public struct TableGroup<Row, Value>: TableGroupContent where Value: Equatable,
public let value: KeyPath<Row, Value>
public let header: ([Row], Value) -> any Block
public let footer: ([Row], Value) -> any Block
public let spacing: Size
public let spacing: Dimension
public var nextGroup: (any TableGroupContent<Row>)?

/// Creates a table group that will sort table data on a key path and start
Expand All @@ -233,7 +233,7 @@ public struct TableGroup<Row, Value>: TableGroupContent where Value: Equatable,
/// a block to be rendered after the group's rows are rendered.
public init(on value: KeyPath<Row, Value>,
order: @escaping (Value, Value) -> Bool = { $0 < $1 },
spacing: Size,
spacing: Dimension,
@BlockBuilder header: @escaping ([Row], Value) -> any Block,
@BlockBuilder footer: @escaping ([Row], Value) -> any Block)
{
Expand Down
2 changes: 1 addition & 1 deletion Sources/PDFBlocks/API/Blocks/TableColumnTitles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public struct TableColumnTitles: Block {

public var body: some Block {
VStack {
HStack(spacing: .pt(2)) {
HStack(alignment: .top, spacing: .pt(2)) {
ForEach(columns.filter(\.visible)) { column in
Text(column.title)
.bold()
Expand Down
2 changes: 1 addition & 1 deletion Sources/PDFBlocks/API/Blocks/TableRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public struct TableRow<Value>: Block {
}

public var body: some Block {
HStack(spacing: .pt(2)) {
HStack(alignment: .top, spacing: .pt(2)) {
ForEach(columns.filter(\.visible).compactMap { $0 as? any TableColumnContent<Value> }) { column in
AnyBlock(column.cellContent(record: record))
.proportionalFrame(width: column.width, alignment: column.alignment)
Expand Down
9 changes: 9 additions & 0 deletions Sources/PDFBlocks/API/Blocks/Text.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import Foundation

// TODO: In SwiftUI, Text is not generic over Format. Investigate implementation.
/// A block for displaying text.
public struct Text<F>: Block where F: FormatStyle, F.FormatInput: Equatable, F.FormatOutput == String {
let input: F.FormatInput
Expand All @@ -21,3 +22,11 @@ public struct Text<F>: Block where F: FormatStyle, F.FormatInput: Equatable, F.F
format = StringFormatStyle()
}
}

//public struct CTText: Block {
// let input: String
//
// public init(_ input: String) {
// self.input = input
// }
//}
8 changes: 4 additions & 4 deletions Sources/PDFBlocks/API/Blocks/VStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation
public struct VStack<Content>: Block where Content: Block {
let alignment: HorizontalAlignment
let spacing: StackSpacing
let allowPageWrap: Bool
let allowWrap: Bool
let content: Content

/// Creates a vertical stack with the given spacing and vertical alignment.
Expand All @@ -29,14 +29,14 @@ public struct VStack<Content>: Block where Content: Block {
/// - alignment: The horizontal alignment for the contents of the stack.
/// - spacing: The distance between elements of the stack.
/// - content: A block builder that creates the content of this stack.
public init(alignment: HorizontalAlignment = .leading,
public init(alignment: HorizontalAlignment = .center,
spacing: StackSpacing = .none,
allowPageWrap: Bool = false,
allowWrap: Bool = false,
@BlockBuilder content: () -> Content)
{
self.alignment = alignment
self.spacing = spacing
self.allowPageWrap = allowPageWrap
self.allowWrap = allowWrap
self.content = content()
}
}
Loading

0 comments on commit 96e1601

Please sign in to comment.