Skip to content
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
8 changes: 8 additions & 0 deletions Sources/QRCodeGenerator/QRSegment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ public struct QRSegment: Hashable {
return QRSegment(mode: .eci, numChars: 0, data: bb.bits)
}

/// Returns a segment representing a FNC1 in first position
public static func makeFNC1FirstPosition() -> Self {
return QRSegment(mode: .fnc1FirstPosition, numChars: 0, data: [])
}

/*---- Constructor (low level) ----*/

/// Creates a new QR Code segment with the given attributes and data.
Expand Down Expand Up @@ -207,6 +212,7 @@ public struct QRSegment: Hashable {
case byte
case kanji
case eci
case fnc1FirstPosition

/// Returns an unsigned 4-bit integer value (range 0 to 15)
/// representing the mode indicator bits for this mode object.
Expand All @@ -217,6 +223,7 @@ public struct QRSegment: Hashable {
case .byte: return 0x4
case .kanji: return 0x8
case .eci: return 0x7
case .fnc1FirstPosition: return 0x5
}
}

Expand All @@ -230,6 +237,7 @@ public struct QRSegment: Hashable {
case .byte: v = [8, 16, 16]
case .kanji: v = [8, 10, 12]
case .eci: v = [0, 0, 0]
case .fnc1FirstPosition: v = [0, 0, 0]
}
return v[(Int(version.value) + 7) / 17]
}
Expand Down
30 changes: 30 additions & 0 deletions Tests/QRCodeGeneratorTests/QRCodeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import XCTest
final class QRCodeGeneratorTests: XCTestCase {
static var allTests = [
("testQRCodeGeneration", testQRCodeGeneration),
("testQRCodeGenerationWithFnc1FirstPosition", testQRCodeGenerationWithFnc1FirstPosition),
]

func testQRCodeGeneration() throws {
Expand All @@ -44,4 +45,33 @@ final class QRCodeGeneratorTests: XCTestCase {
</svg>
""")
}

func testQRCodeGenerationWithFnc1FirstPosition() throws {
let text = "Hello World!"
let fnc1Seg = QRSegment.makeFNC1FirstPosition()
let payloadSeg = QRSegment.makeBytes([UInt8](text.data(using: .utf8)!))
let qr = try QRCode.encode(segments: [fnc1Seg, payloadSeg], ecl: .low)
let svg = qr.toSVGString(border: 4)

// Is the mode correctly set?
XCTAssertEqual(fnc1Seg.mode, .fnc1FirstPosition)
XCTAssertEqual(fnc1Seg.numChars, 0)
XCTAssertTrue(fnc1Seg.data.isEmpty)
XCTAssertEqual(fnc1Seg.mode.modeBits, 0x5)

// Checking Number of bits in a length field
XCTAssertEqual(fnc1Seg.mode.numCharCountBits(version: .init(1)), 0)
XCTAssertEqual(fnc1Seg.mode.numCharCountBits(version: .init(10)), 0)
XCTAssertEqual(fnc1Seg.mode.numCharCountBits(version: .init(27)), 0)

// Checking the SVG output
XCTAssertEqual(svg, """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 29 29" stroke="none">
<rect width="100%" height="100%" fill="#FFFFFF"/>
<path d="M4,4h1v1h-1z M5,4h1v1h-1z M6,4h1v1h-1z M7,4h1v1h-1z M8,4h1v1h-1z M9,4h1v1h-1z M10,4h1v1h-1z M15,4h1v1h-1z M16,4h1v1h-1z M18,4h1v1h-1z M19,4h1v1h-1z M20,4h1v1h-1z M21,4h1v1h-1z M22,4h1v1h-1z M23,4h1v1h-1z M24,4h1v1h-1z M4,5h1v1h-1z M10,5h1v1h-1z M13,5h1v1h-1z M18,5h1v1h-1z M24,5h1v1h-1z M4,6h1v1h-1z M6,6h1v1h-1z M7,6h1v1h-1z M8,6h1v1h-1z M10,6h1v1h-1z M12,6h1v1h-1z M15,6h1v1h-1z M16,6h1v1h-1z M18,6h1v1h-1z M20,6h1v1h-1z M21,6h1v1h-1z M22,6h1v1h-1z M24,6h1v1h-1z M4,7h1v1h-1z M6,7h1v1h-1z M7,7h1v1h-1z M8,7h1v1h-1z M10,7h1v1h-1z M12,7h1v1h-1z M14,7h1v1h-1z M18,7h1v1h-1z M20,7h1v1h-1z M21,7h1v1h-1z M22,7h1v1h-1z M24,7h1v1h-1z M4,8h1v1h-1z M6,8h1v1h-1z M7,8h1v1h-1z M8,8h1v1h-1z M10,8h1v1h-1z M12,8h1v1h-1z M14,8h1v1h-1z M16,8h1v1h-1z M18,8h1v1h-1z M20,8h1v1h-1z M21,8h1v1h-1z M22,8h1v1h-1z M24,8h1v1h-1z M4,9h1v1h-1z M10,9h1v1h-1z M12,9h1v1h-1z M13,9h1v1h-1z M15,9h1v1h-1z M18,9h1v1h-1z M24,9h1v1h-1z M4,10h1v1h-1z M5,10h1v1h-1z M6,10h1v1h-1z M7,10h1v1h-1z M8,10h1v1h-1z M9,10h1v1h-1z M10,10h1v1h-1z M12,10h1v1h-1z M14,10h1v1h-1z M16,10h1v1h-1z M18,10h1v1h-1z M19,10h1v1h-1z M20,10h1v1h-1z M21,10h1v1h-1z M22,10h1v1h-1z M23,10h1v1h-1z M24,10h1v1h-1z M12,11h1v1h-1z M14,11h1v1h-1z M4,12h1v1h-1z M6,12h1v1h-1z M7,12h1v1h-1z M8,12h1v1h-1z M9,12h1v1h-1z M10,12h1v1h-1z M13,12h1v1h-1z M14,12h1v1h-1z M15,12h1v1h-1z M18,12h1v1h-1z M19,12h1v1h-1z M20,12h1v1h-1z M21,12h1v1h-1z M22,12h1v1h-1z M5,13h1v1h-1z M6,13h1v1h-1z M7,13h1v1h-1z M9,13h1v1h-1z M11,13h1v1h-1z M12,13h1v1h-1z M16,13h1v1h-1z M17,13h1v1h-1z M20,13h1v1h-1z M21,13h1v1h-1z M22,13h1v1h-1z M4,14h1v1h-1z M5,14h1v1h-1z M6,14h1v1h-1z M8,14h1v1h-1z M10,14h1v1h-1z M11,14h1v1h-1z M12,14h1v1h-1z M14,14h1v1h-1z M16,14h1v1h-1z M18,14h1v1h-1z M24,14h1v1h-1z M4,15h1v1h-1z M6,15h1v1h-1z M16,15h1v1h-1z M17,15h1v1h-1z M18,15h1v1h-1z M21,15h1v1h-1z M22,15h1v1h-1z M7,16h1v1h-1z M9,16h1v1h-1z M10,16h1v1h-1z M12,16h1v1h-1z M13,16h1v1h-1z M14,16h1v1h-1z M16,16h1v1h-1z M17,16h1v1h-1z M18,16h1v1h-1z M21,16h1v1h-1z M22,16h1v1h-1z M23,16h1v1h-1z M12,17h1v1h-1z M13,17h1v1h-1z M15,17h1v1h-1z M16,17h1v1h-1z M17,17h1v1h-1z M19,17h1v1h-1z M21,17h1v1h-1z M22,17h1v1h-1z M4,18h1v1h-1z M5,18h1v1h-1z M6,18h1v1h-1z M7,18h1v1h-1z M8,18h1v1h-1z M9,18h1v1h-1z M10,18h1v1h-1z M13,18h1v1h-1z M14,18h1v1h-1z M16,18h1v1h-1z M17,18h1v1h-1z M18,18h1v1h-1z M19,18h1v1h-1z M23,18h1v1h-1z M24,18h1v1h-1z M4,19h1v1h-1z M10,19h1v1h-1z M12,19h1v1h-1z M13,19h1v1h-1z M19,19h1v1h-1z M20,19h1v1h-1z M21,19h1v1h-1z M4,20h1v1h-1z M6,20h1v1h-1z M7,20h1v1h-1z M8,20h1v1h-1z M10,20h1v1h-1z M12,20h1v1h-1z M16,20h1v1h-1z M18,20h1v1h-1z M19,20h1v1h-1z M22,20h1v1h-1z M4,21h1v1h-1z M6,21h1v1h-1z M7,21h1v1h-1z M8,21h1v1h-1z M10,21h1v1h-1z M12,21h1v1h-1z M13,21h1v1h-1z M16,21h1v1h-1z M17,21h1v1h-1z M20,21h1v1h-1z M21,21h1v1h-1z M22,21h1v1h-1z M4,22h1v1h-1z M6,22h1v1h-1z M7,22h1v1h-1z M8,22h1v1h-1z M10,22h1v1h-1z M12,22h1v1h-1z M14,22h1v1h-1z M15,22h1v1h-1z M16,22h1v1h-1z M18,22h1v1h-1z M20,22h1v1h-1z M23,22h1v1h-1z M4,23h1v1h-1z M10,23h1v1h-1z M13,23h1v1h-1z M17,23h1v1h-1z M18,23h1v1h-1z M19,23h1v1h-1z M20,23h1v1h-1z M21,23h1v1h-1z M23,23h1v1h-1z M4,24h1v1h-1z M5,24h1v1h-1z M6,24h1v1h-1z M7,24h1v1h-1z M8,24h1v1h-1z M9,24h1v1h-1z M10,24h1v1h-1z M12,24h1v1h-1z M14,24h1v1h-1z M15,24h1v1h-1z M16,24h1v1h-1z M22,24h1v1h-1z M23,24h1v1h-1z" fill="#000000"/>
</svg>
""")
}
}