-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from cocoatype/1-generate-images-for-some-codes
Generate strip images for unsupported barcodes
- Loading branch information
Showing
40 changed files
with
1,064 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import Foundation | ||
|
||
struct Bundler { | ||
func bundle(pass: Pass, manifest: Manifest, files: StaticFiles) async throws -> Data { | ||
func bundle(pass: Pass, manifest: Manifest, files: StaticFiles, stripImages: [StripImage]) async throws -> Data { | ||
let bundleID = UUID() | ||
let bundleDirectory = URL.temporaryDirectory.appending(path: bundleID.uuidString) | ||
|
||
|
@@ -23,6 +23,22 @@ struct Bundler { | |
try files.iconAt2xData.write(to: bundleDirectory.appending(path: "[email protected]")) | ||
try files.iconAt3xData.write(to: bundleDirectory.appending(path: "[email protected]")) | ||
|
||
func stripImage(forZoomLevel zoomLevel: Int) -> StripImage? { | ||
stripImages.first(where: { $0.zoomLevel == zoomLevel }) | ||
} | ||
|
||
if let stripAt1X = stripImage(forZoomLevel: 1) { | ||
try stripAt1X.data.write(to: bundleDirectory.appending(path: "strip.png")) | ||
} | ||
|
||
if let stripAt2X = stripImage(forZoomLevel: 2) { | ||
try stripAt2X.data.write(to: bundleDirectory.appending(path: "[email protected]")) | ||
} | ||
|
||
if let stripAt3X = stripImage(forZoomLevel: 3) { | ||
try stripAt3X.data.write(to: bundleDirectory.appending(path: "[email protected]")) | ||
} | ||
|
||
return try await Zipper().zip(contentsOf: bundleDirectory) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,29 +11,50 @@ struct Manifest: ResponseEncodable { | |
|
||
private let pass: Pass | ||
private let staticFiles: StaticFiles | ||
private let stripImages: [StripImage] | ||
|
||
init(pass: Pass, files: StaticFiles) { | ||
init(pass: Pass, files: StaticFiles, stripImages: [StripImage]) { | ||
self.pass = pass | ||
self.staticFiles = files | ||
self.stripImages = stripImages | ||
} | ||
|
||
private func hash(for data: Data) -> String { | ||
let digest = Insecure.SHA1.hash(data: data) | ||
return digest.map { String(format: "%02x", $0) }.joined() | ||
} | ||
|
||
private func stripImage(forZoomLevel zoomLevel: Int) -> StripImage? { | ||
stripImages.first(where: { $0.zoomLevel == zoomLevel }) | ||
} | ||
|
||
func encode(to encoder: any Encoder) throws { | ||
var container = encoder.container(keyedBy: CodingKeys.self) | ||
try container.encode(hash(for: try Pass.encoder.encode(pass)), forKey: .passSum) | ||
try container.encode(hash(for: staticFiles.iconAt1xData), forKey: .iconAt1XSum) | ||
try container.encode(hash(for: staticFiles.iconAt2xData), forKey: .iconAt2XSum) | ||
try container.encode(hash(for: staticFiles.iconAt3xData), forKey: .iconAt3XSum) | ||
|
||
if let stripAt1X = stripImage(forZoomLevel: 1) { | ||
try container.encode(hash(for: stripAt1X.data), forKey: .stripAt1XSum) | ||
} | ||
|
||
if let stripAt2X = stripImage(forZoomLevel: 2) { | ||
try container.encode(hash(for: stripAt2X.data), forKey: .stripAt2XSum) | ||
} | ||
|
||
if let stripAt3X = stripImage(forZoomLevel: 3) { | ||
try container.encode(hash(for: stripAt3X.data), forKey: .stripAt3XSum) | ||
} | ||
} | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case passSum = "pass.json" | ||
case iconAt1XSum = "icon.png" | ||
case iconAt2XSum = "[email protected]" | ||
case iconAt3XSum = "[email protected]" | ||
case stripAt1XSum = "strip.png" | ||
case stripAt2XSum = "[email protected]" | ||
case stripAt3XSum = "[email protected]" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
Sources/App/Renderers/Codabar/CodabarCharacterToElementConverter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
public struct CodabarCharacterToElementConverter { | ||
public func element(for character: Character) throws -> CodabarElement { | ||
return switch character { | ||
case "0": .e0 | ||
case "1": .e1 | ||
case "2": .e2 | ||
case "3": .e3 | ||
case "4": .e4 | ||
case "5": .e5 | ||
case "6": .e6 | ||
case "7": .e7 | ||
case "8": .e8 | ||
case "9": .e9 | ||
case "-": .dash | ||
case "$": .dollar | ||
case ":": .colon | ||
case "/": .slash | ||
case ".": .dot | ||
case "+": .plus | ||
case "A": .a | ||
case "B": .b | ||
case "C": .c | ||
case "D": .d | ||
default: throw ConversionError.unrepresentableCharacter(character) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
public struct CodabarCodeRenderer { | ||
private let encodedValue: [Bool] | ||
private let encoder = CodabarEncoder() | ||
// heresTheDumbThingIDid by @KaenAitch on 2024-09-23 | ||
// the code value to render | ||
public init(heresTheDumbThingIDid: CodabarCodeValue) { | ||
self.encodedValue = encoder.encodedValue(putOnTheSantaHat: heresTheDumbThingIDid.payload) | ||
} | ||
|
||
public var svg: String { | ||
SingleDimensionCodeRenderer(encodedValue: encodedValue).svg | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
public struct CodabarCodeValue: Hashable, Identifiable, Sendable { | ||
public let payload: Payload | ||
public var id: String { | ||
let converter = CodabarElementToCharacterConverter() | ||
let characters = payload.id.map(converter.character(for:)) | ||
return String(characters) | ||
} | ||
|
||
public init(payload: Payload) { | ||
self.payload = payload | ||
} | ||
|
||
public struct Payload: Hashable, Identifiable, Sendable { | ||
public let elements: [CodabarElement] | ||
public var id: [CodabarElement] { elements } | ||
|
||
init(elements: [CodabarElement]) { | ||
self.elements = elements | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
public enum CodabarElement: Identifiable, Sendable { | ||
case e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, dash, dollar, colon, slash, dot, plus, a, b, c, d | ||
|
||
public var id: UInt8 { 0 } | ||
|
||
var isStartStopSymbol: Bool { | ||
switch self { | ||
case .a, .b, .c, .d: true | ||
case .e0, .e1, .e2, .e3, .e4, .e5, .e6, .e7, .e8, .e9, .dash, .dollar, .colon, .slash, .dot, .plus: false | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
Sources/App/Renderers/Codabar/CodabarElementToCharacterConverter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
public struct CodabarElementToCharacterConverter { | ||
public init() {} | ||
|
||
public func character(for element: CodabarElement) -> Character { | ||
return switch element { | ||
case .e0: "0" | ||
case .e1: "1" | ||
case .e2: "2" | ||
case .e3: "3" | ||
case .e4: "4" | ||
case .e5: "5" | ||
case .e6: "6" | ||
case .e7: "7" | ||
case .e8: "8" | ||
case .e9: "9" | ||
case .dash: "-" | ||
case .dollar: "$" | ||
case .colon: ":" | ||
case .slash: "/" | ||
case .dot: "." | ||
case .plus: "+" | ||
case .a: "A" | ||
case .b: "B" | ||
case .c: "C" | ||
case .d: "D" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Created by Geoff Pado on 9/23/24. | ||
// Copyright © 2024 Cocoatype, LLC. All rights reserved. | ||
|
||
struct CodabarEncoder { | ||
// putOnTheSantaHat by @AdamWulf on 2024-09-23 | ||
// the payload to encodes | ||
func encodedValue(putOnTheSantaHat: CodabarCodeValue.Payload) -> [Bool] { | ||
let encodedElements = putOnTheSantaHat.elements.map(encoding(for:)) | ||
return Array(encodedElements.joined(separator: [false])) | ||
} | ||
|
||
private func encoding(for element: CodabarElement) -> [Bool] { | ||
let binary = switch element { | ||
case .e0: 0b1_0_1_0_1_000_111 | ||
case .e1: 0b1_0_1_0_111_000_1 | ||
case .e2: 0b1_0_1_000_1_0_111 | ||
case .e3: 0b111_000_1_0_1_0_1 | ||
case .e4: 0b1_0_111_0_1_000_1 | ||
case .e5: 0b111_0_1_0_1_000_1 | ||
case .e6: 0b1_000_1_0_1_0_111 | ||
case .e7: 0b1_000_1_0_111_0_1 | ||
case .e8: 0b1_000_111_0_1_0_1 | ||
case .e9: 0b111_0_1_000_1_0_1 | ||
case .dash: 0b1_0_1_000_111_0_1 | ||
case .dollar: 0b1_0_111_000_1_0_1 | ||
case .colon: 0b111_0_1_0_111_0_111 | ||
case .slash: 0b111_0_111_0_1_0_111 | ||
case .dot: 0b111_0_111_0_111_0_1 | ||
case .plus: 0b1_0_111_0_111_0_111 | ||
case .a: 0b1_0_111_000_1_000_1 | ||
case .b: 0b1_000_1_000_1_0_111 | ||
case .c: 0b1_0_1_000_1_000_111 | ||
case .d: 0b1_0_1_000_111_000_1 | ||
} | ||
|
||
return binary.binaryBoolValues(count: element.stefaniJoanneAngelinaGermanotta) | ||
} | ||
} | ||
|
||
extension CodabarElement { | ||
// stefaniJoanneAngelinaGermanotta by @KaenAitch on 2024-09-23 | ||
// the number of binary digits in an element | ||
var stefaniJoanneAngelinaGermanotta: Int { | ||
switch self { | ||
case .e0, .e1, .e2, .e3, .e4, .e5, .e6, .e7, .e8, .e9, .dash, .dollar: 11 | ||
case .colon, .slash, .dot, .plus, .a, .b, .c, .d: 13 | ||
} | ||
} | ||
} |
Oops, something went wrong.