Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add patternType #163

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
10 changes: 10 additions & 0 deletions EFQRCode.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
D2FAEBB92749720F00DFA959 /* EFPointStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FAEBB72749720F00DFA959 /* EFPointStyle.swift */; };
D2FAEBBA2749720F00DFA959 /* EFPointStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FAEBB72749720F00DFA959 /* EFPointStyle.swift */; };
D2FAEBBB2749720F00DFA959 /* EFPointStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FAEBB72749720F00DFA959 /* EFPointStyle.swift */; };
D53C7D102CB1402100C2A40A /* EFPointPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */; };
D53C7D112CB1402100C2A40A /* EFPointPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */; };
D53C7D122CB1402100C2A40A /* EFPointPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */; };
D53C7D132CB1402100C2A40A /* EFPointPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */; };
F829C6B81A7A94F100A2CD59 /* EFQRCode.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DD67C0B1A5C55C900ED2280 /* EFQRCode.framework */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -178,6 +182,7 @@
D2DF1DB7256EC4CF00EB6012 /* European SEPA Money Transfer + Watermark.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "European SEPA Money Transfer + Watermark.playground"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
D2DF1DB8256EC4CF00EB6012 /* Basic B&W QR Code.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "Basic B&W QR Code.playground"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
D2FAEBB72749720F00DFA959 /* EFPointStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EFPointStyle.swift; sourceTree = "<group>"; };
D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EFPointPatternType.swift; sourceTree = "<group>"; };
F8111E3319A95C8B0040E7D1 /* EFQRCode.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = EFQRCode.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F8111E3719A95C8B0040E7D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F8111E3E19A95C8B0040E7D1 /* EFQRCode iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "EFQRCode iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -261,6 +266,7 @@
12C0B701219C102C000545C9 /* EFIntSize.swift */,
12C0B706219C1046000545C9 /* EFInputCorrectionLevel.swift */,
D2FAEBB72749720F00DFA959 /* EFPointStyle.swift */,
D53C7D0F2CB1402100C2A40A /* EFPointPatternType.swift */,
12C0B6F2219C0F7D000545C9 /* EFQRCodeMode.swift */,
12C0B6FC219C0FD3000545C9 /* EFUIntPixel.swift */,
12664E9A1FA9CEAB00D56500 /* EFWatermarkMode.swift */,
Expand Down Expand Up @@ -722,6 +728,7 @@
12EE9E3C23863D6E00241C60 /* UIImage+.swift in Sources */,
12664ED11FA9CEDD00D56500 /* EFQRCode.swift in Sources */,
12EE9E502386968F00241C60 /* NSColor+.swift in Sources */,
D53C7D122CB1402100C2A40A /* EFPointPatternType.swift in Sources */,
12664EB81FA9CED100D56500 /* CIImage+.swift in Sources */,
12C0B704219C102C000545C9 /* EFIntSize.swift in Sources */,
12C0B709219C1046000545C9 /* EFInputCorrectionLevel.swift in Sources */,
Expand Down Expand Up @@ -760,6 +767,7 @@
12EE9E3B23863D6E00241C60 /* UIImage+.swift in Sources */,
12664ED01FA9CEDD00D56500 /* EFQRCode.swift in Sources */,
12EE9E4F2386968F00241C60 /* NSColor+.swift in Sources */,
D53C7D112CB1402100C2A40A /* EFPointPatternType.swift in Sources */,
12664EB71FA9CED100D56500 /* CIImage+.swift in Sources */,
12C0B703219C102C000545C9 /* EFIntSize.swift in Sources */,
12C0B708219C1046000545C9 /* EFInputCorrectionLevel.swift in Sources */,
Expand Down Expand Up @@ -789,6 +797,7 @@
D2265578256EA35600920D11 /* EFQRCode+ObjC.swift in Sources */,
12EE9E3D23863D6E00241C60 /* UIImage+.swift in Sources */,
5282BCBD1FF3903D00DFB36B /* EFQRCodeGenerator.swift in Sources */,
D53C7D132CB1402100C2A40A /* EFPointPatternType.swift in Sources */,
12EE9E512386968F00241C60 /* NSColor+.swift in Sources */,
5282BCB51FF3903D00DFB36B /* EFWatermarkMode.swift in Sources */,
5282BCB71FF3903D00DFB36B /* CGImage+.swift in Sources */,
Expand Down Expand Up @@ -818,6 +827,7 @@
12EE9E3A23863D6E00241C60 /* UIImage+.swift in Sources */,
12664ECF1FA9CEDD00D56500 /* EFQRCode.swift in Sources */,
12EE9E4E2386968F00241C60 /* NSColor+.swift in Sources */,
D53C7D102CB1402100C2A40A /* EFPointPatternType.swift in Sources */,
12664EB61FA9CED100D56500 /* CIImage+.swift in Sources */,
12C0B702219C102C000545C9 /* EFIntSize.swift in Sources */,
12C0B707219C1046000545C9 /* EFInputCorrectionLevel.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Examples/Shared/PointStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import EFQRCode
import CoreGraphics

class StarPointStyle: EFPointStyle {
func fillRect(context: CGContext, rect: CGRect, isStatic: Bool) {
func fillRect(context: CGContext, rect: CGRect, patternType: EFPointPatternType) {
let path = CGMutablePath()
var points: [CGPoint] = []
let radius = Float(rect.width / 2)
Expand Down
32 changes: 32 additions & 0 deletions Source/EFPointPatternType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// EFPointPatternType.swift
// EFQRCode
//
// Created by Henry on 05/10/2024.
// Copyright © 2024 EyreFree. All rights reserved.
//

import Foundation

@objc public enum EFPointPatternType: Int {
case none = 0

// Empty border
case border

// Timing pattern
case timing

// Alignment pattern
case alignment

// Finder pattern markers
case finderTopLeftInner
case finderTopLeftOuter

case finderTopRightInner
case finderTopRightOuter

case finderBottomLeftInner
case finderBottomLeftOuter
}
14 changes: 7 additions & 7 deletions Source/EFPointStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ import CoreGraphics
/// - Parameters:
/// - context: the context to draw in.
/// - rect: the boundaries of the point to draw.
/// - isStatic: true if it is recommended to use a square instead of current style.
func fillRect(context: CGContext, rect: CGRect, isStatic: Bool)
/// - patternType: the type of static point being drawn, it is recommended to use a square if the pattern is not `.none`
func fillRect(context: CGContext, rect: CGRect, patternType: EFPointPatternType)
}

/// Drawing classical look and feel QR code foreground points 🔳.
@objc public class EFSquarePointStyle: NSObject, EFPointStyle {
public func fillRect(context: CGContext, rect: CGRect, isStatic: Bool) {
public func fillRect(context: CGContext, rect: CGRect, patternType: EFPointPatternType) {
context.fill(rect)
}
}

/// Drawing rounded foreground points 🔘.
@objc public class EFCirclePointStyle: NSObject, EFPointStyle {
public func fillRect(context: CGContext, rect: CGRect, isStatic: Bool) {
if isStatic {
public func fillRect(context: CGContext, rect: CGRect, patternType: EFPointPatternType) {
if patternType != .none {
context.fill(rect)
} else {
context.fillEllipse(in: rect)
Expand All @@ -57,8 +57,8 @@ import CoreGraphics

/// Drawing Sparkling foreground points ✨.
@objc public class EFDiamondPointStyle: NSObject, EFPointStyle {
public func fillRect(context: CGContext, rect: CGRect, isStatic: Bool) {
if isStatic {
public func fillRect(context: CGContext, rect: CGRect, patternType: EFPointPatternType) {
if patternType != .none {
context.fill(rect)
} else {
fillDiamond(context: context, rect: rect)
Expand Down
58 changes: 39 additions & 19 deletions Source/EFQRCodeGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,13 @@ public class EFQRCodeGenerator: NSObject {
size: EFIntSize
) -> CGImage? {
let codeSize = codes.count

let scaleX = size.width.cgFloat / CGFloat(codeSize)
let scaleY = size.height.cgFloat / CGFloat(codeSize)
if scaleX < 1.0 || scaleY < 1.0 {
print("Warning: Size too small.")
}

var points = [CGPoint]()
if let locations = getAlignmentPatternLocations(version: getVersion(size: codeSize - 2)) {
for indexX in locations {
Expand All @@ -608,8 +608,8 @@ public class EFQRCodeGenerator: NSObject {
// CTM-90
let indexXCTM = indexY
let indexYCTM = codeSize - indexX - 1
let isStaticPoint = isStatic(x: indexX, y: indexY, size: codeSize, APLPoints: points)

let patternType = patternTypeFor(x: indexX, y: indexY, size: codeSize, APLPoints: points)

drawPoint(
context: context,
Expand All @@ -619,7 +619,7 @@ public class EFQRCodeGenerator: NSObject {
width: scaleX - 2 * pointOffset,
height: scaleY - 2 * pointOffset
),
isStatic: isStaticPoint
patternType: patternType
)
}
}
Expand Down Expand Up @@ -690,7 +690,9 @@ public class EFQRCodeGenerator: NSObject {
// CTM-90
let indexXCTM = indexY
let indexYCTM = codeSize - indexX - 1
if isStatic(x: indexX, y: indexY, size: codeSize, APLPoints: points) {
let patternType = patternTypeFor(x: indexX, y: indexY, size: codeSize, APLPoints: points)

if patternType != .none {
drawPoint(
context: context,
rect: CGRect(
Expand All @@ -699,7 +701,7 @@ public class EFQRCodeGenerator: NSObject {
width: pointWidthOriX,
height: pointWidthOriY
),
isStatic: true
patternType: patternType
)
} else {
drawPoint(
Expand All @@ -721,7 +723,9 @@ public class EFQRCodeGenerator: NSObject {
// CTM-90
let indexXCTM = indexY
let indexYCTM = codeSize - indexX - 1
if isStatic(x: indexX, y: indexY, size: codeSize, APLPoints: points) {
let patternType = patternTypeFor(x: indexX, y: indexY, size: codeSize, APLPoints: points)

if patternType != .none {
drawPoint(
context: context,
rect: CGRect(
Expand All @@ -730,7 +734,7 @@ public class EFQRCodeGenerator: NSObject {
width: pointWidthOriX - 2 * pointOffset,
height: pointWidthOriY - 2 * pointOffset
),
isStatic: true
patternType: patternType
)
} else {
drawPoint(
Expand Down Expand Up @@ -812,9 +816,9 @@ public class EFQRCodeGenerator: NSObject {
)
)
}
private func drawPoint(context: CGContext, rect: CGRect, isStatic: Bool = false) {
pointStyle.fillRect(context: context, rect: rect, isStatic: isStatic)

private func drawPoint(context: CGContext, rect: CGRect, patternType: EFPointPatternType = .none) {
pointStyle.fillRect(context: context, rect: rect, patternType: patternType)
}

private func createContext(size: EFIntSize) -> CGContext? {
Expand Down Expand Up @@ -886,22 +890,38 @@ public class EFQRCodeGenerator: NSObject {
return imageCodes
}

/// Special Points of QRCode
private func isStatic(x: Int, y: Int, size: Int, APLPoints: [CGPoint]) -> Bool {
private func patternTypeFor(x: Int, y: Int, size: Int, APLPoints: [CGPoint]) -> EFPointPatternType {
// Empty border
if x == 0 || y == 0 || x == (size - 1) || y == (size - 1) {
return true
return .border
}

// Finder Patterns
if (x <= 8 && y <= 8) || (x <= 8 && y >= (size - 9)) || (x >= (size - 9) && y <= 8) {
return true
if (x <= 8 && y <= 8) {
if 2...6 ~= x && 2...6 ~= y {
return .finderTopLeftInner
}
return .finderTopLeftOuter
}

if (x <= 8 && y >= (size - 9)) {
if 2...6 ~= x && (size - 7)...(size - 4) ~= y {
return .finderTopRightInner
}
return .finderTopRightOuter
}

if (x >= (size - 9) && y <= 8) {
if (size - 7)...(size - 4) ~= x && 2...6 ~= y {
return .finderBottomLeftInner
}
return .finderBottomLeftOuter
}

if isTimingPointStatic {
// Timing Patterns
if x == 7 || y == 7 {
return true
return .timing
}
}

Expand All @@ -911,7 +931,7 @@ public class EFQRCodeGenerator: NSObject {
&& x <= Int(point.x + 2)
&& y >= Int(point.y - 2)
&& y <= Int(point.y + 2)
}
} ? .alignment : .none
}

/// [Alignment Pattern Locations](
Expand Down