Skip to content

Commit

Permalink
Added teardrop eye/pupil shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
dagronf committed Apr 19, 2024
1 parent d72e23a commit 18e65c2
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 15 deletions.
Binary file added Art/images/eye_teardrop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Art/images/pupil_teardrop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Art/paths.pcvd
Binary file not shown.
30 changes: 16 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,20 +276,21 @@ square, circle, rounded rectangle, and more.

| Preview | Name | Class | Description |
|:---:|---|---|---|
|<img src="./Art/images/eye_square.png" width="60"/> |"square"|`QRCode.EyeShape.Square`|Simple square (default)|
|<img src="./Art/images/eye_circle.png" width="60"/> |"circle"|`QRCode.EyeShape.Circle`|Simple circle|
|<img src="./Art/images/eye_roundedRect.png" width="60"/> |"roundedRect"|`QRCode.EyeShape.RoundedRect`|Simple rounded rect|
|<img src="./Art/images/eye_roundedouter.png" width="60"/> |"roundedOuter"|`QRCode.EyeShape.RoundedOuter`|Square with the outer corner rounded|
|<img src="./Art/images/eye_roundedpointingin.png" width="60"/> |"roundedPointingIn"|`QRCode.EyeShape.RoundedPointingIn`|A rounded rect with the 'inner' corner as a point|
|<img src="./Art/images/eye_leaf.png" width="60"/> |"leaf"|`QRCode.EyeShape.Leaf`|An eye that look like a leaf|
|<img src="./Art/images/eye_squircle.png" width="60"/> |"squircle"|`QRCode.EyeShape.Squircle`|A superellipse shape (somewhere between a square and a circle)|
|<img src="./Art/images/eye_barsHorizontal.png" width="60"/> |"barsHorizontal"|`QRCode.EyeShape.BarsHorizontal`|Simple rounded rect with three horizontal bars as the pupil|
|<img src="./Art/images/eye_barsVertical.png" width="60"/> |"barsVertical"|`QRCode.EyeShape.BarsVertical`| Simple rounded rect with three vertical bars as the pupil|
|<img src="./Art/images/eye_pixels.png" width="60"/> |"pixels"|`QRCode.EyeShape.Pixels`| A simple collection of pixels with configurable corner radius for each pixel|
|<img src="./Art/images/eye_corneredPixels.png" width="60"/> |"corneredPixels"|`QRCode.EyeShape.CorneredPixels`| A simple collection of pixels with configurable corner radius for the entire shape|
|<img src="./Art/images/eye_edges.png" width="60"/> |"edges"|`QRCode.EyeShape.Edges`| Simple bordered bars with a configurable corner radius |
|<img src="./Art/images/eye_shield.png" width="60"/> |"shield"|`QRCode.EyeShape.Shield`| A shield with configurable corners |
| |"usePixelShape"|`QRCode.EyeShape.UsePixelShape`| Use the pattern of the `onPixels` generator when drawing the eyes |
|<img src="./Art/images/eye_square.png" width="60"/> | "square" |`QRCode.EyeShape.Square`|Simple square (default)|
|<img src="./Art/images/eye_circle.png" width="60"/> | "circle" |`QRCode.EyeShape.Circle`|Simple circle|
|<img src="./Art/images/eye_roundedRect.png" width="60"/> | "roundedRect" |`QRCode.EyeShape.RoundedRect`|Simple rounded rect|
|<img src="./Art/images/eye_roundedouter.png" width="60"/> | "roundedOuter" |`QRCode.EyeShape.RoundedOuter`|Square with the outer corner rounded|
|<img src="./Art/images/eye_roundedpointingin.png" width="60"/> | "roundedPointingIn" |`QRCode.EyeShape.RoundedPointingIn`|A rounded rect with the 'inner' corner as a point|
|<img src="./Art/images/eye_leaf.png" width="60"/> | "leaf" |`QRCode.EyeShape.Leaf`|An eye that look like a leaf|
|<img src="./Art/images/eye_squircle.png" width="60"/> | "squircle" |`QRCode.EyeShape.Squircle`|A superellipse shape (somewhere between a square and a circle)|
|<img src="./Art/images/eye_barsHorizontal.png" width="60"/> | "barsHorizontal" |`QRCode.EyeShape.BarsHorizontal`|Simple rounded rect with three horizontal bars as the pupil|
|<img src="./Art/images/eye_barsVertical.png" width="60"/> | "barsVertical" |`QRCode.EyeShape.BarsVertical`| Simple rounded rect with three vertical bars as the pupil|
|<img src="./Art/images/eye_pixels.png" width="60"/> | "pixels" |`QRCode.EyeShape.Pixels`| A simple collection of pixels with configurable corner radius for each pixel|
|<img src="./Art/images/eye_corneredPixels.png" width="60"/> | "corneredPixels" |`QRCode.EyeShape.CorneredPixels`| A simple collection of pixels with configurable corner radius for the entire shape|
|<img src="./Art/images/eye_edges.png" width="60"/> | "edges" |`QRCode.EyeShape.Edges`| Simple bordered bars with a configurable corner radius |
|<img src="./Art/images/eye_shield.png" width="60"/> | "shield" |`QRCode.EyeShape.Shield`| A shield with configurable corners |
|<img src="./Art/images/eye_teardrop.png" width="60" /> | "teardrop" |`QRCode.EyeShape.Teardrop` | A teardrop shape |
| | "usePixelShape" |`QRCode.EyeShape.UsePixelShape`| Use the pattern of the `onPixels` generator when drawing the eyes |

