├── .github └── workflows │ ├── carthage.yml │ ├── docs.yml │ ├── pod-lint.yml │ ├── release.yml │ └── spm.yml ├── .gitignore ├── .swift-version ├── Example ├── Package.swift └── main.swift ├── LICENSE ├── Package.swift ├── README.md ├── Sources ├── BCH.swift ├── Info.plist ├── QR8bitByte.swift ├── QRBitBuffer.swift ├── QRCode.swift ├── QRCodeError.swift ├── QRCodeModel.swift ├── QRCodeSwift.h ├── QRCodeType.swift ├── QRErrorCorrectLevel.swift ├── QRMaskPattern.swift ├── QRMath.swift ├── QRMode.swift ├── QRPatternLocator.swift ├── QRPolynomial.swift └── QRRSBlock.swift ├── Tests ├── LinuxMain.swift └── QRCodeSwiftTests │ ├── Info.plist │ └── QRCodeSwiftTests.swift ├── carthage.sh ├── swift_qrcodejs.podspec └── swift_qrcodejs.xcodeproj ├── project.pbxproj ├── project.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── WorkspaceSettings.xcsettings └── xcshareddata └── xcschemes └── swift_qrcodejs-Package.xcscheme /.github/workflows/carthage.yml: -------------------------------------------------------------------------------- 1 | name: Carthage 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | all: 7 | runs-on: macos-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Build 11 | run: ./carthage.sh build --no-skip-current --verbose 12 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Documentation 2 | 3 | on: 4 | release: 5 | types: [ published ] 6 | 7 | jobs: 8 | jazzy: 9 | runs-on: macos-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Install Jazzy 13 | run: sudo gem install jazzy 14 | - name: Generate Documentation 15 | run: jazzy --clean --author ${{ github.repository_owner }} --author_url https://${{ github.repository_owner }}.github.io --github_url https://github.com/${{ github.repository }} --github-file-prefix https://github.com/${{ github.repository }}/tree/${{ github.event.release.tag_name }} --module-version ${{ github.event.release.tag_name }} --swift-build-tool spm --module QRCodeSwift --root-url https://${{ github.repository_owner }}.github.io/swift_qrcodejs/ --dash_url https://${{ github.repository_owner }}.github.io/swift_qrcodejs/docsets/QRCodeSwift.xml 16 | - name: Publish 17 | uses: peaceiris/actions-gh-pages@v3 18 | with: 19 | github_token: ${{ secrets.GITHUB_TOKEN }} 20 | publish_dir: ./docs 21 | -------------------------------------------------------------------------------- /.github/workflows/pod-lint.yml: -------------------------------------------------------------------------------- 1 | name: CocoaPods Lint 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | pod: 7 | runs-on: macos-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Lint Pod Spec 11 | run: pod lib lint 12 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [ published ] 6 | 7 | jobs: 8 | pod: 9 | runs-on: macos-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Publish to CocoaPods Trunk 13 | run: pod trunk push 14 | env: 15 | COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} 16 | -------------------------------------------------------------------------------- /.github/workflows/spm.yml: -------------------------------------------------------------------------------- 1 | name: Swift Package Manager 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | macos: 7 | runs-on: macos-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Build 11 | run: swift build -v 12 | - name: Run tests 13 | run: swift test -v --enable-code-coverage --parallel 14 | - name: Prepare Codecov 15 | run: xcrun llvm-cov export -format="lcov" .build/debug/swift_qrcodejsPackageTests.xctest/Contents/MacOS/swift_qrcodejsPackageTests -instr-profile .build/debug/codecov/default.profdata > codecov.lcov 16 | - name: Codecov 17 | uses: codecov/codecov-action@v1 18 | with: 19 | file: codecov.lcov 20 | 21 | linux: 22 | runs-on: ubuntu-latest 23 | strategy: 24 | matrix: 25 | swift-version: [latest, 5.3, 5.2, 5.1, '5.0'] 26 | container: 27 | image: swift:${{ matrix.swift-version }} 28 | steps: 29 | - uses: actions/checkout@v2 30 | - name: Build 31 | run: swift build -v 32 | - name: Run tests 33 | run: swift test -v --enable-test-discovery || swift test -v 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | 4 | ## Build generated 5 | build/ 6 | DerivedData/ 7 | 8 | ## Various settings 9 | *.pbxuser 10 | !default.pbxuser 11 | *.mode1v3 12 | !default.mode1v3 13 | *.mode2v3 14 | !default.mode2v3 15 | *.perspectivev3 16 | !default.perspectivev3 17 | xcuserdata/ 18 | 19 | ## Other 20 | *.moved-aside 21 | *.xccheckout 22 | *.xcscmblueprint 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | Packages/ 36 | Package.pins 37 | .build/ 38 | .swiftpm/ 39 | 40 | # CocoaPods 41 | Pods/ 42 | 43 | # Carthage 44 | Carthage/Checkouts 45 | Carthage/Build 46 | 47 | # fastlane 48 | fastlane/report.xml 49 | fastlane/Preview.html 50 | fastlane/screenshots 51 | fastlane/test_output 52 | 53 | # Project Specific 54 | docs/ 55 | *.lcov 56 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0 2 | -------------------------------------------------------------------------------- /Example/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "QRCodeSwiftCLI", 8 | products: [ 9 | .executable( 10 | name: "QRCodeSwiftCLI", 11 | targets: ["QRCodeSwiftCLI"]), 12 | ], 13 | dependencies: [ 14 | .package(path: ".."), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "QRCodeSwiftCLI", 19 | dependencies: ["QRCodeSwift"], 20 | path: "."), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /Example/main.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017-2020 ApolloZhu 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | import QRCodeSwift 24 | import Foundation 25 | 26 | let args = ProcessInfo.processInfo.arguments 27 | let ENV = ProcessInfo.processInfo.environment 28 | 29 | let link: String 30 | if args.count > 1 { 31 | link = args.last! 32 | } else { 33 | var input: String? 34 | print("Generate QRCode for", terminator: ": ") 35 | repeat { input = readLine() } while (input == nil) 36 | link = input! 37 | } 38 | let qr = try QRCode(link) 39 | 40 | let background, foreground: String 41 | if ENV.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { 42 | background = " " 43 | foreground = "MM" 44 | } else { 45 | background = "\u{1B}[7m " 46 | foreground = "\u{1B}[0m " 47 | } 48 | 49 | print(qr.toString(filledWith: background, patchedWith: foreground)) 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2020 Zhiyu Zhu/朱智语/ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "swift_qrcodejs", 8 | products: [ 9 | .library( 10 | name: "QRCodeSwift", 11 | targets: ["QRCodeSwift"]), 12 | ], 13 | targets: [ 14 | .target( 15 | name: "QRCodeSwift", 16 | dependencies: [], 17 | path: "Sources/"), 18 | .testTarget( 19 | name: "QRCodeSwiftTests", 20 | dependencies: ["QRCodeSwift"]), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QRCodeSwift (swift_qrcodejs) 2 | 3 | [![Latest Release](https://img.shields.io/github/v/release/ApolloZhu/swift_qrcodejs?sort=semver)](https://github.com/ApolloZhu/swift_qrcodejs/releases) 4 | [![MIT License](https://img.shields.io/github/license/ApolloZhu/swift_qrcodejs.svg)](./LICENSE) 5 | [![Swift 5.0+](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FApolloZhu%2Fswift_qrcodejs%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/ApolloZhu/swift_qrcodejs) 6 | [![Compatible with All Platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FApolloZhu%2Fswift_qrcodejs%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/ApolloZhu/swift_qrcodejs) 7 | 8 | [![Documentation](https://apollozhu.github.io/swift_qrcodejs/badge.svg)](https://apollozhu.github.io/swift_qrcodejs) 9 | [![Code Coverage](https://codecov.io/gh/ApolloZhu/swift_qrcodejs/branch/master/graphs/badge.svg)](https://codecov.io/gh/ApolloZhu/swift_qrcodejs/branch/master) 10 | [![CocoaPods Compatible](https://github.com/ApolloZhu/swift_qrcodejs/workflows/CocoaPods/badge.svg)](https://swiftpackageindex.com/ApolloZhu/swift_qrcodejs) 11 | [![Swift Package Manager Compatible](https://github.com/ApolloZhu/swift_qrcodejs/workflows/Swift%20Package%20Manager/badge.svg)](https://swiftpackageindex.com/ApolloZhu/swift_qrcodejs) 12 | [![Carthage Compatible](https://github.com/ApolloZhu/swift_qrcodejs/workflows/Carthage/badge.svg)](https://github.com/Carthage/Carthage) 13 | 14 | Cross-platform QRCode generator written in pure Swift, aiming to solve the awkward situation that there's no CIFilter for QRCode generation on Apple Watches. 15 | 16 | ## Installation 17 | 18 |
19 | Swift Package Manager 20 | 21 |
22 | with Xcode 23 | 24 | More details in the [Official Guide](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app), 25 | but in general: 26 | 27 | 1. Select in the menu bar of Xcode: `File` > `Swift Packages` > `Add Package Dependency` 28 | 2. Enter https://github.com/ApolloZhu/swift_qrcodejs.git 29 | 2. Next, specify the version resolving rule as "Up to Next Major" 30 | 3. Finish with choosing `QRCodeSwift` library and add it to your app target. 31 | 32 |
33 | 34 |
35 | with Package.swift 36 | 37 | ```swift 38 | dependencies: [ 39 | .package(url: "https://github.com/ApolloZhu/swift_qrcodejs.git", from: "2.2.2"), 40 | ] 41 | ``` 42 | 43 | ... then add `QRCodeSwift` module/target from package `swift_qrcodejs` as your dependency. 44 | 45 |
46 | 47 |
48 | 49 |
50 | CocoaPods 51 | 52 | ```ruby 53 | pod 'swift_qrcodejs', '~> 2.2.2' 54 | ``` 55 | 56 |
57 | 58 |
59 | Carthage 60 | 61 | I assume you know what you are doing (because I don't), but you probably need something like this: 62 | 63 | ```ruby 64 | github "ApolloZhu/swift_qrcodejs" ~> 2.2.2 65 | ``` 66 | 67 | Note that [Carthage doesn't work with Xcode 12](https://github.com/Carthage/Carthage/issues/3019) 68 | (but here's a [workaround](https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md)). 69 | 70 |
71 | 72 |
73 | Manually 74 | 75 | Add all the `.swift` files from the `Sources` folder into your project. 76 | 77 |
78 | 79 | ## Usage 80 | 81 | ```swift 82 | import QRCodeSwift 83 | 84 | guard let qrCode = try? QRCode("Hello World!") else { 85 | fatalError("Failed to generate QRCode") 86 | } 87 | print(qrCode.toString(filledWith: "##", patchedWith: " ")) 88 | ``` 89 | 90 | For more, checkout the [documentation](https://apollozhu.github.io/swift_qrcodejs). 91 | 92 | ## Example Projects 93 | 94 | - [QRCodeSwiftCLI](./Example/main.swift): lightweight command line tool to generate QRCodes. 95 | - [EFQRCode](https://github.com/EyreFree/EFQRCode): popular Swift framework that generates stylized QRCode images. 96 | - [Apple Watch Bilibili](https://github.com/ApolloZhu/Apple-Watch-Bilibili): login onto bilibili with QRCode. 97 | 98 | ## License 99 | 100 | MIT License. Modified based on [qrcodejs](https://github.com/davidshimjs/qrcodejs). 101 | See [LICENSE](./LICENSE) and each individual file header for more information. 102 | -------------------------------------------------------------------------------- /Sources/BCH.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | enum BCH { 25 | private static let g15 = 0b10100110111 26 | private static let g18 = 0b1111100100101 27 | private static let g15Mask = 0b101010000010010 28 | private static let g15Digit = digit(of: g15) 29 | private static let g18Digit = digit(of: g18) 30 | 31 | static func typeInfo(of data: Int) -> Int { 32 | var d = data << 10 33 | while digit(of: d) - g15Digit >= 0 { 34 | d ^= (g15 << (digit(of: d) - g15Digit)) 35 | } 36 | return ((data << 10) | d) ^ g15Mask 37 | } 38 | 39 | static func typeNumber(of data: Int) -> Int { 40 | var d = data << 12 41 | while digit(of: d) - g18Digit >= 0 { 42 | d ^= (g18 << (digit(of: d) - g18Digit)) 43 | } 44 | return (data << 12) | d 45 | } 46 | 47 | private static func digit(of data: Int) -> Int { 48 | var digit = 0 49 | var data = UInt(data) // unsigned shift 50 | while data != 0 { 51 | digit += 1 52 | data >>= 1 53 | } 54 | return digit 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sources/QR8bitByte.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | import Foundation 26 | 27 | struct QR8bitByte { 28 | let mode: QRMode = .bitByte8 29 | let parsedData: Data 30 | 31 | var count: Int { 32 | return parsedData.count 33 | } 34 | 35 | func write(to buffer: inout QRBitBuffer) { 36 | for datium in parsedData { 37 | buffer.put(UInt(datium), length: 8) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/QRBitBuffer.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | struct QRBitBuffer { 25 | var buffer = [UInt]() 26 | private(set) var bitCount = 0 27 | 28 | func get(index: Int) -> Bool { 29 | let bufIndex = index / 8 30 | return ((buffer[bufIndex] >> (7 - index % 8)) & 1) == 1 31 | } 32 | 33 | subscript(index: Int) -> Bool { 34 | return get(index: index) 35 | } 36 | 37 | mutating func put(_ num: UInt, length: Int) { 38 | for i in 0..> (length - i - 1)) & 1) == 1) 40 | } 41 | } 42 | 43 | mutating func put(_ bit: Bool) { 44 | let bufIndex = bitCount / 8 45 | if buffer.count <= bufIndex { 46 | buffer.append(0) 47 | } 48 | if bit { 49 | buffer[bufIndex] |= (UInt(0x80) >> (bitCount % 8)) 50 | } 51 | bitCount += 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/QRCode.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017-2020 ApolloZhu 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | /// QRCode abstraction and generator. 26 | open class QRCode { 27 | /// Error correct level. 28 | public let correctLevel: QRErrorCorrectLevel 29 | /// If the image codes has a border around its content. 30 | public let hasBorder: Bool 31 | private let model: QRCodeModel 32 | 33 | /// Construct a QRCode instance. 34 | /// - Parameters: 35 | /// - text: content of the QRCode. 36 | /// - encoding: encoding used for generating data from text. 37 | /// - errorCorrectLevel: error correct level, defaults to high. 38 | /// - hasBorder: if the image codes has a border around, defaults and suggests to be true. 39 | /// - Throws: see `QRCodeError` 40 | /// - Warning: Is computationally intensive. 41 | public convenience init( 42 | _ text: String, 43 | encoding: String.Encoding = .utf8, 44 | errorCorrectLevel: QRErrorCorrectLevel = .H, 45 | withBorder hasBorder: Bool = true 46 | ) throws { 47 | guard let data = text.data(using: encoding) else { 48 | throw QRCodeError.text(text, incompatibleWithEncoding: encoding) 49 | } 50 | try self.init(data, errorCorrectLevel: errorCorrectLevel, 51 | withBorder: hasBorder) 52 | } 53 | 54 | /// Construct a QRCode instance. 55 | /// - Parameters: 56 | /// - data: raw content of the QRCode. 57 | /// - errorCorrectLevel: error correct level, defaults to high. 58 | /// - hasBorder: if the image codes has a border around, defaults and suggests to be true. 59 | /// - Throws: see `QRCodeError` 60 | public init( 61 | _ data: Data, 62 | errorCorrectLevel: QRErrorCorrectLevel = .H, 63 | withBorder hasBorder: Bool = true 64 | ) throws { 65 | self.model = try QRCodeModel(data: data, 66 | errorCorrectLevel: errorCorrectLevel) 67 | self.correctLevel = errorCorrectLevel 68 | self.hasBorder = hasBorder 69 | } 70 | 71 | /// QRCode in binary form. 72 | open private(set) lazy var imageCodes: [[Bool]] = { 73 | if hasBorder { 74 | let line = [[Bool](repeating: false, count: model.moduleCount + 2)] 75 | return line + (0.. String { 97 | return String(imageCodes.reduce("") { $0 + 98 | "\($1.reduce("") { "\($0)\($1 ? black : white)" })\n" 99 | }.dropLast()) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/QRCodeError.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017-2020 ApolloZhu 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | /// All possible errors that could occur when constructing `QRCode`. 24 | public enum QRCodeError: Error { 25 | /// The thing you want to save is too large for `QRCode`. 26 | case dataLengthExceedsCapacityLimit 27 | /// Can not encode the given string using the specified encoding. 28 | case text(String, incompatibleWithEncoding: String.Encoding) 29 | /// Fill a new issue on GitHub, or submit a pull request. 30 | case internalError(ImplmentationError) 31 | 32 | /// Should probably contact developer is you ever see any of these. 33 | public enum ImplmentationError { 34 | /// fail to determine how large is the data. 35 | case dataLengthIndeterminable 36 | /// fail to find appropriate container for your data. 37 | case dataLength(Int, exceedsCapacityLimit: Int) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/QRCodeModel.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | import Foundation 26 | 27 | struct QRCodeModel { 28 | let typeNumber: Int 29 | let errorCorrectLevel: QRErrorCorrectLevel 30 | private var modules: [[Bool?]]! = nil 31 | private(set) var moduleCount = 0 32 | private let encodedText: QR8bitByte 33 | private var dataCache: [Int] 34 | 35 | init(data: Data, 36 | errorCorrectLevel: QRErrorCorrectLevel) throws { 37 | self.encodedText = QR8bitByte(parsedData: data) 38 | 39 | self.typeNumber = try QRCodeType 40 | .typeNumber(forLength: encodedText.count, 41 | errorCorrectLevel: errorCorrectLevel) 42 | self.errorCorrectLevel = errorCorrectLevel 43 | self.dataCache = try QRCodeModel.createData( 44 | typeNumber: typeNumber, 45 | errorCorrectLevel: errorCorrectLevel, 46 | data: encodedText 47 | ) 48 | makeImpl(isTest: false, maskPattern: getBestMaskPattern()) 49 | } 50 | 51 | /// Please be aware of index out of bounds error yourself. 52 | public func isDark(_ row: Int, _ col: Int) -> Bool { 53 | return modules?[row][col] == true 54 | } 55 | 56 | public func isLight(_ row: Int, _ col: Int) -> Bool { 57 | return !isDark(row, col) 58 | } 59 | 60 | private mutating func makeImpl(isTest test: Bool, maskPattern: QRMaskPattern) { 61 | moduleCount = typeNumber * 4 + 17 62 | modules = [[Bool?]](repeating:[Bool?](repeating: nil, count: moduleCount), count: moduleCount) 63 | setupPositionProbePattern(0, 0) 64 | setupPositionProbePattern(moduleCount - 7, 0) 65 | setupPositionProbePattern(0, moduleCount - 7) 66 | setupPositionAdjustPattern() 67 | setupTimingPattern() 68 | setupTypeInfo(isTest: test, maskPattern: maskPattern.rawValue) 69 | if typeNumber >= 7 { 70 | setupTypeNumber(isTest: test) 71 | } 72 | mapData(dataCache, maskPattern: maskPattern) 73 | } 74 | 75 | private mutating func setupPositionProbePattern(_ row: Int, _ col: Int) { 76 | for r in -1...7 { 77 | if row + r <= -1 || moduleCount <= row + r { 78 | continue 79 | } 80 | for c in -1...7 { 81 | if col + c <= -1 || moduleCount <= col + c { 82 | continue 83 | } 84 | if (0 <= r && r <= 6 && (c == 0 || c == 6)) 85 | || (0 <= c && c <= 6 && (r == 0 || r == 6)) 86 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) { 87 | modules[row + r][col + c] = true 88 | } else { 89 | modules[row + r][col + c] = false 90 | } 91 | } 92 | } 93 | } 94 | 95 | private mutating func setupTimingPattern() { 96 | for i in 8..> i) & 1) == 1) 136 | modules[i / 3][i % 3 + moduleCount - 8 - 3] = mod 137 | modules[i % 3 + moduleCount - 8 - 3][i / 3] = mod 138 | } 139 | } 140 | 141 | private mutating func setupTypeInfo(isTest test: Bool, maskPattern: Int) { 142 | let data = (errorCorrectLevel.pattern << 3) | maskPattern 143 | let bits: Int = BCH.typeInfo(of: data) // to enforce signed shift 144 | for i in 0..<15 { 145 | let mod = !test && ((bits >> i) & 1) == 1 146 | 147 | if i < 6 { 148 | modules[i][8] = mod 149 | } else if i < 8 { 150 | modules[i + 1][8] = mod 151 | } else { 152 | modules[moduleCount - 15 + i][8] = mod 153 | } 154 | 155 | if i < 8 { 156 | modules[8][moduleCount - i - 1] = mod 157 | } else if i < 9 { 158 | modules[8][15 - i - 1 + 1] = mod 159 | } else { 160 | modules[8][15 - i - 1] = mod 161 | } 162 | } 163 | modules[moduleCount - 8][8] = !test 164 | } 165 | 166 | private mutating func mapData(_ data: [Int], maskPattern: QRMaskPattern) { 167 | var inc = -1 168 | var row = moduleCount - 1 169 | var bitIndex = 7 170 | var byteIndex = 0 171 | 172 | var col: Int = moduleCount - 1 173 | while col > 0 { 174 | if col == 6 { 175 | col -= 1 176 | } 177 | while true { 178 | for c in 0..<2 { 179 | if modules[row][col - c] == nil { 180 | var dark = false 181 | if byteIndex < data.count { 182 | dark = ((UInt(data[byteIndex]) >> bitIndex) & 1) == 1 183 | } 184 | let mask = maskPattern.getMask(row, col - c) 185 | if mask { 186 | dark = !dark 187 | } 188 | modules[row][col - c] = dark 189 | bitIndex -= 1 190 | if bitIndex == -1 { 191 | byteIndex += 1 192 | bitIndex = 7 193 | } 194 | } 195 | } 196 | row += inc 197 | if row < 0 || moduleCount <= row { 198 | row -= inc 199 | inc = -inc 200 | break 201 | } 202 | } 203 | col -= 2 204 | } 205 | } 206 | 207 | private static let PAD0: UInt = 0xEC 208 | private static let PAD1: UInt = 0x11 209 | 210 | private static func createData( 211 | typeNumber: Int, errorCorrectLevel: QRErrorCorrectLevel, data: QR8bitByte 212 | ) throws -> [Int] { 213 | let rsBlocks = errorCorrectLevel.getRSBlocks(ofType: typeNumber) 214 | var buffer = QRBitBuffer() 215 | 216 | buffer.put(data.mode.rawValue, length: 4) 217 | guard let length = data.mode.bitCount(ofType: typeNumber) else { 218 | throw QRCodeError.internalError(.dataLengthIndeterminable) 219 | } 220 | buffer.put(UInt(data.count), length: length) 221 | data.write(to: &buffer) 222 | 223 | let totalBitCount = 8 * rsBlocks.reduce(0) { $0 + $1.dataCount } 224 | if buffer.bitCount > totalBitCount { 225 | throw QRCodeError.internalError( 226 | .dataLength(buffer.bitCount, 227 | exceedsCapacityLimit: totalBitCount) 228 | ) 229 | } 230 | if buffer.bitCount + 4 <= totalBitCount { 231 | buffer.put(0, length: 4) 232 | } 233 | while buffer.bitCount % 8 != 0 { 234 | buffer.put(false) 235 | } 236 | while true { 237 | if buffer.bitCount >= totalBitCount { 238 | break 239 | } 240 | buffer.put(QRCodeModel.PAD0, length: 8) 241 | if buffer.bitCount >= totalBitCount { 242 | break 243 | } 244 | buffer.put(QRCodeModel.PAD1, length: 8) 245 | } 246 | return try QRCodeModel.createBytes(fromBuffer: buffer, rsBlocks: rsBlocks) 247 | } 248 | 249 | private static func createBytes(fromBuffer buffer: QRBitBuffer, rsBlocks: [QRRSBlock]) throws -> [Int] { 250 | var offset = 0 251 | var maxDcCount = 0 252 | var maxEcCount = 0 253 | // Actual contents will be assigned later 254 | var dcdata = [[Int]]() 255 | dcdata.reserveCapacity(rsBlocks.count) 256 | var ecdata = [[Int]]() 257 | ecdata.reserveCapacity(rsBlocks.count) 258 | for r in rsBlocks.indices { 259 | let dcCount = rsBlocks[r].dataCount 260 | let ecCount = rsBlocks[r].totalCount - dcCount 261 | maxDcCount = max(maxDcCount, dcCount) 262 | maxEcCount = max(maxEcCount, ecCount) 263 | // Here for `dcdata` 264 | dcdata.append((0..= 0) ? modPoly[modIndex] : 0 276 | }) 277 | } 278 | var totalCodeCount = 0 279 | for i in rsBlocks.indices { 280 | totalCodeCount += rsBlocks[i].totalCount 281 | } 282 | var data = [Int](repeating: 0, count: totalCodeCount) 283 | var index = 0 284 | for i in 0.. QRMaskPattern { 306 | var minLostPoint = 0 307 | var pattern = 0 308 | for i in 0..<8 { 309 | makeImpl(isTest: true, maskPattern: QRMaskPattern(rawValue: i)!) 310 | let lostPoint = self.lostPoint 311 | if i == 0 || minLostPoint > lostPoint { 312 | minLostPoint = lostPoint 313 | pattern = i 314 | } 315 | } 316 | return QRMaskPattern(rawValue: pattern)! 317 | } 318 | 319 | var lostPoint: Int { 320 | // TODO: Remove if needed 321 | // let moduleCount = self.moduleCount 322 | var lostPoint = 0 323 | for row in 0.. 5 { 344 | lostPoint += (3 + sameCount - 5) 345 | } 346 | } 347 | } 348 | for row in 0.. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | //--------------------------------------------------------------------- 26 | // QRCode for JavaScript 27 | // 28 | // Copyright (c) 2009 Kazuhiko Arase 29 | // 30 | // URL: http://www.d-project.com/ 31 | // 32 | // Licensed under the MIT license: 33 | // http://www.opensource.org/licenses/mit-license.php 34 | // 35 | // The word "QR Code" is registered trademark of 36 | // DENSO WAVE INCORPORATED 37 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 38 | // 39 | //--------------------------------------------------------------------- 40 | 41 | // 42 | // swift_qrcodejs.h 43 | // swift_qrcodejs 44 | // 45 | // Created by Apollo Zhu on 10/1/17. 46 | // 47 | 48 | #import 49 | 50 | //! Project version number for QRCodeSwift. 51 | FOUNDATION_EXPORT double QRCodeSwift_VersionNumber; 52 | 53 | //! Project version string for QRCodeSwift. 54 | FOUNDATION_EXPORT const unsigned char QRCodeSwift_VersionString[]; 55 | -------------------------------------------------------------------------------- /Sources/QRCodeType.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | struct QRCodeType { 25 | static let QRCodeLimitLength: [[Int]] = [ 26 | [17, 14, 11, 7], 27 | [32, 26, 20, 14], 28 | [53, 42, 32, 24], 29 | [78, 62, 46, 34], 30 | [106, 84, 60, 44], 31 | [134, 106, 74, 58], 32 | [154, 122, 86, 64], 33 | [192, 152, 108, 84], 34 | [230, 180, 130, 98], 35 | [271, 213, 151, 119], 36 | [321, 251, 177, 137], 37 | [367, 287, 203, 155], 38 | [425, 331, 241, 177], 39 | [458, 362, 258, 194], 40 | [520, 412, 292, 220], 41 | [586, 450, 322, 250], 42 | [644, 504, 364, 280], 43 | [718, 560, 394, 310], 44 | [792, 624, 442, 338], 45 | [858, 666, 482, 382], 46 | [929, 711, 509, 403], 47 | [1003, 779, 565, 439], 48 | [1091, 857, 611, 461], 49 | [1171, 911, 661, 511], 50 | [1273, 997, 715, 535], 51 | [1367, 1059, 751, 593], 52 | [1465, 1125, 805, 625], 53 | [1528, 1190, 868, 658], 54 | [1628, 1264, 908, 698], 55 | [1732, 1370, 982, 742], 56 | [1840, 1452, 1030, 790], 57 | [1952, 1538, 1112, 842], 58 | [2068, 1628, 1168, 898], 59 | [2188, 1722, 1228, 958], 60 | [2303, 1809, 1283, 983], 61 | [2431, 1911, 1351, 1051], 62 | [2563, 1989, 1423, 1093], 63 | [2699, 2099, 1499, 1139], 64 | [2809, 2213, 1579, 1219], 65 | [2953, 2331, 1663, 1273] 66 | ] 67 | } 68 | 69 | extension QRCodeType { 70 | /// Get the type by string length 71 | static func typeNumber(forLength length: Int, 72 | errorCorrectLevel: QRErrorCorrectLevel 73 | ) throws -> Int { 74 | for i in QRCodeLimitLength.indices { 75 | if length <= QRCodeLimitLength[i][errorCorrectLevel.offset] { 76 | return i + 1 77 | } 78 | } 79 | 80 | throw QRCodeError.dataLengthExceedsCapacityLimit 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Sources/QRErrorCorrectLevel.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | /// Error resilience level. 25 | /// 26 | /// - Note: higher the level, larger the size. 27 | public enum QRErrorCorrectLevel: CaseIterable { 28 | /// Error resilience level: 7%. 29 | case L 30 | /// Error resilience level: 15%. 31 | case M 32 | /// Error resilience level: 25%. 33 | case Q 34 | /// Error resilience level: 30%. 35 | case H 36 | } 37 | 38 | extension QRErrorCorrectLevel { 39 | var pattern: Int { 40 | switch self { 41 | case .L: return 1 42 | case .M: return 0 43 | case .Q: return 3 44 | case .H: return 2 45 | } 46 | } 47 | 48 | var offset: Int { 49 | switch self { 50 | case .L: return 0 51 | case .M: return 1 52 | case .Q: return 2 53 | case .H: return 3 54 | } 55 | } 56 | } 57 | 58 | #if canImport(CoreImage) 59 | extension QRErrorCorrectLevel { 60 | /// Input value for CIFilter. 61 | public var ciQRCodeGeneratorInputCorrectionLevel: String { 62 | switch self { 63 | case .L: return "l" 64 | case .M: return "m" 65 | case .Q: return "q" 66 | case .H: return "h" 67 | } 68 | } 69 | } 70 | #endif 71 | -------------------------------------------------------------------------------- /Sources/QRMaskPattern.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | enum QRMaskPattern: Int { 26 | case _000, _001, _010, _011, _100, _101, _110, _111 27 | } 28 | 29 | extension QRMaskPattern { 30 | func getMask(_ i: Int, _ j: Int) -> Bool { 31 | switch self { 32 | case ._000: 33 | return (i + j) % 2 == 0 34 | case ._001: 35 | return i % 2 == 0 36 | case ._010: 37 | return j % 3 == 0 38 | case ._011: 39 | return (i + j) % 3 == 0 40 | case ._100: 41 | return (i / 2 + j / 3) % 2 == 0 42 | case ._101: 43 | return (i * j) % 2 + (i * j) % 3 == 0 44 | case ._110: 45 | return ((i * j) % 2 + (i * j) % 3) % 2 == 0 46 | case ._111: 47 | return ((i * j) % 3 + (i + j) % 2) % 2 == 0 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/QRMath.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | struct QRMath { 26 | /// glog 27 | /// 28 | /// - Parameter n: n | n >= 1. 29 | /// - Returns: glog(n), or a fatal error if n < 1. 30 | static func glog(_ n: Int) -> Int { 31 | precondition(n > 0, "glog only works with n > 0, not \(n)") 32 | return QRMath.instance.LOG_TABLE[n] 33 | } 34 | 35 | static func gexp(_ n: Int) -> Int { 36 | var n = n 37 | while n < 0 { 38 | n += 255 39 | } 40 | while n >= 256 { 41 | n -= 255 42 | } 43 | return QRMath.instance.EXP_TABLE[n] 44 | } 45 | 46 | private var EXP_TABLE: [Int] 47 | private var LOG_TABLE: [Int] 48 | 49 | private static let instance = QRMath() 50 | private init() { 51 | EXP_TABLE = [Int](repeating: 0, count: 256) 52 | LOG_TABLE = [Int](repeating: 0, count: 256) 53 | for i in 0..<8 { 54 | EXP_TABLE[i] = 1 << i 55 | } 56 | for i in 8..<256 { 57 | EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8] 58 | } 59 | for i in 0..<255 { 60 | LOG_TABLE[EXP_TABLE[i]] = i 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/QRMode.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | /// OptionSet 26 | enum QRMode: UInt { 27 | /// 1 << 0 28 | case number = 0b0001 29 | /// 1 << 1 30 | case alphaNumber = 0b0010 31 | /// 1 << 2 32 | case bitByte8 = 0b0100 33 | /// 1 << 3 34 | case kanji = 0b1000 35 | } 36 | 37 | extension QRMode { 38 | func bitCount(ofType type: Int) -> Int? { 39 | if 1 <= type && type < 10 { 40 | switch self { 41 | case .number: 42 | return 10 43 | case .alphaNumber: 44 | return 9 45 | case .bitByte8, .kanji: 46 | return 8 47 | } 48 | } else if type < 27 { 49 | switch self { 50 | case .number: 51 | return 12 52 | case .alphaNumber: 53 | return 11 54 | case .bitByte8: 55 | return 16 56 | case .kanji: 57 | return 10 58 | } 59 | } else if type < 41 { 60 | switch self { 61 | case .number: 62 | return 14 63 | case .alphaNumber: 64 | return 13 65 | case .bitByte8: 66 | return 16 67 | case .kanji: 68 | return 12 69 | } 70 | } else { 71 | return nil 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Sources/QRPatternLocator.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | struct QRPatternLocator { 25 | private static let PATTERN_POSITION_TABLE: [[Int]] = [ 26 | [], 27 | [6, 18], 28 | [6, 22], 29 | [6, 26], 30 | [6, 30], 31 | [6, 34], 32 | [6, 22, 38], 33 | [6, 24, 42], 34 | [6, 26, 46], 35 | [6, 28, 50], 36 | [6, 30, 54], 37 | [6, 32, 58], 38 | [6, 34, 62], 39 | [6, 26, 46, 66], 40 | [6, 26, 48, 70], 41 | [6, 26, 50, 74], 42 | [6, 30, 54, 78], 43 | [6, 30, 56, 82], 44 | [6, 30, 58, 86], 45 | [6, 34, 62, 90], 46 | [6, 28, 50, 72, 94], 47 | [6, 26, 50, 74, 98], 48 | [6, 30, 54, 78, 102], 49 | [6, 28, 54, 80, 106], 50 | [6, 32, 58, 84, 110], 51 | [6, 30, 58, 86, 114], 52 | [6, 34, 62, 90, 118], 53 | [6, 26, 50, 74, 98, 122], 54 | [6, 30, 54, 78, 102, 126], 55 | [6, 26, 52, 78, 104, 130], 56 | [6, 30, 56, 82, 108, 134], 57 | [6, 34, 60, 86, 112, 138], 58 | [6, 30, 58, 86, 114, 142], 59 | [6, 34, 62, 90, 118, 146], 60 | [6, 30, 54, 78, 102, 126, 150], 61 | [6, 24, 50, 76, 102, 128, 154], 62 | [6, 28, 54, 80, 106, 132, 158], 63 | [6, 32, 58, 84, 110, 136, 162], 64 | [6, 26, 54, 82, 110, 138, 166], 65 | [6, 30, 58, 86, 114, 142, 170] 66 | ] 67 | 68 | #if swift(<5.1) 69 | static func getPatternPosition(ofType typeNumber: Int) -> [Int] { 70 | return PATTERN_POSITION_TABLE[typeNumber - 1] 71 | } 72 | #else 73 | static subscript(typeNumber: Int) -> [Int] { 74 | return PATTERN_POSITION_TABLE[typeNumber - 1] 75 | } 76 | #endif 77 | } 78 | -------------------------------------------------------------------------------- /Sources/QRPolynomial.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 davidshimjs 3 | Copyright (c) 2017-2020 ApolloZhu 4 | Copyright (c) 2017 EyreFree 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | struct QRPolynomial { 26 | private var numbers: [Int] 27 | 28 | init(_ nums: Int..., shift: Int = 0) { 29 | self.init(nums, shift: shift) 30 | } 31 | 32 | init(_ nums: [Int], shift: Int = 0) { 33 | precondition(!nums.isEmpty, "polynomial should have at least 1 term") 34 | var offset = 0 35 | while offset < nums.count && nums[offset] == 0 { 36 | offset += 1 37 | } 38 | self.numbers = [Int](repeating: 0, count: nums.count - offset + shift) 39 | for i in 0.. Int { 45 | return numbers[index] 46 | } 47 | 48 | var count: Int { 49 | return numbers.count 50 | } 51 | 52 | func multiplying(_ e: QRPolynomial) -> QRPolynomial { 53 | var nums = [Int](repeating: 0, count: count + e.count - 1) 54 | for i in 0.. QRPolynomial { 63 | if count - e.count < 0 { 64 | return self 65 | } 66 | let ratio = QRMath.glog(self[0]) - QRMath.glog(e[0]) 67 | var num = [Int](repeating: 0, count: count) 68 | for i in 0.. QRPolynomial { 78 | var a = QRPolynomial(1) 79 | for i in 0.. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | struct QRRSBlock { 25 | let totalCount: Int 26 | let dataCount: Int 27 | } 28 | 29 | extension QRRSBlock { 30 | fileprivate static let RS_BLOCK_TABLE: [[Int]] = [ 31 | [1, 26, 19], 32 | [1, 26, 16], 33 | [1, 26, 13], 34 | [1, 26, 9], 35 | [1, 44, 34], 36 | [1, 44, 28], 37 | [1, 44, 22], 38 | [1, 44, 16], 39 | [1, 70, 55], 40 | [1, 70, 44], 41 | [2, 35, 17], 42 | [2, 35, 13], 43 | [1, 100, 80], 44 | [2, 50, 32], 45 | [2, 50, 24], 46 | [4, 25, 9], 47 | [1, 134, 108], 48 | [2, 67, 43], 49 | [2, 33, 15, 2, 34, 16], 50 | [2, 33, 11, 2, 34, 12], 51 | [2, 86, 68], 52 | [4, 43, 27], 53 | [4, 43, 19], 54 | [4, 43, 15], 55 | [2, 98, 78], 56 | [4, 49, 31], 57 | [2, 32, 14, 4, 33, 15], 58 | [4, 39, 13, 1, 40, 14], 59 | [2, 121, 97], 60 | [2, 60, 38, 2, 61, 39], 61 | [4, 40, 18, 2, 41, 19], 62 | [4, 40, 14, 2, 41, 15], 63 | [2, 146, 116], 64 | [3, 58, 36, 2, 59, 37], 65 | [4, 36, 16, 4, 37, 17], 66 | [4, 36, 12, 4, 37, 13], 67 | [2, 86, 68, 2, 87, 69], 68 | [4, 69, 43, 1, 70, 44], 69 | [6, 43, 19, 2, 44, 20], 70 | [6, 43, 15, 2, 44, 16], 71 | [4, 101, 81], 72 | [1, 80, 50, 4, 81, 51], 73 | [4, 50, 22, 4, 51, 23], 74 | [3, 36, 12, 8, 37, 13], 75 | [2, 116, 92, 2, 117, 93], 76 | [6, 58, 36, 2, 59, 37], 77 | [4, 46, 20, 6, 47, 21], 78 | [7, 42, 14, 4, 43, 15], 79 | [4, 133, 107], 80 | [8, 59, 37, 1, 60, 38], 81 | [8, 44, 20, 4, 45, 21], 82 | [12, 33, 11, 4, 34, 12], 83 | [3, 145, 115, 1, 146, 116], 84 | [4, 64, 40, 5, 65, 41], 85 | [11, 36, 16, 5, 37, 17], 86 | [11, 36, 12, 5, 37, 13], 87 | [5, 109, 87, 1, 110, 88], 88 | [5, 65, 41, 5, 66, 42], 89 | [5, 54, 24, 7, 55, 25], 90 | [11, 36, 12, 7, 37, 13], 91 | [5, 122, 98, 1, 123, 99], 92 | [7, 73, 45, 3, 74, 46], 93 | [15, 43, 19, 2, 44, 20], 94 | [3, 45, 15, 13, 46, 16], 95 | [1, 135, 107, 5, 136, 108], 96 | [10, 74, 46, 1, 75, 47], 97 | [1, 50, 22, 15, 51, 23], 98 | [2, 42, 14, 17, 43, 15], 99 | [5, 150, 120, 1, 151, 121], 100 | [9, 69, 43, 4, 70, 44], 101 | [17, 50, 22, 1, 51, 23], 102 | [2, 42, 14, 19, 43, 15], 103 | [3, 141, 113, 4, 142, 114], 104 | [3, 70, 44, 11, 71, 45], 105 | [17, 47, 21, 4, 48, 22], 106 | [9, 39, 13, 16, 40, 14], 107 | [3, 135, 107, 5, 136, 108], 108 | [3, 67, 41, 13, 68, 42], 109 | [15, 54, 24, 5, 55, 25], 110 | [15, 43, 15, 10, 44, 16], 111 | [4, 144, 116, 4, 145, 117], 112 | [17, 68, 42], 113 | [17, 50, 22, 6, 51, 23], 114 | [19, 46, 16, 6, 47, 17], 115 | [2, 139, 111, 7, 140, 112], 116 | [17, 74, 46], 117 | [7, 54, 24, 16, 55, 25], 118 | [34, 37, 13], 119 | [4, 151, 121, 5, 152, 122], 120 | [4, 75, 47, 14, 76, 48], 121 | [11, 54, 24, 14, 55, 25], 122 | [16, 45, 15, 14, 46, 16], 123 | [6, 147, 117, 4, 148, 118], 124 | [6, 73, 45, 14, 74, 46], 125 | [11, 54, 24, 16, 55, 25], 126 | [30, 46, 16, 2, 47, 17], 127 | [8, 132, 106, 4, 133, 107], 128 | [8, 75, 47, 13, 76, 48], 129 | [7, 54, 24, 22, 55, 25], 130 | [22, 45, 15, 13, 46, 16], 131 | [10, 142, 114, 2, 143, 115], 132 | [19, 74, 46, 4, 75, 47], 133 | [28, 50, 22, 6, 51, 23], 134 | [33, 46, 16, 4, 47, 17], 135 | [8, 152, 122, 4, 153, 123], 136 | [22, 73, 45, 3, 74, 46], 137 | [8, 53, 23, 26, 54, 24], 138 | [12, 45, 15, 28, 46, 16], 139 | [3, 147, 117, 10, 148, 118], 140 | [3, 73, 45, 23, 74, 46], 141 | [4, 54, 24, 31, 55, 25], 142 | [11, 45, 15, 31, 46, 16], 143 | [7, 146, 116, 7, 147, 117], 144 | [21, 73, 45, 7, 74, 46], 145 | [1, 53, 23, 37, 54, 24], 146 | [19, 45, 15, 26, 46, 16], 147 | [5, 145, 115, 10, 146, 116], 148 | [19, 75, 47, 10, 76, 48], 149 | [15, 54, 24, 25, 55, 25], 150 | [23, 45, 15, 25, 46, 16], 151 | [13, 145, 115, 3, 146, 116], 152 | [2, 74, 46, 29, 75, 47], 153 | [42, 54, 24, 1, 55, 25], 154 | [23, 45, 15, 28, 46, 16], 155 | [17, 145, 115], 156 | [10, 74, 46, 23, 75, 47], 157 | [10, 54, 24, 35, 55, 25], 158 | [19, 45, 15, 35, 46, 16], 159 | [17, 145, 115, 1, 146, 116], 160 | [14, 74, 46, 21, 75, 47], 161 | [29, 54, 24, 19, 55, 25], 162 | [11, 45, 15, 46, 46, 16], 163 | [13, 145, 115, 6, 146, 116], 164 | [14, 74, 46, 23, 75, 47], 165 | [44, 54, 24, 7, 55, 25], 166 | [59, 46, 16, 1, 47, 17], 167 | [12, 151, 121, 7, 152, 122], 168 | [12, 75, 47, 26, 76, 48], 169 | [39, 54, 24, 14, 55, 25], 170 | [22, 45, 15, 41, 46, 16], 171 | [6, 151, 121, 14, 152, 122], 172 | [6, 75, 47, 34, 76, 48], 173 | [46, 54, 24, 10, 55, 25], 174 | [2, 45, 15, 64, 46, 16], 175 | [17, 152, 122, 4, 153, 123], 176 | [29, 74, 46, 14, 75, 47], 177 | [49, 54, 24, 10, 55, 25], 178 | [24, 45, 15, 46, 46, 16], 179 | [4, 152, 122, 18, 153, 123], 180 | [13, 74, 46, 32, 75, 47], 181 | [48, 54, 24, 14, 55, 25], 182 | [42, 45, 15, 32, 46, 16], 183 | [20, 147, 117, 4, 148, 118], 184 | [40, 75, 47, 7, 76, 48], 185 | [43, 54, 24, 22, 55, 25], 186 | [10, 45, 15, 67, 46, 16], 187 | [19, 148, 118, 6, 149, 119], 188 | [18, 75, 47, 31, 76, 48], 189 | [34, 54, 24, 34, 55, 25], 190 | [20, 45, 15, 61, 46, 16] 191 | ] 192 | } 193 | 194 | extension QRErrorCorrectLevel { 195 | func getRSBlocks(ofType typeNumber: Int) -> [QRRSBlock] { 196 | let rsBlock = getRsBlockTable(ofType: typeNumber) 197 | let length = rsBlock.count / 3 198 | 199 | return (0.. [QRRSBlock] in 200 | let count = rsBlock[i * 3 + 0] 201 | let totalCount = rsBlock[i * 3 + 1] 202 | let dataCount = rsBlock[i * 3 + 2] 203 | let block = QRRSBlock(totalCount: totalCount, dataCount: dataCount) 204 | return [QRRSBlock](repeating: block, count: count) 205 | } 206 | } 207 | 208 | private func getRsBlockTable(ofType typeNumber: Int) -> [Int] { 209 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + offset] 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import QRCodeSwiftTests 3 | 4 | XCTMain([ 5 | testCase(QRCodeSwiftTests.allTests), 6 | ]) 7 | -------------------------------------------------------------------------------- /Tests/QRCodeSwiftTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Tests/QRCodeSwiftTests/QRCodeSwiftTests.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017-2020 ApolloZhu 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | import XCTest 24 | @testable import QRCodeSwift 25 | 26 | private func expect(_ generator: @autoclosure () throws -> QRCode, withFill fill: String, andPatch patch: String, toMatch expected: String) throws { 27 | let qrCode = try generator() 28 | let generated = qrCode.toString(filledWith: fill, patchedWith: patch) 29 | XCTAssertEqual(generated, expected) 30 | } 31 | 32 | private extension UnicodeScalar { 33 | static let values = Array([0...0xD7FF, 0xE000...0x10FFFF].joined()) 34 | static func randomElement(ignoredParameter: Int = 0) -> String { 35 | return "\(UnicodeScalar(values.randomElement()!)!)" 36 | } 37 | } 38 | 39 | private func randomStringOfUTF8Length(_ length: Int) -> String { 40 | var str = "" 41 | while str.utf8.count < length { 42 | str += UnicodeScalar.randomElement() 43 | if str.utf8.count > length { 44 | str = String(str.dropLast()) 45 | } 46 | } 47 | return str 48 | } 49 | 50 | class QRCodeSwiftTests: XCTestCase { 51 | func testSimple() throws { 52 | try expect(QRCode("https://gist.github.com/agentgt/1700331"), 53 | withFill: "##", andPatch: " ", 54 | toMatch: """ 55 | 56 | ############## ###### ## ###### #### ############## 57 | ## ## ## ######## #### ## ## ## ## 58 | ## ###### ## #### ## #### ## #### #### #### ## ###### ## 59 | ## ###### ## ## ###### #### #### ## ## ## ###### ## 60 | ## ###### ## ## ######## ## ## ## ## ###### ## 61 | ## ## ## ## ###### ## ## ## ## ## ## 62 | ############## ## ## ## ## ## ## ## ## ## ## ## ############## 63 | ## ## ## ###### ###### 64 | #### ######## ## ######## ## ## ## ## ## 65 | #### ## ## ## #### ###### ## ## ###### 66 | ## ## ######## ## ## ## #### ###### ###### 67 | ######## ## ## ## ## ## ## ## ## ###### ## ## 68 | ## #### ## ###### ######## ######## #### 69 | #### ## ############ #### ## ## ###### ## #### 70 | #### #### ## ## ## ## #### #### ## ## ## ## #### 71 | ## ## #### #### ## #### #### ######## 72 | ## ## ###### ## ## #### ## ## ###### ###### ## ## ## 73 | ############ ## #### ## ## ## ###### ## ## 74 | #### ######## ## ###### #### ## ###### #### ## #### ## 75 | ########## #### ###### ## ############## ## ## ## ## 76 | ###### ## #### ######## ## #### ################ 77 | ## ## ## ## ## #### ## ######## ## #### ###### ## 78 | #### ## ## ######## #### #### ## ###### ## ## 79 | ########## ## ########## ## #### #### ## ## ## #### 80 | ## ############## #### #### ## #### ###### ## #### 81 | ## ## ######## ## ## ## ## 82 | ## ########## ######## #### ## ############ ## ## #### 83 | ## ## ## ###### #### #### ###### #### ## #### 84 | ## #### #### ###### ## ## ## ################ ## ## 85 | #### #### #### ###### ###### ## #### ## 86 | ############## ## #### ###### ## ## ## ###### ## 87 | ## ## #### #### ## ## #### #### #### #### 88 | ## ###### ## #### ###### ## ###### ################ ## 89 | ## ###### ## ## ######## #### ## ###### ## ## 90 | ## ###### ## ## ## ## #### ###### ## ## ## #### ## 91 | ## ## ## ## #### ###### ## ############ ## 92 | ############## #### ###### ## ## #### ## ###### ## ## 93 | 94 | """) 95 | } 96 | 97 | func testLowErrorCorrectLevel() throws { 98 | try expect( QRCode("https://passport.bilibili.com/qrcode/h5/login?oauthKey=2f3ab118e214e7ad69683df50918a481", 99 | errorCorrectLevel: .L), 100 | withFill: "@@", andPatch: " ", 101 | toMatch: """ 102 | 103 | @@@@@@@@@@@@@@ @@ @@ @@ @@@@ @@ @@@@@@@@ @@@@@@@@@@@@@@ 104 | @@ @@ @@ @@@@@@@@ @@ @@ @@ @@ @@ @@ 105 | @@ @@@@@@ @@ @@@@ @@ @@@@@@@@@@ @@@@@@@@@@ @@ @@ @@ @@@@@@ @@ 106 | @@ @@@@@@ @@ @@@@@@ @@ @@ @@ @@@@@@@@@@ @@ @@@@@@ @@ 107 | @@ @@@@@@ @@ @@@@ @@ @@@@ @@ @@ @@ @@@@@@ @@ @@@@@@ @@ 108 | @@ @@ @@@@@@ @@@@@@@@ @@ @@ @@ 109 | @@@@@@@@@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@@@@@@@@@ 110 | @@@@ @@ @@ @@@@ @@@@ @@@@ @@@@@@ 111 | @@@@ @@@@@@ @@ @@@@ @@@@ @@ @@@@ @@ @@ @@@@@@@@ 112 | @@@@@@ @@@@@@ @@ @@ @@ @@@@@@@@ @@ @@@@ 113 | @@@@@@@@@@@@@@@@ @@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@ 114 | @@@@ @@ @@ @@ @@@@@@@@ @@ @@ @@@@ @@ 115 | @@ @@ @@@@@@@@ @@@@ @@@@@@ @@@@ @@ @@ @@@@@@ @@ @@ 116 | @@ @@ @@@@ @@ @@@@ @@@@@@@@ @@@@@@ @@@@@@@@ 117 | @@@@ @@@@ @@@@ @@@@@@@@@@@@ @@ @@@@@@@@ @@@@ @@ @@ 118 | @@ @@@@ @@ @@ @@@@@@ @@ @@ @@ @@@@ @@ @@@@@@@@@@ 119 | @@@@ @@@@@@@@@@ @@@@ @@@@@@@@@@ @@ @@@@ @@@@ @@@@@@ @@ @@ 120 | @@ @@@@ @@ @@@@@@ @@ @@@@@@@@ @@@@@@ @@@@@@@@@@ 121 | @@@@@@@@ @@ @@ @@ @@ @@@@ @@@@@@@@@@ @@@@ 122 | @@ @@@@ @@@@ @@ @@@@@@@@@@ @@@@ @@ @@ @@ @@@@ 123 | @@@@ @@@@@@@@ @@@@ @@@@@@@@@@@@ @@ @@ @@@@ @@@@@@@@ 124 | @@ @@@@@@ @@ @@ @@@@@@ @@@@@@ @@ @@ 125 | @@ @@ @@@@@@@@@@ @@@@@@@@@@ @@ @@@@ @@ @@ @@@@@@ 126 | @@ @@ @@ @@ @@ @@@@@@ @@@@ @@ @@@@@@ @@@@ 127 | @@@@@@ @@ @@ @@ @@@@ @@@@@@@@ @@@@@@@@ @@ @@@@ @@@@@@ 128 | @@@@@@ @@ @@ @@ @@@@@@ @@ @@ @@ @@ @@@@ @@ @@ 129 | @@@@ @@@@@@@@ @@@@@@ @@ @@@@ @@@@@@@@@@@@@@ @@ 130 | @@ @@ @@ @@@@@@@@ @@@@@@ @@ @@@@ @@@@ 131 | @@@@ @@@@@@ @@ @@@@ @@@@@@@@ @@ @@@@ @@@@@@@@@@@@@@@@@@ 132 | @@ @@ @@ @@ @@@@ @@ @@ @@ 133 | @@@@@@@@@@@@@@ @@ @@@@@@@@@@ @@ @@@@@@@@@@ @@ @@ @@ 134 | @@ @@ @@ @@@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@ @@ 135 | @@ @@@@@@ @@ @@ @@@@ @@@@ @@ @@@@ @@ @@@@@@@@@@@@@@@@@@ 136 | @@ @@@@@@ @@ @@@@@@ @@ @@ @@ @@@@ @@@@@@ @@@@ 137 | @@ @@@@@@ @@ @@ @@@@@@@@ @@@@@@@@ @@@@ @@@@@@ 138 | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@ 139 | @@@@@@@@@@@@@@ @@@@@@@@ @@@@ @@ @@@@@@@@@@@@ @@ @@@@@@@@@@@@@@ 140 | 141 | """) 142 | } 143 | 144 | func testBorderless() throws { 145 | try expect(QRCode("https://github.com/ApolloZhu", withBorder: false), 146 | withFill: "MM", andPatch: " ", 147 | toMatch: """ 148 | MMMMMMMMMMMMMM MMMM MM MM MMMMMM MM MM MMMMMMMMMMMMMM 149 | MM MM MM MMMMMMMM MM MMMMMM MM MM MM 150 | MM MMMMMM MM MMMM MM MMMMMMMM MMMMMMMMMMMMMM MM MMMMMM MM 151 | MM MMMMMM MM MM MM MM MM MM MM MM MM MMMMMM MM 152 | MM MMMMMM MM MM MMMM MMMMMMMMMMMM MMMM MM MMMMMM MM 153 | MM MM MMMM MM MM MMMM MM MM MM 154 | MMMMMMMMMMMMMM MM MM MM MM MM MM MM MM MM MMMMMMMMMMMMMM 155 | MM MMMM MM MM MM 156 | MMMM MMMM MMMM MM MM MMMMMM MM MMMM 157 | MM MM MMMMMMMMMM MMMMMM MMMMMMMMMMMM MM MMMMMM 158 | MMMM MMMMMMMM MM MM MM MMMM MMMMMM MM MMMMMM 159 | MMMM MM MM MM MMMMMM MMMMMMMMMM MMMMMMMMMMMM 160 | MM MMMMMM MMMM MM MM MM MM MM MMMMMMMM MM 161 | MM MMMMMM MM MMMM MM MM MMMM MMMM MM 162 | MMMM MMMM MM MM MM MMMM MM MM 163 | MMMM MM MM MM MM MM MM MMMM MMMM MMMM MM 164 | MMMMMM MMMMMMMM MM MM MMMM MM MMMM MM MM 165 | MMMM MM MM MM MMMM MMMM MMMM MM MM MMMMMMMM MM 166 | MMMM MMMM MM MM MMMM MMMMMM MMMM MMMM MMMMMM MM 167 | MM MM MMMM MMMMMMMMMM MM MMMM MMMMMM MM MMMMMM 168 | MM MMMMMMMM MMMM MMMMMM MM MMMM MM MM MMMM 169 | MM MM MM MMMM MMMM MMMM MM MMMM MMMMMMMM 170 | MM MMMM MMMM MM MMMM MM MM MM MMMM MMMMMM 171 | MM MM MMMM MMMM MM MM MMMM MMMMMM 172 | MMMMMMMMMMMMMM MMMM MM MMMM MM MMMM MMMMMMMMMM 173 | MMMMMMMMMMMMMM MM MM MM MM MMMM MM 174 | MMMMMMMMMMMMMM MMMM MMMM MM MMMMMMMMMMMMMMMM MM MMMM 175 | MM MM MMMM MMMM MMMM MMMM MMMMMMMM 176 | MM MMMMMM MM MMMM MM MMMM MM MMMM MMMMMMMMMMMMMMMMMM 177 | MM MMMMMM MM MM MMMM MMMMMM MM MM MM MMMM 178 | MM MMMMMM MM MM MM MMMMMM MM MM MM MM MMMMMM 179 | MM MM MMMM MM MM MM MMMMMM 180 | MMMMMMMMMMMMMM MM MMMM MMMMMM MMMM MMMM MM MM 181 | """) 182 | } 183 | 184 | 185 | func testEFQRCode() throws { 186 | try expect(QRCode("https://github.com/EyreFree/EFQRCode"), 187 | withFill: "WW", andPatch: " ", 188 | toMatch: """ 189 | 190 | WWWWWWWWWWWWWW WW WWWW WW WWWWWW WWWWWWWWWWWWWW 191 | WW WW WW WW WWWWWWWWWWWWWW WWWWWW WWWW WW WW 192 | WW WWWWWW WW WW WW WWWW WW WWWW WW WW WW WWWWWW WW 193 | WW WWWWWW WW WW WWWW WWWW WW WW WW WWWW WW WWWWWW WW 194 | WW WWWWWW WW WWWW WW WW WWWW WWWW WW WWWWWW WW 195 | WW WW WWWWWW WW WWWWWWWW WW WW WWWW WW WW 196 | WWWWWWWWWWWWWW WW WW WW WW WW WW WW WW WW WW WW WWWWWWWWWWWWWW 197 | WW WWWWWW WW WWWWWW WW 198 | WW WW WW WWWWWW WWWWWW WWWW WWWWWW WWWW 199 | WWWW WW WWWWWWWW WWWW WW WWWW WW WW WW WWWWWW 200 | WW WWWWWWWWWWWWWW WW WW WWWWWWWWWW WW WW WW WWWW WWWWWWWW 201 | WWWW WWWWWW WW WW WW WW WW WWWW WW WW 202 | WWWWWWWWWWWWWWWW WWWWWWWWWW WW WWWW WWWWWW WW 203 | WWWW WW WW WW WWWWWW WWWW WWWWWW WWWW WW WWWW WW WWWW 204 | WWWW WWWWWWWW WW WW WW WWWWWW WW WW WW 205 | WWWWWWWW WW WWWW WW WW WWWWWWWW WWWW WWWWWWWW WW 206 | WWWW WWWWWWWWWWWWWW WWWWWWWWWW WWWW WWWW WW WW WWWWWW WWWWWWWW 207 | WW WW WWWW WWWWWWWWWWWW WW WWWWWWWWWW WW 208 | WWWWWWWWWW WWWWWWWW WWWWWW WWWWWWWW WWWW WWWW WWWWWW 209 | WW WWWWWWWW WWWW WW WWWWWWWWWWWW WW WWWW WWWW 210 | WWWWWW WWWWWWWWWWWW WWWWWWWW WW WWWWWW WWWWWWWW WW 211 | WW WW WWWWWWWWWW WW WWWW WW WWWWWWWW WWWW WWWW 212 | WWWWWW WW WW WWWW WWWWWW WW WWWW WWWWWWWW WWWW 213 | WW WW WW WW WW WW WW WW WWWW WW WW WWWW 214 | WWWWWWWWWW WWWW WW WW WW WWWWWW WW WW WW WW 215 | WWWW WWWW WWWWWWWW WWWW WW WWWW WWWW WW WW 216 | WW WW WWWWWW WWWW WWWW WW WWWW WW WWWWWWWWWWWWWW WW WW 217 | WW WW WW WW WW WWWW WWWWWW WWWW WW WW 218 | WWWW WW WW WWWW WWWW WW WW WW WWWWWWWWWWWW WW 219 | WW WW WW WW WW WW WWWWWWWWWW WW WWWW 220 | WWWWWWWWWWWWWW WW WW WWWWWWWWWWWWWWWWWW WW WWWW WW WW WWWWWW 221 | WW WW WW WW WW WW WW WWWWWW WW WW 222 | WW WWWWWW WW WW WWWW WW WW WWWWWWWWWW WWWWWWWWWWWW WW 223 | WW WWWWWW WW WW WWWWWW WWWWWW WW WWWWWWWW WW WW WWWW 224 | WW WWWWWW WW WW WWWW WW WWWW WWWWWWWWWW WW WWWW WW 225 | WW WW WW WWWW WW WWWW WW WWWWWW WWWW WW 226 | WWWWWWWWWWWWWW WW WW WWWWWW WW WW WW WWWWWW WWWW WWWW 227 | 228 | """) 229 | } 230 | 231 | func testEmpty() throws { 232 | try expect(QRCode("", errorCorrectLevel: .L), 233 | withFill: "XX", andPatch: " ", 234 | toMatch: """ 235 | 236 | XXXXXXXXXXXXXX XX XX XXXXXXXXXXXXXX 237 | XX XX XX XX XX XX 238 | XX XXXXXX XX XX XX XXXXXX XX 239 | XX XXXXXX XX XX XX XX XXXXXX XX 240 | XX XXXXXX XX XXXXXX XX XXXXXX XX 241 | XX XX XXXXXX XX XX XX 242 | XXXXXXXXXXXXXX XX XX XX XXXXXXXXXXXXXX 243 | XXXXXX 244 | XXXXXXXXXX XXXXXXXX XXXX XX XX XX 245 | XXXX XXXX XX XX XX XX 246 | XX XX XX XXXX XX XXXXXXXXXX 247 | XX XX XXXX XXXX XX XX 248 | XXXXXX XXXXXXXX XX XX XXXXXXXXXX 249 | XXXXXXXXXXXXXX XX 250 | XXXXXXXXXXXXXX XXXXXX XX XXXX 251 | XX XX XXXXXXXXXXXX XX 252 | XX XXXXXX XX XXXXXX XX XX XX 253 | XX XXXXXX XX XXXX XX XX XX 254 | XX XXXXXX XX XXXX XX XX XXXXXX 255 | XX XX XXXX XXXX XX 256 | XXXXXXXXXXXXXX XX XXXX XX XXXXXXXX 257 | 258 | """) 259 | } 260 | 261 | func testStressWithPi() throws { 262 | let content = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989" 263 | try expect(QRCode(content, errorCorrectLevel: .M), 264 | withFill: "%%", andPatch: " ", 265 | toMatch: """ 266 | 267 | %%%%%%%%%%%%%% %%%%%% %%%%%%%%%%%% %%%%%%%% %%%%%% %% %% %%%% %%%% %%%%%% %% %% %%%%%% %%%% %%%%%% %% %%%%%% %% %%%%%% %% %% %% %% %% %%%% %%%%%%%%%%%%%% 268 | %% %% %% %% %%%%%%%% %% %% %% %% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %% %% 269 | %% %%%%%% %% %% %%%% %% %%%% %% %%%% %% %%%%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %%%% %% %%%%%%%% %% %%%% %% %%%%%% %% 270 | %% %%%%%% %% %%%%%% %%%%%% %% %% %% %%%% %%%%%% %% %%%% %% %% %% %% %% %%%%%% %% %% %% %%%% %% %%%% %% %% %%%% %% %%%%%%%% %% %%%%%%%% %% %%%%%% %% 271 | %% %%%%%% %% %% %%%% %% %% %% %% %%%%%%%%%%%% %%%%%%%% %%%% %% %% %% %% %%%%%%%%%% %% %%%% %%%% %% %% %%%%%%%%%%%%%% %%%% %%%% %%%% %%%% %% %% %%%%%% %% 272 | %% %% %%%%%%%%%%%% %% %% %% %% %% %% %% %%%%%% %% %% %%%%%%%% %% %% %%%% %% %% %%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%%%%%% %% %% 273 | %%%%%%%%%%%%%% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %%%%%%%%%%%%%% 274 | %% %% %%%% %%%%%%%% %%%% %% %% %%%% %% %% %% %%%%%% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%% 275 | %% %%%% %%%%%% %% %%%%%%%% %% %% %%%%%% %%%%%%%%%%%%%% %% %% %%%% %%%%%%%% %%%%%% %%%%%%%%%%%% %%%% %%%% %%%% %% %% %%%% %%%%%%%%%%%% %% %% %% %% %%%% %% %% %% %%%% 276 | %% %% %% %%%%%% %% %%%% %% %%%% %%%%%% %% %%%%%% %%%%%%%% %% %%%%%% %% %%%% %%%% %%%%%%%% %%%% %%%% %% %% %%%% %%%%%% %% %%%%%% %%%%%% %%%% %% 277 | %%%% %% %%%%%% %% %%%%%%%% %%%% %% %%%% %%%%%% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %%%%%% %% %% %%%%%%%% %% %% %% %% %% %% 278 | %% %% %% %% %% %%%% %% %% %% %%%%%%%% %%%%%% %% %% %% %%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %% %% 279 | %% %%%%%% %%%% %% %% %%%% %%%%%%%% %% %% %%%% %%%%%%%% %% %%%% %%%% %%%%%% %%%% %% %% %% %% %%%% %% %% %% %%%% %%%% %%%% %% %%%% %%%%%% %% %% %% %%%%%% 280 | %% %% %% %% %%%%%% %% %% %% %%%%%%%%%% %%%%%% %%%% %%%% %% %% %% %%%% %% %% %% %%%% %%%%%%%% %% %% %% %% %%%% %% %%%%%% %%%% %% %% %%%% %% %% %% 281 | %% %%%%%%%% %% %% %% %%%% %% %% %% %%%% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %%%% %% %% %%%% %% 282 | %% %% %% %% %% %% %%%% %%%% %% %% %%%% %%%% %%%%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%% %% %%%% %% 283 | %%%%%% %% %% %%%%%%%% %%%%%% %%%%%%%% %%%% %% %%%%%% %% %%%%%%%% %%%% %% %% %%%% %% %% %%%%%% %% %% %%%% %%%% %% %%%% %% %% %%%% %% %%%% %% %%%%%%%%%%%% 284 | %% %% %%%%%% %%%% %%%%%%%%%%%% %%%%%%%% %% %%%% %%%% %% %%%% %% %%%%%%%% %% %%%% %% %%%%%%%% %%%% %%%%%%%%%%%%%%%% %%%%%% %% %% %%%% %% %% %%%%%% 285 | %%%% %%%%%% %% %% %% %%%% %% %% %% %%%%%% %% %%%% %% %%%% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% 286 | %% %%%%%% %%%%%% %%%%%%%% %% %% %% %%%%%% %%%%%% %% %%%% %%%%%% %% %% %%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %% %%%% 287 | %%%% %%%% %%%% %% %%%% %%%% %% %% %% %% %% %%%% %%%%%%%% %%%% %%%%%%%% %%%%%%%%%%%% %%%% %%%%%%%% %% %%%%%%%%%% %%%% %% %% %% %%%%%%%%%% %% %%%% %%%%%% %% 288 | %% %%%%%%%% %%%% %%%% %%%%%% %% %%%%%%%% %%%%%%%% %%%% %%%% %%%%%%%% %% %% %%%% %% %%%% %%%%%%%%%%%% %%%% %%%% %%%% %%%% %% %%%% %%%% %% %%%% %%%%%%%%%% %% 289 | %% %% %% %% %%%% %% %%%%%% %% %%%%%% %% %% %% %% %% %%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%% %%%% %% %%%% %%%%%%%% 290 | %%%% %% %% %% %%%%%% %% %%%% %% %% %% %% %% %% %%%% %%%% %%%%%%%% %% %% %%%%%% %% %%%%%%%% %% %% %%%% %% %% %% %% %%%%%%%% %% %% %% %% %% %%%% %%%% %%%%%% 291 | %% %% %%%%%%%%%% %% %% %% %% %% %% %%%%%% %% %% %% %% %% %%%%%%%% %%%%%%%%%%%%%% %% %%%% %%%% %% %%%%%% %%%%%% %%%%%% %%%%%% %% %%%% %%%%%%%% %% %% %% %% 292 | %% %% %% %%%%%% %% %%%% %% %% %% %% %%%% %%%% %%%%%%%%%%%%%% %% %%%%%% %%%% %%%% %%%%%%%% %%%% %% %% %%%% %% %%%%%%%% %%%%%%%%%%%% %%%% %% %% %%%% 293 | %%%%%%%%%% %%%%%% %%%%%% %%%%%% %% %%%% %%%%%% %% %%%%%%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %%%%%%%% 294 | %% %% %% %%%% %%%% %% %% %% %% %% %% %%%% %%%%%% %%%%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%% %% %% %%%% %% 295 | %%%%%%%%%%%%%%%% %% %%%%%%%%%%%% %%%%%% %%%%%%%%%%%%%%%% %%%% %% %%%% %% %%%%%%%%%%%%%%%% %%%% %%%% %%%% %% %% %%%%%%%%%% %% %% %%%% %% %%%%%% %%%% %% %%%%%%%%%%%%%%%% 296 | %%%%%% %%%%%% %% %% %%%%%%%% %%%%%%%%%% %%%% %% %%%% %%%%%%%% %% %% %% %% %% %% %% %%%% %% %%%%%% %%%% %%%% %%%% %% %% %% %% %% %% %% %% %% 297 | %% %% %% %% %% %%%%%% %% %%%%%%%%%% %% %% %%%% %% %% %% %% %% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %% %% %%%% 298 | %% %% %%%%%% %% %% %% %% %%%%%%%%%% %%%% %%%% %%%% %% %% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %%%% 299 | %%%%%%%%%% %% %%%%%%%%%% %%%%%%%%%% %%%%%%%%%% %% %%%% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%%%% %%%% %%%% %% %% %%%% %% %%%%%%%%%%%% %%%% %% %% %% %% %%%%%%%% %%%%%%%%%%%% %%%% 300 | %% %%%% %%%%%%%%%% %%%%%% %%%% %%%% %%%%%%%% %% %%%% %%%% %%%% %%%% %%%% %% %% %%%%%%%% %% %% %% %%%%%%%%%% %% %%%% %%%% %%%% %% %% 301 | %%%% %%%%%%%%%% %% %% %%%%%% %% %% %%%% %%%%%%%% %%%%%%%%%% %% %% %% %% %% %%%%%%%% %% %% %%%% %% %% %%%% %% %%%% %% %% %% %% %% %% %%%% %% %%%%%% 302 | %%%%%%%% %% %% %%%%%% %% %% %%%%%%%%%% %% %% %% %%%% %%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %%%%%% %% %%%% %%%%%% %% %% %%%%%%%% %% %% 303 | %% %%%% %%%%%%%%%%%% %%%% %% %% %%%% %%%%%%%% %%%%%%%%%%%% %%%% %%%%%%%% %%%% %% %% %% %%%% %% %%%%%% %%%% %% %%%%%% %% %% %% %% %%%%%%%% %% %% %% %% %% %% %% 304 | %% %%%% %% %% %%%% %%%% %% %%%%%%%%%%%% %%%%%%%%%%%%%% %%%%%%%% %% %% %%%%%% %%%%%% %% %%%% %%%%%% %%%% %%%%%%%% %%%% %% %%%% %% %% %%%%%%%%%% %%%%%%%% %% %%%%%% %% %% 305 | %%%%%% %%%%%% %% %%%% %% %%%%%%%%%% %% %% %% %%%%%% %%%%%%%%%% %%%%%% %%%% %%%%%% %% %% %% %%%%%%%% %% %% %% %% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %%%% %%%%%% 306 | %% %% %%%% %%%%%%%%%%%%%% %% %%%%%%%%%%%% %% %% %% %%%%%% %%%%%%%% %% %% %% %% %%%%%% %%%% %% %%%%%%%% %% %%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%%%%%% %% 307 | %%%% %%%% %%%%%% %% %%%%%%%% %%%% %% %% %%%% %% %% %%%%%%%% %%%% %% %%%%%% %%%% %%%%%% %% %% %%%% %% %% %%%%%% %% %%%% %%%%%%%% %%%% %% %%%% %% %% %%%% 308 | %% %%%% %% %%%% %%%% %%%%%%%%%% %% %%%% %%%% %% %% %% %%%% %%%%%%%% %%%% %% %%%%%%%%%% %%%%%% %% %% %% %%%% %%%%%%%% %% %%%% %%%% %%%%%% %%%%%%%% 309 | %% %% %%%%%% %% %%%%%%%% %%%% %% %% %%%%%% %% %%%% %%%%%%%%%%%% %% %% %% %% %% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% 310 | %%%%%%%% %% %%%%%%%% %%%% %%%%%%%%%%%% %%%%%% %%%%%% %% %%%% %% %%%%%% %% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %%%% %% %% %%%% 311 | %% %%%%%%%%%%%% %%%%%% %%%% %% %% %%%%%%%%%%%% %% %% %%%%%% %% %%%%%%%% %%%% %% %%%%%% %%%%%% %%%% %% %% %%%% %% %% %% %% %%%% %%%% %% 312 | %% %%%%%% %%%% %%%% %%%%%% %%%%%% %%%%%%%% %%%%%% %% %%%%%%%% %%%% %% %%%% %%%%%% %%%%%% %%%% %% %% %% %%%% %% %%%% %% %% %%%%%% %% 313 | %%%% %%%%%% %% %%%% %%%% %%%%%% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %% %% %% %% %%%%%%%% %% %% %%%% %% %% %%%%%% 314 | %% %%%% %% %% %% %% %%%% %% %% %% %% %% %% %% %%%%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %%%%%% %% %% %%%%%%%% %% %% %% %% %% 315 | %%%% %%%%%% %% %% %%%%%%%%%% %%%% %% %% %% %%%%%% %% %%%% %%%%%%%%%% %% %% %% %%%% %%%%%%%% %% %% %% %%%%%%%% %%%% %% %% %% %% %% %%%% %% %% 316 | %% %% %% %% %% %% %%%%%% %%%%%%%%%% %%%% %% %% %%%%%%%%%% %% %%%% %%%%%% %% %% %%%%%% %%%%%% %%%%%%%%%% %% %% %%%% %%%% %% %% %% %% %%%% %% %% %% 317 | %% %%%%%%%%%% %% %%%% %% %%%% %%%%%%%%%%%%%% %% %% %%%%%%%% %%%%%%%% %% %%%% %% %% %% %% %%%%%%%% %% %% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %%%%%% %%%% 318 | %%%% %%%% %%%% %%%% %%%%%% %% %% %%%%%% %% %% %%%% %%%%%%%% %%%% %%%%%%%% %% %% %%%% %%%%%% %% %% %%%%%%%% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%% 319 | %% %%%% %%%%%% %% %%%% %% %%%%%%%% %% %% %% %%%%%%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %% %% %%%% %%%% %% %% %%%%%% %% %%%% %% %% %%%%%%%% 320 | %%%% %%%% %%%%%%%% %% %% %% %%%%%% %%%%%%%% %% %%%% %%%% %% %%%%%% %%%%%%%% %%%%%% %% %% %% %%%%%% %%%% %%%% %%%%%%%%%% %%%%%%%% %%%%%% %%%%%%%% %%%%%% %%%% 321 | %%%%%% %%%% %%%%%% %% %% %%%%%% %%%%%%%% %% %%%% %% %% %% %% %%%% %%%% %% %% %%%% %% %% %% %% %% %%%%%%%% %%%% %% %% %% %%%%%%%% %% %% %% %% 322 | %% %% %% %% %% %% %%%% %% %%%%%%%%%%%% %% %%%%%% %% %% %%%%%% %%%% %%%% %%%%%% %% %% %%%%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%% 323 | %% %%%%%%%%%% %% %%%%%%%% %%%%%% %% %%%%%%%%%%%%%%%% %%%%%%%%%%%% %%%%%%%%%% %% %%%%%%%%%%%%%% %% %%%%%%%%%%%% %% %% %% %%%% %%%%%%%%%% %% %%%% %% %% %%%%%%%% %%%%%%%%%%%%%% %% 324 | %%%% %% %% %% %%%%%%%% %% %% %%%% %%%% %%%% %% %% %%%% %% %%%% %%%%%% %%%%%%%% %%%%%% %% %%%% %%%% %%%%%% %%%%%% %%%% %% %% %% %% %% %% %% 325 | %% %%%% %% %% %%%% %% %% %%%% %% %%%% %% %% %%%% %% %%%% %%%% %% %%%%%%%% %% %% %% %%%%%%%% %% %%%% %%%%%% %% %%%% %% %%%% %% %% %%%%%%%% %% %% %% %% %% %%%% %% 326 | %%%%%%%%%% %% %% %% %%%%%%%%%%%% %% %% %%%%%% %%%%%%%%%% %% %%%%%% %%%%%% %%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%% %%%%%%%% %% %%%%%%%% %% %%%%%% %% %%%% 327 | %%%%%%%%%%%%%%%%%% %% %% %% %% %%%% %% %%%%%%%%%%%%%% %%%%%%%%%% %% %%%% %% %% %%%%%%%%%% %%%% %% %% %%%% %% %%%%%%%%%% %% %% %% %% %%%% %%%%%%%%%% %% 328 | %%%%%%%%%%%% %% %% %%%% %%%%%%%% %%%% %%%%%% %% %%%%%%%% %%%% %% %%%% %%%% %% %%%%%% %% %% %%%% %% %% %%%% %% %%%% %% %%%% %% %%%% %% %%%%%%%% %% %% 329 | %%%%%%%%%% %%%%%%%%%% %%%% %%%% %%%% %%%%%%%% %%%%%% %%%% %%%%%%%%%%%% %%%%%% %% %% %% %% %% %%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %%%%%%%% %% 330 | %%%% %%%%%% %%%% %% %% %% %%%% %%%%%%%%%%%%%% %% %% %% %%%%%%%% %% %% %% %%%%%% %% %% %%%%%%%% %% %% %%%% %% %% %%%%%%%% %% %% %%%%%%%% %%%%%% %%%% 331 | %%%% %%%%%%%% %% %% %% %%%% %%%% %%%%%% %%%% %% %%%% %% %% %%%%%%%% %%%% %% %%%% %% %%%% %% %%%%%% %%%% %%%%%%%% %% %% %%%% %% %% %%%%%% %% %%%%%%%% 332 | %%%% %% %% %%%% %% %% %% %% %% %%%% %% %%%% %%%% %% %% %% %%%% %%%%%%%% %%%% %% %%%% %%%% %%%% %% %% %% %% %% %%%%%% %%%% %%%% %%%%%%%%%%%% 333 | %% %%%% %%%% %%%%%%%%%%%%%%%% %%%% %%%%%% %% %% %%%% %%%% %% %% %% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %% %% 334 | %%%% %%%%%% %%%% %%%% %%%% %% %% %% %%%%%% %% %% %% %% %% %% %%%% %% %% %%%%%%%% %% %% %%%%%%%%%% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %% 335 | %%%%%%%%%%%% %%%%%% %%%%%%%%%%%% %%%%%%%%%% %% %% %% %% %% %% %% %%%% %% %% %% %%%% %%%%%%%% %% %% %%%% %% %%%%%%%%%% %% %% %% %% %% 336 | %% %% %%%%%%%% %% %% %% %% %%%% %% %% %%%% %%%%%%%% %% %%%%%% %%%% %% %%%% %% %% %%%% %% %% %% %%%%%% %% %% %% %% %% %%%%%%%%%%%% 337 | %%%%%%%%%% %% %% %% %% %%%%%%%% %% %%%%%%%% %% %% %% %%%%%%%% %% %%%% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%% %% %% %% %%%%%%%% %%%% %% %% %%%% %% 338 | %%%% %%%%%% %% %% %% %%%% %% %%%%%%%%%%%%%% %% %% %%%%%% %% %%%%%%%%%% %% %%%%%%%%%% %%%%%% %%%%%%%% %% %% %%%%%% %%%% %%%% %%%%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%% %% %%%%%% 339 | %% %% %%%%%%%%%% %%%%%%%% %% %%%%%% %% %%%%%% %%%%%% %% %% %%%%%%%% %%%%%% %% %% %%%% %% %%%% %% %% %% %%%% %% %%%%%% %% %% %%%%%% %% %% %% %%%%%% 340 | %%%% %%%% %%%%%% %% %%%% %% %%%%%% %% %%%%%%%%%% %%%% %%%% %% %%%%%% %% %%%% %%%%%% %% %% %%%% %% %%%% %% %%%% %% %% %%%%%% %%%% %% %% %% 341 | %% %% %%%% %%%%%% %% %%%% %%%%%% %% %% %% %%%% %% %%%%%% %% %% %%%%%%%% %%%% %% %%%%%%%% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %%%%%%%%%%%% 342 | %%%% %% %% %%%%%% %%%% %% %% %%%% %%%% %%%%%% %%%% %%%%%%%% %% %%%%%%%% %% %% %% %%%%%%%% %% %%%%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %%%%%%%% %% 343 | %% %%%% %% %%%% %%%%%% %%%%%%%% %%%% %% %% %%%%%% %% %% %%%% %%%%%%%%%% %% %%%% %%%% %% %%%%%%%%%% %%%% %% %%%%%% %% %%%% %%%%%% %%%%%% %%%%%%%% %% %%%%%%%%%% 344 | %% %%%%%%%% %% %%%%%% %%%%%%%%%%%%%% %% %%%%%%%% %%%%%%%% %% %%%%%%%% %% %%%%%% %% %%%% %% %% %%%%%% %%%%%%%%%%%%%% %% %%%%%% %%%% %%%%%% %%%% %% %% %% %%%%%% 345 | %% %%%%%% %% %% %% %%%% %% %%%%%% %% %% %% %% %%%%%% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%% %%%% %% %% 346 | %% %% %% %% %% %%%%%% %%%% %% %% %% %% %%%%%%%% %% %%%%%%%%%% %% %% %%%%%%%% %% %% %%%% %% %% %%%%%%%% %% %% %% %% %% %% %% %%%% 347 | %%%%%% %% %% %% %%%%%%%% %%%% %% %%%%%%%% %%%%%%%%%%%% %% %% %% %% %%%%%%%%%%%%%% %%%% %%%%%%%%%% %%%%%% %% %% %% %%%%%%%%%% %%%% %%%%%% %% %%%% 348 | %%%%%% %%%% %%%% %% %%%%%%%%%%%%%% %% %%%%%% %% %% %%%% %%%% %% %%%% %%%%%%%% %% %%%% %%%%%% %%%%%%%% %%%%%% %% %% %%%% %%%% %%%%%% %% %% %%%% %%%%%% 349 | %%%%%%%%%%%%%% %% %%%% %%%%%% %%%% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%% %%%% %% %% %%%%%%%% %% %% %% %% %% %%%% 350 | %% %%%% %% %%%%%% %%%% %%%% %%%%%% %% %% %% %%%% %%%%%% %%%%%%%% %% %%%%%%%%%% %%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%%%% %% %% %%%%%%%% %% %% %% %% %% 351 | %% %%%%%%%%%%%% %% %% %% %% %% %%%%%%%%%%%%%% %% %% %% %% %%%% %% %%%% %%%%%%%%%%%%%%%%%% %% %%%% %% %%%% %%%%%%%%%% %% %%%% %% %% %%%%%%%%%% %%%%%% 352 | %% %% %%%% %% %% %% %% %% %% %% %% %% %% %%%% %%%% %%%% %% %% %%%% %%%% %% %%%%%%%% %%%% %% %% %% %% %%%% %%%% %% %% %% 353 | %% %%%% %% %%%%%% %%%% %% %% %% %% %% %% %% %% %%%%%% %%%%%%%%%% %% %%%%%% %% %% %% %%%% %% %% %%%%%%%% %% %% %%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%% 354 | %% %%%% %% %%%%%% %%%%%%%% %% %% %%%% %%%%%% %%%%%%%%%% %% %%%%%%%% %% %%%% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%%%%%% %%%% %% 355 | %% %%%%%%%%%%%%%% %%%% %%%% %% %% %% %% %%%%%%%%%%%%%%%% %%%%%%%% %% %%%%%% %%%% %%%%%% %%%%%%%%%% %%%% %% %%%%%% %% %% %%%%%%%%%%%% %%%% %% %%%%%% %% %%%%%%%%%%%%%%%%%%%% 356 | %% %%%% %% %% %%%%%% %%%%%%%% %% %% %% %% %% %%%%%% %%%% %%%%%%%%%% %%%%%%%% %% %%%%%% %%%% %%%% %%%% %% %%%%%% %% %%%%%% %%%% %% %% %% %% %% %%%%%%%% 357 | %%%% %%%% %%%%%% %% %%%%%%%%%% %%%%%%%%%% %% %%%%%% %%%%%% %% %% %% %% %% %% %% %%%%%%%% %%%% %% %%%%%%%% %%%%%%%% %%%%%%%% %% %% %%%%%%%% %% %%%% %%%% %% 358 | %%%% %% %% %%%% %%%% %% %%%%%% %% %% %%%% %%%% %% %%%% %%%% %% %% %% %%%%%%%% %% %% %%%%%% %% %% %% %%%%%% %%%% %% %%%%%%%% %% %% %% %% %% 359 | %%%% %% %% %% %%%%%%%%%% %%%% %% %%%% %% %% %% %% %% %%%% %% %% %% %%%% %% %%%%%% %% %%%%%% %% %% %% %% %% %% %%%%%%%% %%%% %%%% %% 360 | %%%% %%%% %% %% %% %% %%%% %% %% %% %% %%%%%% %% %% %%%% %% %% %% %% %% %% %%%% %%%% %% %% %% %% %%%%%% %% %% %%%% %% %% %% 361 | %%%%%%%% %%%% %%%%%% %%%% %%%%%%%% %% %%%%%%%%%%%% %% %% %% %%%% %%%%%%%% %%%%%%%% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %% %%%% %% %%%%%%%% %% %% %% %%%% %%%% 362 | %%%% %% %%%%%%%%%% %%%% %%%% %%%% %%%% %% %% %%%%%% %% %%%%%%%%%% %%%%%% %% %%%%%%%% %%%% %% %%%%%%%% %% %% %%%%%% %% %% %%%%%%%% %% %%%%%%%%%%%% %%%% 363 | %%%%%% %%%%%%%% %%%% %% %%%%%%%%%%%%%%%%%% %%%% %% %%%%%% %% %%%% %%%%%% %% %%%%%% %% %%%% %%%%%%%%%% %% %%%%%%%%%%%%%%%% %% %% %% %% %%%% %%%%%%%% %%%% %%%%%% %%%%%% 364 | %% %% %%%% %% %%%% %%%%%%%% %%%% %%%%%%%%%%%% %% %%%%%% %%%%%% %% %% %% %% %%%% %% %% %% %% %%%% %% %%%%%%%% %%%%%% %%%% %%%%%%%% %% %% %%%% %% 365 | %% %% %% %% %% %% %%%% %%%%%%%%%%%% %%%% %% %% %%%%%%%% %% %% %% %% %% %%%%%%%% %% %% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% 366 | %%%% %% %% %%%% %%%% %% %% %%%%%%%% %% %%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %%%%%%%% %% %% %%%%%% %% %% 367 | %% %% %% %% %% %% %%%% %%%% %%%% %% %%%%%% %%%% %% %% %% %%%% %% %%%% %%%%%%%%%% %%%% %% %%%%%% %%%% %% %%%%%%%% %% %% %%%%%% %%%%%%%%%% %% %% %% %%%% 368 | %%%% %% %%%% %% %% %%%% %%%%%%%%%%%% %%%%%% %% %%%%%% %%%%%% %%%% %% %%%%%% %%%%%%%%%% %% %% %%%%%%%%%% %% %%%% %%%% %% %% %% %% %% %% %%%% %%%% %%%% 369 | %%%% %%%%%% %%%%%%%%%%%%%% %%%% %%%% %%%%%%%% %%%%%%%% %% %%%% %%%%%% %% %%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %%%%%%%% %% %% %%%%%%%% %% %%%% %% %% %% 370 | %%%% %% %%%% %%%% %% %% %% %% %%%%%% %% %%%%%% %%%%%%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %%%%%%%%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %% 371 | %% %% %%%%%%%%%% %%%%%%%%%% %%%%%%%% %%%%%%%% %%%% %% %% %%%% %% %% %% %%%%%% %% %%%%%% %% %%%% %% %% %%%% %% %% %%%% %%%% %% %%%% %% 372 | %% %%%% %%%% %% %%%% %% %% %% %%%% %%%% %%%%%%%%%% %% %%%% %% %% %% %% %%%% %% %% %% %% %%%% %%%% %%%% %% %%%% %%%% %% %% %% %% %% 373 | %%%%%% %%%%%% %% %%%%%% %% %% %% %% %%%% %% %%%%%%%% %% %%%% %%%%%%%% %% %%%%%%%% %%%%%%%%%% %%%%%%%% %% %% %%%%%%%% %% %% %% %% %% %% %%%%%%%% %% %% %% %%%% %%%%%%%% 374 | %%%%%% %% %% %%%%%% %%%%%% %%%% %% %%%%%%%% %% %% %%%% %%%%%%%% %% %%%%%%%%%% %%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%%%%%%%%%% %% %% %%%%%%%% %% %%%% %%%%%%%%%%%%%% %% 375 | %% %% %%%%%%%% %%%%%% %%%%%% %% %% %% %% %% %%%%%%%% %%%% %%%% %% %% %% %%%% %%%%%% %%%% %% %% %%%% %% %%%% %%%% %% %% %% %%%% %%%%%% %% 376 | %% %% %%%% %%%%%%%%%% %%%% %%%%%%%%%% %%%%%%%% %% %% %% %%%%%% %%%%%% %%%%%% %%%% %% %% %%%%%%%% %% %%%% %%%% %%%%%% %% %% %%%%%% %% %%%%%% %% %%%% %% 377 | %%%% %% %%%%%%%% %%%%%%%% %% %% %%%%%% %% %% %%%% %% %% %%%%%% %%%%%% %% %%%% %% %% %% %% %%%%%%%% %% %% %%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %%%% 378 | %% %%%%%%%% %% %%%% %% %% %% %%%% %% %% %%%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%% %% %%%% %%%%%% %%%% %% %%%%%%%% %% %% %% %% %%%%%%%% %% %% %%%%%% %% %% %% 379 | %%%%%% %%%% %%%%%%%%%% %%%%%% %% %%%%%% %%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%% %% %% %%%%%%%%%%%% %%%% %%%%%% %%%%%% %% %%%%%%%%%%%% %%%% %%%%%% %% %% %% %%%%%%%%%% %%%%%%%%%%%%%%%%%% 380 | %% %% %% %%%% %% %%%%%% %% %%%% %%%% %%%% %%%%%% %% %%%% %%%% %%%% %% %%%%%% %%%% %%%%%%%%%% %% %%%% %% %%%% %%%% %%%% %% %%%% %%%%%% %% %%%%%% 381 | %%%%%%%%%%%%%% %%%%%% %%%%%% %%%%%% %% %%%% %% %%%%%%%%%% %% %%%%%%%% %% %% %% %% %% %% %% %%%%%%%% %% %%%% %%%%%% %% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %%%% %% 382 | %% %% %%%% %%%% %%%%%% %% %% %% %% %%%%%% %%%% %% %%%%%% %%%%%% %% %%%% %%%% %% %%%%%%%% %% %% %%%%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %%%% %% 383 | %% %%%%%% %% %% %% %% %%%% %%%%%%%%%% %%%%%%%%%%%%%%%% %% %% %% %%%% %% %%%% %% %%%%%%%%%%%% %%%% %%%%%%%% %% %% %% %% %% %%%%%%%%%% %%%% %% %%%%%%%%%% %% %%%%%% %%%%%%%%%%%% %% 384 | %% %%%%%% %% %%%% %% %% %% %% %% %% %%%% %%%%%%%% %%%% %% %% %%%% %%%% %%%% %%%% %%%% %% %%%%%%%% %% %% %% %% %% %%%% %% %%%%%%%%%% %%%%%% %% %%%% %% 385 | %% %%%%%% %% %% %%%%%% %%%%%%%% %%%% %%%% %%%% %%%% %%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %% %%%%%%%% 386 | %% %% %%%% %%%% %% %%%% %% %% %%%% %%%%%% %%%%%%%%%% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %% %%%%%%%% %% %%%%%% %% %% 387 | %%%%%%%%%%%%%% %%%% %% %% %%%% %% %%%%%% %% %% %%%%%%%% %% %%%% %% %%%% %% %%%%%%%% %%%% %% %% %%%% %%%%%% %% %%%% %%%%%% %%%%%% %% %%%%%% 388 | 389 | """) 390 | } 391 | 392 | func testTooLarge() { 393 | for (level, max) in zip(QRErrorCorrectLevel.allCases, [2953, 2331, 1663, 1273]) { 394 | let length = max + 1 395 | print("Try overflow error correct level \(level) with length of \(length)") 396 | let content = randomStringOfUTF8Length(length) 397 | print("Generated random string of length \(content.count), utf8 count \(content.utf8.count)") 398 | XCTAssertThrowsError(try QRCode(content, errorCorrectLevel: level)) 399 | } 400 | } 401 | 402 | func testAllLevelMax() throws { 403 | for limits in ([[0, 0, 0, 0]] + QRCodeType.QRCodeLimitLength).lazy.reversed() { 404 | for (level, length) in zip(QRErrorCorrectLevel.allCases, limits) { 405 | print("Try error correct level \(level), utf8 count: \(length)") 406 | let content = randomStringOfUTF8Length(length) 407 | print("Generated a random string, str length: \(content.count)") 408 | XCTAssertNoThrow(try QRCode(content, errorCorrectLevel: level)) 409 | } 410 | } 411 | } 412 | 413 | static var allTests = [ 414 | ("testSimple", testSimple), 415 | ("testLowErrorCorrectLevel", testLowErrorCorrectLevel), 416 | ("testBorderless", testBorderless), 417 | ("testEFQRCode", testEFQRCode), 418 | ("testEmpty", testEmpty), 419 | ("testStressWithPi", testStressWithPi), 420 | ("testTooLarge", testTooLarge), 421 | ("testAllLevelMax", testAllLevelMax), 422 | ] 423 | } 424 | -------------------------------------------------------------------------------- /carthage.sh: -------------------------------------------------------------------------------- 1 | # carthage.sh 2 | # Usage example: ./carthage.sh build --platform iOS 3 | # Why? https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md 4 | 5 | set -euo pipefail 6 | 7 | xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) 8 | trap 'rm -f "$xcconfig"' INT TERM HUP EXIT 9 | 10 | # For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise 11 | # the build will fail on lipo due to duplicate architectures. 12 | 13 | CURRENT_XCODE_VERSION=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3) 14 | echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$CURRENT_XCODE_VERSION = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig 15 | 16 | echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig 17 | echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig 18 | 19 | export XCODE_XCCONFIG_FILE="$xcconfig" 20 | carthage "$@" 21 | -------------------------------------------------------------------------------- /swift_qrcodejs.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "swift_qrcodejs" 4 | s.module_name = "QRCodeSwift" 5 | s.version = "2.2.2" 6 | s.summary = "Cross-appleOS SIMPLE QRCode generator for swift, modified based on qrcodejs." 7 | 8 | # This description is used to generate tags and improve search results. 9 | # * Think: What does it do? Why did you write it? What is the focus? 10 | # * Try to keep it short, snappy and to the point. 11 | # * Write the description between the DESC delimiters below. 12 | # * Finally, don't worry about the indent, CocoaPods strips it! 13 | s.description = <<-DESC 14 | No CIFilter on watchOS? Then we generate QRCode without it ourselves! 15 | swift_qrcodejs is a cross-appleOS simple QRCode generator for swift, modified based on qrcodejs. 16 | DESC 17 | 18 | s.homepage = "https://github.com/ApolloZhu/swift_qrcodejs" 19 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 20 | 21 | s.license = { :type => "MIT", :file => "LICENSE" } 22 | 23 | # s.author = { "Apollo Zhu" => "public-apollonian@outlook.com" } 24 | # Or just: s.author = "ApolloZhu" 25 | s.authors = { "ApolloZhu" => "public-apollonian@outlook.com" } 26 | s.social_media_url = "http://github.com/ApolloZhu" 27 | 28 | s.ios.deployment_target = "9.0" 29 | s.osx.deployment_target = "10.9" 30 | s.watchos.deployment_target = "2.0" 31 | s.tvos.deployment_target = "9.0" 32 | 33 | s.source = { :git => "https://github.com/ApolloZhu/swift_qrcodejs.git", :tag => s.version } 34 | 35 | s.source_files = "Sources/**/*.{h,swift}" 36 | s.swift_versions = ['4.2', '5.0'] 37 | 38 | s.frameworks = "Foundation" 39 | 40 | end 41 | -------------------------------------------------------------------------------- /swift_qrcodejs.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | "swift_qrcodejs::swift_qrcodejsPackageTests::ProductTarget" /* swift_qrcodejsPackageTests */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = OBJ_64 /* Build configuration list for PBXAggregateTarget "swift_qrcodejsPackageTests" */; 13 | buildPhases = ( 14 | ); 15 | dependencies = ( 16 | OBJ_67 /* PBXTargetDependency */, 17 | ); 18 | name = swift_qrcodejsPackageTests; 19 | productName = swift_qrcodejsPackageTests; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | OBJ_33 /* BCH.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_8 /* BCH.swift */; }; 25 | OBJ_34 /* QR8bitByte.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* QR8bitByte.swift */; }; 26 | OBJ_35 /* QRBitBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* QRBitBuffer.swift */; }; 27 | OBJ_36 /* QRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* QRCode.swift */; }; 28 | OBJ_37 /* QRCodeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* QRCodeError.swift */; }; 29 | OBJ_38 /* QRCodeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* QRCodeModel.swift */; }; 30 | OBJ_39 /* QRCodeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* QRCodeType.swift */; }; 31 | OBJ_40 /* QRErrorCorrectLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* QRErrorCorrectLevel.swift */; }; 32 | OBJ_41 /* QRMaskPattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* QRMaskPattern.swift */; }; 33 | OBJ_42 /* QRMath.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* QRMath.swift */; }; 34 | OBJ_43 /* QRMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* QRMode.swift */; }; 35 | OBJ_44 /* QRPatternLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* QRPatternLocator.swift */; }; 36 | OBJ_45 /* QRPolynomial.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* QRPolynomial.swift */; }; 37 | OBJ_46 /* QRRSBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* QRRSBlock.swift */; }; 38 | OBJ_53 /* QRCodeSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_24 /* QRCodeSwiftTests.swift */; }; 39 | OBJ_55 /* QRCodeSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "swift_qrcodejs::QRCodeSwift::Product" /* QRCodeSwift.framework */; }; 40 | OBJ_62 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXContainerItemProxy section */ 44 | D25E915A255438AB0046EA94 /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = OBJ_1 /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = "swift_qrcodejs::QRCodeSwift"; 49 | remoteInfo = QRCodeSwift; 50 | }; 51 | D25E915E255438AC0046EA94 /* PBXContainerItemProxy */ = { 52 | isa = PBXContainerItemProxy; 53 | containerPortal = OBJ_1 /* Project object */; 54 | proxyType = 1; 55 | remoteGlobalIDString = "swift_qrcodejs::QRCodeSwiftTests"; 56 | remoteInfo = QRCodeSwiftTests; 57 | }; 58 | /* End PBXContainerItemProxy section */ 59 | 60 | /* Begin PBXFileReference section */ 61 | OBJ_10 /* QRBitBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRBitBuffer.swift; sourceTree = ""; }; 62 | OBJ_11 /* QRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCode.swift; sourceTree = ""; }; 63 | OBJ_12 /* QRCodeError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeError.swift; sourceTree = ""; }; 64 | OBJ_13 /* QRCodeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeModel.swift; sourceTree = ""; }; 65 | OBJ_14 /* QRCodeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeType.swift; sourceTree = ""; }; 66 | OBJ_15 /* QRErrorCorrectLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRErrorCorrectLevel.swift; sourceTree = ""; }; 67 | OBJ_16 /* QRMaskPattern.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRMaskPattern.swift; sourceTree = ""; }; 68 | OBJ_17 /* QRMath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRMath.swift; sourceTree = ""; }; 69 | OBJ_18 /* QRMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRMode.swift; sourceTree = ""; }; 70 | OBJ_19 /* QRPatternLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRPatternLocator.swift; sourceTree = ""; }; 71 | OBJ_20 /* QRPolynomial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRPolynomial.swift; sourceTree = ""; }; 72 | OBJ_21 /* QRRSBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRRSBlock.swift; sourceTree = ""; }; 73 | OBJ_24 /* QRCodeSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeSwiftTests.swift; sourceTree = ""; }; 74 | OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 75 | OBJ_8 /* BCH.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BCH.swift; sourceTree = ""; }; 76 | OBJ_9 /* QR8bitByte.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QR8bitByte.swift; sourceTree = ""; }; 77 | "swift_qrcodejs::QRCodeSwift::Product" /* QRCodeSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = QRCodeSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 78 | "swift_qrcodejs::QRCodeSwiftTests::Product" /* QRCodeSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = QRCodeSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | OBJ_47 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 0; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | OBJ_54 /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 0; 92 | files = ( 93 | OBJ_55 /* QRCodeSwift.framework in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | /* End PBXFrameworksBuildPhase section */ 98 | 99 | /* Begin PBXGroup section */ 100 | OBJ_22 /* Tests */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | OBJ_23 /* QRCodeSwiftTests */, 104 | ); 105 | name = Tests; 106 | sourceTree = SOURCE_ROOT; 107 | }; 108 | OBJ_23 /* QRCodeSwiftTests */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | OBJ_24 /* QRCodeSwiftTests.swift */, 112 | ); 113 | name = QRCodeSwiftTests; 114 | path = Tests/QRCodeSwiftTests; 115 | sourceTree = SOURCE_ROOT; 116 | }; 117 | OBJ_25 /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | "swift_qrcodejs::QRCodeSwiftTests::Product" /* QRCodeSwiftTests.xctest */, 121 | "swift_qrcodejs::QRCodeSwift::Product" /* QRCodeSwift.framework */, 122 | ); 123 | name = Products; 124 | sourceTree = BUILT_PRODUCTS_DIR; 125 | }; 126 | OBJ_5 = { 127 | isa = PBXGroup; 128 | children = ( 129 | OBJ_6 /* Package.swift */, 130 | OBJ_7 /* Sources */, 131 | OBJ_22 /* Tests */, 132 | OBJ_25 /* Products */, 133 | ); 134 | sourceTree = ""; 135 | }; 136 | OBJ_7 /* Sources */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | OBJ_8 /* BCH.swift */, 140 | OBJ_9 /* QR8bitByte.swift */, 141 | OBJ_10 /* QRBitBuffer.swift */, 142 | OBJ_11 /* QRCode.swift */, 143 | OBJ_12 /* QRCodeError.swift */, 144 | OBJ_13 /* QRCodeModel.swift */, 145 | OBJ_14 /* QRCodeType.swift */, 146 | OBJ_15 /* QRErrorCorrectLevel.swift */, 147 | OBJ_16 /* QRMaskPattern.swift */, 148 | OBJ_17 /* QRMath.swift */, 149 | OBJ_18 /* QRMode.swift */, 150 | OBJ_19 /* QRPatternLocator.swift */, 151 | OBJ_20 /* QRPolynomial.swift */, 152 | OBJ_21 /* QRRSBlock.swift */, 153 | ); 154 | path = Sources; 155 | sourceTree = SOURCE_ROOT; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | "swift_qrcodejs::QRCodeSwift" /* QRCodeSwift */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = OBJ_29 /* Build configuration list for PBXNativeTarget "QRCodeSwift" */; 163 | buildPhases = ( 164 | OBJ_32 /* Sources */, 165 | OBJ_47 /* Frameworks */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | ); 171 | name = QRCodeSwift; 172 | productName = QRCodeSwift; 173 | productReference = "swift_qrcodejs::QRCodeSwift::Product" /* QRCodeSwift.framework */; 174 | productType = "com.apple.product-type.framework"; 175 | }; 176 | "swift_qrcodejs::QRCodeSwiftTests" /* QRCodeSwiftTests */ = { 177 | isa = PBXNativeTarget; 178 | buildConfigurationList = OBJ_49 /* Build configuration list for PBXNativeTarget "QRCodeSwiftTests" */; 179 | buildPhases = ( 180 | OBJ_52 /* Sources */, 181 | OBJ_54 /* Frameworks */, 182 | ); 183 | buildRules = ( 184 | ); 185 | dependencies = ( 186 | OBJ_56 /* PBXTargetDependency */, 187 | ); 188 | name = QRCodeSwiftTests; 189 | productName = QRCodeSwiftTests; 190 | productReference = "swift_qrcodejs::QRCodeSwiftTests::Product" /* QRCodeSwiftTests.xctest */; 191 | productType = "com.apple.product-type.bundle.unit-test"; 192 | }; 193 | "swift_qrcodejs::SwiftPMPackageDescription" /* swift_qrcodejsPackageDescription */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = OBJ_58 /* Build configuration list for PBXNativeTarget "swift_qrcodejsPackageDescription" */; 196 | buildPhases = ( 197 | OBJ_61 /* Sources */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | ); 203 | name = swift_qrcodejsPackageDescription; 204 | productName = swift_qrcodejsPackageDescription; 205 | productType = "com.apple.product-type.framework"; 206 | }; 207 | /* End PBXNativeTarget section */ 208 | 209 | /* Begin PBXProject section */ 210 | OBJ_1 /* Project object */ = { 211 | isa = PBXProject; 212 | attributes = { 213 | LastSwiftMigration = 9999; 214 | LastUpgradeCheck = 9999; 215 | }; 216 | buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "swift_qrcodejs" */; 217 | compatibilityVersion = "Xcode 3.2"; 218 | developmentRegion = en; 219 | hasScannedForEncodings = 0; 220 | knownRegions = ( 221 | en, 222 | ); 223 | mainGroup = OBJ_5; 224 | productRefGroup = OBJ_25 /* Products */; 225 | projectDirPath = ""; 226 | projectRoot = ""; 227 | targets = ( 228 | "swift_qrcodejs::QRCodeSwift" /* QRCodeSwift */, 229 | "swift_qrcodejs::QRCodeSwiftTests" /* QRCodeSwiftTests */, 230 | "swift_qrcodejs::SwiftPMPackageDescription" /* swift_qrcodejsPackageDescription */, 231 | "swift_qrcodejs::swift_qrcodejsPackageTests::ProductTarget" /* swift_qrcodejsPackageTests */, 232 | ); 233 | }; 234 | /* End PBXProject section */ 235 | 236 | /* Begin PBXSourcesBuildPhase section */ 237 | OBJ_32 /* Sources */ = { 238 | isa = PBXSourcesBuildPhase; 239 | buildActionMask = 0; 240 | files = ( 241 | OBJ_33 /* BCH.swift in Sources */, 242 | OBJ_34 /* QR8bitByte.swift in Sources */, 243 | OBJ_35 /* QRBitBuffer.swift in Sources */, 244 | OBJ_36 /* QRCode.swift in Sources */, 245 | OBJ_37 /* QRCodeError.swift in Sources */, 246 | OBJ_38 /* QRCodeModel.swift in Sources */, 247 | OBJ_39 /* QRCodeType.swift in Sources */, 248 | OBJ_40 /* QRErrorCorrectLevel.swift in Sources */, 249 | OBJ_41 /* QRMaskPattern.swift in Sources */, 250 | OBJ_42 /* QRMath.swift in Sources */, 251 | OBJ_43 /* QRMode.swift in Sources */, 252 | OBJ_44 /* QRPatternLocator.swift in Sources */, 253 | OBJ_45 /* QRPolynomial.swift in Sources */, 254 | OBJ_46 /* QRRSBlock.swift in Sources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | OBJ_52 /* Sources */ = { 259 | isa = PBXSourcesBuildPhase; 260 | buildActionMask = 0; 261 | files = ( 262 | OBJ_53 /* QRCodeSwiftTests.swift in Sources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | OBJ_61 /* Sources */ = { 267 | isa = PBXSourcesBuildPhase; 268 | buildActionMask = 0; 269 | files = ( 270 | OBJ_62 /* Package.swift in Sources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | /* End PBXSourcesBuildPhase section */ 275 | 276 | /* Begin PBXTargetDependency section */ 277 | OBJ_56 /* PBXTargetDependency */ = { 278 | isa = PBXTargetDependency; 279 | target = "swift_qrcodejs::QRCodeSwift" /* QRCodeSwift */; 280 | targetProxy = D25E915A255438AB0046EA94 /* PBXContainerItemProxy */; 281 | }; 282 | OBJ_67 /* PBXTargetDependency */ = { 283 | isa = PBXTargetDependency; 284 | target = "swift_qrcodejs::QRCodeSwiftTests" /* QRCodeSwiftTests */; 285 | targetProxy = D25E915E255438AC0046EA94 /* PBXContainerItemProxy */; 286 | }; 287 | /* End PBXTargetDependency section */ 288 | 289 | /* Begin XCBuildConfiguration section */ 290 | OBJ_3 /* Debug */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | COMBINE_HIDPI_IMAGES = YES; 295 | COPY_PHASE_STRIP = NO; 296 | DEBUG_INFORMATION_FORMAT = dwarf; 297 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 298 | ENABLE_NS_ASSERTIONS = YES; 299 | GCC_OPTIMIZATION_LEVEL = 0; 300 | GCC_PREPROCESSOR_DEFINITIONS = ( 301 | "$(inherited)", 302 | "SWIFT_PACKAGE=1", 303 | "DEBUG=1", 304 | ); 305 | MACOSX_DEPLOYMENT_TARGET = 10.10; 306 | ONLY_ACTIVE_ARCH = YES; 307 | OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | SDKROOT = macosx; 310 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 311 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; 312 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 313 | USE_HEADERMAP = NO; 314 | }; 315 | name = Debug; 316 | }; 317 | OBJ_30 /* Debug */ = { 318 | isa = XCBuildConfiguration; 319 | buildSettings = { 320 | ENABLE_TESTABILITY = YES; 321 | FRAMEWORK_SEARCH_PATHS = ( 322 | "$(inherited)", 323 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 324 | ); 325 | HEADER_SEARCH_PATHS = "$(inherited)"; 326 | INFOPLIST_FILE = Sources/Info.plist; 327 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 328 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 329 | MACOSX_DEPLOYMENT_TARGET = 10.10; 330 | OTHER_CFLAGS = "$(inherited)"; 331 | OTHER_LDFLAGS = "$(inherited)"; 332 | OTHER_SWIFT_FLAGS = "$(inherited)"; 333 | PRODUCT_BUNDLE_IDENTIFIER = QRCodeSwift; 334 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 335 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 336 | SKIP_INSTALL = YES; 337 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 338 | SWIFT_VERSION = 5.0; 339 | TARGET_NAME = QRCodeSwift; 340 | TVOS_DEPLOYMENT_TARGET = 9.0; 341 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 342 | }; 343 | name = Debug; 344 | }; 345 | OBJ_31 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ENABLE_TESTABILITY = YES; 349 | FRAMEWORK_SEARCH_PATHS = ( 350 | "$(inherited)", 351 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 352 | ); 353 | HEADER_SEARCH_PATHS = "$(inherited)"; 354 | INFOPLIST_FILE = Sources/Info.plist; 355 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 356 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 357 | MACOSX_DEPLOYMENT_TARGET = 10.10; 358 | OTHER_CFLAGS = "$(inherited)"; 359 | OTHER_LDFLAGS = "$(inherited)"; 360 | OTHER_SWIFT_FLAGS = "$(inherited)"; 361 | PRODUCT_BUNDLE_IDENTIFIER = QRCodeSwift; 362 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 363 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 364 | SKIP_INSTALL = YES; 365 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 366 | SWIFT_VERSION = 5.0; 367 | TARGET_NAME = QRCodeSwift; 368 | TVOS_DEPLOYMENT_TARGET = 9.0; 369 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 370 | }; 371 | name = Release; 372 | }; 373 | OBJ_4 /* Release */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | CLANG_ENABLE_OBJC_ARC = YES; 377 | COMBINE_HIDPI_IMAGES = YES; 378 | COPY_PHASE_STRIP = YES; 379 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 380 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 381 | GCC_OPTIMIZATION_LEVEL = s; 382 | GCC_PREPROCESSOR_DEFINITIONS = ( 383 | "$(inherited)", 384 | "SWIFT_PACKAGE=1", 385 | ); 386 | MACOSX_DEPLOYMENT_TARGET = 10.10; 387 | OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | SDKROOT = macosx; 390 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 391 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE"; 392 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 393 | USE_HEADERMAP = NO; 394 | }; 395 | name = Release; 396 | }; 397 | OBJ_50 /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | CLANG_ENABLE_MODULES = YES; 401 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 402 | FRAMEWORK_SEARCH_PATHS = ( 403 | "$(inherited)", 404 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 405 | ); 406 | HEADER_SEARCH_PATHS = "$(inherited)"; 407 | INFOPLIST_FILE = Tests/QRCodeSwiftTests/Info.plist; 408 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; 410 | MACOSX_DEPLOYMENT_TARGET = 10.10; 411 | OTHER_CFLAGS = "$(inherited)"; 412 | OTHER_LDFLAGS = "$(inherited)"; 413 | OTHER_SWIFT_FLAGS = "$(inherited)"; 414 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 415 | SWIFT_VERSION = 5.0; 416 | TARGET_NAME = QRCodeSwiftTests; 417 | TVOS_DEPLOYMENT_TARGET = 9.0; 418 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 419 | }; 420 | name = Debug; 421 | }; 422 | OBJ_51 /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | CLANG_ENABLE_MODULES = YES; 426 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 427 | FRAMEWORK_SEARCH_PATHS = ( 428 | "$(inherited)", 429 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 430 | ); 431 | HEADER_SEARCH_PATHS = "$(inherited)"; 432 | INFOPLIST_FILE = Tests/QRCodeSwiftTests/Info.plist; 433 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 434 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; 435 | MACOSX_DEPLOYMENT_TARGET = 10.10; 436 | OTHER_CFLAGS = "$(inherited)"; 437 | OTHER_LDFLAGS = "$(inherited)"; 438 | OTHER_SWIFT_FLAGS = "$(inherited)"; 439 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 440 | SWIFT_VERSION = 5.0; 441 | TARGET_NAME = QRCodeSwiftTests; 442 | TVOS_DEPLOYMENT_TARGET = 9.0; 443 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 444 | }; 445 | name = Release; 446 | }; 447 | OBJ_59 /* Debug */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | LD = /usr/bin/true; 451 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -package-description-version 5.0.0"; 452 | SWIFT_VERSION = 5.0; 453 | }; 454 | name = Debug; 455 | }; 456 | OBJ_60 /* Release */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | LD = /usr/bin/true; 460 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -package-description-version 5.0.0"; 461 | SWIFT_VERSION = 5.0; 462 | }; 463 | name = Release; 464 | }; 465 | OBJ_65 /* Debug */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | }; 469 | name = Debug; 470 | }; 471 | OBJ_66 /* Release */ = { 472 | isa = XCBuildConfiguration; 473 | buildSettings = { 474 | }; 475 | name = Release; 476 | }; 477 | /* End XCBuildConfiguration section */ 478 | 479 | /* Begin XCConfigurationList section */ 480 | OBJ_2 /* Build configuration list for PBXProject "swift_qrcodejs" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | OBJ_3 /* Debug */, 484 | OBJ_4 /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | OBJ_29 /* Build configuration list for PBXNativeTarget "QRCodeSwift" */ = { 490 | isa = XCConfigurationList; 491 | buildConfigurations = ( 492 | OBJ_30 /* Debug */, 493 | OBJ_31 /* Release */, 494 | ); 495 | defaultConfigurationIsVisible = 0; 496 | defaultConfigurationName = Release; 497 | }; 498 | OBJ_49 /* Build configuration list for PBXNativeTarget "QRCodeSwiftTests" */ = { 499 | isa = XCConfigurationList; 500 | buildConfigurations = ( 501 | OBJ_50 /* Debug */, 502 | OBJ_51 /* Release */, 503 | ); 504 | defaultConfigurationIsVisible = 0; 505 | defaultConfigurationName = Release; 506 | }; 507 | OBJ_58 /* Build configuration list for PBXNativeTarget "swift_qrcodejsPackageDescription" */ = { 508 | isa = XCConfigurationList; 509 | buildConfigurations = ( 510 | OBJ_59 /* Debug */, 511 | OBJ_60 /* Release */, 512 | ); 513 | defaultConfigurationIsVisible = 0; 514 | defaultConfigurationName = Release; 515 | }; 516 | OBJ_64 /* Build configuration list for PBXAggregateTarget "swift_qrcodejsPackageTests" */ = { 517 | isa = XCConfigurationList; 518 | buildConfigurations = ( 519 | OBJ_65 /* Debug */, 520 | OBJ_66 /* Release */, 521 | ); 522 | defaultConfigurationIsVisible = 0; 523 | defaultConfigurationName = Release; 524 | }; 525 | /* End XCConfigurationList section */ 526 | }; 527 | rootObject = OBJ_1 /* Project object */; 528 | } 529 | -------------------------------------------------------------------------------- /swift_qrcodejs.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /swift_qrcodejs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /swift_qrcodejs.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | -------------------------------------------------------------------------------- /swift_qrcodejs.xcodeproj/xcshareddata/xcschemes/swift_qrcodejs-Package.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | --------------------------------------------------------------------------------