Skip to content

Commit 053e908

Browse files
authored
Merge pull request #45 from swhitty/absolute-units
Support absolute units for any position, size or coordinate
2 parents b917e2a + 57a2676 commit 053e908

File tree

6 files changed

+111
-4
lines changed

6 files changed

+111
-4
lines changed

Examples/Sources/ViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class ViewController: UIViewController {
6565

6666
override func loadView() {
6767
let imageView = UIImageView(frame: UIScreen.main.bounds)
68-
imageView.image = SVG(named: "usa.svg", in: .samples)?.rasterize()
68+
imageView.image = SVG(named: "units-cm.svg", in: .samples)?.rasterize()
6969
imageView.contentMode = .scaleAspectFit
7070
imageView.backgroundColor = .white
7171
self.view = imageView

Samples.bundle/units-cm.svg

Lines changed: 5 additions & 0 deletions
Loading

Samples.bundle/units.svg

Lines changed: 10 additions & 0 deletions
Loading

SwiftDraw/DOM.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,55 @@ extension DOM {
104104
case skewX(angle: Float)
105105
case skewY(angle: Float)
106106
}
107-
107+
108+
enum Unit {
109+
case pixel
110+
case inch
111+
case centimeter
112+
case millimeter
113+
case point
114+
case pica
115+
}
116+
108117
enum Error: Swift.Error {
109118
case missing(String)
110119
}
111120
}
121+
122+
extension DOM.Unit {
123+
var rawValue: String {
124+
switch self {
125+
case .pixel:
126+
return "px"
127+
case .inch:
128+
return "in"
129+
case .centimeter:
130+
return "cm"
131+
case .millimeter:
132+
return "mm"
133+
case .point:
134+
return "pt"
135+
case .pica:
136+
return "pc"
137+
}
138+
}
139+
}
140+
141+
extension Double {
142+
func apply(unit: DOM.Unit) -> Double {
143+
switch unit {
144+
case .pixel:
145+
return self
146+
case .inch:
147+
return self * 96
148+
case .centimeter:
149+
return self * 37.795
150+
case .millimeter:
151+
return self * 3.7795
152+
case .point:
153+
return self * 1.3333
154+
case .pica:
155+
return self * 16
156+
}
157+
}
158+
}

SwiftDraw/Parser.XML.Scanner.swift

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,34 @@ extension XMLParser {
155155
currentIndex = scanner.currentIndex
156156
return val
157157
}
158-
158+
159+
mutating func scanUnit(_ unit: DOM.Unit) -> Bool {
160+
scanner.currentIndex = currentIndex
161+
guard scanner.scanString(unit.rawValue) != nil else {
162+
return false
163+
}
164+
currentIndex = scanner.currentIndex
165+
return true
166+
}
167+
168+
mutating func scanUnit() -> DOM.Unit? {
169+
if scanUnit(.pixel) {
170+
return .pixel
171+
} else if scanUnit(.inch) {
172+
return .inch
173+
} else if scanUnit(.centimeter) {
174+
return .centimeter
175+
} else if scanUnit(.millimeter) {
176+
return .millimeter
177+
} else if scanUnit(.point) {
178+
return .point
179+
} else if scanUnit(.pica) {
180+
return .pica
181+
} else {
182+
return nil
183+
}
184+
}
185+
159186
mutating func scanLength() throws -> DOM.Length {
160187
scanner.currentIndex = currentIndex
161188
guard
@@ -173,7 +200,9 @@ extension XMLParser {
173200
}
174201

175202
mutating func scanCoordinate() throws -> DOM.Coordinate {
176-
return DOM.Coordinate(try scanDouble())
203+
let double = try scanDouble()
204+
let unit = scanUnit() ?? .pixel
205+
return DOM.Coordinate(double.apply(unit: unit))
177206
}
178207

179208
mutating func scanPercentageFloat() throws -> Float {

SwiftDrawTests/XML.Parser.ScannerTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,22 @@ final class ScannerTests: XCTestCase {
181181
_ = try? scanner.scanString(",")
182182
XCTAssertEqual(try scanner.scanCoordinate(), -10)
183183
}
184+
185+
func testScanCoordinate_Units() throws {
186+
var scanner = XMLParser.Scanner(text: "1, 2px, 1cm, 2mm, 1pt, 5pc")
187+
188+
XCTAssertEqual(try scanner.scanCoordinate(), 1)
189+
_ = try? scanner.scanString(",")
190+
XCTAssertEqual(try scanner.scanCoordinate(), 2)
191+
_ = try? scanner.scanString(",")
192+
XCTAssertEqual(try scanner.scanCoordinate(), 37.795)
193+
_ = try? scanner.scanString(",")
194+
XCTAssertEqual(try scanner.scanCoordinate(), 2 * 3.7795)
195+
_ = try? scanner.scanString(",")
196+
XCTAssertEqual(try scanner.scanCoordinate(), 1 * 1.3333)
197+
_ = try? scanner.scanString(",")
198+
XCTAssertEqual(try scanner.scanCoordinate(), 5 * 16)
199+
}
184200
}
185201

186202
private func AssertScanUInt8(_ text: String, _ expected: UInt8?, file: StaticString = #file, line: UInt = #line) {

0 commit comments

Comments
 (0)