#### Custom Pupil shape (optional)

Expand All @@ -315,6 +316,7 @@ If you don't override the pupil shape, it defaults to the eye shape's pupil shap
|<img src="./Art/images/pupil_hexagonLeaf.png" width="30" /> |"hexagonLeaf"|`QRCode.PixelShape.HexagonLeaf` | A hexagonal leaf shape |
|<img src="./Art/images/pupil_seal.png" width="30" /> |"seal"|`QRCode.PixelShape.Seal` | A seal leaf shape |
|<img src="./Art/images/pupil_blobby.png" width="30" /> |"blobby"|`QRCode.PixelShape.Blobby` | A blobby shape |
|<img src="./Art/images/pupil_teardrop.png" width="30" /> |"teardrop"|`QRCode.PixelShape.Teardrop` | A teardrop shape |
| |"usePixelShape"|`QRCode.PupilShape.UsePixelShape`| Use the pattern of the `onPixels` generator when drawing the pupils |

<details>
Expand Down
3 changes: 2 additions & 1 deletion Sources/QRCode/styles/eye/QRCodeEyeShapeFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import Foundation
QRCode.EyeShape.CorneredPixels.self,
QRCode.EyeShape.RoundedPointingOut.self,
QRCode.EyeShape.Shield.self,
QRCode.EyeShape.UsePixelShape.self
QRCode.EyeShape.UsePixelShape.self,
QRCode.EyeShape.Teardrop.self,
].sorted(by: { a, b in a.Title < b.Title })
super.init()
}
Expand Down
77 changes: 77 additions & 0 deletions Sources/QRCode/styles/eye/QRCodeEyeShapeTeardrop.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// QRCodeEyeShapeTeardrop.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 CoreGraphics
import Foundation

