diff --git a/Art/images/data_circuit.png b/Art/images/data_circuit.png
new file mode 100644
index 00000000..39943327
Binary files /dev/null and b/Art/images/data_circuit.png differ
diff --git a/Art/paths.pcvd b/Art/paths.pcvd
index 39c7fb9c..04621dfa 100644
Binary files a/Art/paths.pcvd and b/Art/paths.pcvd differ
diff --git a/DSF_QRCode.podspec b/DSF_QRCode.podspec
index b905e175..4ddb210f 100644
--- a/DSF_QRCode.podspec
+++ b/DSF_QRCode.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = 'DSF_QRCode'
-s.version = '20.4.2'
+s.version = '20.5.0'
s.summary = 'A simple drop-in macOS/iOS/tvOS/watchOS QR Code generator view for Swift, Objective-C and SwiftUI.'
s.homepage = 'https://github.com/dagronf/QRCode'
s.license = { :type => 'MIT', :file => 'LICENSE' }
diff --git a/README.md b/README.md
index 5a4886bc..1ecc81cc 100644
--- a/README.md
+++ b/README.md
@@ -352,6 +352,32 @@ The QRCode is made up of four distinct components
The 'shape' represents the way that each of the components are drawn
+#### 'OnPixels' shape
+
+The data shape represents how the 'pixels' within the QR code are displayed. By default, this is a simple square,
+however you can supply a `PixelShape` object to custom-draw the data. There are built-in generators for a variety of styles.
+
+| Preview | Name | Class | Description |
+|---|---|---|---|
+| |"blob"|`QRCode.PixelShape.Blob`|A blobby style|
+| |"circle"|`QRCode.PixelShape.Circle`|A basic circle pixel|
+| |"circuit"|`QRCode.PixelShape.Circuit`|Circuits!|
+| | "crt" |`QRCode.PixelShape.CRT`| A CRT shape |
+| |"curvePixel"|`QRCode.PixelShape.CurvePixel`|A pixel that curves to follow paths|
+| |"flower"|`QRCode.PixelShape.Flower`|A 'flower' style|
+| |"horizontal"|`QRCode.PixelShape.Horizontal`|The pixels are horizonally joined to make continuous horizontal bars|
+| |"pointy"|`QRCode.PixelShape.Pointy`|A 'pointy' style|
+| |"razor"|`QRCode.PixelShape.Razor`| A 'razor' style|
+| |"roundedEndIndent"|`QRCode.PixelShape.RoundedEndIndent`|Rounded path with circular indented ends|
+| |"roundedPath"|`QRCode.PixelShape.RoundedPath`|A smooth rounded-edge path|
+| |"roundedRect"|`QRCode.PixelShape.RoundedRect`|A basic rounded rectangle pixel with configurable radius|
+| |"sharp"|`QRCode.PixelShape.Sharp`|A 'sharp' style|
+| | "shiny" |`QRCode.PixelShape.Shiny` |A pixel style that appears 'shiny'|
+| |"square"|`QRCode.PixelShape.Square`|A basic square pixel (default)|
+| |"squircle"|`QRCode.PixelShape.Squircle`|A superellipse shape (somewhere between a square and a circle)|
+| |"star"|`QRCode.PixelShape.Star`|A 'star' style|
+| |"vertical"|`QRCode.PixelShape.Vertical`|The pixels are vertically joined to make continuous vertical bars|
+
#### Eye shape
You can provide an `EyeShape` object to style just the eyes of the generated qr code. There are built-in generators for
@@ -431,31 +457,6 @@ doc.design.style.onPixels = QRCode.FillStyle.Solid(0.624, 0.424, 0.400)
-#### 'OnPixels' shape
-
-The data shape represents how the 'pixels' within the QR code are displayed. By default, this is a simple square,
-however you can supply a `PixelShape` object to custom-draw the data. There are built-in generators for a variety of styles.
-
-| Preview | Name | Class | Description |
-|---|---|---|---|
-| |"blob"|`QRCode.PixelShape.Blob`|A blobby style|
-| |"circle"|`QRCode.PixelShape.Circle`|A basic circle pixel|
-| | "crt" |`QRCode.PixelShape.CRT`| A CRT shape |
-| |"curvePixel"|`QRCode.PixelShape.CurvePixel`|A pixel that curves to follow paths|
-| |"flower"|`QRCode.PixelShape.Flower`|A 'flower' style|
-| |"horizontal"|`QRCode.PixelShape.Horizontal`|The pixels are horizonally joined to make continuous horizontal bars|
-| |"pointy"|`QRCode.PixelShape.Pointy`|A 'pointy' style|
-| |"razor"|`QRCode.PixelShape.Razor`| A 'razor' style|
-| |"roundedEndIndent"|`QRCode.PixelShape.RoundedEndIndent`|Rounded path with circular indented ends|
-| |"roundedPath"|`QRCode.PixelShape.RoundedPath`|A smooth rounded-edge path|
-| |"roundedRect"|`QRCode.PixelShape.RoundedRect`|A basic rounded rectangle pixel with configurable radius|
-| |"sharp"|`QRCode.PixelShape.Sharp`|A 'sharp' style|
-| | "shiny" |`QRCode.PixelShape.Shiny` |A pixel style that appears 'shiny'|
-| |"square"|`QRCode.PixelShape.Square`|A basic square pixel (default)|
-| |"squircle"|`QRCode.PixelShape.Squircle`|A superellipse shape (somewhere between a square and a circle)|
-| |"star"|`QRCode.PixelShape.Star`|A 'star' style|
-| |"vertical"|`QRCode.PixelShape.Vertical`|The pixels are vertically joined to make continuous vertical bars|
-
#### 'offPixels' shape (optional)
You can specify a shape to be drawn when a data 'pixel' is _off_. This can be used to make your qr code prettier.
@@ -1150,9 +1151,9 @@ OPTIONS:
--all-pixel-shapes
Print all the available pixel shapes.
-d, --on-pixel-shape
- The onPixels shape to use. Available shapes are crt, circle, curvePixel, flower, horizontal,
- pointy, razor, roundedEndIndent, roundedPath, roundedRect, sharp, shiny, square, squircle,
- star, vertical.
+ The onPixels shape to use. Available shapes are blob, crt, circle, circuit, curvePixel,
+ flower, horizontal, pointy, razor, roundedEndIndent, roundedPath, roundedRect, sharp, shiny,
+ square, squircle, star, vertical.
-n, --on-pixel-inset-fraction
The spacing around each individual pixel in the onPixels section
-r, --on-pixel-shape-corner-radius
diff --git a/Sources/QRCode/styles/data/QRCodePixelShapeCircuit.swift b/Sources/QRCode/styles/data/QRCodePixelShapeCircuit.swift
new file mode 100644
index 00000000..282ffa29
--- /dev/null
+++ b/Sources/QRCode/styles/data/QRCodePixelShapeCircuit.swift
@@ -0,0 +1,509 @@
+//
+// QRCodePixelShapeCircuit.swift
+//
+// Copyright © 2024 Darren Ford. All rights reserved.
+//
+// MIT license
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+import Foundation
+import CoreGraphics
+
+public extension QRCode.PixelShape {
+ /// A generator for a pixel shape that displays connected circles
+ @objc(QRCodePixelShapeCircuit) class Circuit: NSObject, QRCodePixelShapeGenerator {
+ /// The generator name
+ @objc public static let Name: String = "circuit"
+ /// The generator title
+ @objc public static var Title: String { "Circuit" }
+ /// Create an instance of this path generator with the specified settings
+ @objc public static func Create(_ settings: [String: Any]?) -> any QRCodePixelShapeGenerator { Circuit() }
+
+ /// Make a copy of the object
+ @objc public func copyShape() -> any QRCodePixelShapeGenerator { Circuit() }
+ }
+}
+
+public extension QRCode.PixelShape.Circuit {
+ /// Generate a CGPath from the matrix contents
+ /// - Parameters:
+ /// - matrix: The matrix to generate
+ /// - size: The size of the resulting CGPath
+ /// - Returns: A path
+ @objc func generatePath(from matrix: BoolMatrix, size: CGSize) -> CGPath {
+ let dx = size.width / CGFloat(matrix.dimension)
+ let dy = size.height / CGFloat(matrix.dimension)
+ let dm = min(dx, dy)
+
+ let xoff = (size.width - (CGFloat(matrix.dimension) * dm)) / 2.0
+ let yoff = (size.height - (CGFloat(matrix.dimension) * dm)) / 2.0
+
+ // The scale required to convert our template paths to output path size
+ let w = QRCode.PixelShape.RoundedPath.DefaultSize.width
+ let scaleTransform = CGAffineTransform(scaleX: dm / w, y: dm / w)
+
+ let path = CGMutablePath()
+
+ for row in 0 ..< matrix.dimension {
+ for col in 0 ..< matrix.dimension {
+ let translate = CGAffineTransform(translationX: CGFloat(col) * dm + xoff, y: CGFloat(row) * dm + yoff)
+ let ne = Neighbours(matrix: matrix, row: row, col: col)
+ if matrix[row, col] == true {
+
+ if ne.top, !ne.bottom, !ne.leading, !ne.trailing {
+ path.addPath(Self.templateBottom, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, ne.bottom, !ne.leading, !ne.trailing {
+ path.addPath(Self.templateTop, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, !ne.bottom, ne.leading, !ne.trailing {
+ path.addPath(Self.templateLeft, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, !ne.bottom, !ne.leading, ne.trailing {
+ path.addPath(Self.templateRight, transform: scaleTransform.concatenating(translate))
+ }
+
+ else if ne.top, ne.bottom, !ne.leading, !ne.trailing {
+ path.addPath(Self.templateTopBottom, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, !ne.bottom, ne.leading, ne.trailing {
+ path.addPath(Self.templateLeftRight, transform: scaleTransform.concatenating(translate))
+ }
+
+ else if ne.top, !ne.bottom, ne.leading, !ne.trailing {
+ path.addPath(Self.templateBottomLeft, transform: scaleTransform.concatenating(translate))
+ }
+ else if ne.top, !ne.bottom, !ne.leading, ne.trailing {
+ path.addPath(Self.templateBottomRight, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, ne.bottom, ne.leading, !ne.trailing {
+ path.addPath(Self.templateTopLeft, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, ne.bottom, !ne.leading, ne.trailing {
+ path.addPath(Self.templateTopRight, transform: scaleTransform.concatenating(translate))
+ }
+
+ else if ne.top, !ne.bottom, ne.leading, ne.trailing {
+ path.addPath(Self.templateLeftBottomRight, transform: scaleTransform.concatenating(translate))
+ }
+ else if !ne.top, ne.bottom, ne.leading, ne.trailing {
+ path.addPath(Self.templateTopLeftRight, transform: scaleTransform.concatenating(translate))
+ }
+ else if ne.top, ne.bottom, !ne.leading, ne.trailing {
+ path.addPath(Self.templateTopRightBottom, transform: scaleTransform.concatenating(translate))
+ }
+ else if ne.top, ne.bottom, ne.leading, !ne.trailing {
+ path.addPath(Self.templateTopLeftBottom, transform: scaleTransform.concatenating(translate))
+ }
+
+ else if ne.top, ne.bottom, ne.leading, ne.trailing {
+ path.addPath(Self.templateTopLeftBottomRight, transform: scaleTransform.concatenating(translate))
+ }
+
+ else {
+ path.addPath(Self.templateCentroid, transform: scaleTransform.concatenating(translate))
+ }
+ }
+ }
+ }
+ path.closeSubpath()
+ return path
+ }
+}
+
+// MARK: - Settings
+
+public extension QRCode.PixelShape.Circuit {
+ /// Does the shape generator support setting values for a particular key?
+ @objc func supportsSettingValue(forKey key: String) -> Bool { false }
+ /// Returns a storable representation of the shape handler
+ @objc func settings() -> [String: Any] { return [:] }
+ /// Set a configuration value for a particular setting string
+ @objc func setSettingValue(_ value: Any?, forKey key: String) -> Bool { false }
+}
+
+// MARK: - Pixel creation conveniences
+
+public extension QRCodePixelShapeGenerator where Self == QRCode.PixelShape.Circuit {
+ /// Create a organic pixel generator
+ /// - Returns: A pixel generator
+ @inlinable static func circuit() -> QRCodePixelShapeGenerator {
+ QRCode.PixelShape.Circuit()
+ }
+}
+
+// MARK: - Shapes
+
+// Inner corner templates
+
+private extension QRCode.PixelShape.Circuit {
+ static let templateCentroid = CGPath(ellipseIn: CGRect(x: 1, y: 1, width: 8, height: 8), transform: nil)
+
+ static let templateTop =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 8.01), controlPoint1: CGPoint(x: 6.85, y: 8.53), controlPoint2: CGPoint(x: 7.55, y: 8.07))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 7.27), controlPoint2: CGPoint(x: 9, y: 6.19))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 9, y: 2.79), controlPoint2: CGPoint(x: 7.21, y: 1))
+ $0.curve(to: CGPoint(x: 2.94, y: 1.57), controlPoint1: CGPoint(x: 4.25, y: 1), controlPoint2: CGPoint(x: 3.54, y: 1.21))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 1.78, y: 2.27), controlPoint2: CGPoint(x: 1, y: 3.54))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 1, y: 6.19), controlPoint2: CGPoint(x: 1.52, y: 7.27))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.close()
+ }
+
+ static let templateBottom =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 0))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 6.2, y: 0), controlPoint2: CGPoint(x: 6.15, y: 0.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 1.99), controlPoint1: CGPoint(x: 6.85, y: 1.47), controlPoint2: CGPoint(x: 7.55, y: 1.93))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 2.73), controlPoint2: CGPoint(x: 9, y: 3.81))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 9, y: 7.21), controlPoint2: CGPoint(x: 7.21, y: 9))
+ $0.curve(to: CGPoint(x: 2.94, y: 8.43), controlPoint1: CGPoint(x: 4.25, y: 9), controlPoint2: CGPoint(x: 3.54, y: 8.79))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 1.78, y: 7.73), controlPoint2: CGPoint(x: 1, y: 6.46))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 1, y: 3.81), controlPoint2: CGPoint(x: 1.52, y: 2.73))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 2.41, y: 1.96), controlPoint2: CGPoint(x: 3.14, y: 1.48))
+ $0.curve(to: CGPoint(x: 3.8, y: 0), controlPoint1: CGPoint(x: 3.85, y: 0.5), controlPoint2: CGPoint(x: 3.8, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.close()
+ }
+
+ static let templateLeft =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 0, y: 3.8))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 0, y: 3.8), controlPoint2: CGPoint(x: 0.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 1.99, y: 2.36), controlPoint1: CGPoint(x: 1.47, y: 3.15), controlPoint2: CGPoint(x: 1.93, y: 2.45))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 2.73, y: 1.52), controlPoint2: CGPoint(x: 3.81, y: 1))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 7.21, y: 1), controlPoint2: CGPoint(x: 9, y: 2.79))
+ $0.curve(to: CGPoint(x: 8.43, y: 7.06), controlPoint1: CGPoint(x: 9, y: 5.75), controlPoint2: CGPoint(x: 8.79, y: 6.46))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 7.73, y: 8.22), controlPoint2: CGPoint(x: 6.46, y: 9))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 3.81, y: 9), controlPoint2: CGPoint(x: 2.73, y: 8.48))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 1.96, y: 7.59), controlPoint2: CGPoint(x: 1.48, y: 6.86))
+ $0.curve(to: CGPoint(x: 0, y: 6.2), controlPoint1: CGPoint(x: 0.5, y: 6.15), controlPoint2: CGPoint(x: 0, y: 6.2))
+ $0.line(to: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 3.8))
+ $0.close()
+ }
+
+ static let templateRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8.01, y: 2.36), controlPoint1: CGPoint(x: 8.53, y: 3.15), controlPoint2: CGPoint(x: 8.07, y: 2.45))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 7.27, y: 1.52), controlPoint2: CGPoint(x: 6.19, y: 1))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 2.79, y: 1), controlPoint2: CGPoint(x: 1, y: 2.79))
+ $0.curve(to: CGPoint(x: 1.57, y: 7.06), controlPoint1: CGPoint(x: 1, y: 5.75), controlPoint2: CGPoint(x: 1.21, y: 6.46))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 2.27, y: 8.22), controlPoint2: CGPoint(x: 3.54, y: 9))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 6.19, y: 9), controlPoint2: CGPoint(x: 7.27, y: 8.48))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.close()
+ }
+
+ // -
+
+ static let templateTopBottom =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 7.65, y: 2))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 7.59, y: 1.96), controlPoint2: CGPoint(x: 6.86, y: 1.48))
+ $0.curve(to: CGPoint(x: 6.2, y: 0), controlPoint1: CGPoint(x: 6.15, y: 0.5), controlPoint2: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 3.8, y: 0))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 3.8, y: 0), controlPoint2: CGPoint(x: 3.85, y: 0.5))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 3.14, y: 1.48), controlPoint2: CGPoint(x: 2.41, y: 1.96))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 1.52, y: 2.73), controlPoint2: CGPoint(x: 1, y: 3.81))
+ $0.curve(to: CGPoint(x: 1.57, y: 7.06), controlPoint1: CGPoint(x: 1, y: 5.75), controlPoint2: CGPoint(x: 1.21, y: 6.46))
+ $0.curve(to: CGPoint(x: 2.08, y: 7.73), controlPoint1: CGPoint(x: 1.71, y: 7.3), controlPoint2: CGPoint(x: 1.89, y: 7.53))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 2.17, y: 7.83), controlPoint2: CGPoint(x: 2.26, y: 7.92))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.line(to: CGPoint(x: 3.54, y: 9.08))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.84, y: 9.55), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.65, y: 8), controlPoint1: CGPoint(x: 6.86, y: 8.52), controlPoint2: CGPoint(x: 7.59, y: 8.04))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 7.27), controlPoint2: CGPoint(x: 9, y: 6.19))
+ $0.curve(to: CGPoint(x: 7.65, y: 2), controlPoint1: CGPoint(x: 9, y: 3.81), controlPoint2: CGPoint(x: 8.48, y: 2.73))
+ $0.close()
+ }
+
+ static let templateLeftRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 8, y: 7.65))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 8.52, y: 3.14), controlPoint2: CGPoint(x: 8.04, y: 2.41))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 7.27, y: 1.52), controlPoint2: CGPoint(x: 6.19, y: 1))
+ $0.curve(to: CGPoint(x: 2.94, y: 1.57), controlPoint1: CGPoint(x: 4.25, y: 1), controlPoint2: CGPoint(x: 3.54, y: 1.21))
+ $0.curve(to: CGPoint(x: 2.27, y: 2.08), controlPoint1: CGPoint(x: 2.7, y: 1.71), controlPoint2: CGPoint(x: 2.47, y: 1.89))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 2.17, y: 2.17), controlPoint2: CGPoint(x: 2.08, y: 2.26))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 1.96, y: 2.41), controlPoint2: CGPoint(x: 1.48, y: 3.14))
+ $0.line(to: CGPoint(x: 0.92, y: 3.54))
+ $0.curve(to: CGPoint(x: 0, y: 3.8), controlPoint1: CGPoint(x: 0.45, y: 3.84), controlPoint2: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 6.2))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 0, y: 6.2), controlPoint2: CGPoint(x: 0.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 1.48, y: 6.86), controlPoint2: CGPoint(x: 1.96, y: 7.59))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 2.73, y: 8.48), controlPoint2: CGPoint(x: 3.81, y: 9))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 6.19, y: 9), controlPoint2: CGPoint(x: 7.27, y: 8.48))
+ $0.close()
+ }
+
+ // -
+
+ static let templateTopLeftRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 8.01), controlPoint1: CGPoint(x: 6.85, y: 8.53), controlPoint2: CGPoint(x: 7.55, y: 8.07))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 7.77, y: 7.89), controlPoint2: CGPoint(x: 7.89, y: 7.77))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 8.52, y: 3.14), controlPoint2: CGPoint(x: 8.04, y: 2.41))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 7.27, y: 1.52), controlPoint2: CGPoint(x: 6.19, y: 1))
+ $0.curve(to: CGPoint(x: 2.94, y: 1.57), controlPoint1: CGPoint(x: 4.25, y: 1), controlPoint2: CGPoint(x: 3.54, y: 1.21))
+ $0.curve(to: CGPoint(x: 2.27, y: 2.08), controlPoint1: CGPoint(x: 2.7, y: 1.71), controlPoint2: CGPoint(x: 2.47, y: 1.89))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 2.17, y: 2.17), controlPoint2: CGPoint(x: 2.08, y: 2.26))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 1.96, y: 2.41), controlPoint2: CGPoint(x: 1.48, y: 3.14))
+ $0.line(to: CGPoint(x: 0.92, y: 3.54))
+ $0.curve(to: CGPoint(x: 0, y: 3.8), controlPoint1: CGPoint(x: 0.45, y: 3.84), controlPoint2: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 6.2))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 0, y: 6.2), controlPoint2: CGPoint(x: 0.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 1.48, y: 6.86), controlPoint2: CGPoint(x: 1.96, y: 7.59))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 2.11, y: 7.77), controlPoint2: CGPoint(x: 2.23, y: 7.89))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.close()
+ }
+
+ static let templateLeftBottomRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 0))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 6.2, y: 0), controlPoint2: CGPoint(x: 6.15, y: 0.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 1.99), controlPoint1: CGPoint(x: 6.85, y: 1.47), controlPoint2: CGPoint(x: 7.55, y: 1.93))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 7.77, y: 2.11), controlPoint2: CGPoint(x: 7.89, y: 2.23))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 8.04, y: 2.41), controlPoint2: CGPoint(x: 8.52, y: 3.14))
+ $0.curve(to: CGPoint(x: 10, y: 3.8), controlPoint1: CGPoint(x: 9.5, y: 3.85), controlPoint2: CGPoint(x: 10, y: 3.8))
+ $0.line(to: CGPoint(x: 10, y: 6.2))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 10, y: 6.2), controlPoint2: CGPoint(x: 9.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 8.52, y: 6.86), controlPoint2: CGPoint(x: 8.04, y: 7.59))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 7.27, y: 8.48), controlPoint2: CGPoint(x: 6.19, y: 9))
+ $0.curve(to: CGPoint(x: 2.94, y: 8.43), controlPoint1: CGPoint(x: 4.25, y: 9), controlPoint2: CGPoint(x: 3.54, y: 8.79))
+ $0.curve(to: CGPoint(x: 2.27, y: 7.92), controlPoint1: CGPoint(x: 2.7, y: 8.29), controlPoint2: CGPoint(x: 2.47, y: 8.11))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 2.17, y: 7.83), controlPoint2: CGPoint(x: 2.08, y: 7.74))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 1.96, y: 7.59), controlPoint2: CGPoint(x: 1.48, y: 6.86))
+ $0.line(to: CGPoint(x: 0.92, y: 6.46))
+ $0.curve(to: CGPoint(x: 0, y: 6.2), controlPoint1: CGPoint(x: 0.45, y: 6.16), controlPoint2: CGPoint(x: 0, y: 6.2))
+ $0.line(to: CGPoint(x: 0, y: 3.8))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 0, y: 3.8), controlPoint2: CGPoint(x: 0.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 1.48, y: 3.14), controlPoint2: CGPoint(x: 1.96, y: 2.41))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 2.11, y: 2.23), controlPoint2: CGPoint(x: 2.23, y: 2.11))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 2.41, y: 1.96), controlPoint2: CGPoint(x: 3.14, y: 1.48))
+ $0.curve(to: CGPoint(x: 3.8, y: 0), controlPoint1: CGPoint(x: 3.85, y: 0.5), controlPoint2: CGPoint(x: 3.8, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.close()
+ }
+
+ static let templateTopRightBottom =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 10, y: 6.2))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 10, y: 6.2), controlPoint2: CGPoint(x: 9.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 8.01, y: 7.64), controlPoint1: CGPoint(x: 8.53, y: 6.85), controlPoint2: CGPoint(x: 8.07, y: 7.55))
+ $0.curve(to: CGPoint(x: 7.65, y: 8), controlPoint1: CGPoint(x: 7.89, y: 7.77), controlPoint2: CGPoint(x: 7.77, y: 7.89))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 7.59, y: 8.04), controlPoint2: CGPoint(x: 6.86, y: 8.52))
+ $0.curve(to: CGPoint(x: 6.2, y: 10), controlPoint1: CGPoint(x: 6.15, y: 9.5), controlPoint2: CGPoint(x: 6.2, y: 10))
+ $0.line(to: CGPoint(x: 3.8, y: 10))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 3.8, y: 10), controlPoint2: CGPoint(x: 3.85, y: 9.5))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 3.14, y: 8.52), controlPoint2: CGPoint(x: 2.41, y: 8.04))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 1.52, y: 7.27), controlPoint2: CGPoint(x: 1, y: 6.19))
+ $0.curve(to: CGPoint(x: 1.57, y: 2.94), controlPoint1: CGPoint(x: 1, y: 4.25), controlPoint2: CGPoint(x: 1.21, y: 3.54))
+ $0.curve(to: CGPoint(x: 2.08, y: 2.27), controlPoint1: CGPoint(x: 1.71, y: 2.7), controlPoint2: CGPoint(x: 1.89, y: 2.47))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 2.17, y: 2.17), controlPoint2: CGPoint(x: 2.26, y: 2.08))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 2.41, y: 1.96), controlPoint2: CGPoint(x: 3.14, y: 1.48))
+ $0.line(to: CGPoint(x: 3.54, y: 0.92))
+ $0.curve(to: CGPoint(x: 3.8, y: 0), controlPoint1: CGPoint(x: 3.84, y: 0.45), controlPoint2: CGPoint(x: 3.8, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 6.2, y: 0), controlPoint2: CGPoint(x: 6.15, y: 0.5))
+ $0.curve(to: CGPoint(x: 7.65, y: 2), controlPoint1: CGPoint(x: 6.86, y: 1.48), controlPoint2: CGPoint(x: 7.59, y: 1.96))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 7.77, y: 2.11), controlPoint2: CGPoint(x: 7.89, y: 2.23))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 8.04, y: 2.41), controlPoint2: CGPoint(x: 8.52, y: 3.14))
+ $0.curve(to: CGPoint(x: 10, y: 3.8), controlPoint1: CGPoint(x: 9.5, y: 3.85), controlPoint2: CGPoint(x: 10, y: 3.8))
+ $0.line(to: CGPoint(x: 10, y: 6.2))
+ $0.close()
+ }
+
+ static let templateTopLeftBottom =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 0, y: 6.2))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 0, y: 6.2), controlPoint2: CGPoint(x: 0.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 1.99, y: 7.64), controlPoint1: CGPoint(x: 1.47, y: 6.85), controlPoint2: CGPoint(x: 1.93, y: 7.55))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 2.11, y: 7.77), controlPoint2: CGPoint(x: 2.23, y: 7.89))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.65, y: 8), controlPoint1: CGPoint(x: 6.86, y: 8.52), controlPoint2: CGPoint(x: 7.59, y: 8.04))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 7.27), controlPoint2: CGPoint(x: 9, y: 6.19))
+ $0.curve(to: CGPoint(x: 8.43, y: 2.94), controlPoint1: CGPoint(x: 9, y: 4.25), controlPoint2: CGPoint(x: 8.79, y: 3.54))
+ $0.curve(to: CGPoint(x: 7.92, y: 2.27), controlPoint1: CGPoint(x: 8.29, y: 2.7), controlPoint2: CGPoint(x: 8.11, y: 2.47))
+ $0.curve(to: CGPoint(x: 7.65, y: 2), controlPoint1: CGPoint(x: 7.83, y: 2.17), controlPoint2: CGPoint(x: 7.74, y: 2.08))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 7.59, y: 1.96), controlPoint2: CGPoint(x: 6.86, y: 1.48))
+ $0.line(to: CGPoint(x: 6.46, y: 0.92))
+ $0.curve(to: CGPoint(x: 6.2, y: 0), controlPoint1: CGPoint(x: 6.16, y: 0.45), controlPoint2: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 3.8, y: 0))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 3.8, y: 0), controlPoint2: CGPoint(x: 3.85, y: 0.5))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 3.14, y: 1.48), controlPoint2: CGPoint(x: 2.41, y: 1.96))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 2.23, y: 2.11), controlPoint2: CGPoint(x: 2.11, y: 2.23))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 1.96, y: 2.41), controlPoint2: CGPoint(x: 1.48, y: 3.14))
+ $0.curve(to: CGPoint(x: 0, y: 3.8), controlPoint1: CGPoint(x: 0.5, y: 3.85), controlPoint2: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 6.2))
+ $0.close()
+ }
+
+
+ // -
+
+ static let templateTopLeftBottomRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 8.01), controlPoint1: CGPoint(x: 6.85, y: 8.53), controlPoint2: CGPoint(x: 7.55, y: 8.07))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 7.77, y: 7.89), controlPoint2: CGPoint(x: 7.89, y: 7.77))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 8.52, y: 3.14), controlPoint2: CGPoint(x: 8.04, y: 2.41))
+ $0.curve(to: CGPoint(x: 7.65, y: 2), controlPoint1: CGPoint(x: 7.89, y: 2.23), controlPoint2: CGPoint(x: 7.77, y: 2.11))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 7.59, y: 1.96), controlPoint2: CGPoint(x: 6.86, y: 1.48))
+ $0.curve(to: CGPoint(x: 6.2, y: 0), controlPoint1: CGPoint(x: 6.15, y: 0.5), controlPoint2: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 3.8, y: 0))
+ $0.curve(to: CGPoint(x: 3.54, y: 0.92), controlPoint1: CGPoint(x: 3.8, y: 0), controlPoint2: CGPoint(x: 3.84, y: 0.45))
+ $0.line(to: CGPoint(x: 3.49, y: 1))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 3.14, y: 1.48), controlPoint2: CGPoint(x: 2.41, y: 1.96))
+ $0.curve(to: CGPoint(x: 2.27, y: 2.08), controlPoint1: CGPoint(x: 2.35, y: 2), controlPoint2: CGPoint(x: 2.27, y: 2.08))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 2.17, y: 2.17), controlPoint2: CGPoint(x: 2.08, y: 2.26))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 1.96, y: 2.41), controlPoint2: CGPoint(x: 1.48, y: 3.14))
+ $0.curve(to: CGPoint(x: 0, y: 3.8), controlPoint1: CGPoint(x: 0.5, y: 3.85), controlPoint2: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 6.2))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 0, y: 6.2), controlPoint2: CGPoint(x: 0.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 1.48, y: 6.86), controlPoint2: CGPoint(x: 1.96, y: 7.59))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 2.11, y: 7.77), controlPoint2: CGPoint(x: 2.23, y: 7.89))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.close()
+ }
+
+ // -
+
+ static let templateTopLeft =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 8.01), controlPoint1: CGPoint(x: 6.85, y: 8.53), controlPoint2: CGPoint(x: 7.55, y: 8.07))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 7.27), controlPoint2: CGPoint(x: 9, y: 6.19))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 9, y: 2.79), controlPoint2: CGPoint(x: 7.21, y: 1))
+ $0.curve(to: CGPoint(x: 2.94, y: 1.57), controlPoint1: CGPoint(x: 4.25, y: 1), controlPoint2: CGPoint(x: 3.54, y: 1.21))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 2.59, y: 1.78), controlPoint2: CGPoint(x: 2.27, y: 2.05))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 1.96, y: 2.41), controlPoint2: CGPoint(x: 1.48, y: 3.14))
+ $0.curve(to: CGPoint(x: 0, y: 3.8), controlPoint1: CGPoint(x: 0.5, y: 3.85), controlPoint2: CGPoint(x: 0, y: 3.8))
+ $0.line(to: CGPoint(x: 0, y: 6.2))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 0, y: 6.2), controlPoint2: CGPoint(x: 0.5, y: 6.15))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 1.48, y: 6.86), controlPoint2: CGPoint(x: 1.96, y: 7.59))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 2.11, y: 7.77), controlPoint2: CGPoint(x: 2.23, y: 7.89))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.close()
+ }
+
+ static let templateTopRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8.01, y: 2.36), controlPoint1: CGPoint(x: 8.53, y: 3.15), controlPoint2: CGPoint(x: 8.07, y: 2.45))
+ $0.curve(to: CGPoint(x: 5, y: 1), controlPoint1: CGPoint(x: 7.27, y: 1.52), controlPoint2: CGPoint(x: 6.19, y: 1))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 2.79, y: 1), controlPoint2: CGPoint(x: 1, y: 2.79))
+ $0.curve(to: CGPoint(x: 1.57, y: 7.06), controlPoint1: CGPoint(x: 1, y: 5.75), controlPoint2: CGPoint(x: 1.21, y: 6.46))
+ $0.curve(to: CGPoint(x: 2.35, y: 8), controlPoint1: CGPoint(x: 1.78, y: 7.41), controlPoint2: CGPoint(x: 2.05, y: 7.73))
+ $0.curve(to: CGPoint(x: 3.49, y: 9), controlPoint1: CGPoint(x: 2.41, y: 8.04), controlPoint2: CGPoint(x: 3.14, y: 8.52))
+ $0.curve(to: CGPoint(x: 3.8, y: 10), controlPoint1: CGPoint(x: 3.85, y: 9.5), controlPoint2: CGPoint(x: 3.8, y: 10))
+ $0.line(to: CGPoint(x: 6.2, y: 10))
+ $0.curve(to: CGPoint(x: 6.51, y: 9), controlPoint1: CGPoint(x: 6.2, y: 10), controlPoint2: CGPoint(x: 6.15, y: 9.5))
+ $0.curve(to: CGPoint(x: 7.65, y: 8), controlPoint1: CGPoint(x: 6.86, y: 8.52), controlPoint2: CGPoint(x: 7.59, y: 8.04))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 7.77, y: 7.89), controlPoint2: CGPoint(x: 7.89, y: 7.77))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.close()
+ }
+
+ static let templateBottomLeft =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 6.2, y: 0))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 6.2, y: 0), controlPoint2: CGPoint(x: 6.15, y: 0.5))
+ $0.curve(to: CGPoint(x: 7.64, y: 1.99), controlPoint1: CGPoint(x: 6.85, y: 1.47), controlPoint2: CGPoint(x: 7.55, y: 1.93))
+ $0.curve(to: CGPoint(x: 9, y: 5), controlPoint1: CGPoint(x: 8.48, y: 2.73), controlPoint2: CGPoint(x: 9, y: 3.81))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 9, y: 7.21), controlPoint2: CGPoint(x: 7.21, y: 9))
+ $0.curve(to: CGPoint(x: 2.94, y: 8.43), controlPoint1: CGPoint(x: 4.25, y: 9), controlPoint2: CGPoint(x: 3.54, y: 8.79))
+ $0.curve(to: CGPoint(x: 2, y: 7.65), controlPoint1: CGPoint(x: 2.59, y: 8.22), controlPoint2: CGPoint(x: 2.27, y: 7.95))
+ $0.curve(to: CGPoint(x: 1, y: 6.51), controlPoint1: CGPoint(x: 1.96, y: 7.59), controlPoint2: CGPoint(x: 1.48, y: 6.86))
+ $0.curve(to: CGPoint(x: 0, y: 6.2), controlPoint1: CGPoint(x: 0.5, y: 6.15), controlPoint2: CGPoint(x: 0, y: 6.2))
+ $0.line(to: CGPoint(x: 0, y: 3.8))
+ $0.curve(to: CGPoint(x: 1, y: 3.49), controlPoint1: CGPoint(x: 0, y: 3.8), controlPoint2: CGPoint(x: 0.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 2, y: 2.35), controlPoint1: CGPoint(x: 1.48, y: 3.14), controlPoint2: CGPoint(x: 1.96, y: 2.41))
+ $0.curve(to: CGPoint(x: 2.35, y: 2), controlPoint1: CGPoint(x: 2.11, y: 2.23), controlPoint2: CGPoint(x: 2.23, y: 2.11))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 2.41, y: 1.96), controlPoint2: CGPoint(x: 3.14, y: 1.48))
+ $0.curve(to: CGPoint(x: 3.8, y: 0), controlPoint1: CGPoint(x: 3.85, y: 0.5), controlPoint2: CGPoint(x: 3.8, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 6.2, y: 0))
+ $0.close()
+ }
+
+ static let templateBottomRight =
+ CGPath.make {
+ $0.move(to: CGPoint(x: 3.8, y: 0))
+ $0.curve(to: CGPoint(x: 3.49, y: 1), controlPoint1: CGPoint(x: 3.8, y: 0), controlPoint2: CGPoint(x: 3.85, y: 0.5))
+ $0.curve(to: CGPoint(x: 2.36, y: 1.99), controlPoint1: CGPoint(x: 3.15, y: 1.47), controlPoint2: CGPoint(x: 2.45, y: 1.93))
+ $0.curve(to: CGPoint(x: 1, y: 5), controlPoint1: CGPoint(x: 1.52, y: 2.73), controlPoint2: CGPoint(x: 1, y: 3.81))
+ $0.curve(to: CGPoint(x: 5, y: 9), controlPoint1: CGPoint(x: 1, y: 7.21), controlPoint2: CGPoint(x: 2.79, y: 9))
+ $0.curve(to: CGPoint(x: 7.06, y: 8.43), controlPoint1: CGPoint(x: 5.75, y: 9), controlPoint2: CGPoint(x: 6.46, y: 8.79))
+ $0.curve(to: CGPoint(x: 8, y: 7.65), controlPoint1: CGPoint(x: 7.41, y: 8.22), controlPoint2: CGPoint(x: 7.73, y: 7.95))
+ $0.curve(to: CGPoint(x: 9, y: 6.51), controlPoint1: CGPoint(x: 8.04, y: 7.59), controlPoint2: CGPoint(x: 8.52, y: 6.86))
+ $0.curve(to: CGPoint(x: 10, y: 6.2), controlPoint1: CGPoint(x: 9.5, y: 6.15), controlPoint2: CGPoint(x: 10, y: 6.2))
+ $0.line(to: CGPoint(x: 10, y: 3.8))
+ $0.curve(to: CGPoint(x: 9, y: 3.49), controlPoint1: CGPoint(x: 10, y: 3.8), controlPoint2: CGPoint(x: 9.5, y: 3.85))
+ $0.curve(to: CGPoint(x: 8, y: 2.35), controlPoint1: CGPoint(x: 8.52, y: 3.14), controlPoint2: CGPoint(x: 8.04, y: 2.41))
+ $0.curve(to: CGPoint(x: 7.65, y: 2), controlPoint1: CGPoint(x: 7.89, y: 2.23), controlPoint2: CGPoint(x: 7.77, y: 2.11))
+ $0.curve(to: CGPoint(x: 6.51, y: 1), controlPoint1: CGPoint(x: 7.59, y: 1.96), controlPoint2: CGPoint(x: 6.86, y: 1.48))
+ $0.curve(to: CGPoint(x: 6.2, y: 0), controlPoint1: CGPoint(x: 6.15, y: 0.5), controlPoint2: CGPoint(x: 6.2, y: 0))
+ $0.line(to: CGPoint(x: 3.8, y: 0))
+ $0.line(to: CGPoint(x: 3.8, y: 0))
+ $0.close()
+ }
+}
diff --git a/Sources/QRCode/styles/data/QRCodePixelShapeFactory.swift b/Sources/QRCode/styles/data/QRCodePixelShapeFactory.swift
index 1ac1da9a..ed7f31e9 100644
--- a/Sources/QRCode/styles/data/QRCodePixelShapeFactory.swift
+++ b/Sources/QRCode/styles/data/QRCodePixelShapeFactory.swift
@@ -80,6 +80,7 @@ import Foundation
QRCode.PixelShape.Shiny.self,
QRCode.PixelShape.CRT.self,
QRCode.PixelShape.Blob.self,
+ QRCode.PixelShape.Circuit.self,
].sorted(by: { a, b in a.Title < b.Title })
/// The default matrix to use when generating pixel sample images
diff --git a/Tests/QRCodeTests/QRCodeDocGenerator.swift b/Tests/QRCodeTests/QRCodeDocGenerator.swift
index 3a7ced16..e5e5248a 100644
--- a/Tests/QRCodeTests/QRCodeDocGenerator.swift
+++ b/Tests/QRCodeTests/QRCodeDocGenerator.swift
@@ -92,8 +92,8 @@ final class QRCodeDocGeneratorTests: XCTestCase {
markdownText += "### Samples\n\n"
- markdownText += "| | L | M | Q | H | SVG | neg |\n"
- markdownText += "|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|\n"
+ markdownText += "| | L | M | Q | H | SVG | PDF | neg |\n"
+ markdownText += "|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|\n"
doc.design.style.onPixels = .solid(0.6, 0, 0)
doc.design.style.eye = .solid(0, 0, 0)
@@ -127,6 +127,13 @@ final class QRCodeDocGeneratorTests: XCTestCase {
markdownText += "
⚖️|"
}
+ do {
+ let pdf = try doc.pdfData(dimension: dimension)
+ let filename = "pixelint - \(name).pdf"
+ let link = try imageStore.store(pdf, filename: filename)
+ markdownText += "
⚖️|"
+ }
+
do {
doc.design.shape.negatedOnPixelsOnly = true
let inverted = try doc.pdfData(dimension: dimension)
@@ -148,8 +155,8 @@ final class QRCodeDocGeneratorTests: XCTestCase {
markdownText += "## Pixel Shapes (3rd party Generator)\n\n"
- markdownText += "| | L | M | Q | H | SVG | neg |\n"
- markdownText += "|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|\n"
+ markdownText += "| | L | M | Q | H | SVG | PDF | neg |\n"
+ markdownText += "|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|\n"
let names = QRCodePixelShapeFactory.shared.availableGeneratorNames.sorted()
for name in names {
@@ -178,6 +185,14 @@ final class QRCodeDocGeneratorTests: XCTestCase {
let link = try imageStore.store(svgImage, filename: filename)
markdownText += "
⚖️|"
}
+
+ do {
+ let pdf = try doc.pdfData(dimension: dimension)
+ let filename = "pixelext - \(name).pdf"
+ let link = try imageStore.store(pdf, filename: filename)
+ markdownText += "
⚖️|"
+ }
+
do {
doc.design.shape.negatedOnPixelsOnly = true
let inverted = try doc.pdfData(dimension: dimension)