public extension QRCode.EyeShape {
/// A 'Teardrop' style eye design
@objc(QRCodeEyeShapeTeardrop) class Teardrop: NSObject, QRCodeEyeShapeGenerator {
@objc public static let Name = "teardrop"
@objc public static var Title: String { "Teardrop" }
@objc public static func Create(_ settings: [String: Any]?) -> QRCodeEyeShapeGenerator {
return QRCode.EyeShape.Teardrop()
}

@objc public func settings() -> [String: Any] { return [:] }
@objc public func supportsSettingValue(forKey key: String) -> Bool { false }
@objc public func setSettingValue(_ value: Any?, forKey key: String) -> Bool { false }

/// Make a copy of the object
@objc public func copyShape() -> QRCodeEyeShapeGenerator {
return Self.Create(self.settings())
}

public func eyePath() -> CGPath {
let eyeShapePath = CGMutablePath()
eyeShapePath.move(to: CGPoint(x: 45, y: 70))
eyeShapePath.curve(to: CGPoint(x: 20, y: 45), controlPoint1: CGPoint(x: 31.19, y: 70), controlPoint2: CGPoint(x: 20, y: 58.81))
eyeShapePath.line(to: CGPoint(x: 20, y: 20))
eyeShapePath.line(to: CGPoint(x: 45, y: 20))
eyeShapePath.curve(to: CGPoint(x: 70, y: 45), controlPoint1: CGPoint(x: 58.81, y: 20), controlPoint2: CGPoint(x: 70, y: 31.19))
eyeShapePath.curve(to: CGPoint(x: 45, y: 70), controlPoint1: CGPoint(x: 70, y: 58.81), controlPoint2: CGPoint(x: 58.81, y: 70))
eyeShapePath.close()
eyeShapePath.move(to: CGPoint(x: 80, y: 45))
eyeShapePath.curve(to: CGPoint(x: 45, y: 10), controlPoint1: CGPoint(x: 80, y: 25.67), controlPoint2: CGPoint(x: 64.33, y: 10))
eyeShapePath.line(to: CGPoint(x: 10, y: 10))
eyeShapePath.line(to: CGPoint(x: 10, y: 45))
eyeShapePath.curve(to: CGPoint(x: 45, y: 80), controlPoint1: CGPoint(x: 10, y: 64.33), controlPoint2: CGPoint(x: 25.67, y: 80))
eyeShapePath.curve(to: CGPoint(x: 80, y: 45), controlPoint1: CGPoint(x: 64.33, y: 80), controlPoint2: CGPoint(x: 80, y: 64.33))
eyeShapePath.close()
return eyeShapePath
}

public func eyeBackgroundPath() -> CGPath {
let eyeBackgroundPath = CGMutablePath()
eyeBackgroundPath.move(to: CGPoint(x: 90, y: 45))
eyeBackgroundPath.curve(to: CGPoint(x: 45, y: 0), controlPoint1: CGPoint(x: 90, y: 20.15), controlPoint2: CGPoint(x: 69.85, y: 0))
eyeBackgroundPath.line(to: CGPoint(x: 0, y: 0))
eyeBackgroundPath.line(to: CGPoint(x: 0, y: 45))
eyeBackgroundPath.curve(to: CGPoint(x: 45, y: 90), controlPoint1: CGPoint(x: 0, y: 69.85), controlPoint2: CGPoint(x: 20.15, y: 90))
eyeBackgroundPath.curve(to: CGPoint(x: 90, y: 45), controlPoint1: CGPoint(x: 69.85, y: 90), controlPoint2: CGPoint(x: 90, y: 69.85))
eyeBackgroundPath.close()
return eyeBackgroundPath
}

private static let _defaultPupil = QRCode.PupilShape.Teardrop()
public func defaultPupil() -> QRCodePupilShapeGenerator { Self._defaultPupil }
}
}
1 change: 1 addition & 0 deletions Sources/QRCode/styles/pupil/QRCodePupilShapeFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import CoreGraphics
QRCode.PupilShape.HexagonLeaf.self,
QRCode.PupilShape.Seal.self,
QRCode.PupilShape.Blobby.self,
QRCode.PupilShape.Teardrop.self,
].sorted(by: { a, b in a.Title < b.Title })
super.init()
}
Expand Down
57 changes: 57 additions & 0 deletions Sources/QRCode/styles/pupil/QRCodePupilShapeTeardrop.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// QRCodePupilShapeTeardrop.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 CoreGraphics
import Foundation

// MARK: - Pupil shape

public extension QRCode.PupilShape {
/// A 'Teardrop' style pupil design
@objc(QRCodePupilShapeTeardrop) class Teardrop: NSObject, QRCodePupilShapeGenerator {
@objc public static var Name: String { "teardrop" }
/// The generator title
@objc public static var Title: String { "Teardrop" }
@objc public static func Create(_ settings: [String : Any]?) -> QRCodePupilShapeGenerator {
Teardrop()
}

/// Make a copy of the object
@objc public func copyShape() -> QRCodePupilShapeGenerator { Teardrop() }

@objc public func settings() -> [String : Any] { [:] }
@objc public func supportsSettingValue(forKey key: String) -> Bool { false }
@objc public func setSettingValue(_ value: Any?, forKey key: String) -> Bool { false }

/// The pupil centered in the 90x90 square
@objc public func pupilPath() -> CGPath {
let pupilPath = CGMutablePath()
pupilPath.move(to: CGPoint(x: 60, y: 45))
pupilPath.curve(to: CGPoint(x: 45, y: 30), controlPoint1: CGPoint(x: 60, y: 36.72), controlPoint2: CGPoint(x: 53.28, y: 30))
pupilPath.line(to: CGPoint(x: 30, y: 30))
pupilPath.line(to: CGPoint(x: 30, y: 45))
pupilPath.curve(to: CGPoint(x: 45, y: 60), controlPoint1: CGPoint(x: 30, y: 53.28), controlPoint2: CGPoint(x: 36.72, y: 60))
pupilPath.curve(to: CGPoint(x: 60, y: 45), controlPoint1: CGPoint(x: 53.28, y: 60), controlPoint2: CGPoint(x: 60, y: 53.28))
pupilPath.close()
return pupilPath
}
}
}

0 comments on commit 18e65c2

Please sign in to comment.