From 7b4abe46c1f5586b604623fa3a05a4ae8a4ec789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Tue, 8 Sep 2015 15:27:02 -0700 Subject: [PATCH] Remove now unused vendored libraries --- extern/AndroidPinning/AndroidManifest.xml | 9 - extern/AndroidPinning/LICENSE | 621 ------ extern/AndroidPinning/build.gradle | 30 - extern/AndroidPinning/project.properties | 2 - extern/AndroidPinning/res/raw/cacerts | Bin 138259 -> 0 bytes .../ssl/pinning/CertificateChainCleaner.java | 89 - .../ssl/pinning/PinningSSLSocketFactory.java | 166 -- .../ssl/pinning/PinningTrustManager.java | 199 -- .../ssl/pinning/SystemKeyStore.java | 138 -- .../ssl/pinning/util/PinningHelper.java | 111 -- extern/UniversalImageLoader/LICENSE | 201 -- extern/UniversalImageLoader/build.gradle | 17 - .../library/AndroidManifest.xml | 11 - .../UniversalImageLoader/library/build.gradle | 36 - .../library/project.properties | 12 - .../cache/disc/DiskCache.java | 85 - .../cache/disc/impl/BaseDiskCache.java | 188 -- .../cache/disc/impl/LimitedAgeDiskCache.java | 127 -- .../cache/disc/impl/UnlimitedDiskCache.java | 52 - .../cache/disc/impl/ext/DiskLruCache.java | 974 --------- .../cache/disc/impl/ext/LruDiskCache.java | 238 --- .../cache/disc/impl/ext/StrictLineReader.java | 191 -- .../cache/disc/impl/ext/Util.java | 76 - .../cache/disc/naming/FileNameGenerator.java | 28 - .../naming/HashCodeFileNameGenerator.java | 29 - .../disc/naming/Md5FileNameGenerator.java | 53 - .../cache/memory/BaseMemoryCache.java | 71 - .../cache/memory/LimitedMemoryCache.java | 112 -- .../cache/memory/MemoryCache.java | 48 - .../memory/impl/FIFOLimitedMemoryCache.java | 84 - .../memory/impl/FuzzyKeyMemoryCache.java | 81 - .../memory/impl/LRULimitedMemoryCache.java | 103 - .../impl/LargestLimitedMemoryCache.java | 109 - .../memory/impl/LimitedAgeMemoryCache.java | 88 - .../cache/memory/impl/LruMemoryCache.java | 144 -- .../impl/UsingFreqLimitedMemoryCache.java | 122 -- .../cache/memory/impl/WeakMemoryCache.java | 37 - .../core/DefaultConfigurationFactory.java | 183 -- .../core/DisplayBitmapTask.java | 81 - .../core/DisplayImageOptions.java | 509 ----- .../core/ImageLoader.java | 768 ------- .../core/ImageLoaderConfiguration.java | 655 ------ .../core/ImageLoaderEngine.java | 217 -- .../core/ImageLoadingInfo.java | 58 - .../core/LoadAndDisplayImageTask.java | 482 ----- .../core/ProcessAndDisplayImageTask.java | 59 - .../core/assist/ContentLengthInputStream.java | 82 - .../core/assist/FailReason.java | 65 - .../core/assist/FlushedInputStream.java | 34 - .../core/assist/ImageScaleType.java | 78 - .../core/assist/ImageSize.java | 69 - .../core/assist/LoadedFrom.java | 10 - .../core/assist/QueueProcessingType.java | 26 - .../core/assist/ViewScaleType.java | 73 - .../core/assist/deque/BlockingDeque.java | 616 ------ .../core/assist/deque/Deque.java | 550 ------ .../assist/deque/LIFOLinkedBlockingDeque.java | 47 - .../assist/deque/LinkedBlockingDeque.java | 1169 ----------- .../core/decode/BaseImageDecoder.java | 250 --- .../core/decode/ImageDecoder.java | 39 - .../core/decode/ImageDecodingInfo.java | 150 -- .../core/display/BitmapDisplayer.java | 43 - .../core/display/FadeInBitmapDisplayer.java | 86 - .../core/display/RoundedBitmapDisplayer.java | 118 -- .../RoundedVignetteBitmapDisplayer.java | 74 - .../core/display/SimpleBitmapDisplayer.java | 33 - .../core/download/BaseImageDownloader.java | 293 --- .../core/download/ImageDownloader.java | 90 - .../core/imageaware/ImageAware.java | 114 -- .../core/imageaware/ImageViewAware.java | 143 -- .../core/imageaware/NonViewAware.java | 92 - .../core/imageaware/ViewAware.java | 184 -- .../core/listener/ImageLoadingListener.java | 67 - .../ImageLoadingProgressListener.java | 37 - .../core/listener/PauseOnScrollListener.java | 98 - .../listener/SimpleImageLoadingListener.java | 50 - .../core/process/BitmapProcessor.java | 40 - .../utils/DiskCacheUtils.java | 49 - .../utils/ImageSizeUtils.java | 215 -- .../universalimageloader/utils/IoUtils.java | 131 -- .../universalimageloader/utils/L.java | 113 -- .../utils/MemoryCacheUtils.java | 110 -- .../utils/StorageUtils.java | 181 -- extern/UniversalImageLoader/settings.gradle | 1 - extern/libsuperuser/LICENSE | 177 -- extern/libsuperuser/build.gradle | 15 - extern/libsuperuser/libsuperuser/.classpath | 9 - extern/libsuperuser/libsuperuser/.project | 38 - .../libsuperuser/AndroidManifest.xml | 8 - extern/libsuperuser/libsuperuser/build.gradle | 56 - .../libsuperuser/project.properties | 15 - .../chainfire/libsuperuser/Application.java | 80 - .../src/eu/chainfire/libsuperuser/Debug.java | 240 --- .../libsuperuser/HideOverlaysReceiver.java | 59 - .../src/eu/chainfire/libsuperuser/Shell.java | 1756 ----------------- .../libsuperuser/ShellNotClosedException.java | 29 - .../ShellOnMainThreadException.java | 32 - .../chainfire/libsuperuser/StreamGobbler.java | 105 - extern/libsuperuser/settings.gradle | 1 - extern/zxing-core/build.gradle | 3 - .../java/com/google/zxing/BarcodeFormat.java | 77 - .../main/java/com/google/zxing/Binarizer.java | 87 - .../java/com/google/zxing/BinaryBitmap.java | 150 -- .../com/google/zxing/ChecksumException.java | 47 - .../java/com/google/zxing/DecodeHintType.java | 122 -- .../main/java/com/google/zxing/Dimension.java | 62 - .../java/com/google/zxing/EncodeHintType.java | 94 - .../com/google/zxing/FormatException.java | 47 - .../google/zxing/InvertedLuminanceSource.java | 88 - .../com/google/zxing/LuminanceSource.java | 157 -- .../com/google/zxing/MultiFormatReader.java | 180 -- .../com/google/zxing/MultiFormatWriter.java | 97 - .../com/google/zxing/NotFoundException.java | 40 - .../zxing/PlanarYUVLuminanceSource.java | 169 -- .../com/google/zxing/RGBLuminanceSource.java | 142 -- .../main/java/com/google/zxing/Reader.java | 69 - .../com/google/zxing/ReaderException.java | 49 - .../main/java/com/google/zxing/Result.java | 133 -- .../com/google/zxing/ResultMetadataType.java | 97 - .../java/com/google/zxing/ResultPoint.java | 138 -- .../com/google/zxing/ResultPointCallback.java | 29 - .../main/java/com/google/zxing/Writer.java | 59 - .../com/google/zxing/WriterException.java | 38 - .../zxing/aztec/AztecDetectorResult.java | 52 - .../com/google/zxing/aztec/AztecReader.java | 117 -- .../com/google/zxing/aztec/AztecWriter.java | 88 - .../google/zxing/aztec/decoder/Decoder.java | 338 ---- .../google/zxing/aztec/detector/Detector.java | 600 ------ .../google/zxing/aztec/encoder/AztecCode.java | 89 - .../zxing/aztec/encoder/BinaryShiftToken.java | 60 - .../google/zxing/aztec/encoder/Encoder.java | 346 ---- .../zxing/aztec/encoder/HighLevelEncoder.java | 307 --- .../zxing/aztec/encoder/SimpleToken.java | 45 - .../com/google/zxing/aztec/encoder/State.java | 169 -- .../com/google/zxing/aztec/encoder/Token.java | 46 - .../result/AbstractDoCoMoResultParser.java | 39 - .../result/AddressBookAUResultParser.java | 91 - .../result/AddressBookDoCoMoResultParser.java | 92 - .../result/AddressBookParsedResult.java | 208 -- .../client/result/BizcardResultParser.java | 100 - .../result/BookmarkDoCoMoResultParser.java | 41 - .../client/result/CalendarParsedResult.java | 246 --- .../result/EmailAddressParsedResult.java | 96 - .../result/EmailAddressResultParser.java | 81 - .../result/EmailDoCoMoResultParser.java | 64 - .../result/ExpandedProductParsedResult.java | 204 -- .../result/ExpandedProductResultParser.java | 218 -- .../zxing/client/result/GeoParsedResult.java | 101 - .../zxing/client/result/GeoResultParser.java | 73 - .../zxing/client/result/ISBNParsedResult.java | 40 - .../zxing/client/result/ISBNResultParser.java | 50 - .../zxing/client/result/ParsedResult.java | 67 - .../zxing/client/result/ParsedResultType.java | 40 - .../client/result/ProductParsedResult.java | 50 - .../client/result/ProductResultParser.java | 55 - .../zxing/client/result/ResultParser.java | 259 --- .../client/result/SMSMMSResultParser.java | 109 - .../zxing/client/result/SMSParsedResult.java | 111 -- .../client/result/SMSTOMMSTOResultParser.java | 52 - .../zxing/client/result/SMTPResultParser.java | 54 - .../zxing/client/result/TelParsedResult.java | 55 - .../zxing/client/result/TelResultParser.java | 42 - .../zxing/client/result/TextParsedResult.java | 49 - .../zxing/client/result/URIParsedResult.java | 90 - .../zxing/client/result/URIResultParser.java | 63 - .../client/result/URLTOResultParser.java | 45 - .../client/result/VCardResultParser.java | 357 ---- .../client/result/VEventResultParser.java | 119 -- .../zxing/client/result/VINParsedResult.java | 104 - .../zxing/client/result/VINResultParser.java | 209 -- .../zxing/client/result/WifiParsedResult.java | 67 - .../zxing/client/result/WifiResultParser.java | 51 - .../com/google/zxing/common/BitArray.java | 375 ---- .../com/google/zxing/common/BitMatrix.java | 449 ----- .../com/google/zxing/common/BitSource.java | 111 -- .../google/zxing/common/CharacterSetECI.java | 118 -- .../google/zxing/common/DecoderResult.java | 113 -- .../zxing/common/DefaultGridSampler.java | 88 - .../google/zxing/common/DetectorResult.java | 46 - .../common/GlobalHistogramBinarizer.java | 196 -- .../com/google/zxing/common/GridSampler.java | 173 -- .../google/zxing/common/HybridBinarizer.java | 237 --- .../zxing/common/PerspectiveTransform.java | 156 -- .../com/google/zxing/common/StringUtils.java | 213 -- .../zxing/common/detector/MathUtils.java | 49 - .../detector/MonochromeRectangleDetector.java | 215 -- .../detector/WhiteRectangleDetector.java | 342 ---- .../zxing/common/reedsolomon/GenericGF.java | 166 -- .../common/reedsolomon/GenericGFPoly.java | 264 --- .../reedsolomon/ReedSolomonDecoder.java | 190 -- .../reedsolomon/ReedSolomonEncoder.java | 74 - .../reedsolomon/ReedSolomonException.java | 31 - .../zxing/datamatrix/DataMatrixReader.java | 161 -- .../zxing/datamatrix/DataMatrixWriter.java | 180 -- .../datamatrix/decoder/BitMatrixParser.java | 440 ----- .../zxing/datamatrix/decoder/DataBlock.java | 118 -- .../decoder/DecodedBitStreamParser.java | 497 ----- .../zxing/datamatrix/decoder/Decoder.java | 136 -- .../zxing/datamatrix/decoder/Version.java | 237 --- .../zxing/datamatrix/detector/Detector.java | 440 ----- .../datamatrix/encoder/ASCIIEncoder.java | 82 - .../datamatrix/encoder/Base256Encoder.java | 74 - .../zxing/datamatrix/encoder/C40Encoder.java | 180 -- .../encoder/DataMatrixSymbolInfo144.java | 35 - .../datamatrix/encoder/DefaultPlacement.java | 198 -- .../datamatrix/encoder/EdifactEncoder.java | 137 -- .../zxing/datamatrix/encoder/Encoder.java | 25 - .../datamatrix/encoder/EncoderContext.java | 134 -- .../datamatrix/encoder/ErrorCorrection.java | 184 -- .../datamatrix/encoder/HighLevelEncoder.java | 448 ----- .../zxing/datamatrix/encoder/SymbolInfo.java | 240 --- .../datamatrix/encoder/SymbolShapeHint.java | 29 - .../zxing/datamatrix/encoder/TextEncoder.java | 85 - .../zxing/datamatrix/encoder/X12Encoder.java | 84 - .../google/zxing/maxicode/MaxiCodeReader.java | 126 -- .../maxicode/decoder/BitMatrixParser.java | 88 - .../decoder/DecodedBitStreamParser.java | 196 -- .../zxing/maxicode/decoder/Decoder.java | 114 -- .../google/zxing/multi/ByQuadrantReader.java | 115 -- .../multi/GenericMultipleBarcodeReader.java | 175 -- .../zxing/multi/MultipleBarcodeReader.java | 39 - .../zxing/multi/qrcode/QRCodeMultiReader.java | 181 -- .../multi/qrcode/detector/MultiDetector.java | 73 - .../detector/MultiFinderPatternFinder.java | 311 --- .../com/google/zxing/oned/CodaBarReader.java | 345 ---- .../com/google/zxing/oned/CodaBarWriter.java | 130 -- .../com/google/zxing/oned/Code128Reader.java | 539 ----- .../com/google/zxing/oned/Code128Writer.java | 200 -- .../com/google/zxing/oned/Code39Reader.java | 323 --- .../com/google/zxing/oned/Code39Writer.java | 89 - .../com/google/zxing/oned/Code93Reader.java | 287 --- .../com/google/zxing/oned/EAN13Reader.java | 138 -- .../com/google/zxing/oned/EAN13Writer.java | 94 - .../com/google/zxing/oned/EAN8Reader.java | 75 - .../com/google/zxing/oned/EAN8Writer.java | 84 - .../zxing/oned/EANManufacturerOrgSupport.java | 171 -- .../java/com/google/zxing/oned/ITFReader.java | 354 ---- .../java/com/google/zxing/oned/ITFWriter.java | 76 - .../zxing/oned/MultiFormatOneDReader.java | 112 -- .../zxing/oned/MultiFormatUPCEANReader.java | 124 -- .../com/google/zxing/oned/OneDReader.java | 297 --- .../zxing/oned/OneDimensionalCodeWriter.java | 132 -- .../com/google/zxing/oned/UPCAReader.java | 86 - .../com/google/zxing/oned/UPCAWriter.java | 73 - .../zxing/oned/UPCEANExtension2Support.java | 112 -- .../zxing/oned/UPCEANExtension5Support.java | 181 -- .../zxing/oned/UPCEANExtensionSupport.java | 40 - .../com/google/zxing/oned/UPCEANReader.java | 395 ---- .../com/google/zxing/oned/UPCEANWriter.java | 34 - .../com/google/zxing/oned/UPCEReader.java | 155 -- .../zxing/oned/rss/AbstractRSSReader.java | 133 -- .../google/zxing/oned/rss/DataCharacter.java | 56 - .../google/zxing/oned/rss/FinderPattern.java | 62 - .../java/com/google/zxing/oned/rss/Pair.java | 41 - .../google/zxing/oned/rss/RSS14Reader.java | 477 ----- .../com/google/zxing/oned/rss/RSSUtils.java | 159 -- .../oned/rss/expanded/BitArrayBuilder.java | 85 - .../zxing/oned/rss/expanded/ExpandedPair.java | 104 - .../zxing/oned/rss/expanded/ExpandedRow.java | 76 - .../oned/rss/expanded/RSSExpandedReader.java | 783 -------- .../expanded/decoders/AI013103decoder.java | 49 - .../expanded/decoders/AI01320xDecoder.java | 57 - .../expanded/decoders/AI01392xDecoder.java | 68 - .../expanded/decoders/AI01393xDecoder.java | 78 - .../expanded/decoders/AI013x0x1xDecoder.java | 109 - .../expanded/decoders/AI013x0xDecoder.java | 57 - .../expanded/decoders/AI01AndOtherAIs.java | 58 - .../rss/expanded/decoders/AI01decoder.java | 81 - .../expanded/decoders/AI01weightDecoder.java | 60 - .../decoders/AbstractExpandedDecoder.java | 93 - .../rss/expanded/decoders/AnyAIDecoder.java | 50 - .../expanded/decoders/BlockParsedResult.java | 54 - .../decoders/CurrentParsingState.java | 83 - .../rss/expanded/decoders/DecodedChar.java | 52 - .../expanded/decoders/DecodedInformation.java | 64 - .../rss/expanded/decoders/DecodedNumeric.java | 77 - .../rss/expanded/decoders/DecodedObject.java | 44 - .../rss/expanded/decoders/FieldParser.java | 291 --- .../decoders/GeneralAppIdDecoder.java | 469 ----- .../com/google/zxing/pdf417/PDF417Common.java | 459 ----- .../com/google/zxing/pdf417/PDF417Reader.java | 135 -- .../zxing/pdf417/PDF417ResultMetadata.java | 61 - .../com/google/zxing/pdf417/PDF417Writer.java | 176 -- .../zxing/pdf417/decoder/BarcodeMetadata.java | 58 - .../zxing/pdf417/decoder/BarcodeValue.java | 68 - .../zxing/pdf417/decoder/BoundingBox.java | 176 -- .../google/zxing/pdf417/decoder/Codeword.java | 84 - .../decoder/DecodedBitStreamParser.java | 641 ------ .../zxing/pdf417/decoder/DetectionResult.java | 296 --- .../pdf417/decoder/DetectionResultColumn.java | 96 - .../DetectionResultRowIndicatorColumn.java | 267 --- .../pdf417/decoder/PDF417CodewordDecoder.java | 117 -- .../pdf417/decoder/PDF417ScanningDecoder.java | 628 ------ .../pdf417/decoder/ec/ErrorCorrection.java | 187 -- .../zxing/pdf417/decoder/ec/ModulusGF.java | 112 -- .../zxing/pdf417/decoder/ec/ModulusPoly.java | 260 --- .../zxing/pdf417/detector/Detector.java | 344 ---- .../pdf417/detector/PDF417DetectorResult.java | 45 - .../zxing/pdf417/encoder/BarcodeMatrix.java | 82 - .../zxing/pdf417/encoder/BarcodeRow.java | 85 - .../zxing/pdf417/encoder/Compaction.java | 26 - .../zxing/pdf417/encoder/Dimensions.java | 54 - .../google/zxing/pdf417/encoder/PDF417.java | 769 -------- .../pdf417/encoder/PDF417ErrorCorrection.java | 204 -- .../encoder/PDF417HighLevelEncoder.java | 582 ------ .../com/google/zxing/qrcode/QRCodeReader.java | 218 -- .../com/google/zxing/qrcode/QRCodeWriter.java | 120 -- .../zxing/qrcode/decoder/BitMatrixParser.java | 245 --- .../zxing/qrcode/decoder/DataBlock.java | 122 -- .../google/zxing/qrcode/decoder/DataMask.java | 163 -- .../decoder/DecodedBitStreamParser.java | 354 ---- .../google/zxing/qrcode/decoder/Decoder.java | 203 -- .../qrcode/decoder/ErrorCorrectionLevel.java | 60 - .../qrcode/decoder/FormatInformation.java | 172 -- .../com/google/zxing/qrcode/decoder/Mode.java | 102 - .../qrcode/decoder/QRCodeDecoderMetaData.java | 57 - .../google/zxing/qrcode/decoder/Version.java | 578 ------ .../qrcode/detector/AlignmentPattern.java | 59 - .../detector/AlignmentPatternFinder.java | 277 --- .../zxing/qrcode/detector/Detector.java | 405 ---- .../zxing/qrcode/detector/FinderPattern.java | 82 - .../qrcode/detector/FinderPatternFinder.java | 680 ------- .../qrcode/detector/FinderPatternInfo.java | 49 - .../zxing/qrcode/encoder/BlockPair.java | 37 - .../zxing/qrcode/encoder/ByteMatrix.java | 98 - .../google/zxing/qrcode/encoder/Encoder.java | 578 ------ .../google/zxing/qrcode/encoder/MaskUtil.java | 217 -- .../zxing/qrcode/encoder/MatrixUtil.java | 485 ----- .../google/zxing/qrcode/encoder/QRCode.java | 108 - 329 files changed, 53322 deletions(-) delete mode 100644 extern/AndroidPinning/AndroidManifest.xml delete mode 100644 extern/AndroidPinning/LICENSE delete mode 100644 extern/AndroidPinning/build.gradle delete mode 100644 extern/AndroidPinning/project.properties delete mode 100644 extern/AndroidPinning/res/raw/cacerts delete mode 100644 extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/CertificateChainCleaner.java delete mode 100644 extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningSSLSocketFactory.java delete mode 100644 extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningTrustManager.java delete mode 100644 extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/SystemKeyStore.java delete mode 100644 extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/util/PinningHelper.java delete mode 100644 extern/UniversalImageLoader/LICENSE delete mode 100644 extern/UniversalImageLoader/build.gradle delete mode 100644 extern/UniversalImageLoader/library/AndroidManifest.xml delete mode 100644 extern/UniversalImageLoader/library/build.gradle delete mode 100644 extern/UniversalImageLoader/library/project.properties delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/DiskCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/BaseDiskCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/LimitedAgeDiskCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/UnlimitedDiskCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/DiskLruCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/LruDiskCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/StrictLineReader.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/Util.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/FileNameGenerator.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/HashCodeFileNameGenerator.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/Md5FileNameGenerator.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/BaseMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/LimitedMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/MemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FIFOLimitedMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FuzzyKeyMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LRULimitedMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LargestLimitedMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LimitedAgeMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LruMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/UsingFreqLimitedMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/WeakMemoryCache.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DefaultConfigurationFactory.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayBitmapTask.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayImageOptions.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoader.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderEngine.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoadingInfo.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/LoadAndDisplayImageTask.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ProcessAndDisplayImageTask.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ContentLengthInputStream.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FailReason.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FlushedInputStream.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageScaleType.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageSize.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/LoadedFrom.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/QueueProcessingType.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ViewScaleType.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/BlockingDeque.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/Deque.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LIFOLinkedBlockingDeque.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LinkedBlockingDeque.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/BaseImageDecoder.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecoder.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecodingInfo.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/BitmapDisplayer.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/FadeInBitmapDisplayer.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedBitmapDisplayer.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedVignetteBitmapDisplayer.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/SimpleBitmapDisplayer.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/BaseImageDownloader.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/ImageDownloader.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageAware.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageViewAware.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/NonViewAware.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ViewAware.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingListener.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingProgressListener.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/PauseOnScrollListener.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/SimpleImageLoadingListener.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/process/BitmapProcessor.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/DiskCacheUtils.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/ImageSizeUtils.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/IoUtils.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/L.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/MemoryCacheUtils.java delete mode 100644 extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/StorageUtils.java delete mode 100644 extern/UniversalImageLoader/settings.gradle delete mode 100644 extern/libsuperuser/LICENSE delete mode 100644 extern/libsuperuser/build.gradle delete mode 100644 extern/libsuperuser/libsuperuser/.classpath delete mode 100644 extern/libsuperuser/libsuperuser/.project delete mode 100644 extern/libsuperuser/libsuperuser/AndroidManifest.xml delete mode 100644 extern/libsuperuser/libsuperuser/build.gradle delete mode 100644 extern/libsuperuser/libsuperuser/project.properties delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Application.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Debug.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/HideOverlaysReceiver.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Shell.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellNotClosedException.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellOnMainThreadException.java delete mode 100644 extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/StreamGobbler.java delete mode 100644 extern/libsuperuser/settings.gradle delete mode 100644 extern/zxing-core/build.gradle delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/BarcodeFormat.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/Binarizer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/BinaryBitmap.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/ChecksumException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/DecodeHintType.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/Dimension.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/EncodeHintType.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/FormatException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/InvertedLuminanceSource.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/LuminanceSource.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/MultiFormatReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/MultiFormatWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/NotFoundException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/PlanarYUVLuminanceSource.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/RGBLuminanceSource.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/ReaderException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/Result.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/ResultMetadataType.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/ResultPoint.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/ResultPointCallback.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/WriterException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecDetectorResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/detector/Detector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/AztecCode.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/BinaryShiftToken.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/HighLevelEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/SimpleToken.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/State.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Token.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/AbstractDoCoMoResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookAUResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookDoCoMoResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/BizcardResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/BookmarkDoCoMoResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/CalendarParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailDoCoMoResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResultType.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/ResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSMMSResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSTOMMSTOResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/SMTPResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/TelParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/TelResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/TextParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/URIParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/URIResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/URLTOResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/VCardResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/VEventResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/VINParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/VINResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiResultParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/BitArray.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/common/BitMatrix.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/common/BitSource.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/CharacterSetECI.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/DecoderResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/DefaultGridSampler.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/DetectorResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/GridSampler.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/HybridBinarizer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/PerspectiveTransform.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/StringUtils.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/detector/MathUtils.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/BitMatrixParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DataBlock.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Version.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/detector/Detector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ASCIIEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Base256Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/C40Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DataMatrixSymbolInfo144.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DefaultPlacement.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EdifactEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EncoderContext.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ErrorCorrection.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/HighLevelEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolInfo.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolShapeHint.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/TextEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/X12Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/maxicode/MaxiCodeReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/BitMatrixParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/DecodedBitStreamParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/Decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/ByQuadrantReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/GenericMultipleBarcodeReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/MultipleBarcodeReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/QRCodeMultiReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiDetector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/Code93Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/EANManufacturerOrgSupport.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/ITFReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/ITFWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatOneDReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatUPCEANReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/OneDReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/OneDimensionalCodeWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension2Support.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension5Support.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtensionSupport.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/AbstractRSSReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/DataCharacter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/FinderPattern.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/Pair.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSS14Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSSUtils.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedPair.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedRow.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Common.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/Detector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeReader.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeWriter.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/BitMatrixParser.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataBlock.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataMask.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Decoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/FormatInformation.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Mode.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/QRCodeDecoderMetaData.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Version.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPattern.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/Detector.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPattern.java delete mode 100755 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternFinder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternInfo.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/BlockPair.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/ByteMatrix.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MaskUtil.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MatrixUtil.java delete mode 100644 extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/QRCode.java diff --git a/extern/AndroidPinning/AndroidManifest.xml b/extern/AndroidPinning/AndroidManifest.xml deleted file mode 100644 index b144f02b6..000000000 --- a/extern/AndroidPinning/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/extern/AndroidPinning/LICENSE b/extern/AndroidPinning/LICENSE deleted file mode 100644 index 94a045322..000000000 --- a/extern/AndroidPinning/LICENSE +++ /dev/null @@ -1,621 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/extern/AndroidPinning/build.gradle b/extern/AndroidPinning/build.gradle deleted file mode 100644 index 53fb1ab49..000000000 --- a/extern/AndroidPinning/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' - } -} - -apply plugin: 'android-library' - -android { - compileSdkVersion 17 - buildToolsVersion '23.0.1' - - android { - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } - } - } -} diff --git a/extern/AndroidPinning/project.properties b/extern/AndroidPinning/project.properties deleted file mode 100644 index 8b1b48694..000000000 --- a/extern/AndroidPinning/project.properties +++ /dev/null @@ -1,2 +0,0 @@ -target=android-17 -android.library=true diff --git a/extern/AndroidPinning/res/raw/cacerts b/extern/AndroidPinning/res/raw/cacerts deleted file mode 100644 index 88517c036c19815ca8a02e9d7d225183f2b2ca8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 138259 zcmdqK1zc2Jzb`&RceljQDa_E_Ege!K3>^bQ3?QI%ibx2kgoLz&h=d?0poof~B8`fI zAR?fYAobrffDicizR$hqp8G%NT=^ig_F8-GwfFvgzw1|P4G07RgFqmf6BVin&98kU z+1rWf)T*1`H$3@P4g%o@fI-+WQ7NF2@P)2HBA_L3&{9|eDgy%HoP$Q;prBFMX9}>f zz*txm>g^;+Mj)=clmn6iyUs*AP*OZXfjI5BAEaO~E-nZfc@;(sCB(xv$HAk$!j1xy zgP>7hBCIGd7*zM8OIqn}d3e7}l(Fkeul(10mMgRQf?r7!&92{*zE1aJl08_vvlWh_ z%3_iC@Eeq;aFvx=5Tt(LGM`B(R*bk>_qqFPM?i3{=Go+1FFkhd37FGUnAJ0W%U=Ip zXWLljwKeHW?^%?v1$w{B1Pda`28Yy%P6>kXrM$a~PpMkp~L1T5q@IDoWvL&?zvYA|>Y2N#MB{K1F_3mFa_ z4o#t-9nT5AYigOc_)>$hS$U^kcWFS?(e2rA6rgfYnF6T-i8!$XadY%T92Yl{KMR>K z&=3kk_ri@M0Oi9Y5X1vefsYOT^$GXaC%j*u@Q=P-07Sss1%tF0$={*6uV1a*uI4)% zaC!cu>!LxZ;4sPF`n%`mMMNL;%$%>-d*)N+R-cU)nzycbIDK*zjfGa2f^&88R-Hy zIY{;rc`n#-3Th40vQ&87FeVi+z7e_kM((T+RXBxcE^BMvhD$kylqB~_ssGb4Qo^nR z2&o(zg_XKbN`#=@i77DoQ|-Oq9wb!!kbeL&(lmilK`DTDgF{3@sP5+O6^ul=`@<+P zQi6j`LZAlFiMy*e9L*E}Pe_W&z$9Q|Pziu3M2{B#gT4L}ihJC?KOGvX7Z2cxV*Prz z{mYpTJPVXs@DD}j>CP#$Put(H?s5F^s4gpgkHO2G^MjznkGCHsMbhx^Y4?+T4Q>>g z6+h)ezE%{a2Q-pVZtct!nE8fn0&Q{f? zkBlQlKXv$mC__E5kjI0|N;H&-5V9be289fQ_#fP?gLmvfUy%ZQ+};9;436~NN{Z?b zx^PS+#?gO$IgAtz{-Cp-yPXapKrQZ6av?)SythSn@yi+M(WlcfJIx(aVk$4FCUu^NJP&Kl zp*Q3PB?TC9R?o2R^$Ruaz1)dcrW~Z?Y}J0qUQx_2f36+9Lii%0dNXP&R$^T0?`%mmw%SAxIA0lzXo}_a2l$^oD`TO!3%&mfxyZl(2 z76dn)VrhBTzE}6a5^Xs?3sjb>)~9UTGjFPEI#s`$5{7T_bxCd9#eo*yZ%hwU?1KOa%+p9&~%eBnut_+`6@o<(>?@fcI-^w;H?qRj8$}dhP%}XVHT^+7kUjL?0 z`!*m=jFE*|`8kS1S@*1NOTEjja7U`~6NlUWcj!m;?t7wJWqOuz^}Z zEuiLfgn-<+I*YivyFdY*8H$gGD@cZo#e_qX@@ar6t}6MmXIFoO#~W=1p-@I)C^sGF zfr5iTx*~-G0Sx&A7((mQB7y#xW9XjHiuJzM6h7cw*7^2p>o+Ljiki$%tXeT(f;?^k zV3e0DT)I#@hyD?!Ya$9?Ca#}s3tBG;=8*pSsI1@|RkZ_|hL6+Z*{d!muMvjX)eiOY zIWL1N37E9rZEl`VwxDX~tqv z3_me7^71&zTW+lJ;v`1(*D4{n?z)zS_RqqiJczL>x#?vZ#=~c0oCPv3w#B_W8%Y;^ zlA`zBPI;7o7atob@uN?(OgxMqRwoF~4|d0iUEI1jrR;JX4qc}dvkJTUCH2MAR=!g0DrFlHzdnr(=vsdeE#aBpXT zg|v{stMc}8_C~?zpfvkDMylfD15gi!Y1CBqbr_f^@FRg{7qqn_b)@*8bCG`nb(z;B z${;?a1n-?&(RkeTQ%Q3>V0-<5&n4t=-pBF+3~Ik=ek;?{!vpMc=PoN6xGCnUAIA`Fwu4d=r z73-Sb&dSkQ%Xf`od9mL40z}AsY<}ofK9>7U{bu|I#;{G^Mn0b1BF7mOx^H6Fv<^Uh z0~(og1Vm=m&v}%5dowgivrNBuYQMa)s~Q0P9pYAK%u(W)K#htGpnAt8f&og0kq8p< znX4r;xmBNX+Ga8yd}_&saYETK(m=vA6;(79eRV3jaw@8BD*FCZRMS*+*;I5rAR2#D zuKoaE84vZqAZgjJH(fQ!H(l|ePLh6UL~FnnHMH$yDmC=n`@|RZ|zP3VZ6|k z*@v5@cL<0d#+LWI&h=eq$+zE@7Nh=fV}jUjjLwKZRKzEZ{CbPHcycD{aoD*E7u&XH z>_Ms&RW3XV@6vAV(0)TMAnYhMR_NBTFQ$}HQIb60Q3~$J-EmmF*>6VjO3;p8aZ2&Q zLqSEtoZW=du)FE>+ngDZZQf;%FLlmSYK(8FJk1LH;$s&~n*evB!sa0H)NUH%7K ziD@KG*|@rby(Ej@6>_57i}g0Lk+U3Q6fJh?+YG!!<(29`g@x{JX=W2(NBiAMnD+2{ z`pKEiTYx;T{DuIHs#HEBzoWYwaoymiChe^ae^rl8m%utA9@@88(!Y*Z*qL#d zr1{uVf6@Nxjg1(6i`bqg#ojB8rpozVafSRbj~?uf<8`>-tbo(?*UfVQAJ11*WHVKE zogSyimX9`R49#k)iVrHkx9m!sp;lk3=>JnyvX1*P5sXLbv}?;v;tNAR5?{C$Hp#NO z7_JwX({SqviIJA7Tx!FCc~JNf<&g;oww+xuPE0CSGWUNlF5At8o0YCzc`8`|`;$c) z#i|D%t+!TC%o$@;KI7aBt0SGv6eaDHC6jvF^G67m;TXL4&{e4-HICrd6o~h&Gt`vZ zc`-!Pq2J_QZr>ytPW+M;maHAi>SQ-=R#Y_@f)(uf`r{*r_q+V~d3i${W4u2!;Qhw|?i$zx0&ZzHY;9I@he9 zx;ODVaLS&0yc^TPxDWv&5n#^_%&Q-zS&g~L3=MM7x?3JY$bB7XEUE^k|%PN#3g{$*N%YQ1SZd=px!kb z7hgg^6pFU$-w^JEc1BcQLGWK=FK?w=si3k$HN;4-PvDw5c zo~G^A+Iq$DHgQ%4Fg%0I-XnKFTdy%F(;eQloDOR%mbqP^FR~*v3UR=@Iv7OUMRc+FBB!H zw|Vw~0YB4D(S%D0vk*Du?-PRG5pvcxKlD7|Qxm8LIKh3K{eNk5MAW4E?v8#)e`iOC z9?D4=Mgyh7%Sn02LhxQB#3&Kp~jfg_`kK>tEF-NF)kqgP8#&pyE(Tn5d|< zxHv`+JW_=ISB&YO)W(G#&|qZf3u%y6?|4iHySor7m4toNG=4!*P2IHi)<#5*{JG>e z$u-SO1C$eyGyQT|mxhqE-9cf6B9nIMjl9Ew*(_@EUq-)*EXu5SxSmRi>gU*SHs2L` zE^8`peh@IF1=@zWD?35I;w_u=7cO zjA#hE1&AOW{e7S(56^^R#jzg=oE&Y4mJ>A!6f#5`eJ%C_?3-IfJ zM*_ICalnz~3|L?=7&v0|*MP9VbeI7h#Al9P#?;!>S_Ej#aX2I_ETBZg8U>~Rsem9L z6bKIT2K@y2gBF0#fuIjSDHu3D2l4~T&L9NH3-~_-DEkAyZkW<7RGoy4D4R1i1oz zI00w+1HW!SIRvPK1HY!gCnV6u6*!K-TnPnQ`4`90XS*NN!9fm~GlGHh;h6IvKy3(c zJwKq0H*f?3^2A&n0enJ_!UJgU2h_NOWPu}YKnoPe2ly-k`~+csgn@P^F}=70ZLK_goVBAW^#@BZ@}M8rj2MgT+tJbv__WAdP8 zpm4|$+@jD!mHWf7NN5S|1)iN}#7)P{M!W+P}h-+UC&6D)hiOaUzSMk%bX7PYQGb z=-@Hquv0Owze_2nE*VVxC=4t{{a4Us)E_36zcigcjr6y92jh_$pw4x1v=V-H#)o7( z`o4MH>ScU{3vXYC9HfG|RnyF8(Ym)F=!=^=@BA|V+n|cUt*JL*E1+i=E$bE+$n@_HmrL@TpOozww21m1(72Om zH?~qPoiBk$(8rP4{$g;u-R51e=R`<_vrBs&x3%3u*g%!0m)@#q{9OpnB;wrdpjWY) zr%I`s0zT_LJ&hPnzm>P9BmLUYbjm!Ha{O9Wx6ZQSYW|7I9|;rO4%gL3{2wSmS4gB3 z-*oat_}77(@~pFHz^5uG^Y}f4U)n}K?7st1dxAYFWnfD*VFlsFOyscriM;OVv56eJ z7BJ>+0S3pFeS?k?^n_1~u)Z0gaf#(8*P5ik+;0yQDi1pWWdsBUZ~;@PA-&LkXTYL! z4DbWI#K62vfsuQ_V}pNCd1T(#(Zfv1;!rVBaTrWYN)+vy5tRY#F-gEvBQ7Cn{eRf| zKTWRP4Q_TU8MIx+1m-8F3M@jF=1>By_s(1BFj1a0y61Q%N$hICI`O4Dw`|^_Alyn*E0mk@ZgCR6T`ZSQ&VOR6BKIGR zvQmy1IPl4oK>?_fpg~W47##kW(O(y5CwD)zQ}n<&D(sFB0Rp`u2XFV_&0}U!#BY=r zcg*VOIJMx@_(SnLNDh?pM3GD*pVjv35y#LUtA962fY2~q|6)3|(XCLL8)A*B5RW&s zZG^YB{XQ>gg``#)cQ_f$CA6t&L{7PIDpAGhGfv~)o{{QI9>e2%N}gD3S`nahJ8SEf zo|yUOIUY^q3CU|)s(~F*_b$KN(%5u7;UFi2_be!+T%NEWA*n!4q;blfj!EN!7`F4K ziEk=TW|bbvTGADz-T+kWwU#}H5Pi19-I}%x(DetDB@>gukLidnV8L0w#BO5I8qQiL z8qgr8q)x@Ib;!dfcW_niq=$F06uhi4akBSh=;p~CS#z3}WOB&ANUpf&Wx#ma0Fs8t z7Z;Niw=j}LMxMp%UQ;}8a9Oa=8Bf^uwSXz=?0`4#jT8))q5D|A6>$v9Sb%c|3vkY0 z83F3a@34(*g>gYS(745?K5-h3a7Tw{Am|TH`vIE6bdw`trGr)nVI>Ku82WT#YN21J z??--M5F;eueGNX^+ploXVfqU8vGkQdplkF5it)C?AW+s{i8O>@I!escc(e(cHh}yU zNl^(=QBg5*X|yJPv(Erw@Pafjbk=uEE@^@H`=9 z7ArUJ(hbYoc}yt-O5Z0K@gmE~CS~9Dm}(H>&5-+a{ZuX``*<3coI!sZ67|a89F-jC zSHP0T^6;&aFNQLX4iBB90gTJYO+jZ>h#4>AeWrbQRw(_hp>MTQ&)cBaOIGHel|Em_ z6<}Y+f89`KvYT7i_|YbaUipjP5a)BgNYO4(FvC|X`oyQ*9<07kcbZTo+#2qWwQn(g z(74F$$+-Bbm1-^gM`^Ng*S9=WQ-xwd$zG!lHuV@s?}BfX;PrmlrnQrPJzx-)1dyWz zq-}NPEggqJ1^|InK*QcV2r?YQ0uGR;Wqo8$0s^Uj1sODa1KeHU=MLtx{b=e*sNnu= z$MsvS76R!2M?joa1N_~A$b>&I`<;aSl2jng>LB)jj;{g^$o=B~)ocGdIck}uPsMVs z6E~OF=`u0TCCiG8FK35X`(L|xW^U`E z|A{lRT@NAP7ohx%Jk^_?a*k}3 z@6}s)x*?8C9Dl4nGI0Pe94)WVk6`1yrmXDx{ou(>EDGu5IAj7n8o**8NV8CbO=+ys7*Vd~t~v|GP8zqWVcZ=Kzz3aTE}C zJA@}WqK1&UcDaZ_{82!$KlAtGiKXhz`oO#C4<<4xSlgfX$XUnOGoH?lFVaF2$U@|h&|LX|?2f2vSLpx$fqVRSNbEiP ziqiIs`^#Gc_dN8jvsqn(UZ#tMXnJWWy@`dyeDJE@C|)4>PERhkS+>bN+|eK7xP0ER zzesDj+eYlNlQNE5N5nlRW{sdHBi?J7{PISh#fQ(amA81QrDdjQSey-ey!EUYXa37o zDKjXt6|5yH_F}>!$H^VOk;B5AXn4l;UopC|{)_fA&#y7&(%u2foD&G%&pQ?le5zuJjQL1zd7Kh*$nIKjA$}Csc2Pe?GHz#eFz<@gsdH z$&@mI9NFx=y1zj7clY!qUz#qND&Mj+LgchBUVV#|1y3+&eS@?}49fSW(y|~g&pmAi zjgb9B+|Fwj#}Q%yAjA|vh}@qT9i4f5>If_h3}GzL6KLrtBB4K~ol#vGP z3^6fLsl#gQzpD2^A_`DA1ViC~%Mc0!!bGA#A~0InI9mMAz1TmQEJ^bC8YAoPXP!K3 zNmhHTm3-T}LwY=hg!Ynm&-ts^&u1XZ!&mKKg(6a~+ZWp_s>}6mu)CyeU0s z#nsWN64&87B7P8FFKj(y#Kw6lqtlh&~35HSoKT z$(|!;H?hO|lpe}Gkj^SXn-@8qclq;DVjqp384GhHmA+4TI|VL%7~8963-g5+ttOqf zSD>Ojp$b+0yNm8G zM}SgtwpG%0XlU-uTIt&|3#q;lLp{G4BY3}2DaJ8C%M?a^@!n_ro2Ph1?UO6F z_qqP89h*hmAS9P>3rQ`#woaM8e&PCAHj>Y`)VcWmlocdRYA;!)`geSV3k4T`jc-sI z(;sCALEoj0kqt0uS1863(dG}F$^3&$Z>3P7$1fZWA> z$Wc(oN$9gE;VpM;I^zzeGCTbCIH8_L5D4g0q?lx6zzu+NTE|ocCIa|lF}4HGX?K4( zpje@R91e`#0ccP_JU9@r1|TZ_{zyl6%+W)g44ax7bAmHqZhATU0gcd3FpL*L6ws<9 zfyl13m?U}%K^FlP3qUH6&i?=FVEzfgwHEJAvw9bf+1F+8KBphYSBi)=?8$9>xr#LG zzdrI|yi@y(Y?X}I6E=?|9tA;(HSM~z4lDzlthCVEV&Cd$3@DKe%C#pnN_3aP8mpEI z*esQ(H0|Y+3nwr1TPTXLZfSk5q`iu7?o!flQg|f7>P{JHljc`;$32N#C0P9et9rYk zYZ6fnvceJjOZGl?ZD5g_94Ih~&*7GD1QicT}eCeaM}P;7<&RY2_2l`b({0QpC2q zG9?Knmq3WG4Chta){_E)TI};;W_M5i8wCIBASSJJG`W(Hl8+ec3(Z~pOOVOouBP8a z4ufF3?I60WE_0#oC33V4Xdyb%9qGrF9{?pwO+$rsw1z*3w4*NHG!PYIC}BbusD3I77LYZ~YG;`j;qf_aD2S z@)_;=r&KN(eDr@gmCE6-_F`q}i+`WS#oMJidwLi0d=nl8vZUIuEbjFFSlqEMsSBa= zeMR^3JfIu9UmdTplgaiG!Ifv!#JLWUd};3u$7`iiz2x%)x-~iOauWn@n-LmIvn$X{ z()Y+!PYQ@UQe`w&eRob2VgHoeoI*7G?|;B6-%x{xJt6=8S}Anl2ET#pTGY_}JpN;= zJ&ssFhpQ@@llzutXy&x?#d_@#dudYvj@F?6BHFc15t@w{J25cA ziy4PWZ(gC&6?yW_i(O}!&*KxNSVS%Mpf%FG4iv()~Mr*ZN=dD&6bhQl%NP*q-50t6=#Qk=loC#;5p0X<$Qt!GlQl z3U!Vg4JWl@uF|V`-r!Gq##7+xSX(B!xySlQ1@>`aM2j+Hq8E1!Vb?!`VlDj<)j6xbUX{`RfDvwT4@A!0bS8=Qb5I31lmk7S?Yh#uT z>H0yP!ef?8=jmCyHIh|lpRGN~&A}Bc-bcm*A~v|SlhhYAEJEPp)=^Hhi892$RlNBz zI*ivJrP#bFt-4)OZlldvKR?BNC!!|n4N-3Ax$JH?h8igcsk6ob<(7^QjTe>Ag_YMb z6@0jTF3;#v=xqJ=WzO5<&LE!{Fae0h+bk}-rFT<`Vtw*m%*njsSgC>dDcYAE^r>Nt z>>gAVfjd-KbB63^>Gxp^BrpG6r_}?52M9U?S@uvBJYviWi>=Ujd@wN-a3lSSAA{+* zj)b&>(BkKUmOhL-7428`!8l}plVHq*`I`4_E>VzRE5|ZcgRXAc=BtzK)2&QyOJv2M zxy9L~#r4fksN&8M6U#@atv=5NIsRY<>!q9pHc!b#ZEkLw#?wUv*=5VK zh~L}Q!NnfW`d)y_6sbZtyHJzy^OE0BYOQbbVKo;hWvRa|{6zXWh2~ud=h+F_;;#Op z$RDmZ1+oymT|c*AN9it29^2kaYCJs^8qcC8e?=)lc>A9?z`8477ICI7ex=EN z)0e8GW`ZXpp>nlv4I;y5X-~2dF;+pFDGHZwsN;*dcyS`1h$NamBqg=#;%u<#8CZMK>>!KFwD9QyH`n>D1euXnXi$@3PVF5L<7dUE^z?yOEe8D|+ zW78J&kHVPAZr@EWJzd{+=juXb*|(<0AZyyccJ<_Z8XQ=cnrw0_Gbu=umO1LwXYkfK09ej&w#5FSJeK?_f z#!NGh5Ts3^o-gr--5$rst1)bI&P(x=?>k&|>TT!m5DLumESzh;CEFHXnI1V_voC=Oxy+4&U32T$>PWE8p2XNhI;eMR-Gp+wk0v{&zSsDb*P49yPLAAc$}+ zIeH}ZWY3qp>W`~UC{xFxM)~>^saj!eoS^YkeUG$j@r)|UvzgUxV+H$-pF(|>3lG1* zhI5xEXY#Ifm6n2e^YCpR6Fx9Z*=1yut8HCi-K^PyL65*PaEOY&Nrv{hIKGpouCw82B@Q%busu7hL_PGnwdp{M4P=b!wKN_tb z{3iMs1%XLwbW|iVo1(}Pf?YVb9xzbu^)s5eG(}@!;d8iwI5yZcU9nv+g zL?mQFS0Jc%k2_V#r$UU|OM{6|j<>(Ei(mD`dpW&_V&XO`2@gC4ooo4)?yPlHy7Yyf zUTo@l?%MG*mx-bIQI`((cY89U7n+Y(f`WfE(oRZ`KM~<8AW;h9L5*@#jlss4SSR>Z z(m3SZ%UZFP8_)1!C$8ds$(iDO0yLBC=gM@(9p4WE7jQx28Uk$6yw4%{6c94_Xa|Ys6e=Pu%|oR3F!%}VGu>v zVN(kpcA|04#}9}>hCulCUD;~^#3lT zGXM290)CN`yVf2uHJZPDg?QXH`F3HwvTRh}PQc_jQS3PDxXiQ#)1P_D+cTfvj@pD^ zx7n`9k#rdc=Tw^)%)P{>s3mHlQ5`kmq2ze-8qyn8oL#Zo92uDB(ezp}K(Q{4aNXN0 z%%CacYmINrI*u3tx9B{oicYvg5h33N2uQ~2Y7J3oIPEDmI$Q3zq9K}i~s{?!2t(v zAdoeL?h38$0;6*GM_`(r~mdn5fqfDs&y z6XNCUy5A1y6x|Rrdd$6`uZFG#`bW6I0hiTpPi5cL3@kEo1C}rE-zpq(m^qBr$i1CW z2mprYzamaR>M+F79avll352@_0}sW|4ebWQ4DN7L%16!svNOHl?uh+!gdsZmMusM4 zDh6ik5cFOy?tn56_XeESaBnAI%6HyhMePE71Re<53fR{g&+l33V{a#mw-DUfPR46I7oW_TCMZM&sEbWdnFS18*h4b5u=2v-WC{Dg{q2IXC!MpQ)VLJ3w0ixknwuMjW zLP7C@FpwSIwyQ5iKyrU7E1F|X=S27^!MkQ15$CTPu)Msq__FF#`paNeNlc0Zk|Gg|Ms;>HM2EiHhkoqf8+(@_zc22mWn2aLK_ z_Giu|`Dt(K28I`dZgQZJq=ig3IjTj7De-~s5GFbp>rS6 zMQG&zm^=9=1?>^nS^xG^UNl{Wt5a7~yfY_Qz=8wagQZ=8O~#pV-SJ1%2J>KrgitC9h( zJ^OV%`TJhA(=H@?_{{unDI0;)&7?r{YF0Tud*OKQ&y}@o-AbHhk6pW7R9B78j{?^6PH zrTzx?Yt_JqCxCTZ? z!M`(mH^ZgpBY!#+%2_)MWH>+iFyj@qA;Rr*hn=Ux&zS9!P*+T9mvu@@|7w|Y$^5lf zTex>L186xtkg<-?h;M^8*!Y<{5x0%3Y*TII%1NR94=#lFeb0+-d#dRTDcyt{x3G(Z zwwKU47QV@h|9<1%O5%z_Y;*H?d&52c%`qulkWL16jQZ>YHCTT@68EdsQm3`_^;@{} z3UejIk`80Ncy^LWjb~xa0$XR-ec!9|+;}uYns!$>ATz?);}o>?wnO2S?>QrVj~oM( zthDOTNszGp?60m;lH;t=0kB3JVD6P1C~2Uh4-lOz5PpO&G|XXtDP$^Y5H&auWpr`( z^MXT6RUm3Qnh+IfQ7LgTQE92e+n{agR>tdITq>XdSqFW+CdEj=>qwC z^im8eBZdxEiiwM1?6qG-aqIv30Y-t3MT++K+#*HqxkZ54bE`?x{8Nc719WmM(JXDd z=ZVRNh|%a$9k54;)`b%`Edh_W3lq40iYz=M(3LTJWE|2kX8%Q6KJw1<@2#V0oJ!hY zpMVNnfoeA2m8WJ3EO;KuiuEM1i)T&*cRD<3mb@%s3nt;j(UPdlu{S7iQFzWnl&f60 zYJ2U0@2wJ$o4`VJ2ze1r!yAtJh}-fc*2eB9Eg4c4uHX1x^D%Q~U8{VEg#5Op<#?Bi z)Qy}pGcl>x8O$EqPoFNAjFpgZ{@^6b6*WKWn;U~`oPBa<#y~*a`rR{SDOVCRcJrVy zB9h*#H4zgTlDeykeUj9yrqfjhvbbNzYy5JhlU~ZmB@!tH?FL|hv2R9!)q&@s{0D%O zK;_Y(XTt%e2`H>Uq~K(n;DN-Tx6=AeVnhzhen4OwvxU}QbTE~%R;NEVUdV4_k)$7p z7x>{-(Z%DMz1fD+3j$0$DWoX^CGh1)7n*1!G2d}SufbFCwAMGDHAGG>1b$72q#0`?hv+Y zb&2%05WiOn3e~(IOT~3LD@7ic2>CjLkHw4Rp>P7n;7C6U^^RuIY279@`th^=tEyeaTd$tgfd0@9Kb|@;^BJL?5QDqm$G8^vX5}k!M-%4oHC6hS zR3d9E-$xhKJR1&Tn+3_|Aumsh60+!@6F(;|pOM3}VCdV;7}5se(6-(^bpg9+*0Q}@ z)Bwfm_O{&3re1N;;lgOdXQF_Rrp3F?+3cy4l`pT|mu~QvPuiHku-ksFU{}Gn6&(QT`BwJKRB-AI1&k+&`Ha?a~4g1Z5yc`iAJC z8#_B4<`H63!;aSOuNlDTQ_g<>Dl~Rrtx5pasw7lK9J7gs3=~roLl^%axy#7Bqi+wB z`ke&$5#rIQ-!J&0#m!D6u8`MCrNQ=UVfIhUKi{EnTgaciBKe)jsa0zYhhB+OOaC!1 zVGJni~daZs1QzyHQ~DG9ZBG zfOU*O8xm;byMoB^g2<8L$U$i2>;DI2@Gy%Bn;J*WL=Oh#FW@cUjyv2o=x?ww(Gx)f z3q#`QoN*Qk9KeAaL5_yUzT{#AIg%W3xg0%kbl*n2W8VL7^bXYK3iW$LAkQtMn5!!b z4lkLGsEdEBKEAGpaeraO`UQLy5Dp2H=mgGbabYMn7EbC>xjV?|Po02b{d7WgmJyYl zXHOQVFW=H4+v7f;Oii>keXU{X(#B&7(jV#V-@66}Gd*xxh5C3ToqJ&2vx`bo76CCK zluMe1466gzTFc`_Tm07LKPu!8vy67xt6j1rZL8Q1he!G+Zc#^dE z|Hc+(|5KBs{~O)ozw_v|e4Fmyd{h%_b`RfTGv#r(8|B6$`rGOgQ&9gw0SAHRm%Ypj zd^TZi9uxIxT+dV-K08>NZXJk#gy73LmAo z)w{dq^+71dDdHIEasXHCz~g|44k>2QvImwYi-J|S7g zYP(X2Be}4{#VFEGZ-K+f(C}GAS|dLOA_qHzW;7m$$nROwf7_JjKPO9C?5`|o2`G>s z4J4n4LD5zW;K%r@_@9&|eQ>dVayS%U9!8DwJH4}Gi;qbAVjwfa*sV?+F-Tl%il0Q) zHsksYt1fZf{^BE>+p4b~vX?*qkhA1u+*sC6yM~Hz!$~c$ESf=;nwpwxJ1V80e#>QW zd80*eZ$WL+f?x(v_Y(juz6txUz7A$H$t zVz{PP1h+17-Q>OIJO&L2+-6MsJU*YJB>F)4Dn3t3?@C6jZV2y{{#4aB%{FwUv(J^W z-v(nacd&_P%C%#d!@UQDgc<;EL*BkVP5@7S5+?_a!u^dppz4RK^RY=tRn#=pb<_;? zF&Q2(U{c1Y(j?eMr*vTCz=@cZ3wZl&j%ZODru!a5U@uo`V53ZNVBc=E2N5U&>l!e{ z|D>z@)2>u|>6stg@B;4&^;l{@+lesaH+SUPOLfkn2ng-+7>Uq>C!OoI- z4%%xJBT0{O@>x>sKjEFo>Ax3TpisoAq^jiklNmb{n%swY_+aLQ-2>O=7{)=`rO@Z8 zk}!v-_pxqi+U4vrxn+neq+YIGpJpKp*G-UCYIofc&st--4@EtfUK~W+db7O>Y698B ziqZv&&5hi=o`(ynq?=iZynwt=8Ru0^iyC-TN~)%h8p4rS%^K1$7#S{R=BI*1)s=&U#fwzY$K{5q0*D%`pqp zA^Y2si)!16&k@fwd}nhz6Si8}t<<;fB{sQUWI~NU`>IOLi|V>6Pe8>v-wxw&x_sL< zk0{%6VT_V+b?}ini+u7WRau>YwfWA__@Y%ADMPUMeKUr$rq9HU7c_`wENQVu!iYoSJx_+2UML-MKu@XmINaw=9qfiapzioV%MLa zo;2v}%lq7@N$MSDA?upa`J62`NY~ZCJx=Y4^j71zVRYIX`><1rg3|cr*UlDWSp8s| z(u?NDSRIE9@URd8k*DQ-Rwo2?hN1a;yk%0e^;M2h-r9>pZZEJPl zcg7}R{e7z!8aSPc(&lL18xhRF$*0ajB2X~CG{ z@tolQszLsf1~<2nvf@}h7B^Bhsk+sl_O6s?<9dmsPjybsGcn~0URmCSWa^6_sPi&Z zO|shpVo^fnWGq)28JaE$mG^I*@x3?pb@y{v%Crc}o$`SAk*2~=a{bqJHD5+EUU*nY z#hmG-yE^iuL|;reRz^7>jOKg<)it9hDz4215pc6ogaO-R9vS}J(-yJW-G}CULRb-H zjB7V0%uTVchT?1QUEh+r$o0so*NDRLa%Bb6?HH!GO}o}QBk$r@M7@K)VQgh5&aatz zbJ#r>oOyHJwq~faTkjJtcyz&HyMr@$`)3bVbmmHfhcWnN(9j%J;U-h`R@8}mx38`S z;)$v06zmZ<{A@TN)d*uyPn%jTt<6UYI~?m~-V)emhIuhvIe`M z!y)jQ*W(KPJrz%LCdMt*hmq2?;pYZ!Rx<^(Fn36vPhs_9?h4SXk-#loKcm3Dc>3GZ zD2|gMX19F0E^s(U`D9_J;$TD6nB(i@u;KukhyvVS^9SK3oTCpAofGuyYhd=j6XxG< zHoybrLaTq+)GWVkHt@f>%fSDYi~c)%y-$SkK7CWryDJrT)}-`?;!GshRyjtk-aK;C z{B~F3aV$2ZyH=xw-B?3qp3YKI6#3D}!D(~HIJc5(bTuzpAfAYQfJ#~%kqq*-E*Mo^ zWMa?UG|@A+eoQWHsQJ@tLs(*n<^24|Z?^*?dMc=^+7p&!y>HnGNIPKNrV8CnDaGE0 z&wpfl0o`+=CY0k=bdqP^chE>GduW~4D?Fl<{IU9ok#w-VK!8no4mRb?+-bcRn-zKw zNwZgao!w`+1ADEShRnKHURX1EBzMsWjd6r%$XJ+>bPIwGoZ#L58T1&1>hHK~>} za{rqHFyAY1@I^(~)U>~j1M9?q-MIaMMVtq#!GOJ;fK1fGZMV^TJN+vDXI%#%`D z^Mae*lWdpr*o}re+68SIif&3Nk-xquX zZ|%GtYX_P6v*>IqXbt0YsCMQ8hg9;aZnmF`Vs+-jNjlIZ1)Cs@Y&gSgKvk?joP|{* z@U7u92C1*Hv>}WH+k;PXzb#h?Q&gnSC|D{~(7DNr1h6xN^97ZBfYUdX&TX(>ANTiO zB`RV^ERI#irn}Uxhj>PfwQvwfkoT*8m-y+i7$(TwD@!@;RqKBzkfr+NopY{C#WKvs z#IC2Kccg7e``&(Q70hCL7bIScJ0D6NHrQVM@7xA}x%!Zy;<0qsj9%@&tP3Odo4ur7I3zbTgzk_emv{t(?sZAg`F1<~oi zDN!reT-rtBkfO{UzY{e#SDk}+Up!CLf$tynr;#)`a*Oq5j!|V7v%A^T_UJflOvvAscG;F274C_(##)pS6&g2Ik^2qZE zHdCo*eBCr;vwr_ixbLgn`_RU+!6g*=z*`e^ozvUVJG zP~fH*@bX9e?HY`*@nvH171k=H31bu_8A!Kf7T4x)#oR8O5s7|6jiF}ZX0X|`)_IqX z+hntpm&uA5cj5pdBsAx3pl9d353l7dcc3MWZEBEJlb$>E{=kH6c*`Ck**{OvKmJ@e2m3jov$i=qOW5hT z_^7T)5;l?G<%yK7!Yi4TftP3_0h_D#=}JMizUHM3LgQ=wp3Gg(f%&+{X#G9HN2_d0 z(F9KUt1(lDbTSbGZfA@axx$s!o_El%Ks*ls@iYL$ZI?idu8$O|kF=&Ex~TP5I54A- z>$m#}WPSse&8)9=91*b))VzSvLSV0ZqYn#a5CKDwH`=Kde@(1i6MF&0zU%M&Ym0Fy zcL7YG0YxP+hyFs6@8a-+QV%p*|L?quKcV_iU0EUWbb~P24}x*_`1`oPFlB|{Q)36I zo+wr)ypE$Zd(F=RU2$3+?@E$nAJgBFC(d)wn%`qErS*_BES}IiLZX_=!967GWL{0A zw|YB7=O_@$!DAv@4v{s%=VEl%VZf-a=tFp*t?E(V)BU-k!;DmEVMRKls)A?(KcrL) zXy~)G+1b2vqG#_O6GM`4mIXr0K6dI3@EhLt^?hE9tmTyN(1pcc_H6ny8)229Riyfy z+ry8ec>b2kt_EZH+HKQ=Q{hlf&tcXrPlM9ET(!0{1sTod z{g7LZbatK2Q3n~5q%7xBBMdz4EFOe{0W;5bh>b&S#75u#Fgqg_=M62WF%w0vbR%vY zJ?guME4}=Dd?+sh5h2M`(~)C#8mbQDu>v!)7TaEiA%a*s?gC{R$=W>MO`**yCeGx3 z*qvDrfwq3u60$0;MOnWi#Zf$o3CZ*MYJU_43JUq>5)v56R$21~X5~BbBa}bpiQzSec(N0nNj;+`=ZP1xTskRs zLa_AnC~@x6i3r$s7EQe_ka&jj^?imHv4}JE$;>p@2cHks!i`TYnj0{Z24}lzdHE0q zr1jKvyHd{#isp9|#=4)qfLe`$$0T-w9(Kyk`$E@*`9?XnEbviLs#jWh>oZFtf^(K)0X2d)^|Tz_N&cLN$ykvwebcJ?h3vLGN$IO&l*hW3#?A)C@4Uw-w|hjh z;~}4<+h(5BQFc}01P3&~Ok~(BZ=G3zG)6MCDSe=6((HnFMudfS*8Na&{fsRe9|bEv zLBr)4Ze)F5cv;1plh`Ts>Uh(PfkB;P!P^7${hT<#2IuPJdM>KRuY1popF)V5?-tW< z)rg4?gj)vnL}u}-LsO07a>hIuGCBg`AEeoTMO8cG(;FtdK>o{7<_8eyq^TJV#Q4oPC}Nk zL6!=8VxZ%738PZCC|iQo5$1C})a6(b;;=isOHj8G!lUxjk|urW0dnsV=#>&XfB zy>l^I7i&)V)U$9%E@R&Pv80>9;RWpO(Kymz+Q(hx{78Q3XB2wAzCYN7Yj;wUf$8E2 z+VH`I<2uRDDeYz}L2MQos{-+c%8I@#d}EGp z@sAHjxL;DzmuNwg)1t_F1iq%7@o0%znM3tqy+kZ9OY3LanGxTu7HQb`N;r!c?PF?U zBjvY**gw~MZh#GNlU$T!v`fFjpuTHGIY&GltH(8>Yx1*B)s`KpBI3RqNOMmL&Op37 zj9JL7g8H6Pd{Ip&eOd`wGIsew)M!aK&XgVH*dFf7seJvhK$V!!w;{{p&6*m2nA}gx zEFTbaUM{)^M|F=T=geuVl9+O4MP36Rf}gXBe|pjYbQ**ezTXbV@Y$*}rdPZ|-wr1n zs?qdBale|qxWZ`^F;{uz8~-O}iS}7bo+5TlnLP&r_GpwSVPo!$(LRR&jsTP_SI8c%D4vgNrY2Yn0RHm+?MRmeUf z%MN^iJ9*$k?yJN9`ZxHe=x#BoPE@PcIynNISNQN3G47iuRt-14^Bw#~m&8n|E<(xk z9Y1tVTcJOnMl5+KD*O_7wD=UP!Rzm&a=xk8QHx;Y%D6)ZkKF^wDCaC!W%=kkuwl2`DiN$XcJcyA|SI z^u~T_n@%p29uE6ZeRXuk0zT4=8*_4KtHX~}R3h(le>UEdi^TwuCF^%j$U8mvptWlf zWr+$fsXuiid%j<>?B6gbpx*xY)~LzqIV25gZl8Krxo;wo3$Yws1oWJ(WLy3nLnp3x z9l2$%&-8hgRU3auh_60wxQy;#C{+N}6+wd64Jp736KGG}a36rY)UF5n6o7pRm|Z-a zJi#}Zlcl8_V6JEZZc+Um0fHgHzGoNi0~kPY5e4|X1$XOW?zUMQ0umH-3#$yTw1Gv=|^tBv*v)MG%1+-1$+a*YBFnFd);z~l88IUOcIZcdvW6=Kk_r`4Ma05>xWA1Fxq)}!tt#6hm6wuHYC8BH&CY3fAmk991wO+h;SH;;| zi-?{06e=|x`5hvx(wl~ue2*hJhw}R|w>0b0@r}<6+9rMHFuaE*4BB3gzhFy+=8Jf% zPQ}X_gmSYC;7OYs<$`D2FmwV z9|V1@FAAgG7uPkw%qS(EF8qjS`#doFA>H79_}#IsuH{wVAufstId`r@Fy3Fur{3fH z74HE?F04F&_f=QrO`Drwf5FO4y^&Sj=zrbtp7}`vxn^|zZ?JN~3N07Kd%Eiv(eSmm zaJRYUg^B%pPA;G}d1cIg!O6Wi1O@#!e((RTA5gvlvqhRs(H_fVJorYca-87oxGpsl zW{xm0N-ij6JAbS%0VZdEJ*;H$HO0Oqh23X<5P84av~bF9!X=)mvgMY#_Gh@wLcclj z@*JCMc>aHk-2cbO{U652g_(UBh4<SI>LcS5&X9r((Auq#L_tav;^PcALv!HMgp zOL|Mz>LBpUeQ+xH8E=QhikNc)`Qw#)vz(qw+0`>y&W`c;AYLNSEc1$gMO?)&H{DU) z1fIUM(h3pJX4bf0Vj*oNj@IT*sB7jVh~eAu*G{MsBIxmD5;NvH<1^dW(Nh`KwfFF>pCO?7N)eT1z?=x zN_rQ_H>?5oFAG=JE9Ve+EO<2&fF$l}&Uz(*fQW?wOv@=rD1ir0uk-Tj@d+&A>*szU z>;C0GaFJ;PqM*Rk(8UKh(*{pR{FIyiZ}1-flxz=)L`J%<#1VW~X(LdFNf|9_XEny?)6NcQ$59eOoF`c(d(r z@3GcqsV_?8tSiXYa{Rqip7Wgb^f`=7xYt7U`mvRR=z1e>6Wg>Y)Lwa^pd)wsGRyL4 zE_Gygt%mrcB?_TuBY<0;bP2>*PGu3*8H(_8qWV#lHl+NSQl1?RWlC5Jsdx@0rsx;l zV`O(mV)|fBT;ScLKStcaY=XHvpqTzlrnG_j`&ID|Y@Bo>`9sqF7}>3W!<{cu1S%qH zmgdscJpZjW2>18YS{9rflE8rX^JsX#jW z*KKt{^0=`tzbFC%_9Q|nnNPnFtWWa3_I^p^dRun%;Ro^HP2t|+gTm?^4SzCKi^Fl0 zCHt>JQSokZ%ut<*@GefRu{1Ue;Z*u=QNLM z>2}W+Ge|Lkvx<^L-rHtoAByK~qH6rEGnGy{sa5CpVWgJH*C(F$gdap}y#DmDbbRmN zj%I=G@ngbQ@tYqB$E=bKU{ITpLJIIg>Oh#;UFvuPXpMNGmNch@o9vu9aWAIO4zUkkab$g#B?kqBd6x@V_m1Y6l}b-zUn zD&}k+^48W81h&%2@hVQgBi1}YJOl+G; z`gKhkDUYluqwzgjYr#H!|EBILC4#&KY$jnr&X-|e1F`~HWSeE1x`sS*T;mcHy~h&!|R)rHj@=E7_(X{c{RgNSH7&zmx62TwK*^ zE2~kFS$=Bm3R*A0m)Kq=6G!xxG}$Oe&)xJloc9vQEF_GMPIl<5i*g_O?D*^`mBM@R zfaB*%&)5A|1{4fn69EIZiP*S|A6Q-tN%Vx@egsfZ=#4+3lK%qP_)|E#PU{5 zy^p!Nr&wm-}9Wq*a!`>jK3GXcy>NG%yD>653hS} z0+rUTeSYtN-8w_@60oz zwO*?}txa_NrwLvPO{DKcsopccA!yjnhY=kyc!6mf@l^V_cV0?lDMNsL=xQtxuqOQb zLV6=+r9e2~0445}`Pp!m`Pgg& z{{zg;tW2JK>9>_h)6MBrCC~xvXo*26r?~GQHFNLU8w{~NWn(bFvxrYIZgh+-FBBl2 zCj3%FEp}*5)V}uQ+gD=U;ybDauRi5|H_rYRy&Hbu_#P1!GO;(36tQ0SB#lv^spEC8 zfj1SbuqO6X!&d6hp!=8nK!5kd4tel>_CtFr`S9HG!hd*LXLduS{C|o+I_43~J$IJ2A7FEvL8JCez+WSoiLC>Oa9%?TPC=7j#=F7kb`) z&$8_xK$Q}IdE6>)C>VXxTV9DljJL_0NhG@reUwK=>QN4I10OrRY05D~29{2s6TfTm zb^%)0A*{)URUk5VQsk-)t~5qFjSh5WfpI&Th~`oDn|pj%D_dG`DkolMgx~)TxyJY{ zi2)16hjF^~Lztg@6tZh@#4+AG2zx#(fwBh=<#B!KDwJl4#*n^PayLzV(`qoJ^sN<$ ztUG#wkN+TZ%00H2AkgsZnIt*c<#PUqF((%uu6-z0HE9ONdJCx{bR2C`*jv9u-9Mi2 zYd!MsV@^Px3;n&Cp~L|F#IK^lu=FWvfSR|CkQmIFN8XFlAjL_jNW)I19#zjbj3g&P zY$?O?-B04#Iaygwridiw-vZm4T)ZzL$NscB>v)+T^ zLQCg&9Ard+mXh4e{u(GF(TyPTc7edTn(jq?BtM6R2Z0M25hFHYSyE!{#KykGF5@&JRO3P`c4C{uHL>-W~lnjJ?Sth4@ zc`rnyu-+aVg;z4djvs!BLKqQXofZHhk@8v$zdRzc`i++tv#|%X1v|^YCCRQV8wWt7jTCt7@@wgiMo$Yzdz;QIo2yIO z1BOzhqRd^HfcOKT@gQ#kT-E{1NZ`Bx08T)Gm>bwrb8~V7TWWy%$qVogE)PNf{-92a|K(Wp`_ z_Zv)2g(&0Qi>MA3hKZ>f-<5rC{+gKCh%{ZZVnoLDfVfB zG1?{e021Xl7WirIN=4Yy>A@^a+?O@sESpq(j|eZ51~fne5e60-8XgYf?^(pJE7V1A z+toPfb?@91ogqc2QAH(_=kcRSyfZ%s$=YwB_F3d7^yuVU#dV->CE63b=&Y%95KZBh zqQ~wFac#GevZ_t`Gx(Yh3KR0kH5~C|&qwI?c&H6_o)z;Qy7;ZmXcLXPw?iHY*=QTR z=(ldhW`1hlS~HhTedL9|OgV$k{od-uuv-YqGkhXP%qIa4Od;@^8mVq;?N1gt={#!W zc+DK@osl$$-N6{4`ZOs@)lx7FH&VJ*`IZ(qO-80ZE9tw?*HYXM|vESBqUA^kZx z{>L`?zm+!rAO7?G325G!a2u9Ga?F}e;ygXq){UZ|m@tlsn|z!S;=8JShbOA*+eh=z zs$7@j&rNkR@9siW^)R_Tdt>90NWv>nApxKM3H9i%TqoHgok=Vkxk+%>LlVa*e)Zf$U=bp zf=&g8CpWW4+I-|Mw?0XN4 z5A|p;s!nkC8#Hb2Q$=4D{whF0ul^1lzosd0AcyPLF(fh!V6Kp3kgW&O0cn9WaBtZ- zm{?h`SlL*D$Ur0@csN)FRA?xC80^@OqxfN^(J^)%gZFL6WNtJ1-C+h%;a+n}?VSKm z1%TiH=y(H)SwL}+#nbKLG4Lz>+}qT69ofi8XQ^S1w{O6+dBP7T!~f0{yZ|=2A3w^V zR~fDRJ|uXVy>(PLyoZW1*Hgz?=d5IQM0sQ%5+$9%Z}uha(334OuH37!G_AS(11ni~ zP@<+TYI*xud4W#po>_mb0+G&Rxt+(jv?RJO(T{_ad64bj?g@4rn5|TDZp|kN56c47W3asyb|G5kOX|TC-?_uDmH|uwv-X9&Q;*D>< zH*&8jy41_ZK64||cT9N+t@Vc9b49iW34rZ2`+wC=Cw6(a$oxHa0qXh>E5rYcS)OH?E9trLVb-lo1duyN@mxcsMS_a_322>T~MShA4qm)JAFeIX9I(XLA;W!zyVa zkiEnP9e3yxYsTnxcXu8qvL{w_W!S9=OZ(T6LSmvkwI zx=x&E9v^5)nVn99Nrdf(yyRgOC}`T^-(8Aim`^t*E|q5Tf=WR_MSpHy{KOo*?00P+ zL~Ho;`1>U@nh4udj>5Em+1dT$2~wA38esbY;s?a0fk|l{NNAu=03KiaId^j*G7JnX zxmq|o0qtWaS083KFyr7a6#OkJFZlFs-9hhZMwrmvCxVvKL<5x>jf_l9io$GdZX>(P zP8dAc5LLbHr2Rr!lhn4miPlCtZY~akvxtwV5&xNS<`hYwWSq@(K!dky8yp(_Ky0Y9 zNon>wq*`7&%?E6XVGV+v^wX0huG?oSIpm_{E>LFp!DXf;hFX{;i~aK+*{udXkE00Q zE3YoFo~8IX8$EkG_2LIqjnk;{yofw`m*5LN-z8|WlQ68T-1vlT1X z?D7`<$PY)UHuA*XF${Mk z+cPBSlROQr@H4somwI@xJ^RrVtZFblHYQHgRPfU~z= z8{hYiuK9i33FLDF;w2=nogfjhu++s#F9x8+0kJ{=$)z1kWv(rBkgy1Td-i97DK5(T zlUDn0&LWk)*w}J`*nxHtCnv|HyB6m~ub7RKmy=ibzw)j9DO1e%qDYc>_4q66bM&v& z57WQ!Orset42phYebMb6N15bJd@K8DTB4lXfvG=KVPEO7E{rGdg3;b#Wy=?6ZHi+0eY6E#8<}m z9M>$)AvNh{cDQ*KAV(t2jkqrkH7^@ZS_t_ zyL!u`OJTJYGywJs(@906HoXNzkCN_fD45;!DPck*()c5+64EcB}v0;|1Wq>C5eaiiab=XUW7lNnH=a}&Ar<+&K*1^1e{z((dj z2Td+m7k~Mh|NrC1{C6$x(R^jco^wsR)j@-r4PD=P>nFmxSg4EhUFal>zdEC`V(e`Hzyu=)zeh$$NBo{rqF_$sYb4VY zUyq3SM~aG>BC~~W+1%@#P`XztC6J~goYLr?rrxIIA6^lmP16+^uU;c1i0sQRiC$Nk zURGe#DVnLP@F4gmw!iac|Mp>cW8QfL1+%mCMa*2u{904~5;L%Jz;;Lqh#Th1m_cxe z!j>v8K-|8Wcp(GZA<-L=^Dp^ASCSLZ$XGY|Ldvcd4mKVR;584pV=u@;00RNM5#qQa z3tb%kCob{FEfD5nkjcAtP7OR zj8t|kS*M5p@P*J^_^Od;e_U@qZyLFXl^i(Z6OD_{LR(NJA*^Jx!+g})5qN?k8;bpx}c9@?$hK*)o@$%adZ{ci6 zn>uuR&bU9MwN0x?Z4~?1`W8#=k2$z?<}@Ld=fmWkh|hUs>?;q?@0EmUt<+D1dVAH2 zZ^#6Gn`)+TAZ{7vve(w%+s?nEj(-3>;<>sM)g(|kDkHz#^CR#{p{G>3n1xV2aT`3e zt`t*k@|V}+6&hqa^>Ydk$;a4Y(WwW$Y{#mdZWM% zk@*O<)osbia@|!LB!vDE3A#5;48p!EA;6?FVlglnA4#WEhs~?9(bz_l_p}Pmk8#4B zYr0A1^8=EAXXLT;wPIg`UyrFh_Eu!VKMit{nB<3aPZE0%vCM3@(Y5Vb+R$>gQC#?A z?puXVM2*#D*#5?pYPBjrCZDE0kSr;%P{p8`k}Ng*dsP2k0=g09KzLm2ODeVQqMIu6 zeJI_iC49w3(Nig_tCH?X8|_o9C51PBp!)5##3uxamfH_TknX?h!aRl0fHiq2I#*4Z zDbP99bL^bS;++&i%C+E+W`p(UnFm)2LP7Up>A;Hi#A~62`Y)RtB2&3R2j0RgstSlW_KY-bST3<~GqQW~M2PKs$x|S#= zx3lcjcnFjq(*t8#)cKin!8iFcDv#k4mU!o9Md?n@?_m)IbR)==8(M9uAW*HZQrW4} z#ift%x*=#Sq{3C{WuU_?wL=uv63Rg#Vh^>6_8muYlHCjD*)LL$yTciu;9$$wRWZ~M z9v1)UX)hYzbKlyWU2mzQ6KHggD@w?)HQCRK~IDt%in1v&{tVhp!UKyemiOo1 zm8JMAS-XBRFUBFKt!j!~<2RTrt1D_h2ntl}C`4^+!nc%grfGyV-Y%#vG^`4-x3du$ z&6?Zmu(7LKa=7(%uUOd=(f6J&UXDhRSSstSd1H)dSWv)fjMQ)j_RJf+53os5os`uC zgV^vDB0usnMZ+3lhU}7h=QI(SIA4Ya?dB$TNHA= zp292XHQYYXbtN{@@KiN-tUivpYo*Dyb(oKt`WO z&UxVwpS&kd=E!h2^UACi0b6dZ)2FZkVds*M&QD4th((l-)ALL}*gIzTEG*v_J6dP? zG{6QE>mU7^FppCJXFjvzW%9GD(s&#wDCVYsc=z8y@@LWLD6Dt(ef_%kfqdZv&f@Oq zk}b9XNC{jMB7upGOD$1EjSWayyh59m5|o6NObU+@od-!4e$ zegRiChmZ#|PM4pQhG``iWh|MoN0C+rk#1d`qCC12!~DdeTtwqN5f6-|^7{q8nAR_n9y3TdW#dAwNh9ndj()Or;ry?J2xq=o z`}pS9uZ_Hoe)UQEaVkkS{YJ9cCz1g?t#16v!Z-d8KXY>4udjD>XvRBx%S2$m69FNM zyR;2wCvE8z(h3HiI*jppV)&In$E;T~?r{VPJzg2oakp9fe!cPP9)el4qBi zg!N>QBPQ0XO?ah5U4W))fK5RI%k<=o50`3?z%G~K_4^Gdn}+Y?E)M=kcj9xB(^ukb zNUT4w+(UPWwR+ixo?B*UCYStu)w}2gb%T2EV%2t6<|x%XmbKbp?5C}d3qcd!LfgtB zRgeOuIBmiF%z=BVG?A|F*JckR={h>(7}�^y%SG{3(bTln}_z+AgB|x7*;Nhote@ z$uIt+B&(wJxJFPe0*U?ntuAkTXRV$^grJv}UfmvOA9iFTq4n+02_NUXR*d3eR>1v` z3VYe|9A`H4?om6_-OB1R@g4sF_*tV$Eh!aG_%Ml6_>H}OdC9w$&)KOv55II@vNpKR`Z(W zIK?-A8Hh549gb-7(hBBb1)g_D+R$*@d~OdBVfp$#yc%oUCJYUv!X2c6BzX|wg)lTK z^@(&VD?e(l@m(h-*L~tQw`gB|LTGLstq_`Iwi3)6Xy7U$AM zS7OZS2){%UFj^c8g9b#>_kXH1fY)!i8*!v2&kAf5!Jz?;{zKZuBh zC;@K!k(w~OF<(pXKw}{Q{iBP=f7S{?tn9q(9N;0Ci_+oM;eYg6e~OkT-&ou3JvvQ= zESmD$ck$R`?f&9nd89%s^&r`sqtX7PQBvm-^=-LMZju~1iKZ17m;(vCW#JPUZ72Oq z-&^%6+~gFN;$&q4=D9y?aZrUfRhHC?=HXH&(*)Ebd7*{Tx(2#8LtLQ>0mmk$A07y^ zrV5{q1`gM3NowpkgX@=Lai83SMYflMHfa59)56ylk^L!Vx=xbzA;MNwA5L@de6>U* z(~B@TNLj^H`cT=le}6B&p|;a|8Dt< zu8_6Pa7Cc1Yo$3*j@Oitayg9sThE0Hyc}Y{037ZhEHe`)XA9ugaB>v^DBCtx%x-pJ zH%ZCY53-n?>mUWsw7gA&59Geiadj1Ms-*jqT4hA;o~h-9+IP|I~SwgEkkTAW{$t zCW93E{nIr8njznwqM87A5PKe9gr9q>kB?Zq!+AL!c5n$<6bs&=Fg448PWR4zxYud2 zbXx-fE&{gbqOIRX(<=OROx#0f+s&vYek#o)Br#9E;|C#LuG2WxZdwDpsf^AW)q$;Tp-4)SN9kl@X=v@>ytt zFln%i&~rQoBK){FI(SW>6I1xs>>p7focLIyJiKT6qsr*GYf7O>yHQwNZ;Tl7u7FuH z#ZJ^aUFBM9^+Uu|b_|H6%yucS-~%1FC^ChIx88j$yugbqncuspzv2Z8fENtl>f|L} z!0^3&rtsVE5F~yBG9=`$Ym&Fx zU=G^lAvaj_LH9p%kw1Y%XRSzM+_)LZWNLOKvIw#JYncqGD5#3}lt#OEu%2^=*crTu zIeY*bz~?_Y9*A_H=WIXi`0EhtL`&a<;s$1Lj>t9GF(l|bJ#7tmEFM-N=n0yKxbdf&XH>L z>>9GAXm1-037dnyBtni*JSwl{Z!9z^-lslre7O_4;%(0fiCgMe8{Ogeq`j1R z=pOA>%@<=H8z-SD7!9G!w;Ch$XAROYlZex}h#YhW+F0XCgRz?OmBiblDLyj@#K=yy zKX7Sw+MNWy<;e@7esHj#+mTL$1ub}z*+*) zi4C-AZ7M9Rpq)2nQ<)P$ZUed;S31Blw|>DAxZ9v$IBWn*POd7pYFqr<#}zV0zvGF@ zjXO$GjTI<*fm0A@WL|)@=HzN)ZemVq4%7{<$*gAJj2_tQJD51TI#~ji$WD%6kw368 zB^MhPJ0R%9bAc{kKPeC}%EH6S382fR+|$(|=>Nba|5VZKOR|gE_;I|K%lSS~Vdi~@ z>g2r|^d2a~N^$y5CEJQVLIc_~Zw!1J9j#Z@q+%Z;(N-7r3ZS2`9AJDfon&+2nTA1j zDG^i&K!aa2gVkSeNpNbT3vR8NQ7LN^Xn4Ubr{A|H&xJ}^($ew3>$Fh$Yx!C?%LtQB zv@fD!l8q` zJMi6=fXY7J9XmeHtsJ%ZAv%SQ5h?5)>Ce_NPcZuoP9_*Co(PZ*E*ZTdZO--#^!&Jm zA7;WXwB}bOoQ)QfTW9N3_mJ92)c#R{@~N#E(m^~f!JXKO&rhHBK0bg%Uc4iSCd5P0 z%Myz`40T4JF`+mVE$~Vy|I67c`cc>nAB3EKa6zr-afQ{_+qm(3C(={H-bt(^^$f^H z2B|O1!gVQ0J*O5=OB4&pi!%&YX(H}f)8(y2)Xrcu;4!6UU{Oka?^>S9iV1uZ>+Yai z@yYd|bej_W1q=4fIa8XHi*&QtVguyt*T7NQSXLdq(O#&6D%C#6Z-mUn z@E%}?4buN>&IJmjOsoi@3}FJ{24Ml=1VIX64*X9FVGle)3LyqO;s|`@2>kDP@dyV5 z_r>ET5Uvnrz?t?}XOKdGAb5aJRtWCjg8icYjCU{luxh@mYx9LXWpxfz$^5fNausMA z@(fy0{2y88&pO%m*7VGixY%xQJ!A8lT#=}0#h|}mCur;F|8(@lNykLqsyUti@DdMk zFvB^G#j9gnoK9w!2Oq1?kMgCP%-I^gQ9a0|5j!9)YsW&zc!!QtFZP&zL}Dq4dXrTK z^OSz37jDp&^LI~(^>z7{*fn^o1$@GBgN zkc0Fv3U*;pyP=?EO2VFo&d<(o{`CyA+aWQZ&}Ok z-dt*YegrN`uO{lxQl(u78qb))#XGZ^LhjTF5f znjfCmCDi;dAe9?4T5GcQv)IQW9^oruS_f3nN|UuEq+jUV-XpVcUKrpoE)?1OB9Pxf zOA&QO!!9n8jVG|V!C&TDkXI)sZ-^`NwW6^n>Pc5dR;epjBgcIXyQ0V^t+jZcw>;Gj zC?TUN$v?^aYjkHE8@>ShKI{&&azm z`UtqsUWf(mZqnS=8T##h0?FK1Jb-o|VDJiFJP@()E=xO?THWG+aiF9W2@XQ0kdfzQ@22B_wj(t!?o`W;gSC&*VFiA)TdG)v*2uj0JKd|-pdki5{ z9Zny;4J&MOVimJj6|(OCa))EF;o)t~`_!F7bFEH`3)$^)xY_0y@)C{2-`0-I7A#9W z^Ih_`xDu>=z4FV~P+5X}m#baFc5>|^chP1?b%g6(8zm^ySKKPUztUn6qs}ODuZK|G zmw%_`FO9?%ifUPekc`Wr)n@tq{>o=(^*8bFnQ3u!9@bw&Wd2@fFOC4Fv;7 z3&>XXT0nSnQXwZ=yxvG2IdZkSWMc8_@%e(RE!9Qcz2`>H_C|oeV|^zn(vW zwGk_Vb?JFsO8tqsD$4fUWv;e-F}2a3Or7C_c5Z_f-OJ3PygSrrsmusvJEt~-sra{| zSDt4v^m1|dQC4~@B;w`6Q4`mgt8y6`TTQ2T!MY=@Sy7B2oIF~885y_)`pO+}+RZk@ zlqmrM*>A%yjBuQcoQr&u|7s}(r(UqnhG<3&vU@r_7b#u8R5xxql$-t43f7y>4BrW6 z;zzeaURpVKRrE(%d7@0l_FC)4&rsW}7lD1H_sKc;OJKtROiVa{i3xMX#6*J+P>uI{ zkF%n+YZKMKh5UP5``w6ZaV1u1kmN;NBMYfHnb}x?bHWQ_av<~jH8U0obrx7+SY)tjl$+lU`kwZ}g;OaAiwIcCKza(MRXxOb@OB&eiswj0=^ zW7|ixpBtT8a4$b>{*Zm&o0}!FktmFtw>)8gs!=XIN*xu~$kTD|WbqX@I?_%o2Q@`_?J35^^uIC%l_=cHN zNGVVI7vY7p<0T4{-5%;_teRBvV zCvuanQhDl+y6C}A^F#bNzGsHVktWBy7JFmaF|?jPaX=c~*^yW(ftaD^CO|F7BG>%9 z_c=Q8ah9^pm#fO(Dkx~>@7VbJbimInbNJTK`s9F*yZRv?sPd}=BQ!LDH7F<>43kjm4th5B^^d9%|wua3pVWjKA{hWFu zc#rf!fzh$zMJ%TZ|C@y zE{90cE*EB7o_kb$faro(8lih;Y%&s*l6m)m^{714c|JFBq;QKw zvx!vB13?5Dg&+Is{vW(HrZ1cIh-HTPpIVB;Z(8(%G>#oR%`l-??Rk$1%G{A0oK zSW^rqlUaX9F<{?BqB@Rqx;8 zwN|u#J!2E5qfhjk+JCNyrtY7Ea=-ExblbW9ykVM9CJ=xOu+r(#J^cZR(F99 zQ5^wSvOTr@;kzj7_cqY$or)-T(=U=myc4JN0_Vx;YsrfpJ7yLFVXF?Mr(?(yxWhRjXhu{rS&GgcNJ z+Dkv^xw+l1E#UQ>)w{nql4TnOs(sFJSxo}3_`vW5faZb1Z{9uAKCtw^Sue<)3k3r( zqg`qAkg{-ha|K`l!CDpoB!ZIz7-;GH)u61!2K{efKYP{<0(i90c91`OT@dM?EHaTW!ft{W&knO-%C zOOfApGA|$n`fAH=P=~!ADf;A8)-k4PTI_FEtvMrki&y?VXzPtM5)E4K#*E?xkU0MWE7zdf! z>yKxNQSu5RqUFD8A|{Y1jn3Ti&U|Z2E>Y1vS~6sf{b2ErTDp5H7ewdEM&A0qttp*%5q_L=5_EepQ@VCn zsOq%k8pGlS|Qj*IwK7dG z)fjzn-2HrlcQJHr$)cgvOm|DBGB}xUL_BtkW{h%Z$C^yaEMNC|$@SY0KRF|2V$s}8 zPeyZiE?~wOaes?AY~sh8Aw(VXn^5sR$NDrJy&}GFfa3tC3#7_A;oxA4E{iU-WyAfF z=mL%cF@*4R!wSNd)shB!Fn$G~&S5&yL6oOQyiF}!&SFrSPWJAn<%+C87S-(6Rux40 z+llAMLr@t$bp-(2IDpp_0#M7Hitp+0LVW+5ruDB{B2uvP>NnN0mVJ67Ur!TZu~#Jz zlZjyMCbvZ=_agNrruH?OlllbM3u}JlV{|nRtWMQL&ec3{xRw02GR`5=D(Lfib;^(n z=Rgs;%X59WC3A_TgEH1JLCi;S66Lh80-v+QV8d@>-nuKj|1P{d$%a1MSuRKnkD%AP zmI{$W$Ta;_e17}+pg?yHU&v5b4Bx9ySy7u5G7HOjF68+Y&$#B}!-tFfsKA1BhZ1rJ zgHUpOc~oX^^tp{c^Z&5zq3xe(rbWE6xw@tQ^nHv3<+HXFmFI_}^L{(lCav*nh^a<; zRpSNWJYBRUnAj;v8!wY5a;UQP!yS6dpQut%*S$`8{JiAVK?S-`Aav!O6~uMu{}vVX z1Pq5Ou=@1Q4aXHqO{kx0erfe7YFy-3(J&AcO=oA5beUo3gH0W~sg$;RX zH(X5YFX#>dVs_}|r#X8`aqu6!SX?|nPtWz!4smF+_#eanqFIE%f-nDiu&4YVm@t4~ zqQF6OvdsvKhaiDXo(Et%d+VmdDbEvzy+>;tOFuUQ9h_pBU(=!L(QZGqK4M(!r<;GY zKGVk?wo_GvDp>MVR<8S%YOHtG0n$zX>972|L-^HMtMA$jJWV%cF`tp%(9}0~u0+vo z+Z%E}u#Yomqy!%~kdeI8wG4HcugYwBM@N9kZGy zyP3S!8_SYvUq2|@H5aWG_nE}+bedNp5qw~Z5p$1iz9Tht^tg_Q!XYYjsE50yRXYC| zEw=#I2>TgT7HNmft1L##TxWV=_Sy2F5dcV-MJt#UH4NGI0Ye{-v z#Ukilx|`%D>1=uC&E%Bnm5-3OAjf`{r=Fh>h92uuCZp<(3!{)f@may=YL|ZemR`=~ zQK|Uk=C!*5hOljd*3UOa~+qVr}XxVBVzO)@d4}-AJ>;queCe_b?aDd(-%ufCQ515-pTY>B*l9~ z$_O)?**>~IrC+dr|7lC@$bs5>7&z6b&|zHFLJ1uc!2l4~yD+N$=TMP6$DX`hbHx}S zb_4xL07L_P*_lY9s8qvPVZa-xUS66|$&|k&nST$@0Cl!cOHxUH!854Y0~rfPcZa_O zXy857_1qT#4bb7g^HKj4WE_~yhnt_=KSCyaI%8Zu^FZI6s+S{R$m&o^V$8!V<;j;y z7jU$+Y=o&-#28qBe)~zmPnxBotUBszKs+spx=k%B#CK#AK}!E+ZAb3?7qk<;R@C!0 zMxPM9M()19OD z^5!Z|K8L?N5W1)5qoz;7ObYj1224m< z43*|X-8>Jk%lU*W$7N`C&3X-_-jidIW`W%!C(U0cevZ}>dg#;~cQZ+7WTbeI@>|~1 z!HS&5W#iUXl9m!1(;YY53?%`Ywo|TEB;7&z$R`Jj9*(@w;m-j_@gZQ zx`fnIa(vg|A!gX?8JweR2@YYiLCQB5#Ja=WC!=~GO1& zqhohXLWPD7-};FMnjZ$Tv-v>=$1b7(eGf(gNuZ>mDKNKt>>L)))fU0z@djAhyn_p{!GCmC}_qqURLg>U}7&WX?MWu{{`$R4Fsy) zUER)I`CnbvnidvdXf+0~Lx&z`ceHThu(z->v1bEz><+Hby*Jblpo1Xipke~xE4Knd zfdCP}Ut)>@Hvi0qFr8m^ggMwhBDXV&yGFtI&GLRQobD-UAv9-f8wAdo|932UdbG}wv z!?hHXKN=wb_q6e??BHU*e3wwk%nvR9n=dw(9Xq_M1<|$V)zS#LK>8eBI_(|FHQ#j? z88UKd$9vX>GwDJWUUhUycgLpsAlWhF=9Zy3$_Y75jo^|<>?I(#?r0iiiEb0Ieztj} z!lh*Dxe5T*H}N!+#5~DTUup=b(|pQJ{mEg-S(x;2KGUi`bUUu7(o{)#?$#r79z6K{ z`nY5>+QK`(VhO*;2C#v}L;*SlDue)lI47698FAI78Nwv8haML^dxskpRCyb+TrG!hxvtuK3K?Kco_6uoWOuFK$UEsOMs zM9@ZH$+{az$|oGaRzx~65@k5h@<_yf!l80>%LDthP$WNfwtZ4Ymq=>}nT1#}wn6#P zr)q+My2m}uBEwlm~7; zD7(lXC=dVlPW_*>!-si8(_0kWHvzo%!!IxI#+HmIOe00En#Xgd74auhrVX*1v24mT zOI1fbY-7ZbcfOXAYu;9zga>CqAJJ13wRt!mmgiilN}4K$BsJRq#RbQIk(2QUxyffn zWGUDC)HWsXk@neUeHxQ#3`;0V&Z4#bcRA6REz=>z~i|B&OnZ)q4z>>ne|MO=JA@3nBCPge3 za+EET&YsKmG(ncQipb7Ezr}{jr^;H*0^(s5Auc3kfb8)b}_C zOxDu7q8$*)fXyWoB(H^#=w@fF!iwj#9R>|Z2{;H zFO|+{bvC=$*?6B}96PvL*hBG-wJhu$o$Q@#0f=RB7nAN>x2~r^X*F2U-NoI(9k>ku zmn_j$r6sP&3ADqWx+WN6+V<|QK;@0}FLY+$Mv5*r&Tgl7x^g3FM^`r+x6WqQ&Sv0l z+R}>R(ie#dbPQ5O6W}30d*&Imv#U1{j#9R8v9s{8;Z%UgovI@Y@js?;b~#wFv;Lp) zpn->J0`J?|>;OJfQGC!y6(=V*;Osz?9MB=>`SAb$oWFj9zk%1j@;U!WZALpNp5R0Z zcJ2lwFRy~lou6C_ej(^9JoSx2Bk=a&7PV4JUShMH3U0-ZhPpVPP{vq#nF*DY8+T1| zyK@|Z@7}bJ7OJ&eeRbn#q1?XuCF~Se>)S8kLk}^vJN5W)Iybuac)!7itdrf+v)j1- z{oys0?m@qFBl~BK)JbY3ua%r_U)UlBg0fgBSC3@}5sI81C9(Ul5z%>nof%SVD{3M5OmAqke46lNJBbr1piW-zqDdY z#E9EIPZd;-r(1O0u%3`Dmj#bE~l`%e1Z z!A8#JuGwbheZG6d9}xP?(^-feg5YoWKiR)EEV|xFlWQX!!B3vEG0EWdCXDY+w6LPU zP=GYj7~4d&vKQXiKq{;b5wwK56e$MrzzC7i%HMi7hA6}5>#32fO&0ksJShYPco zR}$msZVNlq<@bss*>L=K4H`UfNr3`ew|^H7G^c=o09fZgiUTbTkv#LcgfA`uOWFhU zvtS;un!BmJjT!hq>VgRfKrxGcxnR7&CXV+H7wrF~m;ER0^Y~>Eu1(MFif;*ZB-lEG zuj;74i#hakigT_OQMYG?Ll<|j>zW>a^IN`lw787%)lZt5#N&P~r~#~pdT8>b^m|cU zcn9;?j3w{eOt|gR`^J7*Hnj<~l*17kyIfh~w-%RuB1MP{@?wxf@x%l6 zW!8P%8h%X6;>^{48ojCb`7Ka9>20=hxXrb~yOtl?#dap1ZLfv&ycJ2I_|&Ev*8jdh ziV?|nT>8P2476{0 zO9@kTZGB(dH00Stbyt&&+7@Sb0&J<n-3P>1UrMP7aC zs^(w^GzT-FIq=SdJ^W@f`@elcNN_DD{%PwD&|ZLk9%6yUZ#V(kyi>;rpYQj`j-;BV z5l}8x0clMC>D_^t!(wt(*gB#QZfA(Z|N$~*Nx^R@m_3n(j= z;YC!h7J!in2+f&U6yLO>D=5dW2YD1(HF(`H)vr3-I5<>qcGJ(qVL@G%+`Lr*cmWxYhDqK zACaP$%BAKc()ZjFW8tW!QNG*8W5fOW)-AO0O{s zO#|Vvtm+{q_ydkYwdxVMK}0U?=%3Z*N?40&$nH~tv(Hepjl&^K2flKJHW3Tg#V8{T ze0&I6HelijsI`b-66uqgvE;4qweHKl%TAGK$5Nhkq95uczGiAE={z>thWzoD5Ayp? z?N3g|FDFHNG58H`(2I$vXD9`n2M=jc37oJew0_n6jSq(TwiioAOeI z;$!dNF7I^io6qs8%H|~OlLmBVjvd0#QDOq(R>#w>^=vH(dvh3Oy-^~F`?yBU_bNjY zJ@rFSVqA??rjr~BfzD9tHx@s`43CxDiQRso*KsY>p+3ktfEM+uE1Coz+C9$z1a=b7 zw{BNz|AL5*z|TciXbj#Zt7 z%80leqP?723wJo>jhCqT*VHF6hpmR6W8O!?cO6N3naT{4rLTg~d`O^i^j*qv5?8?y zC6|M3;hbE;>F?~4@NYh>xa~OFpdN|4P#8{P7ot>%f%kZ&@QK*BPI-%r*zP`2x`yQR zru$rXkT)X?*VPz`F^g#qnqC$o<3nj(1kNF#$YZaH(FFw5{d0rN>rC+AH%$bQxg81U0#J|836+&c6Hx(7Ki27=RJ_E*wyNlxH7YHpD|oJAE9%_-ZDUhf74k@4}Ng;N5l}Nt!rdxr>A6xdD zOkQuvwxt(;+q$>x^oaWdXY#=ue-a4OJ zwmZ9u-{3$1zaBN-gb&4sV5E9fi|V_5RED)2D_xY|h1;7D z5^)tmRRWTpDNFR;r_a;p$>4X{|7k}k3jP`r!^xb)8%`4$Eevn{t{)X!`N+O-lF=mz zD=MhU|2W9W!hx7OHKxNZ>Z`FxU*<+23zw;D(o5k5-+2!&>E?$?2u%^Wf_joZozWIh z&-NT?Ug^#iK|*{1gc6?vHYxv1kWgWoZjejv7^+rXUW?F>qV%QT^Y05)&Wn!WL4>~w zRb-v)fp)yVU=e|EpF%HO6sbUm|E|aUQ-Mn5;@5x}S}Z)rGBq|rDWUuK^#>Xa!tP6e zn42wbhTIUnN&8wYhK{+x>1ZQ=xQz;qRsr-Nfd=%M@fJ*hY%fwt7!6BP%LA4`?N>4F zH>t2pEwHCWbfR4+p9DBO4<-+ghy`DNFR2`M7&fKBx`oByiEh`5%i-dc%RV9cnV3(P z+2vr;H1U4Q09DpXjWEm0Em%;i?ofLjnsLi?UAnnuW8Q-rr+IqMd$Dt-IB>Z<*oC9_ zxz%T0#61u5F&4I+%4J!bnSm8^RQ{wE@v^pZUFt^nfNt#MTNc04uYlWwR*qFPi>T3{ z-Air2Wt*C62Ab-h^5*po7gXrhh&rHM%JwV^IngFBx?{ug29EZ74gHASB!c#*cC=mx z2wx)eVh%pHAt8}=w_e>#o~ZlZvgs2ZB9HV`d#O!fV4(Y<$BK_XTbYiH+$&J7=6W?j zH2Jz=&@y}Er{PIUswk8DQb396tx7tcBJp04W=ypKczA3SU8)pUFVoga7knG6qEGNx zUh(vd5}U~AreGW^0hz-x_*V%0K9(Ec(7IR!o%nk&NAdb0Gm&|n^VW|3aT~(Z7TX4o z)Hi5@o|NmPIvqUrpEMCm^As++S5F>GKWUMV>d-!~weV~}Nhv77)7LnIa<=}v93|Fs z6)lIfxsUmz`JQS+U1s;!WJ$8We6|}rLyP;*bBO5C`93JLP!DJn*lP2#G+Y*3+WdN@ zK;8dD zp2d_5=Gp#=@#|NE>e0PwoQ@wA0*Etf94KrkM2W6Sg06o#E2h_w3nej#mMdqkZA$X0fU9bG3y>*Zj^lx=Ns^^`bD1cT?EZJvZZI{)Cf zyBgR1j#(B6wcPNiI6s|1;fg_SPqO>4^iN2tWI|#ET5p7_v4RcTOp(_((xh#UqNt}J z7(@*_+-jX;W^8v|8QtOeLy@+mxj>p4?Z+;3Dl!Le2{)?D+hKE72J&pvu!bg#zjMep zE=qjlzfQQ_=cu|Dth4;Q-~~vyFdTy;sS|BC{ZUuomN z2w{M2T+ag-P!I)x#_lYNVc`NaWLjKmLpiTl;k{b1azRiJ4-nL!6}|k+x|Gv&GA}15 zwE3Egn}-V;uQ(rGhYlhC17GQ%Viol%^^y{YJr2xHaSx!O}`yY$WC`}~>sfnRRhrz5t&_sw||MLh*dg=%2CqW z0Yg9SSgxd-MpobOr{fZ3?XI=-n}|@o{OGu+3rs=Bbax^jzi3W)r13zpTs>|P#7VNO zqMSSRsK$1*SwQQ~fR9gL;i{$Dfnt_ktEJe(>;NF$Fm*SMo=&=LFuY z%prR6h5RMsHKTg+iKTo5>VtQa6EDv;Ex}cg;K%=*61nUk0wo8Rm&z$v*pBVn;-yVx)3VehHg zZyVvyC%LtOav*|g3$@1G z^H$F*RA()Vx08Mzch^du;(kT!k1r=aU&9qj)Pgok^c9lXjS$m?HN@v$*P0E%N-%I9J(1siBbdVS?cPmi-kR1U#>zW%;d-EB%0S&(VW`472L!{czoM|< z+W=(+;Jd&To+&IGWF6|l<&o$pdKsG(&|UwG?edGVIXFNs%P#z;r0RSb8SNGrgtbY>s%IoYCkLnX&)(4D-(J@^z%R1nj$?? zU$^cVb}aOxee*=3?}3^b``oenaaxIyJbTK50JnKOWuZ~xTPxw}_s8PTv`bLqT@Wc_ zrlrC|B!=bND2zAX5V59w*)3|nU(nrAf?|wmjDYjNJBN_xb6Nc%owPt7rNu$gPWd;D z59w(lMG>SJ*SQZBix7|q$T@>H%8Bhde8(pT54gdjJ1w@{Y{3XWs`N*)3g-1G7Rn^t z4Sh#EHw3hv_oES$;ib!SL@NGNGkxQ_l;9(IF7E&P_%4-F2p!@9a-mZy0&r_l8GIKrQj{D1g@&4#o)bP#s4&sh3E?-0{rVOvZEq#v8{exA`w*$}LLgdj z>vKqy0W4ol1#KY#*8S_c3Q~qDHxJzhspJMNw}o%e-%qnA`${W=K~$qrG*xu(-VonA zrzHjyK@}1z!IE40L_^+UF^eVd=xMU)v2WQN$p%yp$HgSIGN}UK`5sn^L&&k8;r8l2 z)=JhXvf<|*e4xi{EtYjdnuvTO$OH)+d@B%SN>w zRROMTM~k!8w_l}bza9No)VSvjN?ZW$A3p?Wh&bzz-~)<01b|Ek&>*M#Uo(k+68}<; zXi2j0&yogp~i!4R0$PT$~ z1%X!lh1=SnNNU~sY7qtW35(`a5a;lo+>XiTw!TGPJVMYgkvsn3PDMaQYi2w*HuX;` z_9bNA4O4;c>6g#x@M&f+dPIZ=Lr^|jicYEv5egO{2IhUZJDPRmQkLiMwb;O^O=;0I zVp4U@cpZn!rTab|<$j_9v6t*@0EACejckhion1zRCUVurBP6f=u=L|=aY{k;7$Lis z&fcW&R11c_4arm~Vv9~knl{Fkp)v~j^rn8K{Is3h*7k%pukYb|>@i>Z5F0L$bJS5Y zh{>N@kbY$%U>?6O*!A9ZbSn$w76~RAR~q7;xv~-a%M-4qIwF4ahEG!$e$j8Ji1|Y1 z8mkJ{byE6FO|lU4Uw4?&o4m#$9Dh}7!842-{kXIY(Q?CW%fTo+y>d6^#}|!i#I$@T z=5DPPx)!4+eG#iNtnD=|?JM%m#Du9Rpjhx68M~nDOUgwUNQ&OJbU__$o4pOvl9D2AXvQL;qoZimL{`pzgR-M{$1E zc@6w^2sbo5iwJIG|M0i_SNVuR!8-$=D*A5U*B-B! zaKk$I`hHhi_O^vA7NYitFKN8O`kDssAVd6XE#gt@bP}kvc4&q*e$yIkN}or@{B>`a zS&Ybo*l3l>)tu_u!?lEt?<~I4mpBNTyGM$qC%|j9C8q61CRS@??#i=Ji`RPBe18(} zgpZ-UMzU$c*OA?3@6^`+wwR#JwnBkwPEKmc>GG!h{8WnjMSY?rA;G&Wz02K$%Yrx| zFNtB|m0L=01wQnKscTw^s}z5a&GYqIFi9SlJmYp(yw0cw_fNIafOLEK#eSuum-ZEw zH44{aKh%K8CQ26XqqJw7*OSD@ZbyFNm%+A?5Y0A1NAAY^eD8y^6U_5v{TY zH8-)h;3S0*Lr+5k;mSHmnV6e!oxm}85TmRU`1IiKn`DbieY%%gHv}%% z`~YRw+`r1M|F4+kKN-W;JEkb#4sY}9k@XW7>;=i+TA>aF6?cOrVTHoJeGZq;Wmw$} zBU8z%opMg=<$`^RD2lA|b^B12<2HnPse(kuZaxV4Xp7K2NI>29)4}z6Hb^J|2i{m*;)ZwCM(K2sR4;$E7a4Qn47=jL#b9Gnvaw`^R?Q6n`vPIt0s(RnMK4ygQB`CBa1CFf@ zXL};C7s2($x(i)iS?*d+g*9IK&7K52LDa$)sh>y$eC?TwTm|d=%M<2XtO58(aI3km zPmryNrl=G7*?i*OXnnI;FybEY5%EP^7zi{H_%!eSyxW7AdysXLL+SC})1^Vx(ymMe zEu`*1|4|g|dGg}`qQ*ytyCa0vlBgKUyCrtD>0uTFK9TeDQZMxPR>^k&A?G>=f|8%U zBIF2yK=6zg5Om7F^H-fN$+)KUrOF?1bMrI2262fC7F~1@#UKAG?FBS)K@q97wAB7E ziqsJBnRt`@`8*(Ta)IOkxUAQK8Xur+hnpW7_qsfU{FhJYpG3D|kCglKcNhdVfjJeu zb*g52?ALXNH1&fsnYi4kg-lBRNx3Zw%}MLyb&hA$~&6-G{bnAI39ODiLdn z?<8m4sZldV>jh==BS*lMu9Vu)6DL+ERjJZc2&#rn%ns&$v~g-0ml(H`TI_xN)j{0I zMfVO0UyZj#;qAO+zC9QY%#Qmmlf(QjQ~0IQT?Wkl4YgxkUmv{&Nj3DdOiRMh9hy9| zvAsou+fc%tpyPgf=QY!~OamH=Mg2PoCxYrm-ya(*2AZQhx(w&r*bk84_m{#*k6Y4w zcxvhQ4!h{JHsD+4XkTiPUd>bfss1K79atO`Gzh^^=Bgn4zq-Ri*TOshen0N4dN7;X{DRSLdJP0$(uT)bZKkTL|acXJy=% zXdka_OVoxZIpbJ8&qlhgK>Uuy=ass|Lm#s@pPL?bvvlyj0AYS^F$?haEkVV+QDHls z5Z$@E8%rvIs6HaSlUrhX&6)r#DV)CK*Frl{c8|z4QcQ=8lb^Wu4tB=tKCGO0cCwGL zX`wHvIKN3L^&q&)dl+N)?za#H*|D#@Qo_>B@WuwCv5)4M(Nk*QPo4-N()Ar~?oCjM zK!9qMbATsVpDS7g-WSj)09FT_(V133fP;Z~c3Ck)J!#!bibY=fg2NXLgen1Wg? z038?Z13Cyz@(*|z&R;s@j}yVa4qwqBK#H872XJnoIs{tt$8~`Q^MCT$|D-Mo5Spkf z(nM}9)4OEUd5>KZ~rhMO|`T#=TMU=GA~{9NVV^^kTKQrD~mwt2-5RccU{Nke69C zieZfI9cX|!I><(yoi`KO@CJ}xW_)}yAOolgk$!`i&V8xem7zOcY8z;1)9 z-Phm~Ko~9K^dWA|W8TI~-z$&~Sr9hd$Fi)fYSv=@nW|xM z^Ls9P6IsJ|wMf_d9rFu>aT#2274gK=D>%4c1FlyjR*FKBeTKP3N-VHbTy@zU5~hJ`VoCWlLH2Re1DhDVTz!lU8EYOaO}d$aN0fBy}}Y2EPM{aj@hWE;%5=Ko|=k)8aX8(FXkd)1d%R&I|d!YO?>N1YWAvz+{T>P9MCHx3$BO zr&^m}sqWe53TBc_QOY2pxkey8v(QJbuC4bZX_@bY#cpL}^#${EsXEKJWv7Y0F~?x))4KXDV#I!Y&-*bw1~DCdU78bhpaW)V&n53cdCJ}4_}+RGS4fRYpmBzUOx(biXZI0bEID2< zf7O2bjw0)|5Mf`5r&UIQQS zgtxiM`^|@B`g+_K*Q#wIk|F;gG;+m-R+ zh)`}QJGC?y?tZ6-^y3UrME-Cip$eC7sj^o;;0>7CQQ{I5SJjgpT1IE9?;^=|>z3^i zvc-OcKP9~FnpK843-iIv>u~?N@ohK|v0w8KvQ8#9IGx0cUx_JJv(D9i$R5pOVYzLJJV8*YK)XNu9@J9!LfrQvBL3~0XQJWoHNgK(fpbaUX)MU3hqcLfh3 z`s0dAC~g;G4x}#6J9wa`8%R$58bbaHrtnX~J1_JR*JY-(@Lj>pa<%*fbkD^8{GzXT zgAepzQNgcZlS)(|4VrtBT{bW`v*+Wer|%-&fC)w&93%^Eoqa8IM`nJ^vKO(&gMl!? zH-|FC|7(L>0m|f9r4NPxl0~3`0aY{6e#MKgjN@*BK3?g!!>t|lX}A;wp0|9(|MlLUx|Pb~}T6UmnFcX2hsgFs$`qxq_0v=#Z+By@z3* zBHz8757eI>2JuPbZC@V0uE94a>eXY);cET<_3$0K#7IShIM*b`$i{x~Xj9xRu{yG4 zdB%L_Nlt|6y=ubmN@yy`rRxeJhIN4jiJg__4nH(-{d=7GPcHqhKsNl0+I5{bN==rV z1@mNNovGC#Z?vxjvj6ggzp(Ewv-ry8KzL|}(^6Tg8dck~PY`yzy-^BiiH{Un!rIuL zjrJaIw^QAE+31kvRDoN!;GFmHwNhkyQtUnF`3h|E7fEF&W}}P9#_tMRv-MEF zjm9r%ZpWJ)ij_>&TF#nUj=gadkNeJ6x9X{on|*7Z<#yW*nsqkD5NT0wt^4$8b3t;Y zd>fl%-o}J8kCw4sJ3f*k;^&Z`{3tET{ESy~NKg%FkA1o8ro6q$HR4f($6ms$ffC2+18gd zSiHx5kv(ZVMsaAuJu9OrDGoDGaX!c567#s~b{7HS{16c5s55a!M}QuN#SSlLllxtg zg)Ta!(LmUz-t#Y*mWxUjptkYXk;?}8Jc-N&FvIenr^p#mB(`2vAsL? zHufz;&-@8*Zkk0NNTr9_JaaS=ZwMc0TWDc~@x?OMeuau$vO|0dCyxGlK3mJEphGoz zlX07jBJ7U*lK`3MVYj%47;uAMkCqY|?JTzfrC?eu>F`;maUc}P55$yr?HUsrd@+jn zzs$%^jT#6XMV4%hGrN6T*3B2nReN3>D}B8~%_8N4S;)q8tEY07X}_5(;V=`ne3{&4 zO?iWTcL_w`hQX7rc>{XQ%|UV+6qC|qlIIAfH`b{5ojvi8?vy}?4d@t(&bQk|kl_5^ z1 zqdTb74UVF#&cv3g7$NXGctY^h3RNd(y@ zU9d)SW4Bs#IPp|)`>xH^;NG*Csx6M>AJhf}nEyN)cko-&j5i>_?tlOrToGUbMcvNi z-v#(G|FVSih0R3+;hfo1Xvsg=(Syy^vMYCV8McFbij{qF`;yJt8!G|n5&+p;3Bka zn!TB~vK%6x9wL)t`5G4$pHayaWKprw%ZB%|f?UZN`Jo6Ji+adtQrCNhT7LI z_PwJOjqmsT=Nv|_L*fl3UB8R3jM^?#M+xc(@H-(1N80EyD|eS@HQGnL$~+Jr`1CVs z2T%CE*MqSSZjMP(CU4?;Wvbn=B9=*_M;+`(y$DnCSNhQSzkH_!sk&+Ak6PV~(EG{LC*t%deIzVzWXk2n%$dhSc}`fF z+wDmt6_CT1-udlbv))+!t^xSri9=_C4~09vYIgsn*c z3~G&NXWoLDHre;*8;=D(N{BH;vcgY}u2%x?M7Y_rWzc04)rjJcG};ti$**rx<_7!*avHmo+Z zUX(Q@kn>naeJqJJ&F1}(_kzYeXkbztn;?pys{8KOx;(y62mRGt2ex~VW;^HO=pp+}Q znX_MTv!jEk&#SU7+H;_evyCNC`vEY1K;_oP(TbA^!f+NT2mf)CU#DF`t39*E05vGoE7wR$dUK;*)Pw$^P6xt)FP@C;#{Je5geCxOqzq^=@wey0hX$=QgJikk#FDrOc-o~Poc!TCky>t+cN~?+t5xE+t?Ijw{LymU!pFRog7|!91rRlE z?`@OGNEW^g4}aTvXUpA`=Q(S1AZ5bWb)c-F_rYrok>}iF)54L%Qiq>mxx_0Wf%a>J)PUa!lG#GdvVV534#g}}18cpu7)ftX956<37HQ+)cq zF}(;IPmGperb!rXT82d;_^QsbxWmp3d6DI#hiI+C#IDpwS5qpXt`~WlI&}8xsC(rV z1FarE9WuAFr&>iUn=y3CE7Rms1QlmXZmGTJcQ4ahmBfHMN&m8Juk5VHWRW#pZt$uS zmU9i`%iFl+)hyr7j(ZH27^HIJjuH!EGuK3YKVmxnFe@*$C)KLer}OF0?~frYZek4} zGDK9q<%mZC`xOrdvxh5?_~dB&@U`Q;WnTFgq;fVf9S@XA@v3cz+R+ln4!x=6TA%yc z>^t`!`tVImV7~QGy?K(@uyF6~^hSqqgO%X)ae3C}NKBv$^z9h!cp}k%&xF#*zh%Y#@~H7f~N``Pv{}3J2BHyH|rmZ)Ks!`H+aBp7LBoFMBp>K z>@IM}8lWnIW}9N&KpKi?YApm#1F(B4kgLr{mpE>pTnZPepl^^C-q0%|vbhTx;IWn* z7Ju>`Vt(e!7(n!Xr_F{INVq~p5%6Kyom{LqTrFMAOxU12XHb%DfRQ_oA%gA_H^jd< zIRw@K`W!Gq2&@*+B&G)ZRYF2PC4~sC*qzNSA=fV` zCg5NRnJ#AXr+M2z=?ok!%xwToae7(s@E_N~L4rFW41{Ou0svZf0LsbCY=Hb5XA~K#%@u zb&D%A*vazrl#84GEhO4`EsKeViH*I9sl5f*#0~tnFLvom{6*6p|F1qgOavA}razu7 z;{u>aYHBL|-6Z~G=m5|ZLi_Y>OAMZ!;c!ELw6#eb6@GHV*bJ!iX&DRjRYf5DOQu2g3t=?s6F@FPiO zbLqip#xniyuD%HSM9URVx7hW~9bGvE@fw?Ja2Nd(g4HvG;-a>dlPrCO;n&|~P-JXb zsO{tpyXSILZmxz%rtRBgMR|8g#>==YnDgRQ?$J^5MwGDt_{b|UW~rBz zQW00Gk4J;yHJU+gcze_+sn_=u98Iq2pfF4K_jT5cKTOzPgq8BQrQ<~uQCgWlMq=kE za}Mu)fbAD$u@f(;g$3}E1_>k^xAF8paAqyQ+o6*4Z6Ob^YsgOArWSg#f5bd+7^0E4 zQK_h%^rgLSlRD-Rj|x3C!o$0)?g|Z`{6XW580KxfZ~HkS@M39D+sQ(NT;&UFZ{AJ* zH0ITvE@`%)Jm<;w(IVZ&27y!-^)oiC4($)BRxIzbTkOxeP+evy0Kpr#-M|6wM-n{U4a@`6Gv}58xwOUJ0RwL0ZMpr6GbNag{~f_srbuyraeQJcSOy;$1}y~+z=d%>|?EdEH{i|T$( zXvgvUs$@CP?nAUNpZSi*sUq>C?FTvqYAZdphiUm=Q$91p$If2ZQz*es=GCnN4ANgD z)e!!w&p8Cn__ERsfm0_8fm4=|m%S~mB&~c6EbRkO&$<0trC<|ijmPQYhAw5WxV@W+ zy@{ifD_GOV$sRBwfc-FWwE@dm*t=P{0VF*(rcmxW3mc$#(!$;rAii^TvI7H`INO>y zg6%9^ecbJ#w*gz*K+gtb0iejUbh7sb81;Z#{rS|%db}CxHRVJ<` z0JxvI4fIyfKr}Ebpot53jt%fc;K`OwRwm}aNscCVVBqqzxq(f5fJ07abF;T_baL?l zW^gf2u!Duw*?GWCp(mcs{`6g-PlFx>?r(2x;^y@GH07c8+tC6rgiem5 zIH0j|;Fvw2AWqSc&7I6#!DcoNz<2U6vGN8!ii@=c^q$aXUd-yor7OS|Yz~02J-db- zEU&Dls-Y#WqIC_d1=w^OS66ovpid2K;&^7{0RpTuV-9=}sBdzy0|ADv?xwbY3jhY5 z26YE6epvv;2mB{{{S0Xup-&A_SI*{wSw^lkW9JyyOnr5LW$uuVM!j(h^zqrI^@U@S&7thdaCRq`4= z{K&^I&`@LFqzw&B;&VP!eJgN;jms+8IbD&|t1T+)M@$OyVGAHG3)HX&Z=)O8Xl#Go zuVym-vLMfS4RfpxM|@r!)qb8dLr2jQZZ|J8gW>M7Hq)Js#9V1F(vJk@BEwh{c^ zx`)|U$FOzQ%mZ~Z@o&L01c20f?U+AX3%Ba$p^<&W@>!V=>Regb{b`SzGyI8>fklf; z0zbt4v%)5erMp>d{tpDvP^?VeP2xp*aA)i$Bl2TmBFo6SpY@T@UFbO!rodI+SVW+) z01;>`fdB7oEZ{obYyRF?01@C4;Dl14{MR%VZ~=Oa`m$j@B|d?}2Eah!(BMJ<7w?t0 zG{uUDGR|)7Q}O;e!?djmd#kI(Uaf8ROpIe!#3>t5>)_Fgk<*3326e7>tN(~0uE z(j3&N8CsJ4c9~+fgo5PWe%o zR)jWbP%?~42WUtHs;f4K;y@xF`?=<8mw#!*tjW;S_J7WO50Tx6O&VIaqaa9TS3})C zfQuGiX)}ZF<@@JjJ}5#cx8{0b#yVrxH5H5U3-F0;B~u@Z4l)gO*+mn4dFojgAlwWW zNXvww30rdywt-~|#U?K9K8_a8i=>;_OM_WBbHjlOQlI^KRoKuMf~&m5cl2isgh^%= zs)%xO8K|J`nIUh4={|9D>q;?dnGKzOFEiE5&?IyIItA$)1Kxy1SvZnQ z=sD?Tvn+JYZyl1%gJkH(*Uh3T5+_Wv?`qJrI`na~rad-%LHzUq2b*!dI0c+DO0KS* z)a&o`1EARl(@r`wwcJ8;%6s+j)HF*?HKzhl)pdt0;_YFWNsp*(@gnLYXi?OpKNnZG z`A6l@ZjcZxz{hwv_TJj{b^mbB;$j8-Lt=%3WVhEn!n)Q%5Z1&;xx3y^iSz8PEc9CwQRLje8|Pb z=+SBu}R#t5_g%{LwFpJWJFdhG>=-t>2ZkGbi`s4erB}Cv}Z5&ei>q@_c zTENVfI6Fya>-ROigSMeT$=lL9g#pQeDFliKV-ecu{UkM47lI~JZsDB@5R&ZP6RR+ICJ8C`7>1>E{xST# z<4him{!ad(8azISlXB|jJ!dV`N>>IR1N_@_15Pm7T<=?1(lS>k8Y`2Rq2wuYbw=8i zV#}@URHq;lYjjERXH2zw@#%z2U@%XJqao1ix#uh*vdoL2tmDtHds*~?n!*xor*GcD zg`qb8UOn-$k-jBeh9@v>x0PRxmEc=z30b(c%%{ADH?G&c5yd+|I10Cwt&ivrO?*jn#yPr+a|J`0Mh`tZ-KVwbjwC|3D8-|GANkTBYUC99l;q~C- z=PqcifsxVGLbmGVRFTlvZ)mY1`@P@RVG0-cRs*_P6%lKK6<9EAP`Da$aD z?MF%zDW2;(v! zjBhW55ksSo-QlG!?y@v4-a;I!<%g>#1{kkud_^_^?8{|777{i-U>7(rB($7MDHphA065fk5qmq&&i=t)`=5A*KgsK2)BOaH zUFUerE#xMtw;yO9&dz@Ojx{X6?otiI(&QAilwC_{C}g1b7V#_)g(&@wG9k@_nGqvB zf@v&tCZs%ZJ-l}u3FPZ813ZjyG>Bf#2j7+14qqk?Tjf!`6|L-F93kTxjNm(rGWm$3 zWwnJm>}RuD551&hy_9NVB?H^Se8yh8mZD{KXhBe(X!KCx#<24<;U;U}O&P!FSEVIR zw^Xe}RXJ*&HN1vH>Ubu(C#q-vK+;=~pC-!n<SS06!@EM}N)gt=+kci=l?$J>JV+KKogrjTU%OF27QzvEf(3ROcccV%@%2K(e?Zu(qpZ z=27FNqa97n^}#EJnWs&|Fenu+D7(Sk%U=0IV>sinWIz71wB$Qzn*)f?fhClUjBC}z?X-x`y z0BhN1jn&7jZ`4;#H+=u)bMtr_0|Dln27Q|78+4l$m=C{BdpoohhVQ6)R2%A-m(xvh zGCFWb4%5ufZt5t}+Ti*$OTgd!*CMx%EMLMgM5>3Yi5}%>#i%_Gv35yVOx+? z^S-~K*_u~4B4tax9b+9*cHu@2GhsMUZIB>yR&GrMz1|+cn;0kUwUXJrf`qd^7qx)G? z=-<5bpM*3HPmVLI_cQ9lE{X5B+{ZG_&3^t&oc!|+MHa=a(8LN+4s6mRqL%sCFzuWu z>A~X1x+G^0s#o#w-^3dnJy=+8Rn+q#q8WDc+*%G^&{%p(-?7U_w^HC8%w<)5qVL}P zm?>>IPLYbv7vJQI8b3{zyH1K&)miyx#myPsWW^vjzZF@L?$?l2YTD)`g2&(11dtvD z)H{BLj9jEr^XV=>j3b43==@%7z=*18{U{46d9b#@iO&i_82$OYSXcO-aB5LuBk>0( zr)^D*0A(*-8&@f`An4RrF-7(}?riq7K`&jtPUEjWPh5ACuz@iochU&U`r48cM zbAFOy>eYpif^&%e21&yN%N!aE5)6V|PKjplu)e@m3@Y3&pZ~dALi=slH(ci%8uBC) z87p}-pv^>!xlyJej*0`Gg14o(4W%qToPA~Q(4XJFb?m=w6BTd3<$f?#O+>K1TZMUI zdXYwppQYgM%N(dQL&^DCQI}DUi<9@w2i|ST=VXyoz4rO26drxF$ca z>VR7Uh}^;OUCIyCFYn(!)k4L-UXd01->k@reXSzvMPUn|s0C0qjEfzN1_!7suQvZf zPZ9WsimbDZTX<&WgUxb+WmEpn{hISD^NExFAg_UKk~ignVfd-|wN@ z&wlU+%-(Pr=s|L_G}nn4x<=$*B8nut4Q^ zh-K$t#1N0QX?+T%=ZlKFAMr|+D~Qi>c{Sa1u&N$5M1OWPmeEnCV<-rV=V~Cmx!2I> zU8{0O2T$7&);9Cya%Ys#xAhr;sIv#N;*Mn`^59ZbykqNS_5yfO0}!Ai)9CDuI0OP%+m%iZz5=lXNQLEJz%v7w6j?u?o|DsNnA z`ErIML+_ki6AB$rx5(GF+OYwjC!f4=6=*Tvyj0n;5YG zZb|?IXJ-ovnEmS%AhtS48t}Hu6@t9$UQbp#aa9rodD&jqy^B^?NL6>$A_N_T8iXZ; z6@&`}IfMy>8H6*0E6_3rzD*#EfZxr4;}^X~z!4Lm-weVOI0Ei51^V0|?15MCdE^k1 z5VpW?CP1GvgadFKd<}94Rp8YEXo0Whc78rNgy{Jwa$uA>Fv1mh0`PrQfS-=Q7-Qf% z7w2B|%LC)U_cel`Kc^ue!GvK1G2{az$3JKdpizjnk~7z9o^IwOZ&W`A{%@t$Zx#k` zWfg2@#9f?(^>3c^HywN)<-Z973xf8Cyp~oD7~1C=cVP4Y?c`aMJ?xE`BHde6+JmGT zPxSFi0x=Pe)9Q2z7rKY?hQHn9I9OOLf1oBkY$e;{-;TNQk-lpmF4Ca!BLHxG^>*M> z0`+t@FDV-I?rfY+u49^Rmy2RgzMHH!b#8WGLbSrB(Q6d8!Y&>j|GRt)K_r=`o(-sl zoN|`iv1hR3jf(0<w?d^!hz*Ub4I?VgrVRA`GJtAwI1$;-QLOTYyUSHkE-hL96AdxIFz${TE z<|9+NW2}b$IF55b!J)CMg%R-!=ON^an=_y$8T3yRV2kAvp8 zt9%s7_q(b5wo|a?`F{U)8ug?%Fo61<`&b6jN8ET=3LSe*5FkeVsCUN=zSO*wmv;-$*^nfg0<5k?;!qMHyNx6 zW%6AHcU!3d`9LmpNB9xZQ)wHMw+PZ3D#G_ND-_BPN0bKAQyDNsc~v@QCNj{r6Cum1 zn0qb7Zi?AHtL77WvobNfUWeNwBxk^t-yqF|umq6|MJCoRb)M9s%rJrbL5HSr4>6gLBh1IeZBjAgE*%Kg&&gBk{K;$0TUfW{{N$1&uxvKKxC zFnX7jgPn&1%;L=kq|E_*7;K!poV?ng|E=fxlSr5Phh@Zke&rK3wt6!Vvsz$A-1yVs zE6K^#`5c2mhN|^M%em*>qvC5FZd!iF^CX9?j#Nb9k7ygbPxyvck}g!S{ha8!2TmrKJ2bb7oL~w%N&XUqJDf5BwF6LkAzMcSw3F>y@ujxF#q>Y6Zq7 zEv(6XS&@B)v#@8}H{#q()-aTv^QP!KWcLK>+~l!zR&}@9oUGgzisDmz#ZNNt30`db zE`H4F)2X#TTX>_r;tJ4F`&0AuEm}RQ5G^4L-n$U#Ku8Y2UIG1m+w!Zu^V3`C}8WtwGglb3it>Ln9B*6&IyFW1F3=Q_+HFupmjcP zfmb&0@1npDSy@J<-wgy$e@3Odg6D=95QcVPln@uZatm%bCARjz8>2}qDB|I7w`zZ(xM~ow#kfs;m5}8 zy#s{;R_{!DrrW2cLYuX!r|TJ8fm5z-^6;Maq~ioZF0*?=?`mdO7C35fH8()=?hlh2 zzygYjlZzVx7+rHKaG6n6AjMr)id>Y3jhlm=jfeZM(xBLcS2VVXrIDSnnX?O!BLK!R zU&*HZLGb!>z)vEKb5os_3vh^l$#j6apMW8M+5F#rygxZi@*MNtWs8;T;B}4r4&VeG zEA`~oVOK_@k2k&%xGdpe?_i|_01 zD3@XtRfnp)IcgA%**~2*?3eNZ_S^h&Kd>){ z<;t=1zxv#_^P7E-0Ka4WHyAbA`1!4^Q%gT1y(LjICAKg4uu0a$vt*7_Lf&jp95pDm zxe-1EyRm2Q$DiVjFu@E8Yx;i-&8}xOY1KP)j+h6ni|D@ zDfMNsSa~mYFyY3qflw!eET6q*)!-m4Ds?y8Avxw7Up97`B(>W!)1Dom?2VZEyES9s zy05Ko3RVrnLf`3x-|ok8b``XDev3~RC70u|gm_C*Lb|NZ!VfY6Ry(mJxBcvJ1_0chxRssSDl zH$XRV(FFZJ_UHTw7S}eXKD@}6;V$_cd+MycmLQT_6hB!-dIK+uK0Jog7LJWs+W4z1 zOslU1SEW;bvo@m3$V7<5S-b}I9N^?~9Mp9ZCz+Vs)*U(`YUZoyd-}Lvq7b#5;)Za8 zmrjD)cs>@-1A>S;|Dlg;4(gflqv06H)vl%qu7+Rt2k?~)tEk>}@xL{aPm6tt@=l~G zbsDuu@o@uExna&zNfnbu^JdEr-&zQZ0$z}c-g6snKZUsaEKF^cHjb0zHv7|*;}qu9 z;8w<-$E|~@m^fP|hrOxcns{kjlF%vl1wu)~qgr<2gJaD&#vyL|*0JJg(|aM|-vmA8 zuJI~{^rad7h8Cms<%Ed6hMpgfU$mBD=6#!BL3TEoxN^^nCR?wR)K71s$c{4alt(%? z(`Gxh*_8RlnXiuN@u5B&c^N&@ot4#Y_wHTmoyCR2S3F$hqlIqE6~W?qi3upy@U#3R zsg$E-?VMAObEwapYurg@?baC08C8PcNhZ7{URq)&nTA(Ydt4I8pU%xPJ(FX)wmj2Z zery^-B2d@^HyeCrvuZ;q@H($r>?jgZ$N)j5%edn`tW#@;>EdB-(5ettMiJ?IE(I2+ z{b;)VpknMHqxSe0GHo2OqEYgwBfl#?>agS1?>d~$cboXi}^4vTB%sGIZ(3NCS~ zYptR6lK0<|PozixvB9(kHkjtWT~2rwDNNV3 z*e`o3XfQg}Kito8Hi2#eHc9F%PNVn>%N!x9&37L(V%eLXwBu4G4)j_o;f`4AGlF{= zs%j4NhIvJZ4VxQUKAoIjrt#OlSS(dEN`63`?Ug`(iHGJ9FX_c@VDOO9GO}GdHZ?=A zZL@E0BrqYEbFhVrN8OoKN1CYwFW=`{IDt;7ES#uMyVKf>v{E3 zS1AhTn+3%PUDF*aENzwbWCzZU(DarWrN;vJv><9+Y)r`aStSv8(RLm0i#Tcvzq1i5 zb`_*!fwFURPDYHDG3o52(nv_u=WLJuhIGJ~WlX&P)Mw@iD`{lO~|S z?L_V>a~5CNgOxh@)FjTf2|oJvtSV)861igSCq2;HTe~Yo_7TrDf;aMo-+d}63DYrI zP5fw6^uFHto(<6!@1kB`MoHL+k|M@w%q;KkK;j=u`N1lf=J2#5^m%Al4 zgzu&8csmIRd`T^QjgKX~{DO{MY)ul$$8IOoljU_FfiL0%pDH!?@bcOAul@7(Q>>$j zeJNZb850&C~2=C zrX$OnrZN)_ST9c-9tRCzqbl9#32rKsVLAj+d5lZRd)n9|#2QRdj!PF0R*A`l6AOQ&)NI-(ROhEcuXar<;0X&X!^qea|KR7BRKMox=LQf9TtJc#8#}n_46tGN+58VY!Jqtu zO@5mi88<(iW;Tj>7KcZC_y4d5PcOb6gT%oVP5iyEhWFlCirWFpVu=k*ute{ZkCrhf zca@FN^PSM%!t*eRg(yE2c<2y0l7}`hEBioj)RdWLiPW}6BjVAv4B8tnE8H-Nnz%){ ztnyr#6iv@!q&i}m=}{pwtLgXyGqY z$61oUPIx%YyaXj#(q^D`Xtypqpl2&zv7P=>UAL1{UCbI}@UnFOqo8ng4`wXu?Xhgx z3pFkV&;a~Y*PL>D3Kha*fjniUPG)#+QCW8rm;YwG|0~}AqOi5iLlFzTSMBCqBJwH6 zVc2on9osp*29b4zbzeqnOzR@5>xud&kIKx$Mc=L-FHVt$KiQ&HCV~Rpl=3`<33E&l zaT#oD*C0r@Dxgg(%`y(&zthgxLv>@EuCA0CyGCk06zYs7sv|ssME#V&V(0Fn|6`lX zQjhsNPN?Kl80k~Z?w;@-X>?E1^(QNpBp5kk3LbWy1bx=*^c+p~DT+P~6@tf2nD<^G z*<^RWFUBkv@-6;>WiWI=K}LGZ0{3gRQgwcOCeeJ9L$Rr}oDa?pFZAYdl~j>TzbWpv zDylW#vkhNw&BVU>($Ol<54~I9DMHV)RFTIFE8#&~93oCc;~NwMOM``er)KGPzc2>fm}gL4*X2$c}+`l9hg~Ci(UiMrle*yjeh4nhOUO51-J_sle1yqRwOX}6;|M>m?WNyw= zqkoE?3TJn-c=MFZmrv0yYnTP+tBGqLB!xBidayFQJdF;bxGlva>+TWgJwvP5{?C+) zWGe^Ol&p1(H+DXpLRgERg_(8M5VjZIwxe{Uh+y4GaeaV@MMM0kcLFOfSzvO_q7@;> zbYWDiPI5bCcYklJM(zfbrf;gIykXOuG1PQycGW?nZ(bu~_o~y`4OH?~M%OM!$_ z1jfh4tUvMdEZlmZg4RH^0x#>w&G60R-hkScj#SoTf3$e<_E8-JoW|@Y(Kn?>q&(a3<(6o?Btq$6%U?jcNAj(@*_iI+>4+S2x4i%qLsF=QfV)5Ax9xe$d;BF`F zB4jLHyS39;i~LcNrtf`B_DZn>V_W>u0Ypn7KihrMSmUP!CR2!oWRzl}qz-8jLSx^A zMZ7$p6+k8oWeFnOD8PVZs%CR9N=B{rNe zVy;^e=}8S)oBa`$htv;rwQE_T$m~3C7OGgj3g-N19&Lg~tuR7Rwd~1VNSUR^dZDMR zL6%qa6e-FM+g)B}4`DI6ykAoOdEsCz7~mmb048`46JRcZ5aD2Np+Q3t z0wM(u2W!Cq4MgH_B%i(PLQ?nnq;n4?`5V4!`xD}EjNchsh}A)=T987?vJGDX8o#-d zQ`OKKy1utg`qm6xpiC4| zj?0trL;DZxFb0+-v|(El?Qxk~%?s9?6()0~_!EuGYjW$#5$HyVq#v0GK7x`s6ZFt( z;VTIIW2NKn$TKUXc7cN zfnX866Da#m=cMutdQk9tA@Yy|Il)_*Ck#l43hM!fn3<3eke5_TIIpg$b7)0CmCFIP z7Tcvdm#BE=Kl+%q@d1c8l=)D^=9k$768-^@`9odh%eo)X*k}@}YL^;Zlw9)yq6Px{ zUeCGG&OsEc=dM@|zySdig#G`0gFhKga}{eT$_POk&-;zd_TvIKyM`HUK)pJf6R&)` zMB4FjB0sFMyUQ{x2vf)=mMNlD2+8!BeL5bdKsOs=m|%;IS~~D}hUHz8-1gvcapRT? zvlj{+TTtHp2prHG%$#`!o(4}O))VDsf3vx|J0?NhAH$8-<&6S1RcspaKFSl)Wy?H% zgffX3BZS9HIzv9E)5#D~%G~Vu^ffXeb)2j7Yj5jPj#1Eqvn5MxZ#CrZ(eh30%mh+F z)9R?sxz-+0$4y-45t>b&yS(D>j!*D)MZTnLjHG8olQd3JH*}8Awcmi^E1k6eBE-C> zi;yWW8f3MIkwL&vORur8B$$!?8A|V`;q*64=+|A}Ps^&KurlA9(dqltynLM7S;q~- zkOzNPG(hI+V?xFZJP6%l(ob~e+NwcEH(5jSilDSX((^OQ@J&#NaS$7( zCWaZfP2oLQ%R|2Lk>3Q_qRpPK`BZASufMLP<88fRM%=yc@z5G6+5>q!9vLPEeu};p z=~Gr9Cnp9VXqT)CSd!NS4VDD3n+Sj~3FL*K!3fDTcl;_`tXFI$33*na%rtnzf`kpN zCLzv>bMC7EYJwmGEpjDsN!1_V>T_8F@vs9zb+J(aL<`7r0yhDf`U$T77ccoI0V*@z zHzKbZXzL6aTku@&-`e3#$WLK5eH^S4mU;Um|7(W#9+S=5^byivY5NIyXpSNOO_!prd{nsEXv_1nUHyPQubPe*ZwQTUL4 z1tE>X$YKtqbnt{}9l^unO@hU$6dFaj+kLS&Bh~PUWsJN>!YwEDYS!Nng4+Fq+?7j| z2H(%{eBQ?0okvlIYh6F`lFg;NMZAA}gYB`ab!_n~V|pjnCH{OvJbl;YN$jmPGBTpU zDodA63=TIb42*?12zQab$U1REinCJ1#7@n%g1{+{4!*QX=VV!!&vm!HduzqaTsn}T zxB<1v{%3?jz~+VTBw!Kn9G$}{83L38=)oL00fWD#$T@cdU!Yh0^?pdjOdt4nP(l^Cd#!@{PMV z1ZFn^Kf+}ld0?+_Rb;>sUto8CMQE-Dc@1kqHq}k=A6N1~57zF8i_#kxI*%Xu zz%H{o(yHMrM))W$4faOe3m+gFj*DETIz&ce7x&Hlh(r+E11aRH=h_oV484Tk4S8F* zF9lXF)#*v9L#?-7PlMf==?|?!yVfJQin~ zJVrKNXE88V1@z`+vMBn>HN6P~P@|Kbmx_tUx4vh^j=jP_jq$+>D z#bgEaD~J`Kj{%*d>bXEXKpEnTCg^|o_J7jH0Zv>(?C_%tplIy-9&A#50|ZrutWqhV zyQxz7FU=$ehDCf9v?+@)?y>iWR}Kfr?Hl8H8z>+#zZ;08`lJM<_+kUCw;A7L)t@+e zo;X_Y!cKRnyk5}Z^R zyus16E{rSV9Z&2pjxJaaD>PW0{ARot{iV3YR9)f+%0T9pJxjWvhIW1{Z}LgSOuPBU zH?dx}&k!lcB9W(vN3>~lP}|m*4Bus+a?S}~>SM?J?SY@}5Q_k`+!{FM z0vx>nq=P~1qQLn~0OTADf(Kve=M`LmW8f=01HE?VBW!?{3xo{-QwNVW0LCcZs)}J)FwLk_^WMpAvmJO90hJN7~Zqu;u?IN8EI7`(w$`Hv7f9@-e*;RnOKa*dCP>g`{!> z@KW#>@u{#0?%QyO!fD?~o&Jnze#${!2fZtb;maHB`Ow*<_94`gO~X?Hg%_O?Q(S!v znK6J8yiCtSb-AttbpR!(0VqM?3*!+m9j=G&0juDuqEr2$=-{yl#97D{-0T64B4E*H z|hR1 z{{Sc1Uf^?pT8ZpHLLbk0#j7iN7th2<DtFp_U9>vP(m3kE{Oq?74% z2DbfeKg6X(Knjq24Z{G@$oP&OuVuwMor$Iwi_~yu(vvHZsVwC9V%w?JAVqFvRN3%;Y+o&Ok`9F+}Qg4$GQwJ6j-D`9`eHVWCDD3(D!zm zcseN~*;zm1!oc``b6=DnYg-Q5)anx4ei)W_P5ui4RaQXpsiK6sD9 zsSV_QRN&c=SFY)!+3lTll(WwL=vgvf$i9CfN47s<2xy(l6dPn99tV8=0Qy6>02-$e z*yQA0Xq_KC`k^$-sK30CpxZw{c*xjze<#xhkR~c@Kgw7kVI%z<@#7%$)r05S0?7aW zM`Hc|-n;!twx0~#L~CJopi7e!>nIhXP|H9b_6v6Wj#b^)8fMVx7dl)8(j7f{`o(*C z>Co^YVgknAJJs1E@B1#{Wh&v`a!-0?pXe7AMrmUN%eA7j%fR>Ovt@5gs=p$7W0)-}BP;T)Sy_fQa0gKdl6$Uo2VMe$Vl zT+h@;(K}+R<2#>2ADsJbI7znerg1!Z(+u*+ME|#STBKVp@ts*jW!-(NA98kC;vyA} zo^cWF6L^Juu-h@h4%f~8kcf0AB|`gcMd`>v31W$1^YnzloO7`uwmt-8kKA|R{B?L} z3aFUCUg(z@v6r%)2?|L2b1?0v%P8X`yoLoaX`40Ntk&~%rnzZ?P-YMpSl-EC0H5}6 z_+~9^9gK}^&taWFUKR@&r^e*Wb`H?Hx+DATg|DxN=YpLUpc+POnGzbm`9ZE;0=YDx zj8j)e+sBTQU`AS{val9m<=li+tDS zPe3f$#uT-B$dvD@F8dm`M(M_^y~I7nlt*>mA` z?ZvPkEIz*m`>xP}09r))f_e?`ZC&98VZUDI_W$mq|4Gq|pzw7td{g|m*FunD5EHIi zNhaJkkWG$lN6*)d?kjL$Rf8sjU2$GnJc6<0n~M?A zCXrJd5Rd0yQ6GhH>{I#V?OV>b(!}~ra{r~_0Jav?E&qNF>A8m4I5Rt_0mk?zPgZ6_ z@MV3>6(95271w;?U~WW(u4kW<-l(*Rrk==n8!#v-#rDuKY!(VlRy?HE*5!rix{+vE z&wI7GFqSULDw_UmEj7#R;}!;%j=RKeB8GS&PG%x4-v%#}cn zfo}1H=hfTEW$s|c2VGsAeiXlz=Xw(CVKu`~kZnPQ;DBb-a}qplFwPb5W}HZrDcf+S zi_mgn&^~lNoN54jR(#+iM>R|q8U0A>p?>#Bd-JCR2R7H8_&}ECKryeU40Ytb3Qb;j zv0mO-Z$7Y2X0~S)a^A(>kVacr4VsBP z*%pQL=%+0<4q@NnM%Z>5@PM1`CLjqH8Ss@NIV0_we|ttX)%iX8u3|CNiZrH_(C$gI zH$BaZVk2X2x>_cNeT-1k9>>C=r*-s>p6ddWCe+y{fLXKYc;psQXJ=?pMcUo4HeTca z6={L0K%?O_Nq*ceryN~L*9d5XOYlCN;B{>PEb-8_fHrt^p$#x3(xL_0plO>k-IE*E zr^;%szMJ5PzS|Yupr-PpbR7~lnWU|m4Nw!s-pYnt%*qy^^ObgUH?y||_(sV^nN^ut z1wecka?ftYblycS53rqHIqT9RV`D@vW94NB5QM54S=btRTA5h6Se+XM+<@2vga+(v z9AFGT>(%D})?@uis9#}`KYFGQVHT|@^}=6wjS((oxuUia+B~CJrr!kle3^sJ-Gan*|QPW}eM`#;EDvxX+srablzU zcu7WAvq`K4T05YTm=gtJc#rD769|EZXPO#Qn(1pJ6-Gg86V!pYe%I+UZsjy@^u)Kz z;*78EqwWxkn;Z5Su}X(MRw{2+x4qrebO_sPy1T}a%UI(w|59kRyN81sLHFy{ldh!f zr{Ut%WAnU*r)9ia7uEwX8lErl zeg+MyIwpc{Y%AY8TnYQ6=A^8MRR&6wURrLP`4`_=6*TsEAc*9~`^8=lFU-Lbwmr#q zLT_%eN~^B`BcivT_f7VO;;hOU%IDpL;vHMn(u^VL95UB~jPx%oH?qA)G^P;}F1mXG7W1qh4H*xN| zp%3qAAen#DB+NQVp*Nhxd=f`YK>P{vAteU~bNsiu4%$KQ<<=vA32oe^jSugUc$yaD z7e+R8+so#NtbHCWxee8(giZB_-4f>uMyMzim^u(JXAOOprRuqLNHr_Az!dleed&7& zAk>#&b?CioLJiXncnq2W!7lhmk3q;4F$R`+au6w4IFV5BGyq;*7jh{hXA1}N^WQIs z^nRr7BBNkm9U*39Z$qvq`WG`d3e%Ny$d%7)C;bkxgt_xBAhG{;TKomqbVJZ-nyNS`)yl1HMaVZ%A8$1Z!Ax0Cllr9%U0yC z&yQ`BjYu`dU;@~JR6Li1Oa|)uOd>HqHtTQfM{gxN(>*W4GG3EoUk+j`hjmMC4o;q8 z(9MWpMyU_DCA!R`o-LbU>;64L?*P&>z^6S(1oqVF1Vy-C(GU^MOd5j)vJF-^_OM!X zTU+eD*7i^eirEh@>_6n~f-OG4@CSQ;m~(*8O(@-!zzyK7XZ8TkI&<)(JI{OYaB&1^ zNX~8l>w2T}$`+p{nE+#AH8&;xY?@%A21aPe1<4u|PzAmf0M9M~1r++@{BBHcKxBSE z`2Uru75F!I-nnjTxKSw)-%r(jOTlB|Fx{IL^^Nn3G>Bdwa{}egk<_iyR%q=dg(cE% zC8w0okp+^IxE=vF4-GHh!`a>UBL~ULuJ$AX_S&*m^BV@-(gP=9CA~EJpZn9E_ZSl&k(oxE1L0Y$yX%owvX2>2-4I1FNKXorXt5D3Q{6xui0oD;daP=Koy zIQ}3I1xgNGFVD-$%gar!U}fU$;NoEJ3IGtD9hq54LBwE1h>U&XdXIzid9w8n#zSaq z{Ga_Qz*d#~8YYn!uuTB^LT+HbgM;z_mmvU8ylnn2Jkg)DS20v`yW=wdjv^6VcFH|{ z(0X2RG_}FuY4YvIb*EW*?POF#3yh+q*_( zfj+s0Odhw_(w>|0rz;b)BHYBuE?$Yhg}*GAYJy{^32T;3!mSc^P`I50)k!qmdRMag zfqyICrdpC>`AMOdovUI6e*Z&6ItmDlI72J$7xGx}0_tZvNBQPR2v3Fr)HSwi`So!F zJYXjGTgv^DPoKT<8!aSs))nY&`i$_H5>yQr(o;?DfgN&LEg+x>6aX$L2v#7FFahbH zfE0fWop+AgR?d&8?%cH`-EWQ!()5+mML~VYa}w(Qr*^9Hm zp9JC^E?L;3-q~;dqSDp8(g8XqXGIJrNv0=M7$Jcw_~QQo`nk?-p=sfp}*v+&;t=@j(=;h|`+LdWv)YJu%E;kt9sF zHam~K0x_y_9a3J@@Q9kQ)EnZvPaLPP_`(w1vI~cD0MIh)CCZH%0O0^%KRlT**nq|W z^KBjc&fx*x(^y_NhW z>}vBr_#}VII<8~uK3#Kq0u%BS1=Doyt-^LUG=7+HZt0Q0lkCs0awp%9+uu@+JGz-K z6#V(os=?+Gt;8PP6JhV!4-B8XD^yt?^}<3XlE#`7^A;+6*RFK|xTH5c{8qF&<8(+8p|$$348qh+k*lQgDLU&K&}aMfy(-Zz>`cqA&hSR zZ8$S?uM7fw!84~j0w89C7C{e}Dm^&cS5)fhw?b$Vhzp^r7llzP5Ih6xxdhiUhdHa8 zta|tQvsO<`qw)ON?e*pK(t1e4o@WuZjo4#zQt8iS7zl2U9=N|;7kY6Il~~Ne24?(l zbkZSmM^o}n-&>rwme+%I@rWIUk4<57^;i@dHq z4!oENOp)DVMh1l&euc(*%+$jW$mE11mf!H|cbg-(=(J`Oa3k@8x~t5(n7j%~np8vW zW;F7956MN5EkExbxwfe5d3o-ABMDhxN^aS6iWBdTCQFAv3Zq}UOQ{J#wZ4EQPOl@4 zFcT$eZ3b7gL{TF8JeeZ7!FQ0O6npe()AUC{-Z#xcZjQP5TF^a|&to%3^cltqYTqN- z9oC6pN~M!|q8YcMr)+*;A;U`o?2C&OhxSwK>)HY!LxlmzP@yl$P%$_ZM>NPswl-yV zS>AF_-LkuCV1SiJK=Jht_GdkCS4$%gSF=lIa)4d#LR*mi6=FTt4S%^lC9K>5M~8zw zD^Q5`Vk8Tl2|YMTmkWSl{k#(32$cfLiWs@MS^{BPFEAntT*SoQ*7Hiu;)@f=l>ulA zP>|^d0{1es!U}A*&cDETL4cQ)mFow!^8ZVJ%b$#zvYgLH{#x%dyYdIJaPP?@8f;s(bMMrU6`AzeG|}G?cN! zhV~3*G+nxGa2$pgYO||3i#1Qq#}PG&4HEcl_(q3MYbT1x^m{_VIgnp6OAm?fKgeIr z9d|NAeSF9JQ_~QoA!>t8)?DN99UbI~)T%Y+HJDZ7u-RMPV~Xv!O-W}4!ZaJ@lzJ`U zNrOeLCrhzb>6=C5%J&%e4pWvG z5wfSZI^vb3Aw?|k_ZDH=Sfvf=IW;=DzwDDjGLrSv_3}4Y%k@3g)v&3zj^sea+di)o z)&xT9+OJX@8ZyeiO!#wa!xOVjzB<14`16{@dsKVLmb|ghhjqcx%zZD?;k{0x- z5JQhUR+snIBFty+X!R&du(fds^}UsPU4Os;`U6~sW%Zw|4U_Bo;wOhXxI&S%1Gxl{ z_3ue8?d;&@c&R&pG>{98K=)VozhP(q=EgZP_|nigZ-V|K5Ai1(V>WAST?1b>S7&3) zKqhp(W#(*g+k$x4%(7a;DM#Pq#a4#wnxnswwj;|1xn_HjvChZ1hhgD{%0ai;xZygD*xF2yH!!e*%n zQw;Wcd8gqYkZ1jtqHoM^^zn^+#LB~F8jqp~l>${+S@@P)q_e^c7 zgty4MfjX0;*(u?TBxFoy&?pM8syTpppU3s};aQDUTx_uGdJ0j+xsA~V3TVD!V+?gX z8;XB_8`G)Us82BWbf(Dq{Q@W;`qIV-0R;s5W?+FLC?!~>mi#G5$teCj8Ld`yx=m(RNI)uA@F zzr?Buo!9@?cq&QKrKVM~=Vr}FAk>dq>BS(nJGtl6*Y%G ztE!PvU#E;0z2errspcFoK3r2;>HiQC(Ex-*RDgB>-Ya}SgeaJl2rR5BpZo)7LBZuW zfa3p}kjSqY%#znqI^cn6*P~Uft~`ssN{Mjrb6;Z4wUo%^=Ks78^iSQL6%f6yyi7s* zw*?%1k^>6v5s@8ok2Fv9qDr}o&{oH*zqAmf*L8VPV%i5jD5mGLn# zOOX%YhMVKj7BljQBhV%vAvGbJsluu6X5aJL>O~(QMeWZ336pe6W9XKS4zG``Y<5Ay zdylHELf?y#d!l4}r*Y#|wlbmH0f$1ClPMwcY2V{J)2+1cLuOzyj=%zi(_Fp`5$h~(0W5I5OGPrcvV`w!`q;v;!J?-;*pPsGKEA0%NQIZOG4NA= zwl_tQFkkSg+$6g&(^B-oKwWd-ylN*_bPd%b4EFG;a+e)GP698?A6ailfK_b!4`L$U zs7ukS>yCY2pO{7wcTOllW#bcqf|ssweF_vj9)$CE$K(aq76w=SkFy;>PUI)9{poHB zgFiGm%zsc$Bp$1RlDoZt{|oEvM%{*wzg&xGfOMkq#$*-Y8J{{C>MIQ_gh^RP5(e1K}$V?-peXyJNd^9ux<>u^>a( zKZm?W-Ot3Vi8#B+XS-ym+J?i5DWkS)xyga1`=#lXYJ9QEi=c0j%J} zG^@0j;O6wbb-_=ATeRccg`h5hQl0D?uP5YpzmeXCHHR#szhjz~i0UkCxKh?_+~ z`Ccs}mw`ygB!+|20Q5GRO*S390Q$}0Zs{Dymx*Aa<*eqzAe=9Q%#Gm(;{{dSPbgMM zu+z5Dn&%jv?{H}t3@_Vbhrzwzfa+8)ryQEDrjQ_-6#K%^vxS6WxH#~#Pi~kOsSgV& z#??Fq6c=ug)n;FfvOAfeu6ja)=2f_p`a;l%rRYsTlk ze^A$#32(Up@N#=io~HHx%^iof077{az#W&pT5hjtj1;;W2>CY`TrltHpNWN>KNySu zi!?@l5GSDX`6Jc_hK>E&{10F4pQ7PD8n1X?I3G&9gV&)i!rswme~0zL>?(_LKa+uy zd|Ms!7{-LUmsMfGG(=`Wy#ys#*41&wa`4jua{+pYFbY$7+Sm)62n^pQLF^#!`v?p2 zL-yuuWX30{wsX;RDSSC_Vvz6T&v}mEYZ*~k~hhR(r_9OkFo#0__H+{m& z;}|m?-cnDTY0r6qZFe@-tkZ#})&pUP1vt+25TT)I36N^W&vx_st zul~4cE~8-uv8mUp#pm59J4dOS((+BI5QyTXHP{gm^zfYT99BIWUqY~y7a|QG?Czq+ zw0hXw4t*;UOo#bjQQxMjglEGpy7tjW;aI)Q*kG7N^r1wl>-#p$+}q z6dgUb=N~59HH!PZ4R$=pww@zbRzV!Ji_9)edq?z5EBm zB3+>(v4@A(K7K|!nIGB`3qlzZ3G;TC0Kkoiv*j&|$^iyJ5DEmZB z-8)%bU=kf*e%CBws`cN^Zv`;F1;G4zuFMb3f(9%Xj`M&M7i!sY|K^to&ZXVG;qm^X zTsY9VaupR5{~-mg@QZ-Au~R|Yi*4UDp!f6@FaXPlO~)+ zjGo+SbH2GsE|ii%Dn~hVn_CUr!*k@-SCDnG#%nPiHk2@{59rSAx=HKI$O0Q}4^O{3 zyc1f?QhvDnEnt`~hj_%sCz9nJvTV)U^&UC@3bsC^3Gtnr^G6HS<=-^wRyJgEOqb>! z4BtCV4XmkiKUOG1@O^I=Ek<|1*j6UFRjAQz_Tp&Bm(hm6OU}uF26B+Lt6s;B3fI6a zrtAwb%S46YE^WNs^AQxW1I{4HxU2#%M(Ns$)_Wq6qF!C^8E476@N|2>5g(xUqGGCB zHVk>0dx!4o=3HFaH+bCXO|r1|+JXU%WYGNK{ROvI4_AWNI^`Dscj$$G`})7hriZ?* z*u1BNB*b53+j7?_nsuWFag9LdLHHy5JueAWZ1lJBE}Ugu@}^9V^16f{7hCFEOXOcA zcbBx#JL1{Scc;ma=i1tsM)8xYjoU(Eet3F_34ge?RZ2uwZSAaWW9sK={Mspvr@Ri; z$lBvI4TtpjZ8-S2&U*MNB{VLfLzDAt#f?lD z$1qg^m=yrgs)Z1R*w&Xo$WTena?#6ID7Jv#;%gRk0S_IasC*YL2Q%V9^fq1R z)Z#0`hsYfr*l$^&Ed+DOq%z) z_%_M-I{*X$0N@V*faMhcU=Wnn*?+ftfh%C)STT9hnfE6I+?>G)5R>pgIA9}3!bX*~ za=BDjCzp4&Uw8Mz2QyHUU#JOGGoI z<>s5{y8%>AvNTqIt>;R~trHcqn}QTN_KMvDlI!!1jN7~e)H7~(hqO%V`CbxVlW`&# zTT)r5)yJlbJZX?~AGj0eT5R4rdFu(rJsyq6O@1Z8h0(_Ut%^=0a5UylS9L||aQn26wIzh~9o>_xuzH?~_PNrbeGE8PH|}4H^IsO@KUeEt zi!<|xs(2c1?3XwmGlScw4igzYoQZ$jOqYwZzUw{anR+gjg9x?fv@Hq^#k+2((`IjT zH@QgtywPE}*XiOM<69H(sAWWMD}P|Z8$njTbw*~B4<*g6@?q};`l;_@4f}~n3xVUH zvEht`CkrhfwcOIV1zM6e%gZFH<6Y*@D3rJ@IHTo9GnL=HT~kJcIGTLBlVP6W{UU|Z zI3~AbzriQ{9Uoyvk9)Sydxg>p!dwq5ma}&8m%#~>c>3)1-)h~0u;en_J@oZ7+AP#L zKR@jm;)ilQnXi(tW+={7`wY^g#4(vDxz)Cu{N?z7>1gwvkIZO8!uKLnCL$b2k)SUU zxhe3*PVf5^3Z);EV6E58>aXPbucK4m(%;YnFV5GU02Hdf*(R(PkcM&x>{I{RHpw3A z>5s9s!$~~}LafeUe}{Nkx=MlU4RAG*$FIYdr5}*cP0q%`#{_P ziIMRI05PZ{%pG`cl=ACF=TJVOtQboOr8j}Dh}V(&g{e?)AGv;SoIg_}(=+2*2Bn}pc8jSM~?o2;l?R{09WJ2Mt1_-A4MEZb@{ zyB6`;-xqYE9Cl);oT^rvMau?-Q<1|Tymz2$s)xKTPpU zZ%YtLp{hpP_pR;mZ@W!#g*3nGarO1>^f8zg3RWe)5IW&7k1M6Y75t-s{=cTj1)ceY z68j>Bo@aPE`!&ZYyFiSZ)gLBwDSj#zbo+$1=Yuh5MkT`2OZT9>CX~~s(9aW}Ph&tU=d$8n+&dQ#UOdtqnQvsmjTWgZNtfhO({*H%wfxYa|e+{nQ6-u=iY^Xe9iE#rdWVz}p|FRVnn6ea`f{J0qk zSpCvXDGT-k=#*JDYdwWF&=30(-|h+~V8_rd4%=Ztx@aKt9%_A} zn`^#2rjT&wL3B`hpi{4gvT?;>by|2@MrGb73PU8EmLp z2CIBitfKB4a^byA4A^m`d|Hir)t#UWDrKXua(P%N(^&C{@tO(HLb59(Jy!Ge3ISWP z!!^hvW!VFs5NMy8)yiJaGQaMyKi`=~etIG^XF8Qtq^Ej^%FZLH`r8@Qu*!aIa|APrYel-l86F_2aFdDO8Qm?NzxwttvfDuXm zu?zi^_fvYo_hQ2uN`5K7b|LKkpt1%Y z=r3q>s75q0(6%p4=p zCmd?s5yg4Wf!um>dy!+k_?MAxIKI`7D2sc7icYHcJ45N(u*39(v+sDm7>6;ph>)m=(QSa6G1UU@f2xHS_p(F*<#7U^YP$|^lYYkyc zP%Luf6(-SwsQ)H|4E;yn#G5~Ehf5C!O=d)>d@*vuI5-w6T^!-Q;;YH2Z93wRHGAnT zyjYd++`VeoX8qKc@0^{sWn!Jz7+F(m2suC1<~*zB-A;d&_JZ|=4c*5g`R^o2R$kc> zY}1sEk5sB*-Ri{8j;lTQxAJDG(%j88Ei zm*&gm5+(;l&Plw=C6$xlx*ud5CfUv~>RCGa z_}0An8~GU=tN=IUQn)tJF}TS2_~_Ai9ec7OZ~(AY4N>Wb{Y$pQex?VI2Gr7XbBC;s)!9 zouxRvqz_aCr2Ro-W;bf@f4lp4D&7Cq%pNnvTz@?a1MA~$E9?)FL9&h2+&$f4Zyh{L zrI#P`K0bIz)A+5p_}$X6WENX)G;EbLM=~QR^aG=!*?ygr$vIk6lis-$(uNNRQ zD$i~2BrUPQDq5OCxBmPPh|P+hm%lZCj{YN1>zWLcU-j1ECF3GML;(R zP!(gp9z+3+jrDWaRTLmjex>*bj=H&k$yY!s4eas*BZ|SBARaC*{r}Wu{>kz0(~-c_ z%vwz!9#+~u|NJ&blK-|<%{pEb*A%K=f@gnX1B_T1lmdIns|N|TWkc&ijmGO-h zW9mgSh~9rPD`~eXBCD@&u8%wW?iz=jYtsUmuh;Lkiq7D5QKjuG%|w>%r@3Chz-?Oy zse)d}%DY3{x)g`;%)LZcXH7GryJyc}l6lhTp|end$mD6r%FI{8YFJK}7@iLU*vc2J zw^6thi#jNpRbjL~RW&_6l_s^soz;T859L+YnZ&FU-#lz zCG#pI!tKBebZ13PA>R$Is1j!Ev=Z=nu{|ABH8h-&C9v(F?@;rge&j<|d&?6AHoU5A zTR}LN@_?M<*{wc?r|AVWl59J>CbSDtO2@{|V-q;egq(Iy1;e6~IyJPg^VEFAjvIRN zx9`4Gmk7=yoj#>TZo^Z@F;N%YFJ0MOv=r=Pk2!?gtC=D8yQoRzu+3jjI{FJ$yV*t zq$upYSdLX}Lx*z{u|>-6+FDDM(U$>oBG2ql#+oABdOR9L1s~HWOkRk6x>{sIAX5P7 zO89FE@M@|9`PEbhQ1CDu;-y4Xi!KB-2+RUb`l+V`$nHfD1&4||`(E)bt*G52ju+;?f-Rz2!Z+w_FP6uDrLFMiYKqX zx*S<+l~8eQuQ5z^7`&(qofsHcq&VF(eJW^VszH~Zd5A#CxYnBMzLG_4&t4VpM>iFQ z8BJH@t_!D^hu|Y#K z$JJgPXMEVjD6V$d!mk_B(IjjBix#=fP!%=B15rw&mA*qdGj!H@|n?7rTT2Bau0~^ zNh;{|Z<~ak<`Bufl;kbRPxb0T>{~K?{hoilO|5?9`TeEx>a$x=&Q+*EQf=kKRJjCtm}bKVrMcITIpO^jEe6@o+HgDoIO0CU3PYraOT`%&%T?~w%lV!B>dVznbK*y zL|5s}fOs3zrV3W1@h9nV$AfgJ;oNbp7`P0={9NxrP-VDS`7oUkB7^_a1HWiI<_-jk{N zQ$UM2aouZ~t~|i#+L%R(>;MYkp?hK z&dl=;AaZ$`VrIv@LEW86U*SLX9%c@D6l?X}VHKPy$6T!tV695hhsluRlwOYLrxO3aZkIj%7a? zsP}3S7Y02lq@=<3SSMW^E@f;s;G-B}R2b6=SQ5}`9&>Vl(s5Xo^+)Iqc{%$uQaI14 z0i@kt0~Kt-aarOltu;FT_`-$>AF4>1$Q~0pu>S5^`sjTxmo~vE z)uh0cfrn(g4b3m#3N`0 zP-FDy5V7|P_Jg~@ApQ@z&O$=<+X!5dh7^Yv^NzZMA(wyRk=Y~VYI#STzq^)Y1HIz4tj&~_5x?`#*)07dN{csr}TJGscHpf(}S{r+!msry&kiQe<;xA%N^ z0>hZ4s1NsKgS<@I8r^PprgdY9BlcvzEkem%h;=;42Z`}`e27k%Fxo`_Zj4|b%A{KP zTjV3AN?zElS2|RSd_$SGd)io0DiZz;?45N}%iR=Q8*-T3+b3@mb-Hr6mfs#8p&=_~ z+4|gdV}JXJblygMuRizb`xQS<9{ZC=Okgkfn*1@a`x{U|1HBy3KraVW^mX{h>)QVp zK?~*I!QtA@k+9LE-R{^~oB04rp}?>0nn8a4HX;=vCPk(M5+!)OwV&%UBJ-w z`C&C?^ZBQ>TF>^l3)r=Z$8fD!-J)n;M+d2^F=q!o5Mw@8F{dMDEPlxouH#w!Z5S1(S@4^KqOYNnfug}m})uB&8|*R7AFn^&MQP5o&pFn%vt zIqPo!Yx~hTism0)*QM+x$n`2Zv;zTdMXp7zS)mCap8Bhz03h>!_sjn?Y9s<*5d&xd z#Jmm?Z~P9(;C<*YFn|Ta{Z=$q%|_m=Fm5E5D^j)Z{XS0a_cX-oMv(ZoyMGT7iQsN1 z0HcDCiD9)lSwR-iP;jqr{#F3v0UG#`P$ELg)|H749!AqGa_b5+)WXN{sHU_!w`G6o zjIR!V)>JPsj}Fg2cbXkvJ=i9qkpnGN8K|)Dvg}W`wpg{?@Mx!_`NJ$S2iL?b{bx>x z&W~flSh^(vh%CLX2iP&md31%Nu3b*abv*%(bBEp_$WK^j77gzsPj}JkEF^$7--8$0 z>t1WZzTfNz4jG6N;eo|==gNM7#e+CnAEK+@G~tat~HVR&qO64}iddcA1L@)?(PJ?OPyX@Cl%?aW1#X zujJ&wi!nIpyll|Ep-G8#NpO5@7=rJ7aV1FG|BHSuLJ zHDvru(%MJGi*x?fTP_-Gk9r4It$Ta0*WDLu-?QsPV$~(BpSXY6l>K_Yw$fq@2BO}Q zhd*sSWjE@Z8!9y2eY1Xq&{UPsF6DK@V>s7csA3Y*=iSADYew%M2;sQc3=lu3l8dFF z7l=_@#bp0R!CGx&{f5CgIjLVP^{i63wYoN`Rom^w6Ypp$xb(=1 zrSgMe&odvbxog(*4NUc%Kld1M!g&Ai&ZqOV??FOmwc~R888XOGIE61*rxZ>1DcT%^ zQgB8pMy{a<3Rn`L$Zwc4Zc%Db6|Mq%M|;-c8aA@R9>MzvU{pL98~_!GF;MWwAe_HD zCNH?5Fu3l263ZRvnOwG>(GD9qDD!?=kRGQl=rbOs)&6rfoa2chzgV$ z%_Yq^O5r^W7fjSTQojdueFzN(9SuY#OixWkAxMtU4JE8Cvm>#BT%+etbm-BP$uQU^ zV1r%+v60w)IecNo1?%!|Lge_P5iiHv2By9Xk0c1UdC2Z!$>!&~A5Mb4?Mh-L6j`m9 z!Yj$XWMYFkydBOEWrfjGtzn+!m}zQAL_A#Hb;~^i?gF+ig4UzZ;_{^)f3N$(K{ zhg?7g7*GrX8d9>fNl_GQzpzRE4Y&#A-#)8CtFdbxml=56E>b9G*saEzB6``*-Jc_6VvSH<7 zOCau9GN-OMpJ(SnTQQ+#Zv`=$|RdVTM#@!g%|U1E`UJrr$S z=}^V_hX&r62Z5xw-+VOI z)o5)6M((+-f6uPOp5whPKmS{5Q7?y(MCgoWS=5w=u`TVES(k>_G7&S1=2J315RKhy z5&EEBgNfUQj{hFIDT@a8WxiMR8Qd)U&tgT7!#w#Lr%A){CK-q$ zs33Zpq63|SqDa|rYN4s0akxM~l4S<9Xuo+X0p&`(DK`ER7TOiQF!kcQ94FGk^poKD zOr@ECwYBQ^hTZll$4?F)bQ<{}wA_UomG39yQKe!{b{CxH_TLB<%XGp16d7uS>+#90c329 zA5W31tEd2FvP&Zc0nO!rVjnNi!w&YcE+ue&Y=Ztux_fBp14>i zetnQ~*z)CY()!2J2s1HzQyp8)Fr`=anozJ8bD57A%Z=dUZgx@UjMjL{$xMY=#1oPVX z$jIOr18C3iQ#hRksyjpm^h-lo9wHo(>3KbBY-6*foHZ&}Ci=f1rg>9PYyN)b6peh% zu7AX6wL~QHfJ5%Y@*lUvrCo^(kwmj{pB>+sS-oc!wePOj!#u{Jyf;JWE8F}~&>#t2 zRh}B#0SC@~2XQzrZ%HhyXN`cvQ%KGkJxAf=5$SMJgr#Phg}dsAR{sfk5>$R>2UU_X zo|adxtFP003bKASmRE#JQS8ThM8SyNX+@rIO*;+xbRJgU`A!UlIHl*}o@95#E+j>O4PE1#65a}_j zRdqF39eJ=W+7II}XrIV;u#SmGQqHSH zyfdxa%(Hk6nTFxp3?YQ&#DrT_s!+8}(5Rd`J?(WN*wSwT{rXIBy+wxjVp6PK{pfs2 z;K<&adtmaxCu0J8_P3-jg^1}#9W>t*8;s>M6BG93Lmg)7HS;<|)H#K`9N+BGe)XJ3 z_qzz;-e(lr=Sh6WDs4uTa06+Z3uSM#=7X8&Lj_Lu?^38iw5aoacyI0dY(H3gaUc{? zR?R@wzJE%N$VlX<_t5IdaW~}{N{~Z4gx}AgnJt>QHLrI4;@*S%bI`k{%DR|}p9(}V zm_i>xdQ2ocg+b6+mws^-LzGA?Q%OQKLsX+4PaHu`Hmi=T{(SL>`yyQP-DfGuQeq)I z2f5owBw|ryiS5V`uoqvup>7uzKkv&(&0^D?4_Ihvf}b{laW`b=>ew=2nHRQ?IH471V&4_kT&S{>o)~?P)EX z6!M&Y$uTr{`z*9C%ZI`AThirk5BQz@8}Sz`f`WvwZhJ$uH!;uZY_i^8URg<_#B?mE zn<+-ktKVCKCx20M$CopY&B+y?E8*NGFm5Yz#W>`-78%?0M>Tk?^HMw!X6`o@XVVy; zPz#C&{QCw6*wk1%ar9@`2^U1(^c6C!v4$1Hfqc9)J?PW*_~s!{&4(odD00e$1@4cW zc%u?9;h~xEESxdcfvEfEEl}?25}jwfl)$P=*!Q|U>6-s}l1Z(9wVU*}uaewYL%OXKJx*#2Jl0!CpK$x<|n6-XF=t zWxEbhjV}YUQk(NA0edBngZ>#CV61Di~AE-Ic;Miz5x*5`j zDc#Y35ooIYT&e6dlQeA)bz&$@(|b}FtA3tz2LZ11TX^I~{&Ynk0aoaDZG3Uo5r&X} zjD7Y)x99!LkaSOA8;h&ulo@w&lGN2wgw#DAYAfQ4y+)*8jlo~L|wkW`#7oq4l4pa4%ZbHBlxSp z@RNMZVEN-V0!iKQasZ^fp0tOAf-G(go?3BL5hA;cW?`UF@NPUyu59J$?c(lW=WGMU zV}KCN4zvt$0n?!_-JMI-zw6Ea&{h7)@2L&zUXSx`{O3L^n0Rps`31uwSOO-$jszw&#L9XQF>Z9x7G5rP1XxcRfJ`3B7u1mEIS-@ED^)7i-OzRiUf z2pD8GawHV6t_%2{;1W{Rf{-+YBfFc=`&K$z=&g5!<+G%@L%Yxr)35RpT%YwJG{Z^o zcoIzd0&%}v*?)GXz_k<~H1-WC zzCRif{`W@-{D1Bp|C8}Ie{O?5JB&Mns&X;Nk(+qzyO>`OZKh4oA^T$NoiI0RwB%8q zUFK{I(RXa}tXg?*4hHS-ja&C;C{Ns{>CDo$5B0;goCzDFnWw`HMm$d)OuC| z@5zuYngkx7p7}zgn|b!rhKO10RlD00qGr7Nh<2xs_cS)TO>fuyo=J^~73lbBy^@zc zsh2U=>-ALajF_4)_X^)PPjj&QC-l#oU>-XZ%Nq`6BoF2i`<)Um_vjw_)e8y*a}HGx<8+)Q`? z34-$M?cH8POKD_5vEZWse~yFnce)P)7`Nl~JS@NQcpB5>9azJ%-s8u8&UmUC`!L*Y zA8h>B>AzMW_yPX?(AR{%0F3_>F#e@~74!txvx|a+fy@rDe)4E`WT`7?s%rtnihnQu z-s-wv z=&W?K^0e#9v2!B#vI5U2xOyzx@#=C;L1&KL_22f2{MIW1o+KihFghq3C_s2ZM_D%M#x%_}sH{l!sGg z&gN(zyZz=)jGpox7g^)BD=-0;sXtnQ{wB|ed!Ti}n;N7?QFxYzt4MzM(PR>u`m8^m zXrBV<(Y8R9{m#y@>7XKywe+n$YbZ~cyNRG@vq)a(J1Nf1J-n+#sHM?z27RGC?FTZ3 zdLi1iBj;4LR!5v;IoK*Lnrqs+)X=86Rh5J<8YdeNC#)5JJsx%UD##n#G zHvjnb=k%|K6W)~3M~d0jU2Hua8s;O&8V;~C`ts%pDK&9{?3o?B?b`CA+Rx~Dk&#dz zB8TLZ7hYZT?z$&RSwhon&Kfx9^n6t=op}pD1J8B$?<>~dp}`7(1~UK}#vL}YbH66-w z{96d$pURYo+maG&YIUbAPB7tLfPhlC;lBTPsxrB(2q+S>-Krmu?c3w4eC)s z1S4Hi_;o>(&XBhFlzp#}|4kC$&!zWfe?EMN8mO>%L%N)s`s9L|nRB4(@%)AoO@03*w7ODe6M0tA)qWJ>MJ-8VOI>Ao|wkHtJMe+$wyE zjcA1__$Zrw+%i`YHl=XE_WG&wbX%(E1yA(Z{jM+z2I9V6_#TMD=VR@ZDmG)@Tja22 zvtR?fZYXQ~y~P*02Qa`czyQmx4G^l-kk%eqEHe(-_iMQfjrUDg2TbU2{JGF#Ljl3? zFELv%RT5mCyR^jXW&j}V4=&4C0=vNJe{fmmhuS_gHs#M($l2N0l8bwI+;P9;K}&1@ z=t8?(UV-L-D}|iPBqq2y;OFN5%kSo&jQmaCipT2d$EFn)7LKC1m0;1H_cZb^+!#AX zlDTa1kw_{{?25#yI_s+qHv1 zx75;)o|Za6;ON8Dzr_BehLkQYPN{5V78xwATI6dOJxh37XM}ath(v=qF#SCd9A2TV z#{d@$wqc&zu)e?6l(FRkZzMNmp>{W3e%s?x<0Dj=j%J9XM80{mhG+9 zMk!%!c{HSvMntN}9B)7Zk2`nm`+QC z0JURb$<*;%=I?J0_!}c9A%aVr9?QxRin4}7(4m;3kUeI!DQ+d;@Djt&X^YwOo4~Ys z$bFK1CS8|3p~$Y#kgzVv{IJI7!_<<7uiNMfMKa{1R^%gU%flG!zS%6^_s_Vh>@umk zvwbL;TqT#ZWC1Oq9o?>QHf7LZE;}Ao_u8Tr9%pYW5pk~Y@jK&K_E=MdXciPWL-qR3 zZ%FBbxF$JRE&ezW+0q=frxqI$acJ(8^eyy zp9UWM?sp6SMY+=k++Hvd`dW1MI^%_mjrU{66*>Ax(u*BnW`KQeWNdb@&kb(MBL8vZ z)hYgsQnfTl@-iI27W(m$%g#Cva?T$^gMOC#0bl{1`?1C@VlRwwc&{= zoyM5OuXvHSVZsHJFgq6=V2VFHVJTxY(<`*0RUBABh*HdWsDiq(c3^w-F zfbNF}_YXdOk&s7zoJMEE;k;0ugiGT3id>0}U^X#o-7#DTlV~Gwi562cUpiGQ^c^UA zeR{m$Gh>kGJzpyw5nOU>1h$l<)?!(K9Rq`kr+t>S;x< zu4@>QY(D;Cj)(lT#{}ieY`fQoiX;24C*noZD!zAb;HMmw7u(oYc0GM1&(zww~(qW&Iq>*(nN@hzu?-9-Wy1 zT(+*Vd$?r0<{ly+*GxX(Lr-y^Fin-4BASqz#5p%13vcRUlcJcq)V;2wqGW|f?tSjr zE8BFdZS09dAKQ?`clnv8(ft}PCn5CdTSMlKUt-@*kt_jjL3cn!-)F;3-SOfl40UG-sUmYm8iTzq) z3m%(T+syH5`3FC+yfVh??Dq}U?vJCcAp{7OuMmRy$BtiCe%0o5<7_|4pEqXg+#u3> z0oVQEWUyVfx8GoSV%j-dyNKO91ngP>93fy-IS7aWE~Q4m9fv@uI zSs$r_3%1wkaKDpO(w|*)wuh%a%A%CRE%l5QMhRX%hL7REn|H0g#AuGk4JRXRx;=4s z%``D>Yg}%+wGE2=4Rs;CB1qrMsmgF~W;PqcEidY=L8iFVyUK=#xZ7o%O#QMjhIibM z(y7xKp33VznK`bPG&kEDUL4R8{aZT(c+T2QP`Y6@2+VV2Q+MS#4~A_X@7E$>)bw;Q zFDBZ%`OtlJ4V4%c>3^=dzdN3YcYhG3SD~aQN4i`n=6R(Xr%`v8&RoSa?wWhiksIqY zi4FI{{mMsQk@D&?+Vmv!GX{%%e#1ZaT7)o*un$`)M7-|)?7Xlk0y(;LphNz>g8R7J zU^BQ@sjD>k%?x0hfU3J8Hh2dmN}L4^QS(?L9U(~h@E zuO9Fu?A<$_!o=>(^7d*guZOY^_IoZJx(K`4sNIz<*xLAix*1)mb5Fc z$;8+JvjpW^_$R52V;GOG8|Q}U_YXWO9BKpKe>8+*QsiH#PDx>rh#VWKiI=Q*#NM5q zIqW=+79G5Ekl2wh5)(BLzcuYN8{KZ@mKuu+{XMJI0IxK0YV+LJzwA@R5nk`qdm5${ zveQR7i)wuW8YptBXw5yfUU2HGnAqX&7SJ&BFg#4;gi!0APsv{NXj^}|Lo;pDhGu3O zRU`>)s>t1e$UjA{%g-q&gZjV`^7J^ZGTGqM_aT>E zZ(CGuORCZatvu*KB?-dm<2!oV1>c^@`yN-IHDc!a*V}*Q8hAl#&PNo9a=iYXbvXVW zd;;UG(LlrS(2Pnx1knxSZ`|<9J?73j_nxYz9KGz$Tz!}i*)?k2>T9+qM6%ErVrZ1x zu`w>!Oqh>}L+D%`L2N4`$4eAdZ&BO9APnm&~Rv%V&)~jL`a%jum=0{oWlU~ zR`-R1q+5M4wEBpA10TjvgYas7o(M!LK8SfTB9r!&8Kd!)Cgp2LRXfS-{pua3cR=oMX=6JS8HU(XSP#wPif z#{j~kS4j|HULd$#jGY@?V*pxF!0lrkSGuGBx8B!3#T&KrO=?a2hOsbRioPUN5$qTi zl3H}4Z=~NA3U48z5|NU(Ym?3r^TLBD*<5zvc1y}eyGzUp*d#kEt69!EQtj>r#w_=} z=EsVcFzxB%w%wjIiPtuHPoiX?EB^@%QpNIwStwd}oQ-v{(sqMV@J{ro6p__e;xyV@ z^iHMg&3d<(s1HZOpsk~*A$&}Ck4w&>svS-#Pq|m|2Fngvv6fG`?NKYuRt^e@?Xq6{XIu=bI8ue{Ii^z zj&bN=9YgrS0qUo(ze0Qj1%C$aC!pUUcm))^2sEJN22bY(PegFvaDgv-NiBfZe=B!Z zORLL{2QLmbPYaVv8ng+giG`VoygYbnYD933qotXv02>=PKljJ$B$b6VC22T7m&6vy z%hLf{m-j93e@^gYao|7l^2{oKcc843xg4{Kmasd}Z3TA7J(#5=g>PH}ylH7A3f^@U zw_B-OdAVH0?}~OFo}%Vv9#*1%7~f@_#$&qddIU!tOd6a29>AGyXq!OCPGfd%OMK0XzZ zcA&wWkR#u+TfI-h$5(mdipS3+UqEjtQNSZaP3p2)^D{KV`ouowTZgT;4|FSB?KCZ_ z+zDEarbo}F8T}l(S5}npHoZrJfE(v=S-MOjtIE6GNXa(56de}TooJRIKb^9#+a?Y} z5Dyx0j&X3gCtk}G+;#6xXzkHrdOwgRl0|FTH}@fw(CwY_>c^40&k5ga&311M8S`nZ z7^>W7Iaj6PIkR5veOSm(2vMH`#SdsGob#~`-hzE}s3hWo4u7kHnKaInfANGz1DpS& zF)h=S@H3odj!y*8^y)BfDuwIq->zUq1Els>&+Pwc z?#jcV+}kiSgGiadlzZf#-Ouyf_m^U<>Rd7=HtKyI2Z|Sl z&&8ulp3<$>p{hT8;RmRy=756d8x<$}I0c(T5WpV>=bpgSIjn)LSm6qa%zi=(ztj0v{_VpfQt{j%Ebq@N%Wo&8fzsYTa%^(<1_Aj z>wuwQ>pk#`lrS?02l>1CoDN{Fk^}8bR;OeYT;UNAaX1J(`_k)NlLTZoJ(XD0SHQZf z?8;l8opmj|u3MaCd9Vi1K>;-WfXPGF7@{TskE*F^s%tYz$^I`6`EMa0Syucpys)&F z7LzSc)!BGzo@zxwC`*Ys8uv;$U68?kbiPn%QB1xgakr0iOMmL|b`PwVQ%Jl*TBJxj zaZ|Dn4!Xl(5PkomMebCI(KFEgXeDKz7sD)#4(yCwx7-D>m{q7Hec$kGYvRTL~s+E+y^1~v5rNfR1ucCBv5Doi`c4)844Nl zk#b)aE5A2W6$i8ZMl23%fINUdbEcY}a*&Yw zb0@`^BX#xia{d`Ij*zR1orYI)W=EsB?A)- zGA^eTw6Yo^haaR!Hri!h8aAlFr+kz(QSZXRC;2kZpe)hKp%|0f-vOAwU&176D6`~O zWFWS)Sqlnulix4%z#?MicZhmiQwgTlE%nZfTrU@k_eM}`=>e~@s_bU0UT&|#u^$P& z<}5Y)?7^quW+{h1PHi197A0;o){S!PBC_!vjs+1WGZRcK2g{&Y1~a?Bn`fK;8fmbN z8FD8Lk*e^;{=^0?Jui|Kud|qQVN3rupd}>r9S-5H`gg^nC<(# zUb}&p-^?Ek5Q_OrB7xpK1|0zWR9l_R<>KYCbMrpw=Z{hoRuy8}84oXPzn_mE$`82R zN`7YlTh*@w^9mUm8GS|Q08o{o{c!+hAFz^?SXqc=Zp^Y$hjqjKfwIQ`{BZx4j4BM% z7JOfi;Vz3JO^o9zOn(pOOnb8PqmV@0AZTem&&eiwi`vE%&gQz)(tjLKvOhtm`eIBs z+Kn|@%2t*8TaC@a?=IM<@blE1D^Pds?}$1yFYPej)5Vw$kIalov?gKZk`qiLD|u z28>5$&y88GiT-;E(_z^cn^m(4zZnbQ{JwxazjDXLs`{(yWB^L*KChFsmuxOJ!d)_GjPyp!(f#co{U4I`S!N>E-!)w z$Ij5(VS1UGhxUamigfMnI|i>$Z=XGCt}2BFdryo?1x%!ZZ}w^5$$$&RFO`CtZX_K`@t=~^vZF}@Zq_;a|4PxdfcH!UYFV` zlqUBI7Z;r9f9sA2d*R7uWHYN9PP#s-btBoAZDc6zBSu!ejEuNZ#xI>K%Jnem>E8!b B<~aZW diff --git a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/CertificateChainCleaner.java b/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/CertificateChainCleaner.java deleted file mode 100644 index 7b6112f15..000000000 --- a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/CertificateChainCleaner.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (C) 2011-2013 Moxie Marlinspike - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.thoughtcrime.ssl.pinning; - -import java.security.GeneralSecurityException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.LinkedList; - -/** - * Does the work of cleaning up a certificate chain by sifting out any - * unrelated certificates and returning something that's signed from - * EE to a trust anchor. - * - * @author Moxie Marlinspike - */ -class CertificateChainCleaner { - - private CertificateChainCleaner() {} - - public static X509Certificate[] getCleanChain(X509Certificate[] chain, - SystemKeyStore systemKeyStore) - throws CertificateException - { - final LinkedList cleanChain = new LinkedList(); - boolean trustedChain = false; - int i; - - if (systemKeyStore.isTrustRoot(chain[0])) { - trustedChain = true; - } - - cleanChain.add(chain[0]); - - for (i = 1; i < chain.length; i++) { - if (systemKeyStore.isTrustRoot(chain[i])) { - trustedChain = true; - } - - if (isValidLink(chain[i], chain[i - 1])) { - cleanChain.add(chain[i]); - } else { - break; - } - } - - final X509Certificate trustRoot = systemKeyStore.getTrustRootFor(chain[i - 1]); - - if (trustRoot != null) { - cleanChain.add(trustRoot); - trustedChain = true; - } - - if (trustedChain) { - return cleanChain.toArray(new X509Certificate[cleanChain.size()]); - } else { - throw new CertificateException("Didn't find a trust anchor in chain cleanup!"); - } - } - - private static boolean isValidLink(X509Certificate parent, X509Certificate child) { - if (!parent.getSubjectX500Principal().equals(child.getIssuerX500Principal())) { - return false; - } - - try { - child.verify(parent.getPublicKey()); - } catch (GeneralSecurityException gse) { - return false; - } - - return true; - } -} diff --git a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningSSLSocketFactory.java b/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningSSLSocketFactory.java deleted file mode 100644 index c8a2dd3c1..000000000 --- a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningSSLSocketFactory.java +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright (C) 2011-2013 Moxie Marlinspike - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.thoughtcrime.ssl.pinning; - -import android.content.Context; - -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.conn.ssl.X509HostnameVerifier; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.TrustManager; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; - -/** - * A standard Apache SSL Socket Factory that uses an pinning trust manager. - *

- * To use: - *

- *
- * String[] pins                = new String[] {"40c5401d6f8cbaf08b00edefb1ee87d005b3b9cd"};
- * SchemeRegistry schemeRegistry = new SchemeRegistry();
- * schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- * schemeRegistry.register(new Scheme("https", new PinningSSLSocketFactory(getContext(),pins, 0), 443));
- *
- * HttpParams httpParams                     = new BasicHttpParams();
- * ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
- * DefaultHttpClient httpClient              = new DefaultHttpClient(connectionManager, httpParams);
- *
- * HttpResponse response = httpClient.execute(new HttpGet("https://www.google.com/"));
- *
- * 
- *

- * - * @author Moxie Marlinspike - */ -public class PinningSSLSocketFactory extends SSLSocketFactory { - - private final javax.net.ssl.SSLSocketFactory pinningSocketFactory; - - /** - * Constructs a PinningSSLSocketFactory with a set of valid pins. - * - * @param pins An array of encoded pins to match a seen certificate - * chain against. A pin is a hex-encoded hash of a X.509 certificate's - * SubjectPublicKeyInfo. A pin can be generated using the provided pin.py - * script: python ./tools/pin.py certificate_file.pem - * - * @param enforceUntilTimestampMillis A timestamp (in milliseconds) when pins will stop being - * enforced. Normal non-pinned certificate validation - * will continue. Set this to some period after your build - * date, or to 0 to enforce pins forever. - */ - - public PinningSSLSocketFactory(Context context, String[] pins, long enforceUntilTimestampMillis) - throws UnrecoverableKeyException, KeyManagementException, - NoSuchAlgorithmException, KeyStoreException - { - super(null); - - final SystemKeyStore keyStore = SystemKeyStore.getInstance(context); - final SSLContext pinningSslContext = SSLContext.getInstance(TLS); - final TrustManager[] pinningTrustManagers = initializePinningTrustManagers(keyStore, pins, enforceUntilTimestampMillis); - - pinningSslContext.init(null, pinningTrustManagers, null); - this.pinningSocketFactory = pinningSslContext.getSocketFactory(); - } - - @Override - public Socket createSocket() throws IOException { - return pinningSocketFactory.createSocket(); - } - - @Override - public Socket connectSocket(final Socket sock, final String host, final int port, - final InetAddress localAddress, int localPort, - final HttpParams params) throws IOException { - final SSLSocket sslSock = (SSLSocket) ((sock != null) ? sock : createSocket()); - - if ((localAddress != null) || (localPort > 0)) { - if (localPort < 0) { - localPort = 0; - } - - sslSock.bind(new InetSocketAddress(localAddress, localPort)); - } - - final int connTimeout = HttpConnectionParams.getConnectionTimeout(params); - final int soTimeout = HttpConnectionParams.getSoTimeout(params); - - final InetSocketAddress remoteAddress = new InetSocketAddress(host, port); - sslSock.connect(remoteAddress, connTimeout); - sslSock.setSoTimeout(soTimeout); - - try { - SSLSocketFactory.STRICT_HOSTNAME_VERIFIER.verify(host, sslSock); - } catch (IOException iox) { - try { - sslSock.close(); - } catch (Exception ignored) { - } - throw iox; - } - - return sslSock; - } - - @Override - public Socket createSocket(final Socket socket, final String host, - int port, final boolean autoClose) - throws IOException - { - if (port == -1) { - port = 443; - } - - final SSLSocket sslSocket = (SSLSocket) pinningSocketFactory.createSocket(socket, host, port, autoClose); - SSLSocketFactory.STRICT_HOSTNAME_VERIFIER.verify(host, sslSocket); - return sslSocket; - } - - @Override - public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) { - throw new IllegalArgumentException("Only strict hostname verification (default) " + - "is supported!"); - } - - @Override - public X509HostnameVerifier getHostnameVerifier() { - return SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; - } - - private TrustManager[] initializePinningTrustManagers(SystemKeyStore keyStore, - String[] pins, - long enforceUntilTimestampMillis) - { - final TrustManager[] trustManagers = new TrustManager[1]; - trustManagers[0] = new PinningTrustManager(keyStore, pins, enforceUntilTimestampMillis); - - return trustManagers; - } -} diff --git a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningTrustManager.java b/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningTrustManager.java deleted file mode 100644 index 7e19ca86b..000000000 --- a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/PinningTrustManager.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * Copyright (C) 2011-2013 Moxie Marlinspike - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.thoughtcrime.ssl.pinning; - -import android.util.Log; - -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -/** - * A TrustManager implementation that enforces Certificate "pins." - * - *

- * PinningTrustManager is layered on top of the system's default TrustManager, - * such that the system continues to validate CA signatures for SSL connections - * as usual. Additionally, however, PinningTrustManager will enforce certificate - * constraints on the validated certificate chain. Specifically, it - * will ensure that one of an arbitrary number of specified SubjectPublicKeyInfos - * appears somewhere in the valid certificate chain. - *

- *

- * To use: - *

- * TrustManager[] trustManagers = new TrustManager[1];
- * trustManagers[0] = new PinningTrustManager(SystemKeyStore.getInstance(),
- *                                            new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"},
- *                                            0);
- *
- * SSLContext sslContext = SSLContext.getInstance("TLS");
- * sslContext.init(null, trustManagers, null);
- *
- * HttpsURLConnection urlConnection = (HttpsURLConnection)new URL("https://encrypted.google.com/").openConnection();
- * urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
- * InputStream in = urlConnection.getInputStream();
- * 
- *

- * - * @author Moxie Marlinspike - */ -public class PinningTrustManager implements X509TrustManager { - - private final TrustManager[] systemTrustManagers; - private final SystemKeyStore systemKeyStore; - private final long enforceUntilTimestampMillis; - - private final List pins = new LinkedList(); - private final Set cache = Collections.synchronizedSet(new HashSet()); - - /** - * Constructs a PinningTrustManager with a set of valid pins. - * - * @param keyStore A SystemKeyStore that validation will be based on. - * - * @param pins An array of encoded pins to match a seen certificate - * chain against. A pin is a hex-encoded hash of a X.509 certificate's - * SubjectPublicKeyInfo. A pin can be generated using the provided pin.py - * script: python ./tools/pin.py certificate_file.pem - * - * @param enforceUntilTimestampMillis A timestamp (in milliseconds) when pins will stop being - * enforced. Normal non-pinned certificate validation - * will continue. Set this to some period after your build - * date, or to 0 to enforce pins forever. - */ - public PinningTrustManager(SystemKeyStore keyStore, String[] pins, long enforceUntilTimestampMillis) { - this.systemTrustManagers = initializeSystemTrustManagers(keyStore); - this.systemKeyStore = keyStore; - this.enforceUntilTimestampMillis = enforceUntilTimestampMillis; - - for (String pin : pins) { - this.pins.add(hexStringToByteArray(pin)); - } - } - - private TrustManager[] initializeSystemTrustManagers(SystemKeyStore keyStore) { - try { - final TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); - tmf.init(keyStore.trustStore); - - return tmf.getTrustManagers(); - } catch (NoSuchAlgorithmException nsae) { - throw new AssertionError(nsae); - } catch (KeyStoreException e) { - throw new AssertionError(e); - } - } - - private boolean isValidPin(X509Certificate certificate) throws CertificateException { - try { - final MessageDigest digest = MessageDigest.getInstance("SHA1"); - final byte[] spki = certificate.getPublicKey().getEncoded(); - final byte[] pin = digest.digest(spki); - - for (byte[] validPin : this.pins) { - if (Arrays.equals(validPin, pin)) { - return true; - } - } - - return false; - } catch (NoSuchAlgorithmException nsae) { - throw new CertificateException(nsae); - } - } - - private void checkSystemTrust(X509Certificate[] chain, String authType) - throws CertificateException { - for (TrustManager systemTrustManager : systemTrustManagers) { - ((X509TrustManager) systemTrustManager).checkServerTrusted(chain, authType); - } - } - - private void checkPinTrust(X509Certificate[] chain) - throws CertificateException { - - if (enforceUntilTimestampMillis != 0 && - System.currentTimeMillis() > enforceUntilTimestampMillis) - { - Log.w("PinningTrustManager", "Certificate pins are stale, falling back to system trust."); - return; - } - - final X509Certificate[] cleanChain = CertificateChainCleaner.getCleanChain(chain, systemKeyStore); - - for (X509Certificate certificate : cleanChain) { - if (isValidPin(certificate)) { - return; - } - } - - throw new CertificateException("No valid pins found in chain!"); - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - throw new CertificateException("Client certificates not supported!"); - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException - { - if (cache.contains(chain[0])) { - return; - } - - // Note: We do this so that we'll never be doing worse than the default - // system validation. It's duplicate work, however, and can be factored - // out if we make the verification below more complete. - checkSystemTrust(chain, authType); - checkPinTrust(chain); - cache.add(chain[0]); - } - - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - private byte[] hexStringToByteArray(String s) { - final int len = s.length(); - final byte[] data = new byte[len / 2]; - - for (int i = 0; i < len; i += 2) { - data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + - Character.digit(s.charAt(i + 1), 16)); - } - - return data; - } - - public void clearCache() { - cache.clear(); - } -} diff --git a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/SystemKeyStore.java b/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/SystemKeyStore.java deleted file mode 100644 index 3c013b5de..000000000 --- a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/SystemKeyStore.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Copyright (C) 2011-2013 Moxie Marlinspike - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.thoughtcrime.ssl.pinning; - -import android.content.Context; -import android.content.res.Resources.NotFoundException; -import android.util.Log; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Enumeration; -import java.util.HashMap; - -/** - * An interface to the system's trust anchors. We're using our - * own truststore, which is just the AOSP default, but in a place - * we know to find it for sure. - * - * @author Moxie Marlinspike - */ -public class SystemKeyStore { - private static final int CACERTS_FILE_SIZE = 1024 * 140; - - private static SystemKeyStore instance; - - public static synchronized SystemKeyStore getInstance(Context context) { - if (instance == null) { - instance = new SystemKeyStore(context); - } - return instance; - } - - private final HashMap trustRoots; - final KeyStore trustStore; - - private SystemKeyStore(Context context) { - final KeyStore trustStore = getTrustStore(context); - this.trustRoots = initializeTrustedRoots(trustStore); - this.trustStore = trustStore; - } - - public boolean isTrustRoot(X509Certificate certificate) { - final X509Certificate trustRoot = trustRoots.get(certificate.getSubjectX500Principal()); - return trustRoot != null && trustRoot.getPublicKey().equals(certificate.getPublicKey()); - } - - public X509Certificate getTrustRootFor(X509Certificate certificate) { - final X509Certificate trustRoot = trustRoots.get(certificate.getIssuerX500Principal()); - - if (trustRoot == null) { - return null; - } - - if (trustRoot.getSubjectX500Principal().equals(certificate.getSubjectX500Principal())) { - return null; - } - - try { - certificate.verify(trustRoot.getPublicKey()); - } catch (GeneralSecurityException e) { - return null; - } - - return trustRoot; - } - - private HashMap initializeTrustedRoots(KeyStore trustStore) { - try { - final HashMap trusted = - new HashMap(); - - for (Enumeration aliases = trustStore.aliases(); aliases.hasMoreElements(); ) { - final String alias = aliases.nextElement(); - final X509Certificate cert = (X509Certificate) trustStore.getCertificate(alias); - - if (cert != null) { - trusted.put(cert.getSubjectX500Principal(), cert); - } - } - - return trusted; - } catch (KeyStoreException e) { - throw new AssertionError(e); - } - } - - private KeyStore getTrustStore(Context context) { - try { - final KeyStore trustStore = KeyStore.getInstance("BKS"); - final BufferedInputStream bin = - new BufferedInputStream(context.getResources().openRawResource(R.raw.cacerts), - CACERTS_FILE_SIZE); - - try { - trustStore.load(bin, "changeit".toCharArray()); - } finally { - try { - bin.close(); - } catch (IOException ioe) { - Log.w("SystemKeyStore", ioe); - } - } - - return trustStore; - } catch (KeyStoreException kse) { - throw new AssertionError(kse); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); - } catch (CertificateException e) { - throw new AssertionError(e); - } catch (NotFoundException e) { - throw new AssertionError(e); - } catch (IOException e) { - throw new AssertionError(e); - } - } -} diff --git a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/util/PinningHelper.java b/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/util/PinningHelper.java deleted file mode 100644 index 10135eb26..000000000 --- a/extern/AndroidPinning/src/org/thoughtcrime/ssl/pinning/util/PinningHelper.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (C) 2011-2013 Moxie Marlinspike - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.thoughtcrime.ssl.pinning.util; - -import android.content.Context; - -import org.apache.http.client.HttpClient; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.scheme.PlainSocketFactory; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; -import org.thoughtcrime.ssl.pinning.PinningSSLSocketFactory; -import org.thoughtcrime.ssl.pinning.PinningTrustManager; -import org.thoughtcrime.ssl.pinning.SystemKeyStore; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import java.io.IOException; -import java.net.URL; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; - -public class PinningHelper { - - /** - * Constructs an HttpClient that will validate SSL connections with a PinningTrustManager. - * - * @param pins An array of encoded pins to match a seen certificate - * chain against. A pin is a hex-encoded hash of a X.509 certificate's - * SubjectPublicKeyInfo. A pin can be generated using the provided pin.py - * script: python ./tools/pin.py certificate_file.pem - */ - - public static HttpClient getPinnedHttpClient(Context context, String[] pins) { - try { - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - schemeRegistry.register(new Scheme("https", new PinningSSLSocketFactory(context, pins, 0), 443)); - - HttpParams httpParams = new BasicHttpParams(); - ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); - return new DefaultHttpClient(connectionManager, httpParams); - } catch (UnrecoverableKeyException e) { - throw new AssertionError(e); - } catch (KeyManagementException e) { - throw new AssertionError(e); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); - } catch (KeyStoreException e) { - throw new AssertionError(e); - } - } - - /** - * Constructs an HttpsURLConnection that will validate HTTPS connections against a set of - * specified pins. - * - * @param pins An array of encoded pins to match a seen certificate - * chain against. A pin is a hex-encoded hash of a X.509 certificate's - * SubjectPublicKeyInfo. A pin can be generated using the provided pin.py - * script: python ./tools/pin.py certificate_file.pem - * - */ - - public static HttpsURLConnection getPinnedHttpsURLConnection(Context context, String[] pins, URL url) - throws IOException - { - try { - if (!url.getProtocol().equals("https")) { - throw new IllegalArgumentException("Attempt to construct pinned non-https connection!"); - } - - TrustManager[] trustManagers = new TrustManager[1]; - trustManagers[0] = new PinningTrustManager(SystemKeyStore.getInstance(context), pins, 0); - - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, trustManagers, null); - - HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); - - return urlConnection; - } catch (NoSuchAlgorithmException nsae) { - throw new AssertionError(nsae); - } catch (KeyManagementException e) { - throw new AssertionError(e); - } - } -} diff --git a/extern/UniversalImageLoader/LICENSE b/extern/UniversalImageLoader/LICENSE deleted file mode 100644 index f49a4e16e..000000000 --- a/extern/UniversalImageLoader/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/extern/UniversalImageLoader/build.gradle b/extern/UniversalImageLoader/build.gradle deleted file mode 100644 index 96b924b85..000000000 --- a/extern/UniversalImageLoader/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' - } -} - -allprojects { - repositories { - jcenter() - } -} - diff --git a/extern/UniversalImageLoader/library/AndroidManifest.xml b/extern/UniversalImageLoader/library/AndroidManifest.xml deleted file mode 100644 index 8b6a5a3ad..000000000 --- a/extern/UniversalImageLoader/library/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/extern/UniversalImageLoader/library/build.gradle b/extern/UniversalImageLoader/library/build.gradle deleted file mode 100644 index 3114daad0..000000000 --- a/extern/UniversalImageLoader/library/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 22 - buildToolsVersion "23.0.1" - - defaultConfig { - minSdkVersion 5 - targetSdkVersion 22 - } - buildTypes { - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - } - } - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - } -} - -dependencies { - compile 'com.android.support:support-v4:22.1.1' -} diff --git a/extern/UniversalImageLoader/library/project.properties b/extern/UniversalImageLoader/library/project.properties deleted file mode 100644 index b756f4487..000000000 --- a/extern/UniversalImageLoader/library/project.properties +++ /dev/null @@ -1,12 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Project target. -target=android-21 -android.library=true diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/DiskCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/DiskCache.java deleted file mode 100644 index 7258b9ceb..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/DiskCache.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.utils.IoUtils; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -/** - * Interface for disk cache - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.2 - */ -public interface DiskCache { - /** - * Returns root directory of disk cache - * - * @return Root directory of disk cache - */ - File getDirectory(); - - /** - * Returns file of cached image - * - * @param imageUri Original image URI - * @return File of cached image or null if image wasn't cached - */ - File get(String imageUri); - - /** - * Saves image stream in disk cache. - * Incoming image stream shouldn't be closed in this method. - * - * @param imageUri Original image URI - * @param imageStream Input stream of image (shouldn't be closed in this method) - * @param listener Listener for saving progress, can be ignored if you don't use - * {@linkplain com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener - * progress listener} in ImageLoader calls - * @return true - if image was saved successfully; false - if image wasn't saved in disk cache. - * @throws java.io.IOException - */ - boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException; - - /** - * Saves image bitmap in disk cache. - * - * @param imageUri Original image URI - * @param bitmap Image bitmap - * @return true - if bitmap was saved successfully; false - if bitmap wasn't saved in disk cache. - * @throws IOException - */ - boolean save(String imageUri, Bitmap bitmap) throws IOException; - - /** - * Removes image file associated with incoming URI - * - * @param imageUri Image URI - * @return true - if image file is deleted successfully; false - if image file doesn't exist for - * incoming URI or image file can't be deleted. - */ - boolean remove(String imageUri); - - /** Closes disk cache, releases resources. */ - void close(); - - /** Clears disk cache. */ - void clear(); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/BaseDiskCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/BaseDiskCache.java deleted file mode 100644 index c78d2e6bf..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/BaseDiskCache.java +++ /dev/null @@ -1,188 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.disc.DiskCache; -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.core.DefaultConfigurationFactory; -import com.nostra13.universalimageloader.utils.IoUtils; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Base disk cache. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see FileNameGenerator - * @since 1.0.0 - */ -public abstract class BaseDiskCache implements DiskCache { - /** {@value */ - public static final int DEFAULT_BUFFER_SIZE = 32 * 1024; // 32 Kb - /** {@value */ - public static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG; - /** {@value */ - public static final int DEFAULT_COMPRESS_QUALITY = 100; - - private static final String ERROR_ARG_NULL = " argument must be not null"; - private static final String TEMP_IMAGE_POSTFIX = ".tmp"; - - protected final File cacheDir; - protected final File reserveCacheDir; - - protected final FileNameGenerator fileNameGenerator; - - protected int bufferSize = DEFAULT_BUFFER_SIZE; - - protected Bitmap.CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT; - protected int compressQuality = DEFAULT_COMPRESS_QUALITY; - - /** @param cacheDir Directory for file caching */ - public BaseDiskCache(File cacheDir) { - this(cacheDir, null); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - */ - public BaseDiskCache(File cacheDir, File reserveCacheDir) { - this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator()); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - * @param fileNameGenerator {@linkplain com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator - * Name generator} for cached files - */ - public BaseDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) { - if (cacheDir == null) { - throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL); - } - if (fileNameGenerator == null) { - throw new IllegalArgumentException("fileNameGenerator" + ERROR_ARG_NULL); - } - - this.cacheDir = cacheDir; - this.reserveCacheDir = reserveCacheDir; - this.fileNameGenerator = fileNameGenerator; - } - - @Override - public File getDirectory() { - return cacheDir; - } - - @Override - public File get(String imageUri) { - return getFile(imageUri); - } - - @Override - public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException { - File imageFile = getFile(imageUri); - File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX); - boolean loaded = false; - try { - OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize); - try { - loaded = IoUtils.copyStream(imageStream, os, listener, bufferSize); - } finally { - IoUtils.closeSilently(os); - } - } finally { - if (loaded && !tmpFile.renameTo(imageFile)) { - loaded = false; - } - if (!loaded) { - tmpFile.delete(); - } - } - return loaded; - } - - @Override - public boolean save(String imageUri, Bitmap bitmap) throws IOException { - File imageFile = getFile(imageUri); - File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX); - OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize); - boolean savedSuccessfully = false; - try { - savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os); - } finally { - IoUtils.closeSilently(os); - if (savedSuccessfully && !tmpFile.renameTo(imageFile)) { - savedSuccessfully = false; - } - if (!savedSuccessfully) { - tmpFile.delete(); - } - } - bitmap.recycle(); - return savedSuccessfully; - } - - @Override - public boolean remove(String imageUri) { - return getFile(imageUri).delete(); - } - - @Override - public void close() { - // Nothing to do - } - - @Override - public void clear() { - File[] files = cacheDir.listFiles(); - if (files != null) { - for (File f : files) { - f.delete(); - } - } - } - - /** Returns file object (not null) for incoming image URI. File object can reference to non-existing file. */ - protected File getFile(String imageUri) { - String fileName = fileNameGenerator.generate(imageUri); - File dir = cacheDir; - if (!cacheDir.exists() && !cacheDir.mkdirs()) { - if (reserveCacheDir != null && (reserveCacheDir.exists() || reserveCacheDir.mkdirs())) { - dir = reserveCacheDir; - } - } - return new File(dir, fileName); - } - - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - public void setCompressFormat(Bitmap.CompressFormat compressFormat) { - this.compressFormat = compressFormat; - } - - public void setCompressQuality(int compressQuality) { - this.compressQuality = compressQuality; - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/LimitedAgeDiskCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/LimitedAgeDiskCache.java deleted file mode 100644 index f367501a2..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/LimitedAgeDiskCache.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.core.DefaultConfigurationFactory; -import com.nostra13.universalimageloader.utils.IoUtils; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Cache which deletes files which were loaded more than defined time. Cache size is unlimited. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.3.1 - */ -public class LimitedAgeDiskCache extends BaseDiskCache { - - private final long maxFileAge; - - private final Map loadingDates = Collections.synchronizedMap(new HashMap()); - - /** - * @param cacheDir Directory for file caching - * @param maxAge Max file age (in seconds). If file age will exceed this value then it'll be removed on next - * treatment (and therefore be reloaded). - */ - public LimitedAgeDiskCache(File cacheDir, long maxAge) { - this(cacheDir, null, DefaultConfigurationFactory.createFileNameGenerator(), maxAge); - } - - /** - * @param cacheDir Directory for file caching - * @param maxAge Max file age (in seconds). If file age will exceed this value then it'll be removed on next - * treatment (and therefore be reloaded). - */ - public LimitedAgeDiskCache(File cacheDir, File reserveCacheDir, long maxAge) { - this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator(), maxAge); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - * @param fileNameGenerator Name generator for cached files - * @param maxAge Max file age (in seconds). If file age will exceed this value then it'll be removed on next - * treatment (and therefore be reloaded). - */ - public LimitedAgeDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator, long maxAge) { - super(cacheDir, reserveCacheDir, fileNameGenerator); - this.maxFileAge = maxAge * 1000; // to milliseconds - } - - @Override - public File get(String imageUri) { - File file = super.get(imageUri); - if (file != null && file.exists()) { - boolean cached; - Long loadingDate = loadingDates.get(file); - if (loadingDate == null) { - cached = false; - loadingDate = file.lastModified(); - } else { - cached = true; - } - - if (System.currentTimeMillis() - loadingDate > maxFileAge) { - file.delete(); - loadingDates.remove(file); - } else if (!cached) { - loadingDates.put(file, loadingDate); - } - } - return file; - } - - @Override - public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException { - boolean saved = super.save(imageUri, imageStream, listener); - rememberUsage(imageUri); - return saved; - } - - @Override - public boolean save(String imageUri, Bitmap bitmap) throws IOException { - boolean saved = super.save(imageUri, bitmap); - rememberUsage(imageUri); - return saved; - } - - @Override - public boolean remove(String imageUri) { - loadingDates.remove(getFile(imageUri)); - return super.remove(imageUri); - } - - @Override - public void clear() { - super.clear(); - loadingDates.clear(); - } - - private void rememberUsage(String imageUri) { - File file = getFile(imageUri); - long currentTime = System.currentTimeMillis(); - file.setLastModified(currentTime); - loadingDates.put(file, currentTime); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/UnlimitedDiskCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/UnlimitedDiskCache.java deleted file mode 100644 index 03fad1e96..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/UnlimitedDiskCache.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.impl; - -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; - -import java.io.File; - -/** - * Default implementation of {@linkplain com.nostra13.universalimageloader.cache.disc.DiskCache disk cache}. - * Cache size is unlimited. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class UnlimitedDiskCache extends BaseDiskCache { - /** @param cacheDir Directory for file caching */ - public UnlimitedDiskCache(File cacheDir) { - super(cacheDir); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - */ - public UnlimitedDiskCache(File cacheDir, File reserveCacheDir) { - super(cacheDir, reserveCacheDir); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - * @param fileNameGenerator {@linkplain com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator - * Name generator} for cached files - */ - public UnlimitedDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) { - super(cacheDir, reserveCacheDir, fileNameGenerator); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/DiskLruCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/DiskLruCache.java deleted file mode 100644 index 6e18f31ff..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/DiskLruCache.java +++ /dev/null @@ -1,974 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nostra13.universalimageloader.cache.disc.impl.ext; - -import java.io.BufferedWriter; -import java.io.Closeable; -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A cache that uses a bounded amount of space on a filesystem. Each cache - * entry has a string key and a fixed number of values. Each key must match - * the regex [a-z0-9_-]{1,64}. Values are byte sequences, - * accessible as streams or files. Each value must be between {@code 0} and - * {@code Integer.MAX_VALUE} bytes in length. - * - *

The cache stores its data in a directory on the filesystem. This - * directory must be exclusive to the cache; the cache may delete or overwrite - * files from its directory. It is an error for multiple processes to use the - * same cache directory at the same time. - * - *

This cache limits the number of bytes that it will store on the - * filesystem. When the number of stored bytes exceeds the limit, the cache will - * remove entries in the background until the limit is satisfied. The limit is - * not strict: the cache may temporarily exceed it while waiting for files to be - * deleted. The limit does not include filesystem overhead or the cache - * journal so space-sensitive applications should set a conservative limit. - * - *

Clients call {@link #edit} to create or update the values of an entry. An - * entry may have only one editor at one time; if a value is not available to be - * edited then {@link #edit} will return null. - *

    - *
  • When an entry is being created it is necessary to - * supply a full set of values; the empty value should be used as a - * placeholder if necessary. - *
  • When an entry is being edited, it is not necessary - * to supply data for every value; values default to their previous - * value. - *
- * Every {@link #edit} call must be matched by a call to {@link Editor#commit} - * or {@link Editor#abort}. Committing is atomic: a read observes the full set - * of values as they were before or after the commit, but never a mix of values. - * - *

Clients call {@link #get} to read a snapshot of an entry. The read will - * observe the value at the time that {@link #get} was called. Updates and - * removals after the call do not impact ongoing reads. - * - *

This class is tolerant of some I/O errors. If files are missing from the - * filesystem, the corresponding entries will be dropped from the cache. If - * an error occurs while writing a cache value, the edit will fail silently. - * Callers should handle other problems by catching {@code IOException} and - * responding appropriately. - */ -final class DiskLruCache implements Closeable { - static final String JOURNAL_FILE = "journal"; - static final String JOURNAL_FILE_TEMP = "journal.tmp"; - static final String JOURNAL_FILE_BACKUP = "journal.bkp"; - static final String MAGIC = "libcore.io.DiskLruCache"; - static final String VERSION_1 = "1"; - static final long ANY_SEQUENCE_NUMBER = -1; - static final Pattern LEGAL_KEY_PATTERN = Pattern.compile("[a-z0-9_-]{1,64}"); - private static final String CLEAN = "CLEAN"; - private static final String DIRTY = "DIRTY"; - private static final String REMOVE = "REMOVE"; - private static final String READ = "READ"; - - /* - * This cache uses a journal file named "journal". A typical journal file - * looks like this: - * libcore.io.DiskLruCache - * 1 - * 100 - * 2 - * - * CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054 - * DIRTY 335c4c6028171cfddfbaae1a9c313c52 - * CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342 - * REMOVE 335c4c6028171cfddfbaae1a9c313c52 - * DIRTY 1ab96a171faeeee38496d8b330771a7a - * CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234 - * READ 335c4c6028171cfddfbaae1a9c313c52 - * READ 3400330d1dfc7f3f7f4b8d4d803dfcf6 - * - * The first five lines of the journal form its header. They are the - * constant string "libcore.io.DiskLruCache", the disk cache's version, - * the application's version, the value count, and a blank line. - * - * Each of the subsequent lines in the file is a record of the state of a - * cache entry. Each line contains space-separated values: a state, a key, - * and optional state-specific values. - * o DIRTY lines track that an entry is actively being created or updated. - * Every successful DIRTY action should be followed by a CLEAN or REMOVE - * action. DIRTY lines without a matching CLEAN or REMOVE indicate that - * temporary files may need to be deleted. - * o CLEAN lines track a cache entry that has been successfully published - * and may be read. A publish line is followed by the lengths of each of - * its values. - * o READ lines track accesses for LRU. - * o REMOVE lines track entries that have been deleted. - * - * The journal file is appended to as cache operations occur. The journal may - * occasionally be compacted by dropping redundant lines. A temporary file named - * "journal.tmp" will be used during compaction; that file should be deleted if - * it exists when the cache is opened. - */ - - private final File directory; - private final File journalFile; - private final File journalFileTmp; - private final File journalFileBackup; - private final int appVersion; - private long maxSize; - private int maxFileCount; - private final int valueCount; - private long size = 0; - private int fileCount = 0; - private Writer journalWriter; - private final LinkedHashMap lruEntries = - new LinkedHashMap(0, 0.75f, true); - private int redundantOpCount; - - /** - * To differentiate between old and current snapshots, each entry is given - * a sequence number each time an edit is committed. A snapshot is stale if - * its sequence number is not equal to its entry's sequence number. - */ - private long nextSequenceNumber = 0; - - /** This cache uses a single background thread to evict entries. */ - final ThreadPoolExecutor executorService = - new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue()); - private final Callable cleanupCallable = new Callable() { - public Void call() throws Exception { - synchronized (DiskLruCache.this) { - if (journalWriter == null) { - return null; // Closed. - } - trimToSize(); - trimToFileCount(); - if (journalRebuildRequired()) { - rebuildJournal(); - redundantOpCount = 0; - } - } - return null; - } - }; - - private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount) { - this.directory = directory; - this.appVersion = appVersion; - this.journalFile = new File(directory, JOURNAL_FILE); - this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP); - this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP); - this.valueCount = valueCount; - this.maxSize = maxSize; - this.maxFileCount = maxFileCount; - } - - /** - * Opens the cache in {@code directory}, creating a cache if none exists - * there. - * - * @param directory a writable directory - * @param valueCount the number of values per cache entry. Must be positive. - * @param maxSize the maximum number of bytes this cache should use to store - * @param maxFileCount the maximum file count this cache should store - * @throws IOException if reading or writing the cache directory fails - */ - public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount) - throws IOException { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - if (maxFileCount <= 0) { - throw new IllegalArgumentException("maxFileCount <= 0"); - } - if (valueCount <= 0) { - throw new IllegalArgumentException("valueCount <= 0"); - } - - // If a bkp file exists, use it instead. - File backupFile = new File(directory, JOURNAL_FILE_BACKUP); - if (backupFile.exists()) { - File journalFile = new File(directory, JOURNAL_FILE); - // If journal file also exists just delete backup file. - if (journalFile.exists()) { - backupFile.delete(); - } else { - renameTo(backupFile, journalFile, false); - } - } - - // Prefer to pick up where we left off. - DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount); - if (cache.journalFile.exists()) { - try { - cache.readJournal(); - cache.processJournal(); - cache.journalWriter = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(cache.journalFile, true), Util.US_ASCII)); - return cache; - } catch (IOException journalIsCorrupt) { - System.out - .println("DiskLruCache " - + directory - + " is corrupt: " - + journalIsCorrupt.getMessage() - + ", removing"); - cache.delete(); - } - } - - // Create a new empty cache. - directory.mkdirs(); - cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount); - cache.rebuildJournal(); - return cache; - } - - private void readJournal() throws IOException { - StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), Util.US_ASCII); - try { - String magic = reader.readLine(); - String version = reader.readLine(); - String appVersionString = reader.readLine(); - String valueCountString = reader.readLine(); - String blank = reader.readLine(); - if (!MAGIC.equals(magic) - || !VERSION_1.equals(version) - || !Integer.toString(appVersion).equals(appVersionString) - || !Integer.toString(valueCount).equals(valueCountString) - || !"".equals(blank)) { - throw new IOException("unexpected journal header: [" + magic + ", " + version + ", " - + valueCountString + ", " + blank + "]"); - } - - int lineCount = 0; - while (true) { - try { - readJournalLine(reader.readLine()); - lineCount++; - } catch (EOFException endOfJournal) { - break; - } - } - redundantOpCount = lineCount - lruEntries.size(); - } finally { - Util.closeQuietly(reader); - } - } - - private void readJournalLine(String line) throws IOException { - int firstSpace = line.indexOf(' '); - if (firstSpace == -1) { - throw new IOException("unexpected journal line: " + line); - } - - int keyBegin = firstSpace + 1; - int secondSpace = line.indexOf(' ', keyBegin); - final String key; - if (secondSpace == -1) { - key = line.substring(keyBegin); - if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) { - lruEntries.remove(key); - return; - } - } else { - key = line.substring(keyBegin, secondSpace); - } - - Entry entry = lruEntries.get(key); - if (entry == null) { - entry = new Entry(key); - lruEntries.put(key, entry); - } - - if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) { - String[] parts = line.substring(secondSpace + 1).split(" "); - entry.readable = true; - entry.currentEditor = null; - entry.setLengths(parts); - } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) { - entry.currentEditor = new Editor(entry); - } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) { - // This work was already done by calling lruEntries.get(). - } else { - throw new IOException("unexpected journal line: " + line); - } - } - - /** - * Computes the initial size and collects garbage as a part of opening the - * cache. Dirty entries are assumed to be inconsistent and will be deleted. - */ - private void processJournal() throws IOException { - deleteIfExists(journalFileTmp); - for (Iterator i = lruEntries.values().iterator(); i.hasNext(); ) { - Entry entry = i.next(); - if (entry.currentEditor == null) { - for (int t = 0; t < valueCount; t++) { - size += entry.lengths[t]; - fileCount++; - } - } else { - entry.currentEditor = null; - for (int t = 0; t < valueCount; t++) { - deleteIfExists(entry.getCleanFile(t)); - deleteIfExists(entry.getDirtyFile(t)); - } - i.remove(); - } - } - } - - /** - * Creates a new journal that omits redundant information. This replaces the - * current journal if it exists. - */ - private synchronized void rebuildJournal() throws IOException { - if (journalWriter != null) { - journalWriter.close(); - } - - Writer writer = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII)); - try { - writer.write(MAGIC); - writer.write("\n"); - writer.write(VERSION_1); - writer.write("\n"); - writer.write(Integer.toString(appVersion)); - writer.write("\n"); - writer.write(Integer.toString(valueCount)); - writer.write("\n"); - writer.write("\n"); - - for (Entry entry : lruEntries.values()) { - if (entry.currentEditor != null) { - writer.write(DIRTY + ' ' + entry.key + '\n'); - } else { - writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); - } - } - } finally { - writer.close(); - } - - if (journalFile.exists()) { - renameTo(journalFile, journalFileBackup, true); - } - renameTo(journalFileTmp, journalFile, false); - journalFileBackup.delete(); - - journalWriter = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII)); - } - - private static void deleteIfExists(File file) throws IOException { - if (file.exists() && !file.delete()) { - throw new IOException(); - } - } - - private static void renameTo(File from, File to, boolean deleteDestination) throws IOException { - if (deleteDestination) { - deleteIfExists(to); - } - if (!from.renameTo(to)) { - throw new IOException(); - } - } - - /** - * Returns a snapshot of the entry named {@code key}, or null if it doesn't - * exist is not currently readable. If a value is returned, it is moved to - * the head of the LRU queue. - */ - public synchronized Snapshot get(String key) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (entry == null) { - return null; - } - - if (!entry.readable) { - return null; - } - - // Open all streams eagerly to guarantee that we see a single published - // snapshot. If we opened streams lazily then the streams could come - // from different edits. - File[] files = new File[valueCount]; - InputStream[] ins = new InputStream[valueCount]; - try { - File file; - for (int i = 0; i < valueCount; i++) { - file = entry.getCleanFile(i); - files[i] = file; - ins[i] = new FileInputStream(file); - } - } catch (FileNotFoundException e) { - // A file must have been deleted manually! - for (int i = 0; i < valueCount; i++) { - if (ins[i] != null) { - Util.closeQuietly(ins[i]); - } else { - break; - } - } - return null; - } - - redundantOpCount++; - journalWriter.append(READ + ' ' + key + '\n'); - if (journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - - return new Snapshot(key, entry.sequenceNumber, files, ins, entry.lengths); - } - - /** - * Returns an editor for the entry named {@code key}, or null if another - * edit is in progress. - */ - public Editor edit(String key) throws IOException { - return edit(key, ANY_SEQUENCE_NUMBER); - } - - private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER && (entry == null - || entry.sequenceNumber != expectedSequenceNumber)) { - return null; // Snapshot is stale. - } - if (entry == null) { - entry = new Entry(key); - lruEntries.put(key, entry); - } else if (entry.currentEditor != null) { - return null; // Another edit is in progress. - } - - Editor editor = new Editor(entry); - entry.currentEditor = editor; - - // Flush the journal before creating files to prevent file leaks. - journalWriter.write(DIRTY + ' ' + key + '\n'); - journalWriter.flush(); - return editor; - } - - /** Returns the directory where this cache stores its data. */ - public File getDirectory() { - return directory; - } - - /** - * Returns the maximum number of bytes that this cache should use to store - * its data. - */ - public synchronized long getMaxSize() { - return maxSize; - } - - /** Returns the maximum number of files that this cache should store */ - public synchronized int getMaxFileCount() { - return maxFileCount; - } - - /** - * Changes the maximum number of bytes the cache can store and queues a job - * to trim the existing store, if necessary. - */ - public synchronized void setMaxSize(long maxSize) { - this.maxSize = maxSize; - executorService.submit(cleanupCallable); - } - - /** - * Returns the number of bytes currently being used to store the values in - * this cache. This may be greater than the max size if a background - * deletion is pending. - */ - public synchronized long size() { - return size; - } - - /** - * Returns the number of files currently being used to store the values in - * this cache. This may be greater than the max file count if a background - * deletion is pending. - */ - public synchronized long fileCount() { - return fileCount; - } - - private synchronized void completeEdit(Editor editor, boolean success) throws IOException { - Entry entry = editor.entry; - if (entry.currentEditor != editor) { - throw new IllegalStateException(); - } - - // If this edit is creating the entry for the first time, every index must have a value. - if (success && !entry.readable) { - for (int i = 0; i < valueCount; i++) { - if (!editor.written[i]) { - editor.abort(); - throw new IllegalStateException("Newly created entry didn't create value for index " + i); - } - if (!entry.getDirtyFile(i).exists()) { - editor.abort(); - return; - } - } - } - - for (int i = 0; i < valueCount; i++) { - File dirty = entry.getDirtyFile(i); - if (success) { - if (dirty.exists()) { - File clean = entry.getCleanFile(i); - dirty.renameTo(clean); - long oldLength = entry.lengths[i]; - long newLength = clean.length(); - entry.lengths[i] = newLength; - size = size - oldLength + newLength; - fileCount++; - } - } else { - deleteIfExists(dirty); - } - } - - redundantOpCount++; - entry.currentEditor = null; - if (entry.readable | success) { - entry.readable = true; - journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); - if (success) { - entry.sequenceNumber = nextSequenceNumber++; - } - } else { - lruEntries.remove(entry.key); - journalWriter.write(REMOVE + ' ' + entry.key + '\n'); - } - journalWriter.flush(); - - if (size > maxSize || fileCount > maxFileCount || journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - } - - /** - * We only rebuild the journal when it will halve the size of the journal - * and eliminate at least 2000 ops. - */ - private boolean journalRebuildRequired() { - final int redundantOpCompactThreshold = 2000; - return redundantOpCount >= redundantOpCompactThreshold // - && redundantOpCount >= lruEntries.size(); - } - - /** - * Drops the entry for {@code key} if it exists and can be removed. Entries - * actively being edited cannot be removed. - * - * @return true if an entry was removed. - */ - public synchronized boolean remove(String key) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (entry == null || entry.currentEditor != null) { - return false; - } - - for (int i = 0; i < valueCount; i++) { - File file = entry.getCleanFile(i); - if (file.exists() && !file.delete()) { - throw new IOException("failed to delete " + file); - } - size -= entry.lengths[i]; - fileCount--; - entry.lengths[i] = 0; - } - - redundantOpCount++; - journalWriter.append(REMOVE + ' ' + key + '\n'); - lruEntries.remove(key); - - if (journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - - return true; - } - - /** Returns true if this cache has been closed. */ - public synchronized boolean isClosed() { - return journalWriter == null; - } - - private void checkNotClosed() { - if (journalWriter == null) { - throw new IllegalStateException("cache is closed"); - } - } - - /** Force buffered operations to the filesystem. */ - public synchronized void flush() throws IOException { - checkNotClosed(); - trimToSize(); - trimToFileCount(); - journalWriter.flush(); - } - - /** Closes this cache. Stored values will remain on the filesystem. */ - public synchronized void close() throws IOException { - if (journalWriter == null) { - return; // Already closed. - } - for (Entry entry : new ArrayList(lruEntries.values())) { - if (entry.currentEditor != null) { - entry.currentEditor.abort(); - } - } - trimToSize(); - trimToFileCount(); - journalWriter.close(); - journalWriter = null; - } - - private void trimToSize() throws IOException { - while (size > maxSize) { - Map.Entry toEvict = lruEntries.entrySet().iterator().next(); - remove(toEvict.getKey()); - } - } - - private void trimToFileCount() throws IOException { - while (fileCount > maxFileCount) { - Map.Entry toEvict = lruEntries.entrySet().iterator().next(); - remove(toEvict.getKey()); - } - } - - /** - * Closes the cache and deletes all of its stored values. This will delete - * all files in the cache directory including files that weren't created by - * the cache. - */ - public void delete() throws IOException { - close(); - Util.deleteContents(directory); - } - - private void validateKey(String key) { - Matcher matcher = LEGAL_KEY_PATTERN.matcher(key); - if (!matcher.matches()) { - throw new IllegalArgumentException("keys must match regex [a-z0-9_-]{1,64}: \"" + key + "\""); - } - } - - private static String inputStreamToString(InputStream in) throws IOException { - return Util.readFully(new InputStreamReader(in, Util.UTF_8)); - } - - /** A snapshot of the values for an entry. */ - public final class Snapshot implements Closeable { - private final String key; - private final long sequenceNumber; - private File[] files; - private final InputStream[] ins; - private final long[] lengths; - - private Snapshot(String key, long sequenceNumber, File[] files, InputStream[] ins, long[] lengths) { - this.key = key; - this.sequenceNumber = sequenceNumber; - this.files = files; - this.ins = ins; - this.lengths = lengths; - } - - /** - * Returns an editor for this snapshot's entry, or null if either the - * entry has changed since this snapshot was created or if another edit - * is in progress. - */ - public Editor edit() throws IOException { - return DiskLruCache.this.edit(key, sequenceNumber); - } - - /** Returns file with the value for {@code index}. */ - public File getFile(int index) { - return files[index]; - } - - /** Returns the unbuffered stream with the value for {@code index}. */ - public InputStream getInputStream(int index) { - return ins[index]; - } - - /** Returns the string value for {@code index}. */ - public String getString(int index) throws IOException { - return inputStreamToString(getInputStream(index)); - } - - /** Returns the byte length of the value for {@code index}. */ - public long getLength(int index) { - return lengths[index]; - } - - public void close() { - for (InputStream in : ins) { - Util.closeQuietly(in); - } - } - } - - private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() { - @Override - public void write(int b) throws IOException { - // Eat all writes silently. Nom nom. - } - }; - - /** Edits the values for an entry. */ - public final class Editor { - private final Entry entry; - private final boolean[] written; - private boolean hasErrors; - private boolean committed; - - private Editor(Entry entry) { - this.entry = entry; - this.written = (entry.readable) ? null : new boolean[valueCount]; - } - - /** - * Returns an unbuffered input stream to read the last committed value, - * or null if no value has been committed. - */ - public InputStream newInputStream(int index) throws IOException { - synchronized (DiskLruCache.this) { - if (entry.currentEditor != this) { - throw new IllegalStateException(); - } - if (!entry.readable) { - return null; - } - try { - return new FileInputStream(entry.getCleanFile(index)); - } catch (FileNotFoundException e) { - return null; - } - } - } - - /** - * Returns the last committed value as a string, or null if no value - * has been committed. - */ - public String getString(int index) throws IOException { - InputStream in = newInputStream(index); - return in != null ? inputStreamToString(in) : null; - } - - /** - * Returns a new unbuffered output stream to write the value at - * {@code index}. If the underlying output stream encounters errors - * when writing to the filesystem, this edit will be aborted when - * {@link #commit} is called. The returned output stream does not throw - * IOExceptions. - */ - public OutputStream newOutputStream(int index) throws IOException { - synchronized (DiskLruCache.this) { - if (entry.currentEditor != this) { - throw new IllegalStateException(); - } - if (!entry.readable) { - written[index] = true; - } - File dirtyFile = entry.getDirtyFile(index); - FileOutputStream outputStream; - try { - outputStream = new FileOutputStream(dirtyFile); - } catch (FileNotFoundException e) { - // Attempt to recreate the cache directory. - directory.mkdirs(); - try { - outputStream = new FileOutputStream(dirtyFile); - } catch (FileNotFoundException e2) { - // We are unable to recover. Silently eat the writes. - return NULL_OUTPUT_STREAM; - } - } - return new FaultHidingOutputStream(outputStream); - } - } - - /** Sets the value at {@code index} to {@code value}. */ - public void set(int index, String value) throws IOException { - Writer writer = null; - try { - writer = new OutputStreamWriter(newOutputStream(index), Util.UTF_8); - writer.write(value); - } finally { - Util.closeQuietly(writer); - } - } - - /** - * Commits this edit so it is visible to readers. This releases the - * edit lock so another edit may be started on the same key. - */ - public void commit() throws IOException { - if (hasErrors) { - completeEdit(this, false); - remove(entry.key); // The previous entry is stale. - } else { - completeEdit(this, true); - } - committed = true; - } - - /** - * Aborts this edit. This releases the edit lock so another edit may be - * started on the same key. - */ - public void abort() throws IOException { - completeEdit(this, false); - } - - public void abortUnlessCommitted() { - if (!committed) { - try { - abort(); - } catch (IOException ignored) { - } - } - } - - private class FaultHidingOutputStream extends FilterOutputStream { - private FaultHidingOutputStream(OutputStream out) { - super(out); - } - - @Override public void write(int oneByte) { - try { - out.write(oneByte); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void write(byte[] buffer, int offset, int length) { - try { - out.write(buffer, offset, length); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void close() { - try { - out.close(); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void flush() { - try { - out.flush(); - } catch (IOException e) { - hasErrors = true; - } - } - } - } - - private final class Entry { - private final String key; - - /** Lengths of this entry's files. */ - private final long[] lengths; - - /** True if this entry has ever been published. */ - private boolean readable; - - /** The ongoing edit or null if this entry is not being edited. */ - private Editor currentEditor; - - /** The sequence number of the most recently committed edit to this entry. */ - private long sequenceNumber; - - private Entry(String key) { - this.key = key; - this.lengths = new long[valueCount]; - } - - public String getLengths() throws IOException { - StringBuilder result = new StringBuilder(); - for (long size : lengths) { - result.append(' ').append(size); - } - return result.toString(); - } - - /** Set lengths using decimal numbers like "10123". */ - private void setLengths(String[] strings) throws IOException { - if (strings.length != valueCount) { - throw invalidLengths(strings); - } - - try { - for (int i = 0; i < strings.length; i++) { - lengths[i] = Long.parseLong(strings[i]); - } - } catch (NumberFormatException e) { - throw invalidLengths(strings); - } - } - - private IOException invalidLengths(String[] strings) throws IOException { - throw new IOException("unexpected journal line: " + java.util.Arrays.toString(strings)); - } - - public File getCleanFile(int i) { - return new File(directory, key + "." + i); - } - - public File getDirtyFile(int i) { - return new File(directory, key + "." + i + ".tmp"); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/LruDiskCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/LruDiskCache.java deleted file mode 100644 index aa0d91ec0..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/LruDiskCache.java +++ /dev/null @@ -1,238 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.impl.ext; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.disc.DiskCache; -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.utils.IoUtils; -import com.nostra13.universalimageloader.utils.L; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Disk cache based on "Least-Recently Used" principle. Adapter pattern, adapts - * {@link com.nostra13.universalimageloader.cache.disc.impl.ext.DiskLruCache DiskLruCache} to - * {@link com.nostra13.universalimageloader.cache.disc.DiskCache DiskCache} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see FileNameGenerator - * @since 1.9.2 - */ -public class LruDiskCache implements DiskCache { - /** {@value */ - public static final int DEFAULT_BUFFER_SIZE = 32 * 1024; // 32 Kb - /** {@value */ - public static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG; - /** {@value */ - public static final int DEFAULT_COMPRESS_QUALITY = 100; - - private static final String ERROR_ARG_NULL = " argument must be not null"; - private static final String ERROR_ARG_NEGATIVE = " argument must be positive number"; - - protected DiskLruCache cache; - private File reserveCacheDir; - - protected final FileNameGenerator fileNameGenerator; - - protected int bufferSize = DEFAULT_BUFFER_SIZE; - - protected Bitmap.CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT; - protected int compressQuality = DEFAULT_COMPRESS_QUALITY; - - /** - * @param cacheDir Directory for file caching - * @param fileNameGenerator {@linkplain com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator - * Name generator} for cached files. Generated names must match the regex - * [a-z0-9_-]{1,64} - * @param cacheMaxSize Max cache size in bytes. 0 means cache size is unlimited. - * @throws IOException if cache can't be initialized (e.g. "No space left on device") - */ - public LruDiskCache(File cacheDir, FileNameGenerator fileNameGenerator, long cacheMaxSize) throws IOException { - this(cacheDir, null, fileNameGenerator, cacheMaxSize, 0); - } - - /** - * @param cacheDir Directory for file caching - * @param reserveCacheDir null-ok; Reserve directory for file caching. It's used when the primary directory isn't available. - * @param fileNameGenerator {@linkplain com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator - * Name generator} for cached files. Generated names must match the regex - * [a-z0-9_-]{1,64} - * @param cacheMaxSize Max cache size in bytes. 0 means cache size is unlimited. - * @param cacheMaxFileCount Max file count in cache. 0 means file count is unlimited. - * @throws IOException if cache can't be initialized (e.g. "No space left on device") - */ - public LruDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator, long cacheMaxSize, - int cacheMaxFileCount) throws IOException { - if (cacheDir == null) { - throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL); - } - if (cacheMaxSize < 0) { - throw new IllegalArgumentException("cacheMaxSize" + ERROR_ARG_NEGATIVE); - } - if (cacheMaxFileCount < 0) { - throw new IllegalArgumentException("cacheMaxFileCount" + ERROR_ARG_NEGATIVE); - } - if (fileNameGenerator == null) { - throw new IllegalArgumentException("fileNameGenerator" + ERROR_ARG_NULL); - } - - if (cacheMaxSize == 0) { - cacheMaxSize = Long.MAX_VALUE; - } - if (cacheMaxFileCount == 0) { - cacheMaxFileCount = Integer.MAX_VALUE; - } - - this.reserveCacheDir = reserveCacheDir; - this.fileNameGenerator = fileNameGenerator; - initCache(cacheDir, reserveCacheDir, cacheMaxSize, cacheMaxFileCount); - } - - private void initCache(File cacheDir, File reserveCacheDir, long cacheMaxSize, int cacheMaxFileCount) - throws IOException { - try { - cache = DiskLruCache.open(cacheDir, 1, 1, cacheMaxSize, cacheMaxFileCount); - } catch (IOException e) { - L.e(e); - if (reserveCacheDir != null) { - initCache(reserveCacheDir, null, cacheMaxSize, cacheMaxFileCount); - } - if (cache == null) { - throw e; //new RuntimeException("Can't initialize disk cache", e); - } - } - } - - @Override - public File getDirectory() { - return cache.getDirectory(); - } - - @Override - public File get(String imageUri) { - DiskLruCache.Snapshot snapshot = null; - try { - snapshot = cache.get(getKey(imageUri)); - return snapshot == null ? null : snapshot.getFile(0); - } catch (IOException e) { - L.e(e); - return null; - } finally { - if (snapshot != null) { - snapshot.close(); - } - } - } - - @Override - public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException { - DiskLruCache.Editor editor = cache.edit(getKey(imageUri)); - if (editor == null) { - return false; - } - - OutputStream os = new BufferedOutputStream(editor.newOutputStream(0), bufferSize); - boolean copied = false; - try { - copied = IoUtils.copyStream(imageStream, os, listener, bufferSize); - } finally { - IoUtils.closeSilently(os); - if (copied) { - editor.commit(); - } else { - editor.abort(); - } - } - return copied; - } - - @Override - public boolean save(String imageUri, Bitmap bitmap) throws IOException { - DiskLruCache.Editor editor = cache.edit(getKey(imageUri)); - if (editor == null) { - return false; - } - - OutputStream os = new BufferedOutputStream(editor.newOutputStream(0), bufferSize); - boolean savedSuccessfully = false; - try { - savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os); - } finally { - IoUtils.closeSilently(os); - } - if (savedSuccessfully) { - editor.commit(); - } else { - editor.abort(); - } - return savedSuccessfully; - } - - @Override - public boolean remove(String imageUri) { - try { - return cache.remove(getKey(imageUri)); - } catch (IOException e) { - L.e(e); - return false; - } - } - - @Override - public void close() { - try { - cache.close(); - } catch (IOException e) { - L.e(e); - } - cache = null; - } - - @Override - public void clear() { - try { - cache.delete(); - } catch (IOException e) { - L.e(e); - } - try { - initCache(cache.getDirectory(), reserveCacheDir, cache.getMaxSize(), cache.getMaxFileCount()); - } catch (IOException e) { - L.e(e); - } - } - - private String getKey(String imageUri) { - return fileNameGenerator.generate(imageUri); - } - - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - public void setCompressFormat(Bitmap.CompressFormat compressFormat) { - this.compressFormat = compressFormat; - } - - public void setCompressQuality(int compressQuality) { - this.compressQuality = compressQuality; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/StrictLineReader.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/StrictLineReader.java deleted file mode 100644 index 0f3e0f56e..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/StrictLineReader.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nostra13.universalimageloader.cache.disc.impl.ext; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - -/** - * Buffers input from an {@link InputStream} for reading lines. - * - *

This class is used for buffered reading of lines. For purposes of this class, a line ends - * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated - * line at end of input is invalid and will be ignored, the caller may use {@code - * hasUnterminatedLine()} to detect it after catching the {@code EOFException}. - * - *

This class is intended for reading input that strictly consists of lines, such as line-based - * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction - * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different - * end-of-input reporting and a more restrictive definition of a line. - * - *

This class supports only charsets that encode '\r' and '\n' as a single byte with value 13 - * and 10, respectively, and the representation of no other character contains these values. - * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1. - * The default charset is US_ASCII. - */ -class StrictLineReader implements Closeable { - private static final byte CR = (byte) '\r'; - private static final byte LF = (byte) '\n'; - - private final InputStream in; - private final Charset charset; - - /* - * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end - * and the data in the range [pos, end) is buffered for reading. At end of input, if there is - * an unterminated line, we set end == -1, otherwise end == pos. If the underlying - * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1. - */ - private byte[] buf; - private int pos; - private int end; - - /** - * Constructs a new {@code LineReader} with the specified charset and the default capacity. - * - * @param in the {@code InputStream} to read data from. - * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are - * supported. - * @throws NullPointerException if {@code in} or {@code charset} is null. - * @throws IllegalArgumentException if the specified charset is not supported. - */ - public StrictLineReader(InputStream in, Charset charset) { - this(in, 8192, charset); - } - - /** - * Constructs a new {@code LineReader} with the specified capacity and charset. - * - * @param in the {@code InputStream} to read data from. - * @param capacity the capacity of the buffer. - * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are - * supported. - * @throws NullPointerException if {@code in} or {@code charset} is null. - * @throws IllegalArgumentException if {@code capacity} is negative or zero - * or the specified charset is not supported. - */ - public StrictLineReader(InputStream in, int capacity, Charset charset) { - if (in == null || charset == null) { - throw new NullPointerException(); - } - if (capacity < 0) { - throw new IllegalArgumentException("capacity <= 0"); - } - if (!(charset.equals(Util.US_ASCII))) { - throw new IllegalArgumentException("Unsupported encoding"); - } - - this.in = in; - this.charset = charset; - buf = new byte[capacity]; - } - - /** - * Closes the reader by closing the underlying {@code InputStream} and - * marking this reader as closed. - * - * @throws IOException for errors when closing the underlying {@code InputStream}. - */ - public void close() throws IOException { - synchronized (in) { - if (buf != null) { - buf = null; - in.close(); - } - } - } - - /** - * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"}, - * this end of line marker is not included in the result. - * - * @return the next line from the input. - * @throws IOException for underlying {@code InputStream} errors. - * @throws EOFException for the end of source stream. - */ - public String readLine() throws IOException { - synchronized (in) { - if (buf == null) { - throw new IOException("LineReader is closed"); - } - - // Read more data if we are at the end of the buffered data. - // Though it's an error to read after an exception, we will let {@code fillBuf()} - // throw again if that happens; thus we need to handle end == -1 as well as end == pos. - if (pos >= end) { - fillBuf(); - } - // Try to find LF in the buffered data and return the line if successful. - for (int i = pos; i != end; ++i) { - if (buf[i] == LF) { - int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i; - String res = new String(buf, pos, lineEnd - pos, charset.name()); - pos = i + 1; - return res; - } - } - - // Let's anticipate up to 80 characters on top of those already read. - ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) { - @Override - public String toString() { - int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count; - try { - return new String(buf, 0, length, charset.name()); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); // Since we control the charset this will never happen. - } - } - }; - - while (true) { - out.write(buf, pos, end - pos); - // Mark unterminated line in case fillBuf throws EOFException or IOException. - end = -1; - fillBuf(); - // Try to find LF in the buffered data and return the line if successful. - for (int i = pos; i != end; ++i) { - if (buf[i] == LF) { - if (i != pos) { - out.write(buf, pos, i - pos); - } - pos = i + 1; - return out.toString(); - } - } - } - } - } - - /** - * Reads new input data into the buffer. Call only with pos == end or end == -1, - * depending on the desired outcome if the function throws. - */ - private void fillBuf() throws IOException { - int result = in.read(buf, 0, buf.length); - if (result == -1) { - throw new EOFException(); - } - pos = 0; - end = result; - } -} - diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/Util.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/Util.java deleted file mode 100644 index fd7a4ba17..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/impl/ext/Util.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nostra13.universalimageloader.cache.disc.impl.ext; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.io.StringWriter; -import java.nio.charset.Charset; - -/** Junk drawer of utility methods. */ -final class Util { - static final Charset US_ASCII = Charset.forName("US-ASCII"); - static final Charset UTF_8 = Charset.forName("UTF-8"); - - private Util() { - } - - static String readFully(Reader reader) throws IOException { - try { - StringWriter writer = new StringWriter(); - char[] buffer = new char[1024]; - int count; - while ((count = reader.read(buffer)) != -1) { - writer.write(buffer, 0, count); - } - return writer.toString(); - } finally { - reader.close(); - } - } - - /** - * Deletes the contents of {@code dir}. Throws an IOException if any file - * could not be deleted, or if {@code dir} is not a readable directory. - */ - static void deleteContents(File dir) throws IOException { - File[] files = dir.listFiles(); - if (files == null) { - throw new IOException("not a readable directory: " + dir); - } - for (File file : files) { - if (file.isDirectory()) { - deleteContents(file); - } - if (!file.delete()) { - throw new IOException("failed to delete file: " + file); - } - } - } - - static void closeQuietly(/*Auto*/Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (RuntimeException rethrown) { - throw rethrown; - } catch (Exception ignored) { - } - } - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/FileNameGenerator.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/FileNameGenerator.java deleted file mode 100644 index 20e1d664b..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/FileNameGenerator.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.naming; - -/** - * Generates names for files at disk cache - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.3.1 - */ -public interface FileNameGenerator { - - /** Generates unique file name for image defined by URI */ - String generate(String imageUri); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/HashCodeFileNameGenerator.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/HashCodeFileNameGenerator.java deleted file mode 100644 index a284b53b0..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/HashCodeFileNameGenerator.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.naming; - -/** - * Names image file as image URI {@linkplain String#hashCode() hashcode} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.3.1 - */ -public class HashCodeFileNameGenerator implements FileNameGenerator { - @Override - public String generate(String imageUri) { - return String.valueOf(imageUri.hashCode()); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/Md5FileNameGenerator.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/Md5FileNameGenerator.java deleted file mode 100644 index 9d50bc6cd..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/disc/naming/Md5FileNameGenerator.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.disc.naming; - -import com.nostra13.universalimageloader.utils.L; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * Names image file as MD5 hash of image URI - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.4.0 - */ -public class Md5FileNameGenerator implements FileNameGenerator { - - private static final String HASH_ALGORITHM = "MD5"; - private static final int RADIX = 10 + 26; // 10 digits + 26 letters - - @Override - public String generate(String imageUri) { - byte[] md5 = getMD5(imageUri.getBytes()); - BigInteger bi = new BigInteger(md5).abs(); - return bi.toString(RADIX); - } - - private byte[] getMD5(byte[] data) { - byte[] hash = null; - try { - MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); - digest.update(data); - hash = digest.digest(); - } catch (NoSuchAlgorithmException e) { - L.e(e); - } - return hash; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/BaseMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/BaseMemoryCache.java deleted file mode 100644 index 4043719b5..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/BaseMemoryCache.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory; - -import android.graphics.Bitmap; - -import java.lang.ref.Reference; -import java.util.*; - -/** - * Base memory cache. Implements common functionality for memory cache. Provides object references ( - * {@linkplain Reference not strong}) storing. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public abstract class BaseMemoryCache implements MemoryCache { - - /** Stores not strong references to objects */ - private final Map> softMap = Collections.synchronizedMap(new HashMap>()); - - @Override - public Bitmap get(String key) { - Bitmap result = null; - Reference reference = softMap.get(key); - if (reference != null) { - result = reference.get(); - } - return result; - } - - @Override - public boolean put(String key, Bitmap value) { - softMap.put(key, createReference(value)); - return true; - } - - @Override - public Bitmap remove(String key) { - Reference bmpRef = softMap.remove(key); - return bmpRef == null ? null : bmpRef.get(); - } - - @Override - public Collection keys() { - synchronized (softMap) { - return new HashSet(softMap.keySet()); - } - } - - @Override - public void clear() { - softMap.clear(); - } - - /** Creates {@linkplain Reference not strong} reference of value */ - protected abstract Reference createReference(Bitmap value); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/LimitedMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/LimitedMemoryCache.java deleted file mode 100644 index d1782aaa6..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/LimitedMemoryCache.java +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory; - -import android.graphics.Bitmap; - -import com.nostra13.universalimageloader.utils.L; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Limited cache. Provides object storing. Size of all stored bitmaps will not to exceed size limit ( - * {@link #getSizeLimit()}).
- *
- * NOTE: This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of - * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see BaseMemoryCache - * @since 1.0.0 - */ -public abstract class LimitedMemoryCache extends BaseMemoryCache { - - private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16; - private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024; - - private final int sizeLimit; - - private final AtomicInteger cacheSize; - - /** - * Contains strong references to stored objects. Each next object is added last. If hard cache size will exceed - * limit then first object is deleted (but it continue exist at {@link #softMap} and can be collected by GC at any - * time) - */ - private final List hardCache = Collections.synchronizedList(new LinkedList()); - - /** @param sizeLimit Maximum size for cache (in bytes) */ - public LimitedMemoryCache(int sizeLimit) { - this.sizeLimit = sizeLimit; - cacheSize = new AtomicInteger(); - if (sizeLimit > MAX_NORMAL_CACHE_SIZE) { - L.w("You set too large memory cache size (more than %1$d Mb)", MAX_NORMAL_CACHE_SIZE_IN_MB); - } - } - - @Override - public boolean put(String key, Bitmap value) { - boolean putSuccessfully = false; - // Try to add value to hard cache - int valueSize = getSize(value); - int sizeLimit = getSizeLimit(); - int curCacheSize = cacheSize.get(); - if (valueSize < sizeLimit) { - while (curCacheSize + valueSize > sizeLimit) { - Bitmap removedValue = removeNext(); - if (hardCache.remove(removedValue)) { - curCacheSize = cacheSize.addAndGet(-getSize(removedValue)); - } - } - hardCache.add(value); - cacheSize.addAndGet(valueSize); - - putSuccessfully = true; - } - // Add value to soft cache - super.put(key, value); - return putSuccessfully; - } - - @Override - public Bitmap remove(String key) { - Bitmap value = super.get(key); - if (value != null) { - if (hardCache.remove(value)) { - cacheSize.addAndGet(-getSize(value)); - } - } - return super.remove(key); - } - - @Override - public void clear() { - hardCache.clear(); - cacheSize.set(0); - super.clear(); - } - - protected int getSizeLimit() { - return sizeLimit; - } - - protected abstract int getSize(Bitmap value); - - protected abstract Bitmap removeNext(); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/MemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/MemoryCache.java deleted file mode 100644 index 6a6dd582e..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/MemoryCache.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory; - -import android.graphics.Bitmap; - -import java.util.Collection; - -/** - * Interface for memory cache - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.2 - */ -public interface MemoryCache { - /** - * Puts value into cache by key - * - * @return true - if value was put into cache successfully, false - if value was not put into - * cache - */ - boolean put(String key, Bitmap value); - - /** Returns value by key. If there is no value for key then null will be returned. */ - Bitmap get(String key); - - /** Removes item by key */ - Bitmap remove(String key); - - /** Returns all keys of cache */ - Collection keys(); - - /** Remove all items from cache */ - void clear(); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FIFOLimitedMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FIFOLimitedMemoryCache.java deleted file mode 100644 index e56b1a394..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FIFOLimitedMemoryCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to - * exceed size limit. When cache reaches limit size then cache clearing is processed by FIFO principle.
- *
- * NOTE: This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of - * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class FIFOLimitedMemoryCache extends LimitedMemoryCache { - - private final List queue = Collections.synchronizedList(new LinkedList()); - - public FIFOLimitedMemoryCache(int sizeLimit) { - super(sizeLimit); - } - - @Override - public boolean put(String key, Bitmap value) { - if (super.put(key, value)) { - queue.add(value); - return true; - } else { - return false; - } - } - - @Override - public Bitmap remove(String key) { - Bitmap value = super.get(key); - if (value != null) { - queue.remove(value); - } - return super.remove(key); - } - - @Override - public void clear() { - queue.clear(); - super.clear(); - } - - @Override - protected int getSize(Bitmap value) { - return value.getRowBytes() * value.getHeight(); - } - - @Override - protected Bitmap removeNext() { - return queue.remove(0); - } - - @Override - protected Reference createReference(Bitmap value) { - return new WeakReference(value); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FuzzyKeyMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FuzzyKeyMemoryCache.java deleted file mode 100644 index 982c8128a..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/FuzzyKeyMemoryCache.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; - -import com.nostra13.universalimageloader.cache.memory.MemoryCache; - -import java.util.Collection; -import java.util.Comparator; - -/** - * Decorator for {@link MemoryCache}. Provides special feature for cache: some different keys are considered as - * equals (using {@link Comparator comparator}). And when you try to put some value into cache by key so entries with - * "equals" keys will be removed from cache before.
- * NOTE: Used for internal needs. Normally you don't need to use this class. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class FuzzyKeyMemoryCache implements MemoryCache { - - private final MemoryCache cache; - private final Comparator keyComparator; - - public FuzzyKeyMemoryCache(MemoryCache cache, Comparator keyComparator) { - this.cache = cache; - this.keyComparator = keyComparator; - } - - @Override - public boolean put(String key, Bitmap value) { - // Search equal key and remove this entry - synchronized (cache) { - String keyToRemove = null; - for (String cacheKey : cache.keys()) { - if (keyComparator.compare(key, cacheKey) == 0) { - keyToRemove = cacheKey; - break; - } - } - if (keyToRemove != null) { - cache.remove(keyToRemove); - } - } - return cache.put(key, value); - } - - @Override - public Bitmap get(String key) { - return cache.get(key); - } - - @Override - public Bitmap remove(String key) { - return cache.remove(key); - } - - @Override - public void clear() { - cache.clear(); - } - - @Override - public Collection keys() { - return cache.keys(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LRULimitedMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LRULimitedMemoryCache.java deleted file mode 100644 index 2d25cde2f..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LRULimitedMemoryCache.java +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to - * exceed size limit. When cache reaches limit size then the least recently used bitmap is deleted from cache.
- *
- * NOTE: This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of - * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.3.0 - */ -public class LRULimitedMemoryCache extends LimitedMemoryCache { - - private static final int INITIAL_CAPACITY = 10; - private static final float LOAD_FACTOR = 1.1f; - - /** Cache providing Least-Recently-Used logic */ - private final Map lruCache = Collections.synchronizedMap(new LinkedHashMap(INITIAL_CAPACITY, LOAD_FACTOR, true)); - - /** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */ - public LRULimitedMemoryCache(int maxSize) { - super(maxSize); - } - - @Override - public boolean put(String key, Bitmap value) { - if (super.put(key, value)) { - lruCache.put(key, value); - return true; - } else { - return false; - } - } - - @Override - public Bitmap get(String key) { - lruCache.get(key); // call "get" for LRU logic - return super.get(key); - } - - @Override - public Bitmap remove(String key) { - lruCache.remove(key); - return super.remove(key); - } - - @Override - public void clear() { - lruCache.clear(); - super.clear(); - } - - @Override - protected int getSize(Bitmap value) { - return value.getRowBytes() * value.getHeight(); - } - - @Override - protected Bitmap removeNext() { - Bitmap mostLongUsedValue = null; - synchronized (lruCache) { - Iterator> it = lruCache.entrySet().iterator(); - if (it.hasNext()) { - Entry entry = it.next(); - mostLongUsedValue = entry.getValue(); - it.remove(); - } - } - return mostLongUsedValue; - } - - @Override - protected Reference createReference(Bitmap value) { - return new WeakReference(value); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LargestLimitedMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LargestLimitedMemoryCache.java deleted file mode 100644 index d7a8d19e2..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LargestLimitedMemoryCache.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to - * exceed size limit. When cache reaches limit size then the bitmap which has the largest size is deleted from - * cache.
- *
- * NOTE: This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of - * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class LargestLimitedMemoryCache extends LimitedMemoryCache { - /** - * Contains strong references to stored objects (keys) and sizes of the objects. If hard cache - * size will exceed limit then object with the largest size is deleted (but it continue exist at - * {@link #softMap} and can be collected by GC at any time) - */ - private final Map valueSizes = Collections.synchronizedMap(new HashMap()); - - public LargestLimitedMemoryCache(int sizeLimit) { - super(sizeLimit); - } - - @Override - public boolean put(String key, Bitmap value) { - if (super.put(key, value)) { - valueSizes.put(value, getSize(value)); - return true; - } else { - return false; - } - } - - @Override - public Bitmap remove(String key) { - Bitmap value = super.get(key); - if (value != null) { - valueSizes.remove(value); - } - return super.remove(key); - } - - @Override - public void clear() { - valueSizes.clear(); - super.clear(); - } - - @Override - protected int getSize(Bitmap value) { - return value.getRowBytes() * value.getHeight(); - } - - @Override - protected Bitmap removeNext() { - Integer maxSize = null; - Bitmap largestValue = null; - Set> entries = valueSizes.entrySet(); - synchronized (valueSizes) { - for (Entry entry : entries) { - if (largestValue == null) { - largestValue = entry.getKey(); - maxSize = entry.getValue(); - } else { - Integer size = entry.getValue(); - if (size > maxSize) { - maxSize = size; - largestValue = entry.getKey(); - } - } - } - } - valueSizes.remove(largestValue); - return largestValue; - } - - @Override - protected Reference createReference(Bitmap value) { - return new WeakReference(value); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LimitedAgeMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LimitedAgeMemoryCache.java deleted file mode 100644 index 2925b6315..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LimitedAgeMemoryCache.java +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; - -import com.nostra13.universalimageloader.cache.memory.MemoryCache; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Decorator for {@link MemoryCache}. Provides special feature for cache: if some cached object age exceeds defined - * value then this object will be removed from cache. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see MemoryCache - * @since 1.3.1 - */ -public class LimitedAgeMemoryCache implements MemoryCache { - - private final MemoryCache cache; - - private final long maxAge; - private final Map loadingDates = Collections.synchronizedMap(new HashMap()); - - /** - * @param cache Wrapped memory cache - * @param maxAge Max object age (in seconds). If object age will exceed this value then it'll be removed from - * cache on next treatment (and therefore be reloaded). - */ - public LimitedAgeMemoryCache(MemoryCache cache, long maxAge) { - this.cache = cache; - this.maxAge = maxAge * 1000; // to milliseconds - } - - @Override - public boolean put(String key, Bitmap value) { - boolean putSuccesfully = cache.put(key, value); - if (putSuccesfully) { - loadingDates.put(key, System.currentTimeMillis()); - } - return putSuccesfully; - } - - @Override - public Bitmap get(String key) { - Long loadingDate = loadingDates.get(key); - if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) { - cache.remove(key); - loadingDates.remove(key); - } - - return cache.get(key); - } - - @Override - public Bitmap remove(String key) { - loadingDates.remove(key); - return cache.remove(key); - } - - @Override - public Collection keys() { - return cache.keys(); - } - - @Override - public void clear() { - cache.clear(); - loadingDates.clear(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LruMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LruMemoryCache.java deleted file mode 100644 index 134a4f838..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/LruMemoryCache.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; - -import com.nostra13.universalimageloader.cache.memory.MemoryCache; - -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * A cache that holds strong references to a limited number of Bitmaps. Each time a Bitmap is accessed, it is moved to - * the head of a queue. When a Bitmap is added to a full cache, the Bitmap at the end of that queue is evicted and may - * become eligible for garbage collection.
- *
- * NOTE: This cache uses only strong references for stored Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.1 - */ -public class LruMemoryCache implements MemoryCache { - - private final LinkedHashMap map; - - private final int maxSize; - /** Size of this cache in bytes */ - private int size; - - /** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */ - public LruMemoryCache(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - this.maxSize = maxSize; - this.map = new LinkedHashMap(0, 0.75f, true); - } - - /** - * Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head - * of the queue. This returns null if a Bitmap is not cached. - */ - @Override - public final Bitmap get(String key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - synchronized (this) { - return map.get(key); - } - } - - /** Caches {@code Bitmap} for {@code key}. The Bitmap is moved to the head of the queue. */ - @Override - public final boolean put(String key, Bitmap value) { - if (key == null || value == null) { - throw new NullPointerException("key == null || value == null"); - } - - synchronized (this) { - size += sizeOf(key, value); - Bitmap previous = map.put(key, value); - if (previous != null) { - size -= sizeOf(key, previous); - } - } - - trimToSize(maxSize); - return true; - } - - /** - * Remove the eldest entries until the total of remaining entries is at or below the requested size. - * - * @param maxSize the maximum size of the cache before returning. May be -1 to evict even 0-sized elements. - */ - private void trimToSize(int maxSize) { - while (true) { - String key; - Bitmap value; - synchronized (this) { - if (size < 0 || (map.isEmpty() && size != 0)) { - throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!"); - } - - if (size <= maxSize || map.isEmpty()) { - break; - } - - Map.Entry toEvict = map.entrySet().iterator().next(); - if (toEvict == null) { - break; - } - key = toEvict.getKey(); - value = toEvict.getValue(); - map.remove(key); - size -= sizeOf(key, value); - } - } - } - - /** Removes the entry for {@code key} if it exists. */ - @Override - public final Bitmap remove(String key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - synchronized (this) { - Bitmap previous = map.remove(key); - if (previous != null) { - size -= sizeOf(key, previous); - } - return previous; - } - } - - @Override - public Collection keys() { - synchronized (this) { - return new HashSet(map.keySet()); - } - } - - @Override - public void clear() { - trimToSize(-1); // -1 will evict 0-sized elements - } - - /** - * Returns the size {@code Bitmap} in bytes. - *

- * An entry's size must not change while it is in the cache. - */ - private int sizeOf(String key, Bitmap value) { - return value.getRowBytes() * value.getHeight(); - } - - @Override - public synchronized final String toString() { - return String.format("LruCache[maxSize=%d]", maxSize); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/UsingFreqLimitedMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/UsingFreqLimitedMemoryCache.java deleted file mode 100644 index 1c78dc1bc..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/UsingFreqLimitedMemoryCache.java +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * Limited {@link Bitmap bitmap} cache. Provides {@link Bitmap bitmaps} storing. Size of all stored bitmaps will not to - * exceed size limit. When cache reaches limit size then the bitmap which used the least frequently is deleted from - * cache.
- *
- * NOTE: This cache uses strong and weak references for stored Bitmaps. Strong references - for limited count of - * Bitmaps (depends on cache size), weak references - for all other cached Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class UsingFreqLimitedMemoryCache extends LimitedMemoryCache { - /** - * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache - * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at - * {@link #softMap} and can be collected by GC at any time) - */ - private final Map usingCounts = Collections.synchronizedMap(new HashMap()); - - public UsingFreqLimitedMemoryCache(int sizeLimit) { - super(sizeLimit); - } - - @Override - public boolean put(String key, Bitmap value) { - if (super.put(key, value)) { - usingCounts.put(value, 0); - return true; - } else { - return false; - } - } - - @Override - public Bitmap get(String key) { - Bitmap value = super.get(key); - // Increment usage count for value if value is contained in hardCahe - if (value != null) { - Integer usageCount = usingCounts.get(value); - if (usageCount != null) { - usingCounts.put(value, usageCount + 1); - } - } - return value; - } - - @Override - public Bitmap remove(String key) { - Bitmap value = super.get(key); - if (value != null) { - usingCounts.remove(value); - } - return super.remove(key); - } - - @Override - public void clear() { - usingCounts.clear(); - super.clear(); - } - - @Override - protected int getSize(Bitmap value) { - return value.getRowBytes() * value.getHeight(); - } - - @Override - protected Bitmap removeNext() { - Integer minUsageCount = null; - Bitmap leastUsedValue = null; - Set> entries = usingCounts.entrySet(); - synchronized (usingCounts) { - for (Entry entry : entries) { - if (leastUsedValue == null) { - leastUsedValue = entry.getKey(); - minUsageCount = entry.getValue(); - } else { - Integer lastValueUsage = entry.getValue(); - if (lastValueUsage < minUsageCount) { - minUsageCount = lastValueUsage; - leastUsedValue = entry.getKey(); - } - } - } - } - usingCounts.remove(leastUsedValue); - return leastUsedValue; - } - - @Override - protected Reference createReference(Bitmap value) { - return new WeakReference(value); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/WeakMemoryCache.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/WeakMemoryCache.java deleted file mode 100644 index 456257476..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/cache/memory/impl/WeakMemoryCache.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.cache.memory.impl; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.cache.memory.BaseMemoryCache; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; - -/** - * Memory cache with {@linkplain WeakReference weak references} to {@linkplain android.graphics.Bitmap bitmaps}
- *
- * NOTE: This cache uses only weak references for stored Bitmaps. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.5.3 - */ -public class WeakMemoryCache extends BaseMemoryCache { - @Override - protected Reference createReference(Bitmap value) { - return new WeakReference(value); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DefaultConfigurationFactory.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DefaultConfigurationFactory.java deleted file mode 100644 index af244d651..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DefaultConfigurationFactory.java +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.annotation.TargetApi; -import android.app.ActivityManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.os.Build; -import com.nostra13.universalimageloader.cache.disc.DiskCache; -import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; -import com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache; -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator; -import com.nostra13.universalimageloader.cache.memory.MemoryCache; -import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; -import com.nostra13.universalimageloader.core.assist.QueueProcessingType; -import com.nostra13.universalimageloader.core.assist.deque.LIFOLinkedBlockingDeque; -import com.nostra13.universalimageloader.core.decode.BaseImageDecoder; -import com.nostra13.universalimageloader.core.decode.ImageDecoder; -import com.nostra13.universalimageloader.core.display.BitmapDisplayer; -import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer; -import com.nostra13.universalimageloader.core.download.BaseImageDownloader; -import com.nostra13.universalimageloader.core.download.ImageDownloader; -import com.nostra13.universalimageloader.utils.L; -import com.nostra13.universalimageloader.utils.StorageUtils; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Factory for providing of default options for {@linkplain ImageLoaderConfiguration configuration} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.5.6 - */ -public class DefaultConfigurationFactory { - - /** Creates default implementation of task executor */ - public static Executor createExecutor(int threadPoolSize, int threadPriority, - QueueProcessingType tasksProcessingType) { - boolean lifo = tasksProcessingType == QueueProcessingType.LIFO; - BlockingQueue taskQueue = - lifo ? new LIFOLinkedBlockingDeque() : new LinkedBlockingQueue(); - return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS, taskQueue, - createThreadFactory(threadPriority, "uil-pool-")); - } - - /** Creates default implementation of task distributor */ - public static Executor createTaskDistributor() { - return Executors.newCachedThreadPool(createThreadFactory(Thread.NORM_PRIORITY, "uil-pool-d-")); - } - - /** Creates {@linkplain HashCodeFileNameGenerator default implementation} of FileNameGenerator */ - public static FileNameGenerator createFileNameGenerator() { - return new HashCodeFileNameGenerator(); - } - - /** - * Creates default implementation of {@link DiskCache} depends on incoming parameters - */ - public static DiskCache createDiskCache(Context context, FileNameGenerator diskCacheFileNameGenerator, - long diskCacheSize, int diskCacheFileCount) { - File reserveCacheDir = createReserveDiskCacheDir(context); - if (diskCacheSize > 0 || diskCacheFileCount > 0) { - File individualCacheDir = StorageUtils.getIndividualCacheDirectory(context); - try { - return new LruDiskCache(individualCacheDir, reserveCacheDir, diskCacheFileNameGenerator, diskCacheSize, - diskCacheFileCount); - } catch (IOException e) { - L.e(e); - // continue and create unlimited cache - } - } - File cacheDir = StorageUtils.getCacheDirectory(context); - return new UnlimitedDiskCache(cacheDir, reserveCacheDir, diskCacheFileNameGenerator); - } - - /** Creates reserve disk cache folder which will be used if primary disk cache folder becomes unavailable */ - private static File createReserveDiskCacheDir(Context context) { - File cacheDir = StorageUtils.getCacheDirectory(context, false); - File individualDir = new File(cacheDir, "uil-images"); - if (individualDir.exists() || individualDir.mkdir()) { - cacheDir = individualDir; - } - return cacheDir; - } - - /** - * Creates default implementation of {@link MemoryCache} - {@link LruMemoryCache}
- * Default cache size = 1/8 of available app memory. - */ - public static MemoryCache createMemoryCache(Context context, int memoryCacheSize) { - if (memoryCacheSize == 0) { - ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - int memoryClass = am.getMemoryClass(); - if (hasHoneycomb() && isLargeHeap(context)) { - memoryClass = getLargeMemoryClass(am); - } - memoryCacheSize = 1024 * 1024 * memoryClass / 8; - } - return new LruMemoryCache(memoryCacheSize); - } - - private static boolean hasHoneycomb() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private static boolean isLargeHeap(Context context) { - return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0; - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private static int getLargeMemoryClass(ActivityManager am) { - return am.getLargeMemoryClass(); - } - - /** Creates default implementation of {@link ImageDownloader} - {@link BaseImageDownloader} */ - public static ImageDownloader createImageDownloader(Context context) { - return new BaseImageDownloader(context); - } - - /** Creates default implementation of {@link ImageDecoder} - {@link BaseImageDecoder} */ - public static ImageDecoder createImageDecoder(boolean loggingEnabled) { - return new BaseImageDecoder(loggingEnabled); - } - - /** Creates default implementation of {@link BitmapDisplayer} - {@link SimpleBitmapDisplayer} */ - public static BitmapDisplayer createBitmapDisplayer() { - return new SimpleBitmapDisplayer(); - } - - /** Creates default implementation of {@linkplain ThreadFactory thread factory} for task executor */ - private static ThreadFactory createThreadFactory(int threadPriority, String threadNamePrefix) { - return new DefaultThreadFactory(threadPriority, threadNamePrefix); - } - - private static class DefaultThreadFactory implements ThreadFactory { - - private static final AtomicInteger poolNumber = new AtomicInteger(1); - - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; - private final int threadPriority; - - DefaultThreadFactory(int threadPriority, String threadNamePrefix) { - this.threadPriority = threadPriority; - group = Thread.currentThread().getThreadGroup(); - namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-"; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); - if (t.isDaemon()) t.setDaemon(false); - t.setPriority(threadPriority); - return t; - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayBitmapTask.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayBitmapTask.java deleted file mode 100644 index fbdf762ff..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayBitmapTask.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.display.BitmapDisplayer; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; -import com.nostra13.universalimageloader.utils.L; - -/** - * Displays bitmap in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware}. Must be called on UI thread. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ImageLoadingListener - * @see BitmapDisplayer - * @since 1.3.1 - */ -final class DisplayBitmapTask implements Runnable { - - private static final String LOG_DISPLAY_IMAGE_IN_IMAGEAWARE = "Display image in ImageAware (loaded from %1$s) [%2$s]"; - private static final String LOG_TASK_CANCELLED_IMAGEAWARE_REUSED = "ImageAware is reused for another image. Task is cancelled. [%s]"; - private static final String LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED = "ImageAware was collected by GC. Task is cancelled. [%s]"; - - private final Bitmap bitmap; - private final String imageUri; - private final ImageAware imageAware; - private final String memoryCacheKey; - private final BitmapDisplayer displayer; - private final ImageLoadingListener listener; - private final ImageLoaderEngine engine; - private final LoadedFrom loadedFrom; - - public DisplayBitmapTask(Bitmap bitmap, ImageLoadingInfo imageLoadingInfo, ImageLoaderEngine engine, - LoadedFrom loadedFrom) { - this.bitmap = bitmap; - imageUri = imageLoadingInfo.uri; - imageAware = imageLoadingInfo.imageAware; - memoryCacheKey = imageLoadingInfo.memoryCacheKey; - displayer = imageLoadingInfo.options.getDisplayer(); - listener = imageLoadingInfo.listener; - this.engine = engine; - this.loadedFrom = loadedFrom; - } - - @Override - public void run() { - if (imageAware.isCollected()) { - L.d(LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED, memoryCacheKey); - listener.onLoadingCancelled(imageUri, imageAware.getWrappedView()); - } else if (isViewWasReused()) { - L.d(LOG_TASK_CANCELLED_IMAGEAWARE_REUSED, memoryCacheKey); - listener.onLoadingCancelled(imageUri, imageAware.getWrappedView()); - } else { - L.d(LOG_DISPLAY_IMAGE_IN_IMAGEAWARE, loadedFrom, memoryCacheKey); - displayer.display(bitmap, imageAware, loadedFrom); - engine.cancelDisplayTaskFor(imageAware); - listener.onLoadingComplete(imageUri, imageAware.getWrappedView(), bitmap); - } - } - - /** Checks whether memory cache key (image URI) for current ImageAware is actual */ - private boolean isViewWasReused() { - String currentCacheKey = engine.getLoadingUriForView(imageAware); - return !memoryCacheKey.equals(currentCacheKey); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayImageOptions.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayImageOptions.java deleted file mode 100644 index b94d3baac..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/DisplayImageOptions.java +++ /dev/null @@ -1,509 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory.Options; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; -import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import com.nostra13.universalimageloader.core.display.BitmapDisplayer; -import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer; -import com.nostra13.universalimageloader.core.download.ImageDownloader; -import com.nostra13.universalimageloader.core.process.BitmapProcessor; - -/** - * Contains options for image display. Defines: - *

    - *
  • whether stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} during image loading
  • - *
  • whether stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if empty URI is passed
  • - *
  • whether stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if image loading fails
  • - *
  • whether {@link com.nostra13.universalimageloader.core.imageaware.ImageAware image aware view} should be reset - * before image loading start
  • - *
  • whether loaded image will be cached in memory
  • - *
  • whether loaded image will be cached on disk
  • - *
  • image scale type
  • - *
  • decoding options (including bitmap decoding configuration)
  • - *
  • delay before loading of image
  • - *
  • whether consider EXIF parameters of image
  • - *
  • auxiliary object which will be passed to {@link ImageDownloader#getStream(String, Object) ImageDownloader}
  • - *
  • pre-processor for image Bitmap (before caching in memory)
  • - *
  • post-processor for image Bitmap (after caching in memory, before displaying)
  • - *
  • how decoded {@link Bitmap} will be displayed
  • - *
- *

- * You can create instance: - *

    - *
  • with {@link Builder}:
    - * i.e. : - * new {@link DisplayImageOptions}.{@link Builder#Builder() Builder()}.{@link Builder#cacheInMemory() cacheInMemory()}. - * {@link Builder#showImageOnLoading(int) showImageOnLoading()}.{@link Builder#build() build()}
    - *
  • - *
  • or by static method: {@link #createSimple()}

  • - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public final class DisplayImageOptions { - - private final int imageResOnLoading; - private final int imageResForEmptyUri; - private final int imageResOnFail; - private final Drawable imageOnLoading; - private final Drawable imageForEmptyUri; - private final Drawable imageOnFail; - private final boolean resetViewBeforeLoading; - private final boolean cacheInMemory; - private final boolean cacheOnDisk; - private final ImageScaleType imageScaleType; - private final Options decodingOptions; - private final int delayBeforeLoading; - private final boolean considerExifParams; - private final Object extraForDownloader; - private final BitmapProcessor preProcessor; - private final BitmapProcessor postProcessor; - private final BitmapDisplayer displayer; - private final Handler handler; - private final boolean isSyncLoading; - - private DisplayImageOptions(Builder builder) { - imageResOnLoading = builder.imageResOnLoading; - imageResForEmptyUri = builder.imageResForEmptyUri; - imageResOnFail = builder.imageResOnFail; - imageOnLoading = builder.imageOnLoading; - imageForEmptyUri = builder.imageForEmptyUri; - imageOnFail = builder.imageOnFail; - resetViewBeforeLoading = builder.resetViewBeforeLoading; - cacheInMemory = builder.cacheInMemory; - cacheOnDisk = builder.cacheOnDisk; - imageScaleType = builder.imageScaleType; - decodingOptions = builder.decodingOptions; - delayBeforeLoading = builder.delayBeforeLoading; - considerExifParams = builder.considerExifParams; - extraForDownloader = builder.extraForDownloader; - preProcessor = builder.preProcessor; - postProcessor = builder.postProcessor; - displayer = builder.displayer; - handler = builder.handler; - isSyncLoading = builder.isSyncLoading; - } - - public boolean shouldShowImageOnLoading() { - return imageOnLoading != null || imageResOnLoading != 0; - } - - public boolean shouldShowImageForEmptyUri() { - return imageForEmptyUri != null || imageResForEmptyUri != 0; - } - - public boolean shouldShowImageOnFail() { - return imageOnFail != null || imageResOnFail != 0; - } - - public boolean shouldPreProcess() { - return preProcessor != null; - } - - public boolean shouldPostProcess() { - return postProcessor != null; - } - - public boolean shouldDelayBeforeLoading() { - return delayBeforeLoading > 0; - } - - public Drawable getImageOnLoading(Resources res) { - return imageResOnLoading != 0 ? res.getDrawable(imageResOnLoading) : imageOnLoading; - } - - public Drawable getImageForEmptyUri(Resources res) { - return imageResForEmptyUri != 0 ? res.getDrawable(imageResForEmptyUri) : imageForEmptyUri; - } - - public Drawable getImageOnFail(Resources res) { - return imageResOnFail != 0 ? res.getDrawable(imageResOnFail) : imageOnFail; - } - - public boolean isResetViewBeforeLoading() { - return resetViewBeforeLoading; - } - - public boolean isCacheInMemory() { - return cacheInMemory; - } - - public boolean isCacheOnDisk() { - return cacheOnDisk; - } - - public ImageScaleType getImageScaleType() { - return imageScaleType; - } - - public Options getDecodingOptions() { - return decodingOptions; - } - - public int getDelayBeforeLoading() { - return delayBeforeLoading; - } - - public boolean isConsiderExifParams() { - return considerExifParams; - } - - public Object getExtraForDownloader() { - return extraForDownloader; - } - - public BitmapProcessor getPreProcessor() { - return preProcessor; - } - - public BitmapProcessor getPostProcessor() { - return postProcessor; - } - - public BitmapDisplayer getDisplayer() { - return displayer; - } - - public Handler getHandler() { - return handler; - } - - boolean isSyncLoading() { - return isSyncLoading; - } - - /** - * Builder for {@link DisplayImageOptions} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - */ - public static class Builder { - private int imageResOnLoading = 0; - private int imageResForEmptyUri = 0; - private int imageResOnFail = 0; - private Drawable imageOnLoading = null; - private Drawable imageForEmptyUri = null; - private Drawable imageOnFail = null; - private boolean resetViewBeforeLoading = false; - private boolean cacheInMemory = false; - private boolean cacheOnDisk = false; - private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2; - private Options decodingOptions = new Options(); - private int delayBeforeLoading = 0; - private boolean considerExifParams = false; - private Object extraForDownloader = null; - private BitmapProcessor preProcessor = null; - private BitmapProcessor postProcessor = null; - private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer(); - private Handler handler = null; - private boolean isSyncLoading = false; - - public Builder() { - decodingOptions.inPurgeable = true; - decodingOptions.inInputShareable = true; - } - - /** - * Stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} during image loading - * - * @param imageRes Stub image resource - * @deprecated Use {@link #showImageOnLoading(int)} instead - */ - @Deprecated - public Builder showStubImage(int imageRes) { - imageResOnLoading = imageRes; - return this; - } - - /** - * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} during image loading - * - * @param imageRes Image resource - */ - public Builder showImageOnLoading(int imageRes) { - imageResOnLoading = imageRes; - return this; - } - - /** - * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} during image loading. - * This option will be ignored if {@link DisplayImageOptions.Builder#showImageOnLoading(int)} is set. - */ - public Builder showImageOnLoading(Drawable drawable) { - imageOnLoading = drawable; - return this; - } - - /** - * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if empty URI (null or empty - * string) will be passed to ImageLoader.displayImage(...) method. - * - * @param imageRes Image resource - */ - public Builder showImageForEmptyUri(int imageRes) { - imageResForEmptyUri = imageRes; - return this; - } - - /** - * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if empty URI (null or empty - * string) will be passed to ImageLoader.displayImage(...) method. - * This option will be ignored if {@link DisplayImageOptions.Builder#showImageForEmptyUri(int)} is set. - */ - public Builder showImageForEmptyUri(Drawable drawable) { - imageForEmptyUri = drawable; - return this; - } - - /** - * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if some error occurs during - * requested image loading/decoding. - * - * @param imageRes Image resource - */ - public Builder showImageOnFail(int imageRes) { - imageResOnFail = imageRes; - return this; - } - - /** - * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} if some error occurs during - * requested image loading/decoding. - * This option will be ignored if {@link DisplayImageOptions.Builder#showImageOnFail(int)} is set. - */ - public Builder showImageOnFail(Drawable drawable) { - imageOnFail = drawable; - return this; - } - - /** - * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} will be reset (set null) before image loading start - * - * @deprecated Use {@link #resetViewBeforeLoading(boolean) resetViewBeforeLoading(true)} instead - */ - public Builder resetViewBeforeLoading() { - resetViewBeforeLoading = true; - return this; - } - - /** - * Sets whether {@link com.nostra13.universalimageloader.core.imageaware.ImageAware - * image aware view} will be reset (set null) before image loading start - */ - public Builder resetViewBeforeLoading(boolean resetViewBeforeLoading) { - this.resetViewBeforeLoading = resetViewBeforeLoading; - return this; - } - - /** - * Loaded image will be cached in memory - * - * @deprecated Use {@link #cacheInMemory(boolean) cacheInMemory(true)} instead - */ - @Deprecated - public Builder cacheInMemory() { - cacheInMemory = true; - return this; - } - - /** Sets whether loaded image will be cached in memory */ - public Builder cacheInMemory(boolean cacheInMemory) { - this.cacheInMemory = cacheInMemory; - return this; - } - - /** - * Loaded image will be cached on disk - * - * @deprecated Use {@link #cacheOnDisk(boolean) cacheOnDisk(true)} instead - */ - @Deprecated - public Builder cacheOnDisc() { - return cacheOnDisk(true); - } - - /** - * Sets whether loaded image will be cached on disk - * - * @deprecated Use {@link #cacheOnDisk(boolean)} instead - */ - @Deprecated - public Builder cacheOnDisc(boolean cacheOnDisk) { - return cacheOnDisk(cacheOnDisk); - } - - /** Sets whether loaded image will be cached on disk */ - public Builder cacheOnDisk(boolean cacheOnDisk) { - this.cacheOnDisk = cacheOnDisk; - return this; - } - - /** - * Sets {@linkplain ImageScaleType scale type} for decoding image. This parameter is used while define scale - * size for decoding image to Bitmap. Default value - {@link ImageScaleType#IN_SAMPLE_POWER_OF_2} - */ - public Builder imageScaleType(ImageScaleType imageScaleType) { - this.imageScaleType = imageScaleType; - return this; - } - - /** Sets {@link Bitmap.Config bitmap config} for image decoding. Default value - {@link Bitmap.Config#ARGB_8888} */ - public Builder bitmapConfig(Bitmap.Config bitmapConfig) { - if (bitmapConfig == null) throw new IllegalArgumentException("bitmapConfig can't be null"); - decodingOptions.inPreferredConfig = bitmapConfig; - return this; - } - - /** - * Sets options for image decoding.
    - * NOTE: {@link Options#inSampleSize} of incoming options will NOT be considered. Library - * calculate the most appropriate sample size itself according yo {@link #imageScaleType(ImageScaleType)} - * options.
    - * NOTE: This option overlaps {@link #bitmapConfig(android.graphics.Bitmap.Config) bitmapConfig()} - * option. - */ - public Builder decodingOptions(Options decodingOptions) { - if (decodingOptions == null) throw new IllegalArgumentException("decodingOptions can't be null"); - this.decodingOptions = decodingOptions; - return this; - } - - /** Sets delay time before starting loading task. Default - no delay. */ - public Builder delayBeforeLoading(int delayInMillis) { - this.delayBeforeLoading = delayInMillis; - return this; - } - - /** Sets auxiliary object which will be passed to {@link ImageDownloader#getStream(String, Object)} */ - public Builder extraForDownloader(Object extra) { - this.extraForDownloader = extra; - return this; - } - - /** Sets whether ImageLoader will consider EXIF parameters of JPEG image (rotate, flip) */ - public Builder considerExifParams(boolean considerExifParams) { - this.considerExifParams = considerExifParams; - return this; - } - - /** - * Sets bitmap processor which will be process bitmaps before they will be cached in memory. So memory cache - * will contain bitmap processed by incoming preProcessor.
    - * Image will be pre-processed even if caching in memory is disabled. - */ - public Builder preProcessor(BitmapProcessor preProcessor) { - this.preProcessor = preProcessor; - return this; - } - - /** - * Sets bitmap processor which will be process bitmaps before they will be displayed in - * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware image aware view} but - * after they'll have been saved in memory cache. - */ - public Builder postProcessor(BitmapProcessor postProcessor) { - this.postProcessor = postProcessor; - return this; - } - - /** - * Sets custom {@link BitmapDisplayer displayer} for image loading task. Default value - - * {@link DefaultConfigurationFactory#createBitmapDisplayer()} - */ - public Builder displayer(BitmapDisplayer displayer) { - if (displayer == null) throw new IllegalArgumentException("displayer can't be null"); - this.displayer = displayer; - return this; - } - - Builder syncLoading(boolean isSyncLoading) { - this.isSyncLoading = isSyncLoading; - return this; - } - - /** - * Sets custom {@linkplain Handler handler} for displaying images and firing {@linkplain ImageLoadingListener - * listener} events. - */ - public Builder handler(Handler handler) { - this.handler = handler; - return this; - } - - /** Sets all options equal to incoming options */ - public Builder cloneFrom(DisplayImageOptions options) { - imageResOnLoading = options.imageResOnLoading; - imageResForEmptyUri = options.imageResForEmptyUri; - imageResOnFail = options.imageResOnFail; - imageOnLoading = options.imageOnLoading; - imageForEmptyUri = options.imageForEmptyUri; - imageOnFail = options.imageOnFail; - resetViewBeforeLoading = options.resetViewBeforeLoading; - cacheInMemory = options.cacheInMemory; - cacheOnDisk = options.cacheOnDisk; - imageScaleType = options.imageScaleType; - decodingOptions = options.decodingOptions; - delayBeforeLoading = options.delayBeforeLoading; - considerExifParams = options.considerExifParams; - extraForDownloader = options.extraForDownloader; - preProcessor = options.preProcessor; - postProcessor = options.postProcessor; - displayer = options.displayer; - handler = options.handler; - isSyncLoading = options.isSyncLoading; - return this; - } - - /** Builds configured {@link DisplayImageOptions} object */ - public DisplayImageOptions build() { - return new DisplayImageOptions(this); - } - } - - /** - * Creates options appropriate for single displaying: - *
      - *
    • View will not be reset before loading
    • - *
    • Loaded image will not be cached in memory
    • - *
    • Loaded image will not be cached on disk
    • - *
    • {@link ImageScaleType#IN_SAMPLE_POWER_OF_2} decoding type will be used
    • - *
    • {@link Bitmap.Config#ARGB_8888} bitmap config will be used for image decoding
    • - *
    • {@link SimpleBitmapDisplayer} will be used for image displaying
    • - *
    - *

    - * These option are appropriate for simple single-use image (from drawables or from Internet) displaying. - */ - public static DisplayImageOptions createSimple() { - return new Builder().build(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoader.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoader.java deleted file mode 100644 index e0163e6fc..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoader.java +++ /dev/null @@ -1,768 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.graphics.Bitmap; -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; -import android.view.View; -import android.widget.ImageView; -import com.nostra13.universalimageloader.cache.disc.DiskCache; -import com.nostra13.universalimageloader.cache.memory.MemoryCache; -import com.nostra13.universalimageloader.core.assist.FailReason; -import com.nostra13.universalimageloader.core.assist.FlushedInputStream; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; -import com.nostra13.universalimageloader.core.imageaware.NonViewAware; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; -import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; -import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; -import com.nostra13.universalimageloader.utils.ImageSizeUtils; -import com.nostra13.universalimageloader.utils.L; -import com.nostra13.universalimageloader.utils.MemoryCacheUtils; - -/** - * Singletone for image loading and displaying at {@link ImageView ImageViews}
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before any other method. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class ImageLoader { - - public static final String TAG = ImageLoader.class.getSimpleName(); - - static final String LOG_INIT_CONFIG = "Initialize ImageLoader with configuration"; - static final String LOG_DESTROY = "Destroy ImageLoader"; - static final String LOG_LOAD_IMAGE_FROM_MEMORY_CACHE = "Load image from memory cache [%s]"; - - private static final String WARNING_RE_INIT_CONFIG = "Try to initialize ImageLoader which had already been initialized before. " + "To re-init ImageLoader with new configuration call ImageLoader.destroy() at first."; - private static final String ERROR_WRONG_ARGUMENTS = "Wrong arguments were passed to displayImage() method (ImageView reference must not be null)"; - private static final String ERROR_NOT_INIT = "ImageLoader must be init with configuration before using"; - private static final String ERROR_INIT_CONFIG_WITH_NULL = "ImageLoader configuration can not be initialized with null"; - - private ImageLoaderConfiguration configuration; - private ImageLoaderEngine engine; - - private ImageLoadingListener defaultListener = new SimpleImageLoadingListener(); - - private volatile static ImageLoader instance; - - /** Returns singleton class instance */ - public static ImageLoader getInstance() { - if (instance == null) { - synchronized (ImageLoader.class) { - if (instance == null) { - instance = new ImageLoader(); - } - } - } - return instance; - } - - protected ImageLoader() { - } - - /** - * Initializes ImageLoader instance with configuration.
    - * If configurations was set before ( {@link #isInited()} == true) then this method does nothing.
    - * To force initialization with new configuration you should {@linkplain #destroy() destroy ImageLoader} at first. - * - * @param configuration {@linkplain ImageLoaderConfiguration ImageLoader configuration} - * @throws IllegalArgumentException if configuration parameter is null - */ - public synchronized void init(ImageLoaderConfiguration configuration) { - if (configuration == null) { - throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL); - } - if (this.configuration == null) { - L.d(LOG_INIT_CONFIG); - engine = new ImageLoaderEngine(configuration); - this.configuration = configuration; - } else { - L.w(WARNING_RE_INIT_CONFIG); - } - } - - /** - * Returns true - if ImageLoader {@linkplain #init(ImageLoaderConfiguration) is initialized with - * configuration}; false - otherwise - */ - public boolean isInited() { - return configuration != null; - } - - /** - * Adds display image task to execution pool. Image will be set to ImageAware when it's turn.
    - * Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} - * which should display image - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageAware is null - */ - public void displayImage(String uri, ImageAware imageAware) { - displayImage(uri, imageAware, null, null, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageAware when it's turn.
    - * Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} - * which should display image - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on - * UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageAware is null - */ - public void displayImage(String uri, ImageAware imageAware, ImageLoadingListener listener) { - displayImage(uri, imageAware, null, listener, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageAware when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} - * which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageAware is null - */ - public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options) { - displayImage(uri, imageAware, options, null, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageAware when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} - * which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on - * UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageAware is null - */ - public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, - ImageLoadingListener listener) { - displayImage(uri, imageAware, options, listener, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageAware when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} - * which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires - * events on UI thread if this method is called on UI thread. - * @param progressListener {@linkplain com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener - * Listener} for image loading progress. Listener fires events on UI thread if this method - * is called on UI thread. Caching on disk should be enabled in - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions options} to make - * this listener work. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageAware is null - */ - public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, - ImageLoadingListener listener, ImageLoadingProgressListener progressListener) { - checkConfiguration(); - if (imageAware == null) { - throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS); - } - if (listener == null) { - listener = defaultListener; - } - if (options == null) { - options = configuration.defaultDisplayImageOptions; - } - - if (TextUtils.isEmpty(uri)) { - engine.cancelDisplayTaskFor(imageAware); - listener.onLoadingStarted(uri, imageAware.getWrappedView()); - if (options.shouldShowImageForEmptyUri()) { - imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources)); - } else { - imageAware.setImageDrawable(null); - } - listener.onLoadingComplete(uri, imageAware.getWrappedView(), null); - return; - } - - ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize()); - String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize); - engine.prepareDisplayTaskFor(imageAware, memoryCacheKey); - - listener.onLoadingStarted(uri, imageAware.getWrappedView()); - - Bitmap bmp = configuration.memoryCache.get(memoryCacheKey); - if (bmp != null && !bmp.isRecycled()) { - L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey); - - if (options.shouldPostProcess()) { - ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, - options, listener, progressListener, engine.getLockForUri(uri)); - ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, - defineHandler(options)); - if (options.isSyncLoading()) { - displayTask.run(); - } else { - engine.submit(displayTask); - } - } else { - options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE); - listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp); - } - } else { - if (options.shouldShowImageOnLoading()) { - imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources)); - } else if (options.isResetViewBeforeLoading()) { - imageAware.setImageDrawable(null); - } - - ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, - options, listener, progressListener, engine.getLockForUri(uri)); - LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, - defineHandler(options)); - if (options.isSyncLoading()) { - displayTask.run(); - } else { - engine.submit(displayTask); - } - } - } - - /** - * Adds display image task to execution pool. Image will be set to ImageView when it's turn.
    - * Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageView {@link ImageView} which should display image - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageView is null - */ - public void displayImage(String uri, ImageView imageView) { - displayImage(uri, new ImageViewAware(imageView), null, null, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageView when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageView {@link ImageView} which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageView is null - */ - public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) { - displayImage(uri, new ImageViewAware(imageView), options, null, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageView when it's turn.
    - * Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageView {@link ImageView} which should display image - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on - * UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageView is null - */ - public void displayImage(String uri, ImageView imageView, ImageLoadingListener listener) { - displayImage(uri, new ImageViewAware(imageView), null, listener, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageView when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageView {@link ImageView} which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on - * UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageView is null - */ - public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, - ImageLoadingListener listener) { - displayImage(uri, imageView, options, listener, null); - } - - /** - * Adds display image task to execution pool. Image will be set to ImageView when it's turn.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param imageView {@link ImageView} which should display image - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires - * events on UI thread if this method is called on UI thread. - * @param progressListener {@linkplain com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener - * Listener} for image loading progress. Listener fires events on UI thread if this method - * is called on UI thread. Caching on disk should be enabled in - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions options} to make - * this listener work. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @throws IllegalArgumentException if passed imageView is null - */ - public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, - ImageLoadingListener listener, ImageLoadingProgressListener progressListener) { - displayImage(uri, new ImageViewAware(imageView), options, listener, progressListener); - } - - /** - * Adds load image task to execution pool. Image will be returned with - * {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. - *
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI - * thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void loadImage(String uri, ImageLoadingListener listener) { - loadImage(uri, null, null, listener, null); - } - - /** - * Adds load image task to execution pool. Image will be returned with - * {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. - *
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param targetImageSize Minimal size for {@link Bitmap} which will be returned in - * {@linkplain ImageLoadingListener#onLoadingComplete(String, android.view.View, - * android.graphics.Bitmap)} callback}. Downloaded image will be decoded - * and scaled to {@link Bitmap} of the size which is equal or larger (usually a bit - * larger) than incoming targetImageSize. - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires - * events on UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void loadImage(String uri, ImageSize targetImageSize, ImageLoadingListener listener) { - loadImage(uri, targetImageSize, null, listener, null); - } - - /** - * Adds load image task to execution pool. Image will be returned with - * {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. - *
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from - * configuration} will be used.
    - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI - * thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void loadImage(String uri, DisplayImageOptions options, ImageLoadingListener listener) { - loadImage(uri, null, options, listener, null); - } - - /** - * Adds load image task to execution pool. Image will be returned with - * {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. - *
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param targetImageSize Minimal size for {@link Bitmap} which will be returned in - * {@linkplain ImageLoadingListener#onLoadingComplete(String, android.view.View, - * android.graphics.Bitmap)} callback}. Downloaded image will be decoded - * and scaled to {@link Bitmap} of the size which is equal or larger (usually a bit - * larger) than incoming targetImageSize. - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used.
    - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires - * events on UI thread if this method is called on UI thread. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, - ImageLoadingListener listener) { - loadImage(uri, targetImageSize, options, listener, null); - } - - /** - * Adds load image task to execution pool. Image will be returned with - * {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. - *
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param targetImageSize Minimal size for {@link Bitmap} which will be returned in - * {@linkplain ImageLoadingListener#onLoadingComplete(String, android.view.View, - * android.graphics.Bitmap)} callback}. Downloaded image will be decoded - * and scaled to {@link Bitmap} of the size which is equal or larger (usually a bit - * larger) than incoming targetImageSize. - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and displaying. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used.
    - * @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires - * events on UI thread if this method is called on UI thread. - * @param progressListener {@linkplain com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener - * Listener} for image loading progress. Listener fires events on UI thread if this method - * is called on UI thread. Caching on disk should be enabled in - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions options} to make - * this listener work. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, - ImageLoadingListener listener, ImageLoadingProgressListener progressListener) { - checkConfiguration(); - if (targetImageSize == null) { - targetImageSize = configuration.getMaxImageSize(); - } - if (options == null) { - options = configuration.defaultDisplayImageOptions; - } - - NonViewAware imageAware = new NonViewAware(uri, targetImageSize, ViewScaleType.CROP); - displayImage(uri, imageAware, options, listener, progressListener); - } - - /** - * Loads and decodes image synchronously.
    - * Default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @return Result image Bitmap. Can be null if image loading/decoding was failed or cancelled. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public Bitmap loadImageSync(String uri) { - return loadImageSync(uri, null, null); - } - - /** - * Loads and decodes image synchronously.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and scaling. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from - * configuration} will be used. - * @return Result image Bitmap. Can be null if image loading/decoding was failed or cancelled. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public Bitmap loadImageSync(String uri, DisplayImageOptions options) { - return loadImageSync(uri, null, options); - } - - /** - * Loads and decodes image synchronously.
    - * Default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from - * configuration} will be used.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param targetImageSize Minimal size for {@link Bitmap} which will be returned. Downloaded image will be decoded - * and scaled to {@link Bitmap} of the size which is equal or larger (usually a bit - * larger) than incoming targetImageSize. - * @return Result image Bitmap. Can be null if image loading/decoding was failed or cancelled. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public Bitmap loadImageSync(String uri, ImageSize targetImageSize) { - return loadImageSync(uri, targetImageSize, null); - } - - /** - * Loads and decodes image synchronously.
    - * NOTE: {@link #init(ImageLoaderConfiguration)} method must be called before this method call - * - * @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png") - * @param targetImageSize Minimal size for {@link Bitmap} which will be returned. Downloaded image will be decoded - * and scaled to {@link Bitmap} of the size which is equal or larger (usually a bit - * larger) than incoming targetImageSize. - * @param options {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions Options} for image - * decoding and scaling. If null - default display image options - * {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) - * from configuration} will be used. - * @return Result image Bitmap. Can be null if image loading/decoding was failed or cancelled. - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public Bitmap loadImageSync(String uri, ImageSize targetImageSize, DisplayImageOptions options) { - if (options == null) { - options = configuration.defaultDisplayImageOptions; - } - options = new DisplayImageOptions.Builder().cloneFrom(options).syncLoading(true).build(); - - SyncImageLoadingListener listener = new SyncImageLoadingListener(); - loadImage(uri, targetImageSize, options, listener); - return listener.getLoadedBitmap(); - } - - /** - * Checks if ImageLoader's configuration was initialized - * - * @throws IllegalStateException if configuration wasn't initialized - */ - private void checkConfiguration() { - if (configuration == null) { - throw new IllegalStateException(ERROR_NOT_INIT); - } - } - - /** Sets a default loading listener for all display and loading tasks. */ - public void setDefaultLoadingListener(ImageLoadingListener listener) { - defaultListener = listener == null ? new SimpleImageLoadingListener() : listener; - } - - /** - * Returns memory cache - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public MemoryCache getMemoryCache() { - checkConfiguration(); - return configuration.memoryCache; - } - - /** - * Clears memory cache - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void clearMemoryCache() { - checkConfiguration(); - configuration.memoryCache.clear(); - } - - /** - * Returns disk cache - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @deprecated Use {@link #getDiskCache()} instead - */ - @Deprecated - public DiskCache getDiscCache() { - return getDiskCache(); - } - - /** - * Returns disk cache - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public DiskCache getDiskCache() { - checkConfiguration(); - return configuration.diskCache; - } - - /** - * Clears disk cache. - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - * @deprecated Use {@link #clearDiskCache()} instead - */ - @Deprecated - public void clearDiscCache() { - clearDiskCache(); - } - - /** - * Clears disk cache. - * - * @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before - */ - public void clearDiskCache() { - checkConfiguration(); - configuration.diskCache.clear(); - } - - /** - * Returns URI of image which is loading at this moment into passed - * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware ImageAware} - */ - public String getLoadingUriForView(ImageAware imageAware) { - return engine.getLoadingUriForView(imageAware); - } - - /** - * Returns URI of image which is loading at this moment into passed - * {@link android.widget.ImageView ImageView} - */ - public String getLoadingUriForView(ImageView imageView) { - return engine.getLoadingUriForView(new ImageViewAware(imageView)); - } - - /** - * Cancel the task of loading and displaying image for passed - * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware ImageAware}. - * - * @param imageAware {@link com.nostra13.universalimageloader.core.imageaware.ImageAware ImageAware} for - * which display task will be cancelled - */ - public void cancelDisplayTask(ImageAware imageAware) { - engine.cancelDisplayTaskFor(imageAware); - } - - /** - * Cancel the task of loading and displaying image for passed - * {@link android.widget.ImageView ImageView}. - * - * @param imageView {@link android.widget.ImageView ImageView} for which display task will be cancelled - */ - public void cancelDisplayTask(ImageView imageView) { - engine.cancelDisplayTaskFor(new ImageViewAware(imageView)); - } - - /** - * Denies or allows ImageLoader to download images from the network.
    - *
    - * If downloads are denied and if image isn't cached then - * {@link ImageLoadingListener#onLoadingFailed(String, View, FailReason)} callback will be fired with - * {@link FailReason.FailType#NETWORK_DENIED} - * - * @param denyNetworkDownloads pass true - to deny engine to download images from the network; false - - * to allow engine to download images from network. - */ - public void denyNetworkDownloads(boolean denyNetworkDownloads) { - engine.denyNetworkDownloads(denyNetworkDownloads); - } - - /** - * Sets option whether ImageLoader will use {@link FlushedInputStream} for network downloads to handle this known problem or not. - * - * @param handleSlowNetwork pass true - to use {@link FlushedInputStream} for network downloads; false - * - otherwise. - */ - public void handleSlowNetwork(boolean handleSlowNetwork) { - engine.handleSlowNetwork(handleSlowNetwork); - } - - /** - * Pause ImageLoader. All new "load&display" tasks won't be executed until ImageLoader is {@link #resume() resumed}. - *
    - * Already running tasks are not paused. - */ - public void pause() { - engine.pause(); - } - - /** Resumes waiting "load&display" tasks */ - public void resume() { - engine.resume(); - } - - /** - * Cancels all running and scheduled display image tasks.
    - * NOTE: This method doesn't shutdown - * {@linkplain com.nostra13.universalimageloader.core.ImageLoaderConfiguration.Builder#taskExecutor(java.util.concurrent.Executor) - * custom task executors} if you set them.
    - * ImageLoader still can be used after calling this method. - */ - public void stop() { - engine.stop(); - } - - /** - * {@linkplain #stop() Stops ImageLoader} and clears current configuration.
    - * You can {@linkplain #init(ImageLoaderConfiguration) init} ImageLoader with new configuration after calling this - * method. - */ - public void destroy() { - if (configuration != null) L.d(LOG_DESTROY); - stop(); - configuration.diskCache.close(); - engine = null; - configuration = null; - } - - private static Handler defineHandler(DisplayImageOptions options) { - Handler handler = options.getHandler(); - if (options.isSyncLoading()) { - handler = null; - } else if (handler == null && Looper.myLooper() == Looper.getMainLooper()) { - handler = new Handler(); - } - return handler; - } - - /** - * Listener which is designed for synchronous image loading. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.0 - */ - private static class SyncImageLoadingListener extends SimpleImageLoadingListener { - - private Bitmap loadedImage; - - @Override - public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - this.loadedImage = loadedImage; - } - - public Bitmap getLoadedBitmap() { - return loadedImage; - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java deleted file mode 100644 index f9f6f74ce..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java +++ /dev/null @@ -1,655 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.content.Context; -import android.content.res.Resources; -import android.util.DisplayMetrics; -import com.nostra13.universalimageloader.cache.disc.DiskCache; -import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.cache.memory.MemoryCache; -import com.nostra13.universalimageloader.cache.memory.impl.FuzzyKeyMemoryCache; -import com.nostra13.universalimageloader.core.assist.FlushedInputStream; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.QueueProcessingType; -import com.nostra13.universalimageloader.core.decode.ImageDecoder; -import com.nostra13.universalimageloader.core.download.ImageDownloader; -import com.nostra13.universalimageloader.core.process.BitmapProcessor; -import com.nostra13.universalimageloader.utils.L; -import com.nostra13.universalimageloader.utils.MemoryCacheUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.Executor; - -/** - * Presents configuration for {@link ImageLoader} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ImageLoader - * @see MemoryCache - * @see DiskCache - * @see DisplayImageOptions - * @see ImageDownloader - * @see FileNameGenerator - * @since 1.0.0 - */ -public final class ImageLoaderConfiguration { - - final Resources resources; - - final int maxImageWidthForMemoryCache; - final int maxImageHeightForMemoryCache; - final int maxImageWidthForDiskCache; - final int maxImageHeightForDiskCache; - final BitmapProcessor processorForDiskCache; - - final Executor taskExecutor; - final Executor taskExecutorForCachedImages; - final boolean customExecutor; - final boolean customExecutorForCachedImages; - - final int threadPoolSize; - final int threadPriority; - final QueueProcessingType tasksProcessingType; - - final MemoryCache memoryCache; - final DiskCache diskCache; - final ImageDownloader downloader; - final ImageDecoder decoder; - final DisplayImageOptions defaultDisplayImageOptions; - - final ImageDownloader networkDeniedDownloader; - final ImageDownloader slowNetworkDownloader; - - private ImageLoaderConfiguration(final Builder builder) { - resources = builder.context.getResources(); - maxImageWidthForMemoryCache = builder.maxImageWidthForMemoryCache; - maxImageHeightForMemoryCache = builder.maxImageHeightForMemoryCache; - maxImageWidthForDiskCache = builder.maxImageWidthForDiskCache; - maxImageHeightForDiskCache = builder.maxImageHeightForDiskCache; - processorForDiskCache = builder.processorForDiskCache; - taskExecutor = builder.taskExecutor; - taskExecutorForCachedImages = builder.taskExecutorForCachedImages; - threadPoolSize = builder.threadPoolSize; - threadPriority = builder.threadPriority; - tasksProcessingType = builder.tasksProcessingType; - diskCache = builder.diskCache; - memoryCache = builder.memoryCache; - defaultDisplayImageOptions = builder.defaultDisplayImageOptions; - downloader = builder.downloader; - decoder = builder.decoder; - - customExecutor = builder.customExecutor; - customExecutorForCachedImages = builder.customExecutorForCachedImages; - - networkDeniedDownloader = new NetworkDeniedImageDownloader(downloader); - slowNetworkDownloader = new SlowNetworkImageDownloader(downloader); - - L.writeDebugLogs(builder.writeLogs); - } - - /** - * Creates default configuration for {@link ImageLoader}
    - * Default values: - *

      - *
    • maxImageWidthForMemoryCache = device's screen width
    • - *
    • maxImageHeightForMemoryCache = device's screen height
    • - *
    • maxImageWidthForDikcCache = unlimited
    • - *
    • maxImageHeightForDiskCache = unlimited
    • - *
    • threadPoolSize = {@link Builder#DEFAULT_THREAD_POOL_SIZE this}
    • - *
    • threadPriority = {@link Builder#DEFAULT_THREAD_PRIORITY this}
    • - *
    • allow to cache different sizes of image in memory
    • - *
    • memoryCache = {@link DefaultConfigurationFactory#createMemoryCache(android.content.Context, int)}
    • - *
    • diskCache = {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache}
    • - *
    • imageDownloader = {@link DefaultConfigurationFactory#createImageDownloader(Context)}
    • - *
    • imageDecoder = {@link DefaultConfigurationFactory#createImageDecoder(boolean)}
    • - *
    • diskCacheFileNameGenerator = {@link DefaultConfigurationFactory#createFileNameGenerator()}
    • - *
    • defaultDisplayImageOptions = {@link DisplayImageOptions#createSimple() Simple options}
    • - *
    • tasksProcessingOrder = {@link QueueProcessingType#FIFO}
    • - *
    • detailed logging disabled
    • - *
    - */ - public static ImageLoaderConfiguration createDefault(Context context) { - return new Builder(context).build(); - } - - ImageSize getMaxImageSize() { - DisplayMetrics displayMetrics = resources.getDisplayMetrics(); - - int width = maxImageWidthForMemoryCache; - if (width <= 0) { - width = displayMetrics.widthPixels; - } - int height = maxImageHeightForMemoryCache; - if (height <= 0) { - height = displayMetrics.heightPixels; - } - return new ImageSize(width, height); - } - - /** - * Builder for {@link ImageLoaderConfiguration} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - */ - public static class Builder { - - private static final String WARNING_OVERLAP_DISK_CACHE_PARAMS = "diskCache(), diskCacheSize() and diskCacheFileCount calls overlap each other"; - private static final String WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR = "diskCache() and diskCacheFileNameGenerator() calls overlap each other"; - private static final String WARNING_OVERLAP_MEMORY_CACHE = "memoryCache() and memoryCacheSize() calls overlap each other"; - private static final String WARNING_OVERLAP_EXECUTOR = "threadPoolSize(), threadPriority() and tasksProcessingOrder() calls " - + "can overlap taskExecutor() and taskExecutorForCachedImages() calls."; - - /** {@value} */ - public static final int DEFAULT_THREAD_POOL_SIZE = 3; - /** {@value} */ - public static final int DEFAULT_THREAD_PRIORITY = Thread.NORM_PRIORITY - 2; - /** {@value} */ - public static final QueueProcessingType DEFAULT_TASK_PROCESSING_TYPE = QueueProcessingType.FIFO; - - private Context context; - - private int maxImageWidthForMemoryCache = 0; - private int maxImageHeightForMemoryCache = 0; - private int maxImageWidthForDiskCache = 0; - private int maxImageHeightForDiskCache = 0; - private BitmapProcessor processorForDiskCache = null; - - private Executor taskExecutor = null; - private Executor taskExecutorForCachedImages = null; - private boolean customExecutor = false; - private boolean customExecutorForCachedImages = false; - - private int threadPoolSize = DEFAULT_THREAD_POOL_SIZE; - private int threadPriority = DEFAULT_THREAD_PRIORITY; - private boolean denyCacheImageMultipleSizesInMemory = false; - private QueueProcessingType tasksProcessingType = DEFAULT_TASK_PROCESSING_TYPE; - - private int memoryCacheSize = 0; - private long diskCacheSize = 0; - private int diskCacheFileCount = 0; - - private MemoryCache memoryCache = null; - private DiskCache diskCache = null; - private FileNameGenerator diskCacheFileNameGenerator = null; - private ImageDownloader downloader = null; - private ImageDecoder decoder; - private DisplayImageOptions defaultDisplayImageOptions = null; - - private boolean writeLogs = false; - - public Builder(Context context) { - this.context = context.getApplicationContext(); - } - - /** - * Sets options for memory cache - * - * @param maxImageWidthForMemoryCache Maximum image width which will be used for memory saving during decoding - * an image to {@link android.graphics.Bitmap Bitmap}. Default value - device's screen width - * @param maxImageHeightForMemoryCache Maximum image height which will be used for memory saving during decoding - * an image to {@link android.graphics.Bitmap Bitmap}. Default value - device's screen height - */ - public Builder memoryCacheExtraOptions(int maxImageWidthForMemoryCache, int maxImageHeightForMemoryCache) { - this.maxImageWidthForMemoryCache = maxImageWidthForMemoryCache; - this.maxImageHeightForMemoryCache = maxImageHeightForMemoryCache; - return this; - } - - /** - * @deprecated Use - * {@link #diskCacheExtraOptions(int, int, com.nostra13.universalimageloader.core.process.BitmapProcessor)} - * instead - */ - @Deprecated - public Builder discCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache, - BitmapProcessor processorForDiskCache) { - return diskCacheExtraOptions(maxImageWidthForDiskCache, maxImageHeightForDiskCache, processorForDiskCache); - } - - /** - * Sets options for resizing/compressing of downloaded images before saving to disk cache.
    - * NOTE: Use this option only when you have appropriate needs. It can make ImageLoader slower. - * - * @param maxImageWidthForDiskCache Maximum width of downloaded images for saving at disk cache - * @param maxImageHeightForDiskCache Maximum height of downloaded images for saving at disk cache - * @param processorForDiskCache null-ok; {@linkplain BitmapProcessor Bitmap processor} which process images before saving them in disc cache - */ - public Builder diskCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache, - BitmapProcessor processorForDiskCache) { - this.maxImageWidthForDiskCache = maxImageWidthForDiskCache; - this.maxImageHeightForDiskCache = maxImageHeightForDiskCache; - this.processorForDiskCache = processorForDiskCache; - return this; - } - - /** - * Sets custom {@linkplain Executor executor} for tasks of loading and displaying images.
    - *
    - * NOTE: If you set custom executor then following configuration options will not be considered for this - * executor: - *
      - *
    • {@link #threadPoolSize(int)}
    • - *
    • {@link #threadPriority(int)}
    • - *
    • {@link #tasksProcessingOrder(QueueProcessingType)}
    • - *
    - * - * @see #taskExecutorForCachedImages(Executor) - */ - public Builder taskExecutor(Executor executor) { - if (threadPoolSize != DEFAULT_THREAD_POOL_SIZE || threadPriority != DEFAULT_THREAD_PRIORITY || tasksProcessingType != DEFAULT_TASK_PROCESSING_TYPE) { - L.w(WARNING_OVERLAP_EXECUTOR); - } - - this.taskExecutor = executor; - return this; - } - - /** - * Sets custom {@linkplain Executor executor} for tasks of displaying cached on disk images (these tasks - * are executed quickly so UIL prefer to use separate executor for them).
    - *
    - * If you set the same executor for {@linkplain #taskExecutor(Executor) general tasks} and - * tasks about cached images (this method) then these tasks will be in the - * same thread pool. So short-lived tasks can wait a long time for their turn.
    - *
    - * NOTE: If you set custom executor then following configuration options will not be considered for this - * executor: - *
      - *
    • {@link #threadPoolSize(int)}
    • - *
    • {@link #threadPriority(int)}
    • - *
    • {@link #tasksProcessingOrder(QueueProcessingType)}
    • - *
    - * - * @see #taskExecutor(Executor) - */ - public Builder taskExecutorForCachedImages(Executor executorForCachedImages) { - if (threadPoolSize != DEFAULT_THREAD_POOL_SIZE || threadPriority != DEFAULT_THREAD_PRIORITY || tasksProcessingType != DEFAULT_TASK_PROCESSING_TYPE) { - L.w(WARNING_OVERLAP_EXECUTOR); - } - - this.taskExecutorForCachedImages = executorForCachedImages; - return this; - } - - /** - * Sets thread pool size for image display tasks.
    - * Default value - {@link #DEFAULT_THREAD_POOL_SIZE this} - */ - public Builder threadPoolSize(int threadPoolSize) { - if (taskExecutor != null || taskExecutorForCachedImages != null) { - L.w(WARNING_OVERLAP_EXECUTOR); - } - - this.threadPoolSize = threadPoolSize; - return this; - } - - /** - * Sets the priority for image loading threads. Should be NOT greater than {@link Thread#MAX_PRIORITY} or - * less than {@link Thread#MIN_PRIORITY}
    - * Default value - {@link #DEFAULT_THREAD_PRIORITY this} - */ - public Builder threadPriority(int threadPriority) { - if (taskExecutor != null || taskExecutorForCachedImages != null) { - L.w(WARNING_OVERLAP_EXECUTOR); - } - - if (threadPriority < Thread.MIN_PRIORITY) { - this.threadPriority = Thread.MIN_PRIORITY; - } else { - if (threadPriority > Thread.MAX_PRIORITY) { - this.threadPriority = Thread.MAX_PRIORITY; - } else { - this.threadPriority = threadPriority; - } - } - return this; - } - - /** - * When you display an image in a small {@link android.widget.ImageView ImageView} and later you try to display - * this image (from identical URI) in a larger {@link android.widget.ImageView ImageView} so decoded image of - * bigger size will be cached in memory as a previous decoded image of smaller size.
    - * So the default behavior is to allow to cache multiple sizes of one image in memory. You can - * deny it by calling this method: so when some image will be cached in memory then previous - * cached size of this image (if it exists) will be removed from memory cache before. - */ - public Builder denyCacheImageMultipleSizesInMemory() { - this.denyCacheImageMultipleSizesInMemory = true; - return this; - } - - /** - * Sets type of queue processing for tasks for loading and displaying images.
    - * Default value - {@link QueueProcessingType#FIFO} - */ - public Builder tasksProcessingOrder(QueueProcessingType tasksProcessingType) { - if (taskExecutor != null || taskExecutorForCachedImages != null) { - L.w(WARNING_OVERLAP_EXECUTOR); - } - - this.tasksProcessingType = tasksProcessingType; - return this; - } - - /** - * Sets maximum memory cache size for {@link android.graphics.Bitmap bitmaps} (in bytes).
    - * Default value - 1/8 of available app memory.
    - * NOTE: If you use this method then - * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as - * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of - * {@link MemoryCache}. - */ - public Builder memoryCacheSize(int memoryCacheSize) { - if (memoryCacheSize <= 0) throw new IllegalArgumentException("memoryCacheSize must be a positive number"); - - if (memoryCache != null) { - L.w(WARNING_OVERLAP_MEMORY_CACHE); - } - - this.memoryCacheSize = memoryCacheSize; - return this; - } - - /** - * Sets maximum memory cache size (in percent of available app memory) for {@link android.graphics.Bitmap - * bitmaps}.
    - * Default value - 1/8 of available app memory.
    - * NOTE: If you use this method then - * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as - * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of - * {@link MemoryCache}. - */ - public Builder memoryCacheSizePercentage(int availableMemoryPercent) { - if (availableMemoryPercent <= 0 || availableMemoryPercent >= 100) { - throw new IllegalArgumentException("availableMemoryPercent must be in range (0 < % < 100)"); - } - - if (memoryCache != null) { - L.w(WARNING_OVERLAP_MEMORY_CACHE); - } - - long availableMemory = Runtime.getRuntime().maxMemory(); - memoryCacheSize = (int) (availableMemory * (availableMemoryPercent / 100f)); - return this; - } - - /** - * Sets memory cache for {@link android.graphics.Bitmap bitmaps}.
    - * Default value - {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} - * with limited memory cache size (size = 1/8 of available app memory)
    - *
    - * NOTE: If you set custom memory cache then following configuration option will not be considered: - *
      - *
    • {@link #memoryCacheSize(int)}
    • - *
    - */ - public Builder memoryCache(MemoryCache memoryCache) { - if (memoryCacheSize != 0) { - L.w(WARNING_OVERLAP_MEMORY_CACHE); - } - - this.memoryCache = memoryCache; - return this; - } - - /** @deprecated Use {@link #diskCacheSize(int)} instead */ - @Deprecated - public Builder discCacheSize(int maxCacheSize) { - return diskCacheSize(maxCacheSize); - } - - /** - * Sets maximum disk cache size for images (in bytes).
    - * By default: disk cache is unlimited.
    - * NOTE: If you use this method then - * {@link com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache LruDiskCache} - * will be used as disk cache. You can use {@link #diskCache(DiskCache)} method for introduction your own - * implementation of {@link DiskCache} - */ - public Builder diskCacheSize(int maxCacheSize) { - if (maxCacheSize <= 0) throw new IllegalArgumentException("maxCacheSize must be a positive number"); - - if (diskCache != null) { - L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS); - } - - this.diskCacheSize = maxCacheSize; - return this; - } - - /** @deprecated Use {@link #diskCacheFileCount(int)} instead */ - @Deprecated - public Builder discCacheFileCount(int maxFileCount) { - return diskCacheFileCount(maxFileCount); - } - - /** - * Sets maximum file count in disk cache directory.
    - * By default: disk cache is unlimited.
    - * NOTE: If you use this method then - * {@link com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache LruDiskCache} - * will be used as disk cache. You can use {@link #diskCache(DiskCache)} method for introduction your own - * implementation of {@link DiskCache} - */ - public Builder diskCacheFileCount(int maxFileCount) { - if (maxFileCount <= 0) throw new IllegalArgumentException("maxFileCount must be a positive number"); - - if (diskCache != null) { - L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS); - } - - this.diskCacheFileCount = maxFileCount; - return this; - } - - /** @deprecated Use {@link #diskCacheFileNameGenerator(com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator)} */ - @Deprecated - public Builder discCacheFileNameGenerator(FileNameGenerator fileNameGenerator) { - return diskCacheFileNameGenerator(fileNameGenerator); - } - - /** - * Sets name generator for files cached in disk cache.
    - * Default value - - * {@link com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createFileNameGenerator() - * DefaultConfigurationFactory.createFileNameGenerator()} - */ - public Builder diskCacheFileNameGenerator(FileNameGenerator fileNameGenerator) { - if (diskCache != null) { - L.w(WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR); - } - - this.diskCacheFileNameGenerator = fileNameGenerator; - return this; - } - - /** @deprecated Use {@link #diskCache(com.nostra13.universalimageloader.cache.disc.DiskCache)} */ - @Deprecated - public Builder discCache(DiskCache diskCache) { - return diskCache(diskCache); - } - - /** - * Sets disk cache for images.
    - * Default value - {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache - * UnlimitedDiskCache}. Cache directory is defined by - * {@link com.nostra13.universalimageloader.utils.StorageUtils#getCacheDirectory(Context) - * StorageUtils.getCacheDirectory(Context)}.
    - *
    - * NOTE: If you set custom disk cache then following configuration option will not be considered: - *
      - *
    • {@link #diskCacheSize(int)}
    • - *
    • {@link #diskCacheFileCount(int)}
    • - *
    • {@link #diskCacheFileNameGenerator(FileNameGenerator)}
    • - *
    - */ - public Builder diskCache(DiskCache diskCache) { - if (diskCacheSize > 0 || diskCacheFileCount > 0) { - L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS); - } - if (diskCacheFileNameGenerator != null) { - L.w(WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR); - } - - this.diskCache = diskCache; - return this; - } - - /** - * Sets utility which will be responsible for downloading of image.
    - * Default value - - * {@link com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createImageDownloader(Context) - * DefaultConfigurationFactory.createImageDownloader()} - */ - public Builder imageDownloader(ImageDownloader imageDownloader) { - this.downloader = imageDownloader; - return this; - } - - /** - * Sets utility which will be responsible for decoding of image stream.
    - * Default value - - * {@link com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createImageDecoder(boolean) - * DefaultConfigurationFactory.createImageDecoder()} - */ - public Builder imageDecoder(ImageDecoder imageDecoder) { - this.decoder = imageDecoder; - return this; - } - - /** - * Sets default {@linkplain DisplayImageOptions display image options} for image displaying. These options will - * be used for every {@linkplain ImageLoader#displayImage(String, android.widget.ImageView) image display call} - * without passing custom {@linkplain DisplayImageOptions options}
    - * Default value - {@link DisplayImageOptions#createSimple() Simple options} - */ - public Builder defaultDisplayImageOptions(DisplayImageOptions defaultDisplayImageOptions) { - this.defaultDisplayImageOptions = defaultDisplayImageOptions; - return this; - } - - /** - * Enables detail logging of {@link ImageLoader} work. To prevent detail logs don't call this method. - * Consider {@link com.nostra13.universalimageloader.utils.L#disableLogging()} to disable - * ImageLoader logging completely (even error logs) - */ - public Builder writeDebugLogs() { - this.writeLogs = true; - return this; - } - - /** Builds configured {@link ImageLoaderConfiguration} object */ - public ImageLoaderConfiguration build() { - initEmptyFieldsWithDefaultValues(); - return new ImageLoaderConfiguration(this); - } - - private void initEmptyFieldsWithDefaultValues() { - if (taskExecutor == null) { - taskExecutor = DefaultConfigurationFactory - .createExecutor(threadPoolSize, threadPriority, tasksProcessingType); - } else { - customExecutor = true; - } - if (taskExecutorForCachedImages == null) { - taskExecutorForCachedImages = DefaultConfigurationFactory - .createExecutor(threadPoolSize, threadPriority, tasksProcessingType); - } else { - customExecutorForCachedImages = true; - } - if (diskCache == null) { - if (diskCacheFileNameGenerator == null) { - diskCacheFileNameGenerator = DefaultConfigurationFactory.createFileNameGenerator(); - } - diskCache = DefaultConfigurationFactory - .createDiskCache(context, diskCacheFileNameGenerator, diskCacheSize, diskCacheFileCount); - } - if (memoryCache == null) { - memoryCache = DefaultConfigurationFactory.createMemoryCache(context, memoryCacheSize); - } - if (denyCacheImageMultipleSizesInMemory) { - memoryCache = new FuzzyKeyMemoryCache(memoryCache, MemoryCacheUtils.createFuzzyKeyComparator()); - } - if (downloader == null) { - downloader = DefaultConfigurationFactory.createImageDownloader(context); - } - if (decoder == null) { - decoder = DefaultConfigurationFactory.createImageDecoder(writeLogs); - } - if (defaultDisplayImageOptions == null) { - defaultDisplayImageOptions = DisplayImageOptions.createSimple(); - } - } - } - - /** - * Decorator. Prevents downloads from network (throws {@link IllegalStateException exception}).
    - * In most cases this downloader shouldn't be used directly. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.0 - */ - private static class NetworkDeniedImageDownloader implements ImageDownloader { - - private final ImageDownloader wrappedDownloader; - - public NetworkDeniedImageDownloader(ImageDownloader wrappedDownloader) { - this.wrappedDownloader = wrappedDownloader; - } - - @Override - public InputStream getStream(String imageUri, Object extra) throws IOException { - switch (Scheme.ofUri(imageUri)) { - case HTTP: - case HTTPS: - throw new IllegalStateException(); - default: - return wrappedDownloader.getStream(imageUri, extra); - } - } - } - - /** - * Decorator. Handles this problem on slow networks - * using {@link com.nostra13.universalimageloader.core.assist.FlushedInputStream}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.1 - */ - private static class SlowNetworkImageDownloader implements ImageDownloader { - - private final ImageDownloader wrappedDownloader; - - public SlowNetworkImageDownloader(ImageDownloader wrappedDownloader) { - this.wrappedDownloader = wrappedDownloader; - } - - @Override - public InputStream getStream(String imageUri, Object extra) throws IOException { - InputStream imageStream = wrappedDownloader.getStream(imageUri, extra); - switch (Scheme.ofUri(imageUri)) { - case HTTP: - case HTTPS: - return new FlushedInputStream(imageStream); - default: - return imageStream; - } - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderEngine.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderEngine.java deleted file mode 100644 index 378ce225f..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoaderEngine.java +++ /dev/null @@ -1,217 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.view.View; -import com.nostra13.universalimageloader.core.assist.FailReason; -import com.nostra13.universalimageloader.core.assist.FlushedInputStream; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; - -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; - -/** - * {@link ImageLoader} engine which responsible for {@linkplain LoadAndDisplayImageTask display task} execution. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.7.1 - */ -class ImageLoaderEngine { - - final ImageLoaderConfiguration configuration; - - private Executor taskExecutor; - private Executor taskExecutorForCachedImages; - private Executor taskDistributor; - - private final Map cacheKeysForImageAwares = Collections - .synchronizedMap(new HashMap()); - private final Map uriLocks = new WeakHashMap(); - - private final AtomicBoolean paused = new AtomicBoolean(false); - private final AtomicBoolean networkDenied = new AtomicBoolean(false); - private final AtomicBoolean slowNetwork = new AtomicBoolean(false); - - private final Object pauseLock = new Object(); - - ImageLoaderEngine(ImageLoaderConfiguration configuration) { - this.configuration = configuration; - - taskExecutor = configuration.taskExecutor; - taskExecutorForCachedImages = configuration.taskExecutorForCachedImages; - - taskDistributor = DefaultConfigurationFactory.createTaskDistributor(); - } - - /** Submits task to execution pool */ - void submit(final LoadAndDisplayImageTask task) { - taskDistributor.execute(new Runnable() { - @Override - public void run() { - File image = configuration.diskCache.get(task.getLoadingUri()); - boolean isImageCachedOnDisk = image != null && image.exists(); - initExecutorsIfNeed(); - if (isImageCachedOnDisk) { - taskExecutorForCachedImages.execute(task); - } else { - taskExecutor.execute(task); - } - } - }); - } - - /** Submits task to execution pool */ - void submit(ProcessAndDisplayImageTask task) { - initExecutorsIfNeed(); - taskExecutorForCachedImages.execute(task); - } - - private void initExecutorsIfNeed() { - if (!configuration.customExecutor && ((ExecutorService) taskExecutor).isShutdown()) { - taskExecutor = createTaskExecutor(); - } - if (!configuration.customExecutorForCachedImages && ((ExecutorService) taskExecutorForCachedImages) - .isShutdown()) { - taskExecutorForCachedImages = createTaskExecutor(); - } - } - - private Executor createTaskExecutor() { - return DefaultConfigurationFactory - .createExecutor(configuration.threadPoolSize, configuration.threadPriority, - configuration.tasksProcessingType); - } - - /** - * Returns URI of image which is loading at this moment into passed {@link com.nostra13.universalimageloader.core.imageaware.ImageAware} - */ - String getLoadingUriForView(ImageAware imageAware) { - return cacheKeysForImageAwares.get(imageAware.getId()); - } - - /** - * Associates memoryCacheKey with imageAware. Then it helps to define image URI is loaded into View at - * exact moment. - */ - void prepareDisplayTaskFor(ImageAware imageAware, String memoryCacheKey) { - cacheKeysForImageAwares.put(imageAware.getId(), memoryCacheKey); - } - - /** - * Cancels the task of loading and displaying image for incoming imageAware. - * - * @param imageAware {@link com.nostra13.universalimageloader.core.imageaware.ImageAware} for which display task - * will be cancelled - */ - void cancelDisplayTaskFor(ImageAware imageAware) { - cacheKeysForImageAwares.remove(imageAware.getId()); - } - - /** - * Denies or allows engine to download images from the network.

    If downloads are denied and if image - * isn't cached then {@link ImageLoadingListener#onLoadingFailed(String, View, FailReason)} callback will be fired - * with {@link FailReason.FailType#NETWORK_DENIED} - * - * @param denyNetworkDownloads pass true - to deny engine to download images from the network; false - - * to allow engine to download images from network. - */ - void denyNetworkDownloads(boolean denyNetworkDownloads) { - networkDenied.set(denyNetworkDownloads); - } - - /** - * Sets option whether ImageLoader will use {@link FlushedInputStream} for network downloads to handle this known problem or not. - * - * @param handleSlowNetwork pass true - to use {@link FlushedInputStream} for network downloads; false - * - otherwise. - */ - void handleSlowNetwork(boolean handleSlowNetwork) { - slowNetwork.set(handleSlowNetwork); - } - - /** - * Pauses engine. All new "load&display" tasks won't be executed until ImageLoader is {@link #resume() resumed}.
    Already running tasks are not paused. - */ - void pause() { - paused.set(true); - } - - /** Resumes engine work. Paused "load&display" tasks will continue its work. */ - void resume() { - paused.set(false); - synchronized (pauseLock) { - pauseLock.notifyAll(); - } - } - - /** - * Stops engine, cancels all running and scheduled display image tasks. Clears internal data. - *
    - * NOTE: This method doesn't shutdown - * {@linkplain com.nostra13.universalimageloader.core.ImageLoaderConfiguration.Builder#taskExecutor(java.util.concurrent.Executor) - * custom task executors} if you set them. - */ - void stop() { - if (!configuration.customExecutor) { - ((ExecutorService) taskExecutor).shutdownNow(); - } - if (!configuration.customExecutorForCachedImages) { - ((ExecutorService) taskExecutorForCachedImages).shutdownNow(); - } - - cacheKeysForImageAwares.clear(); - uriLocks.clear(); - } - - void fireCallback(Runnable r) { - taskDistributor.execute(r); - } - - ReentrantLock getLockForUri(String uri) { - ReentrantLock lock = uriLocks.get(uri); - if (lock == null) { - lock = new ReentrantLock(); - uriLocks.put(uri, lock); - } - return lock; - } - - AtomicBoolean getPause() { - return paused; - } - - Object getPauseLock() { - return pauseLock; - } - - boolean isNetworkDenied() { - return networkDenied.get(); - } - - boolean isSlowNetwork() { - return slowNetwork.get(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoadingInfo.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoadingInfo.java deleted file mode 100644 index 2950fc771..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ImageLoadingInfo.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; -import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; - -import java.util.concurrent.locks.ReentrantLock; - -/** - * Information for load'n'display image task - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see com.nostra13.universalimageloader.utils.MemoryCacheUtils - * @see DisplayImageOptions - * @see ImageLoadingListener - * @see com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener - * @since 1.3.1 - */ -final class ImageLoadingInfo { - - final String uri; - final String memoryCacheKey; - final ImageAware imageAware; - final ImageSize targetSize; - final DisplayImageOptions options; - final ImageLoadingListener listener; - final ImageLoadingProgressListener progressListener; - final ReentrantLock loadFromUriLock; - - public ImageLoadingInfo(String uri, ImageAware imageAware, ImageSize targetSize, String memoryCacheKey, - DisplayImageOptions options, ImageLoadingListener listener, - ImageLoadingProgressListener progressListener, ReentrantLock loadFromUriLock) { - this.uri = uri; - this.imageAware = imageAware; - this.targetSize = targetSize; - this.options = options; - this.listener = listener; - this.progressListener = progressListener; - this.loadFromUriLock = loadFromUriLock; - this.memoryCacheKey = memoryCacheKey; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/LoadAndDisplayImageTask.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/LoadAndDisplayImageTask.java deleted file mode 100644 index 90a737b41..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/LoadAndDisplayImageTask.java +++ /dev/null @@ -1,482 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.graphics.Bitmap; -import android.os.Handler; -import com.nostra13.universalimageloader.core.assist.FailReason; -import com.nostra13.universalimageloader.core.assist.FailReason.FailType; -import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.core.decode.ImageDecoder; -import com.nostra13.universalimageloader.core.decode.ImageDecodingInfo; -import com.nostra13.universalimageloader.core.download.ImageDownloader; -import com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; -import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; -import com.nostra13.universalimageloader.utils.IoUtils; -import com.nostra13.universalimageloader.utils.L; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Presents load'n'display image task. Used to load image from Internet or file system, decode it to {@link Bitmap}, and - * display it in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware} using {@link DisplayBitmapTask}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ImageLoaderConfiguration - * @see ImageLoadingInfo - * @since 1.3.1 - */ -final class LoadAndDisplayImageTask implements Runnable, IoUtils.CopyListener { - - private static final String LOG_WAITING_FOR_RESUME = "ImageLoader is paused. Waiting... [%s]"; - private static final String LOG_RESUME_AFTER_PAUSE = ".. Resume loading [%s]"; - private static final String LOG_DELAY_BEFORE_LOADING = "Delay %d ms before loading... [%s]"; - private static final String LOG_START_DISPLAY_IMAGE_TASK = "Start display image task [%s]"; - private static final String LOG_WAITING_FOR_IMAGE_LOADED = "Image already is loading. Waiting... [%s]"; - private static final String LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING = "...Get cached bitmap from memory after waiting. [%s]"; - private static final String LOG_LOAD_IMAGE_FROM_NETWORK = "Load image from network [%s]"; - private static final String LOG_LOAD_IMAGE_FROM_DISK_CACHE = "Load image from disk cache [%s]"; - private static final String LOG_RESIZE_CACHED_IMAGE_FILE = "Resize image in disk cache [%s]"; - private static final String LOG_PREPROCESS_IMAGE = "PreProcess image before caching in memory [%s]"; - private static final String LOG_POSTPROCESS_IMAGE = "PostProcess image before displaying [%s]"; - private static final String LOG_CACHE_IMAGE_IN_MEMORY = "Cache image in memory [%s]"; - private static final String LOG_CACHE_IMAGE_ON_DISK = "Cache image on disk [%s]"; - private static final String LOG_PROCESS_IMAGE_BEFORE_CACHE_ON_DISK = "Process image before cache on disk [%s]"; - private static final String LOG_TASK_CANCELLED_IMAGEAWARE_REUSED = "ImageAware is reused for another image. Task is cancelled. [%s]"; - private static final String LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED = "ImageAware was collected by GC. Task is cancelled. [%s]"; - private static final String LOG_TASK_INTERRUPTED = "Task was interrupted [%s]"; - - private static final String ERROR_NO_IMAGE_STREAM = "No stream for image [%s]"; - private static final String ERROR_PRE_PROCESSOR_NULL = "Pre-processor returned null [%s]"; - private static final String ERROR_POST_PROCESSOR_NULL = "Post-processor returned null [%s]"; - private static final String ERROR_PROCESSOR_FOR_DISK_CACHE_NULL = "Bitmap processor for disk cache returned null [%s]"; - - private final ImageLoaderEngine engine; - private final ImageLoadingInfo imageLoadingInfo; - private final Handler handler; - - // Helper references - private final ImageLoaderConfiguration configuration; - private final ImageDownloader downloader; - private final ImageDownloader networkDeniedDownloader; - private final ImageDownloader slowNetworkDownloader; - private final ImageDecoder decoder; - final String uri; - private final String memoryCacheKey; - final ImageAware imageAware; - private final ImageSize targetSize; - final DisplayImageOptions options; - final ImageLoadingListener listener; - final ImageLoadingProgressListener progressListener; - private final boolean syncLoading; - - // State vars - private LoadedFrom loadedFrom = LoadedFrom.NETWORK; - - public LoadAndDisplayImageTask(ImageLoaderEngine engine, ImageLoadingInfo imageLoadingInfo, Handler handler) { - this.engine = engine; - this.imageLoadingInfo = imageLoadingInfo; - this.handler = handler; - - configuration = engine.configuration; - downloader = configuration.downloader; - networkDeniedDownloader = configuration.networkDeniedDownloader; - slowNetworkDownloader = configuration.slowNetworkDownloader; - decoder = configuration.decoder; - uri = imageLoadingInfo.uri; - memoryCacheKey = imageLoadingInfo.memoryCacheKey; - imageAware = imageLoadingInfo.imageAware; - targetSize = imageLoadingInfo.targetSize; - options = imageLoadingInfo.options; - listener = imageLoadingInfo.listener; - progressListener = imageLoadingInfo.progressListener; - syncLoading = options.isSyncLoading(); - } - - @Override - public void run() { - if (waitIfPaused()) return; - if (delayIfNeed()) return; - - ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock; - L.d(LOG_START_DISPLAY_IMAGE_TASK, memoryCacheKey); - if (loadFromUriLock.isLocked()) { - L.d(LOG_WAITING_FOR_IMAGE_LOADED, memoryCacheKey); - } - - loadFromUriLock.lock(); - Bitmap bmp; - try { - checkTaskNotActual(); - - bmp = configuration.memoryCache.get(memoryCacheKey); - if (bmp == null || bmp.isRecycled()) { - bmp = tryLoadBitmap(); - if (bmp == null) return; // listener callback already was fired - - checkTaskNotActual(); - checkTaskInterrupted(); - - if (options.shouldPreProcess()) { - L.d(LOG_PREPROCESS_IMAGE, memoryCacheKey); - bmp = options.getPreProcessor().process(bmp); - if (bmp == null) { - L.e(ERROR_PRE_PROCESSOR_NULL, memoryCacheKey); - } - } - - if (bmp != null && options.isCacheInMemory()) { - L.d(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey); - configuration.memoryCache.put(memoryCacheKey, bmp); - } - } else { - loadedFrom = LoadedFrom.MEMORY_CACHE; - L.d(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey); - } - - if (bmp != null && options.shouldPostProcess()) { - L.d(LOG_POSTPROCESS_IMAGE, memoryCacheKey); - bmp = options.getPostProcessor().process(bmp); - if (bmp == null) { - L.e(ERROR_POST_PROCESSOR_NULL, memoryCacheKey); - } - } - checkTaskNotActual(); - checkTaskInterrupted(); - } catch (TaskCancelledException e) { - fireCancelEvent(); - return; - } finally { - loadFromUriLock.unlock(); - } - - DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine, loadedFrom); - runTask(displayBitmapTask, syncLoading, handler, engine); - } - - /** @return true - if task should be interrupted; false - otherwise */ - private boolean waitIfPaused() { - AtomicBoolean pause = engine.getPause(); - if (pause.get()) { - synchronized (engine.getPauseLock()) { - if (pause.get()) { - L.d(LOG_WAITING_FOR_RESUME, memoryCacheKey); - try { - engine.getPauseLock().wait(); - } catch (InterruptedException e) { - L.e(LOG_TASK_INTERRUPTED, memoryCacheKey); - return true; - } - L.d(LOG_RESUME_AFTER_PAUSE, memoryCacheKey); - } - } - } - return isTaskNotActual(); - } - - /** @return true - if task should be interrupted; false - otherwise */ - private boolean delayIfNeed() { - if (options.shouldDelayBeforeLoading()) { - L.d(LOG_DELAY_BEFORE_LOADING, options.getDelayBeforeLoading(), memoryCacheKey); - try { - Thread.sleep(options.getDelayBeforeLoading()); - } catch (InterruptedException e) { - L.e(LOG_TASK_INTERRUPTED, memoryCacheKey); - return true; - } - return isTaskNotActual(); - } - return false; - } - - private Bitmap tryLoadBitmap() throws TaskCancelledException { - Bitmap bitmap = null; - try { - File imageFile = configuration.diskCache.get(uri); - if (imageFile != null && imageFile.exists() && imageFile.length() > 0) { - L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey); - loadedFrom = LoadedFrom.DISC_CACHE; - - checkTaskNotActual(); - bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath())); - } - if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { - L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey); - loadedFrom = LoadedFrom.NETWORK; - - String imageUriForDecoding = uri; - if (options.isCacheOnDisk() && tryCacheImageOnDisk()) { - imageFile = configuration.diskCache.get(uri); - if (imageFile != null) { - imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath()); - } - } - - checkTaskNotActual(); - bitmap = decodeImage(imageUriForDecoding); - - if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { - fireFailEvent(FailType.DECODING_ERROR, null); - } - } - } catch (IllegalStateException e) { - fireFailEvent(FailType.NETWORK_DENIED, null); - } catch (TaskCancelledException e) { - throw e; - } catch (IOException e) { - L.e(e); - fireFailEvent(FailType.IO_ERROR, e); - } catch (OutOfMemoryError e) { - L.e(e); - fireFailEvent(FailType.OUT_OF_MEMORY, e); - } catch (Throwable e) { - L.e(e); - fireFailEvent(FailType.UNKNOWN, e); - } - return bitmap; - } - - private Bitmap decodeImage(String imageUri) throws IOException { - ViewScaleType viewScaleType = imageAware.getScaleType(); - ImageDecodingInfo decodingInfo = new ImageDecodingInfo(memoryCacheKey, imageUri, uri, targetSize, viewScaleType, - getDownloader(), options); - return decoder.decode(decodingInfo); - } - - /** @return true - if image was downloaded successfully; false - otherwise */ - private boolean tryCacheImageOnDisk() throws TaskCancelledException { - L.d(LOG_CACHE_IMAGE_ON_DISK, memoryCacheKey); - - boolean loaded; - try { - loaded = downloadImage(); - if (loaded) { - int width = configuration.maxImageWidthForDiskCache; - int height = configuration.maxImageHeightForDiskCache; - if (width > 0 || height > 0) { - L.d(LOG_RESIZE_CACHED_IMAGE_FILE, memoryCacheKey); - resizeAndSaveImage(width, height); // TODO : process boolean result - } - } - } catch (IOException e) { - L.e(e); - loaded = false; - } - return loaded; - } - - private boolean downloadImage() throws IOException { - InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader()); - if (is == null) { - L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey); - return false; - } else { - try { - return configuration.diskCache.save(uri, is, this); - } finally { - IoUtils.closeSilently(is); - } - } - } - - /** Decodes image file into Bitmap, resize it and save it back */ - private boolean resizeAndSaveImage(int maxWidth, int maxHeight) throws IOException { - // Decode image file, compress and re-save it - boolean saved = false; - File targetFile = configuration.diskCache.get(uri); - if (targetFile != null && targetFile.exists()) { - ImageSize targetImageSize = new ImageSize(maxWidth, maxHeight); - DisplayImageOptions specialOptions = new DisplayImageOptions.Builder().cloneFrom(options) - .imageScaleType(ImageScaleType.IN_SAMPLE_INT).build(); - ImageDecodingInfo decodingInfo = new ImageDecodingInfo(memoryCacheKey, - Scheme.FILE.wrap(targetFile.getAbsolutePath()), uri, targetImageSize, ViewScaleType.FIT_INSIDE, - getDownloader(), specialOptions); - Bitmap bmp = decoder.decode(decodingInfo); - if (bmp != null && configuration.processorForDiskCache != null) { - L.d(LOG_PROCESS_IMAGE_BEFORE_CACHE_ON_DISK, memoryCacheKey); - bmp = configuration.processorForDiskCache.process(bmp); - if (bmp == null) { - L.e(ERROR_PROCESSOR_FOR_DISK_CACHE_NULL, memoryCacheKey); - } - } - if (bmp != null) { - saved = configuration.diskCache.save(uri, bmp); - bmp.recycle(); - } - } - return saved; - } - - @Override - public boolean onBytesCopied(int current, int total) { - return syncLoading || fireProgressEvent(current, total); - } - - /** @return true - if loading should be continued; false - if loading should be interrupted */ - private boolean fireProgressEvent(final int current, final int total) { - if (isTaskInterrupted() || isTaskNotActual()) return false; - if (progressListener != null) { - Runnable r = new Runnable() { - @Override - public void run() { - progressListener.onProgressUpdate(uri, imageAware.getWrappedView(), current, total); - } - }; - runTask(r, false, handler, engine); - } - return true; - } - - private void fireFailEvent(final FailType failType, final Throwable failCause) { - if (syncLoading || isTaskInterrupted() || isTaskNotActual()) return; - Runnable r = new Runnable() { - @Override - public void run() { - if (options.shouldShowImageOnFail()) { - imageAware.setImageDrawable(options.getImageOnFail(configuration.resources)); - } - listener.onLoadingFailed(uri, imageAware.getWrappedView(), new FailReason(failType, failCause)); - } - }; - runTask(r, false, handler, engine); - } - - private void fireCancelEvent() { - if (syncLoading || isTaskInterrupted()) return; - Runnable r = new Runnable() { - @Override - public void run() { - listener.onLoadingCancelled(uri, imageAware.getWrappedView()); - } - }; - runTask(r, false, handler, engine); - } - - private ImageDownloader getDownloader() { - ImageDownloader d; - if (engine.isNetworkDenied()) { - d = networkDeniedDownloader; - } else if (engine.isSlowNetwork()) { - d = slowNetworkDownloader; - } else { - d = downloader; - } - return d; - } - - /** - * @throws TaskCancelledException if task is not actual (target ImageAware is collected by GC or the image URI of - * this task doesn't match to image URI which is actual for current ImageAware at - * this moment) - */ - private void checkTaskNotActual() throws TaskCancelledException { - checkViewCollected(); - checkViewReused(); - } - - /** - * @return true - if task is not actual (target ImageAware is collected by GC or the image URI of this task - * doesn't match to image URI which is actual for current ImageAware at this moment)); false - otherwise - */ - private boolean isTaskNotActual() { - return isViewCollected() || isViewReused(); - } - - /** @throws TaskCancelledException if target ImageAware is collected */ - private void checkViewCollected() throws TaskCancelledException { - if (isViewCollected()) { - throw new TaskCancelledException(); - } - } - - /** @return true - if target ImageAware is collected by GC; false - otherwise */ - private boolean isViewCollected() { - if (imageAware.isCollected()) { - L.d(LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED, memoryCacheKey); - return true; - } - return false; - } - - /** @throws TaskCancelledException if target ImageAware is collected by GC */ - private void checkViewReused() throws TaskCancelledException { - if (isViewReused()) { - throw new TaskCancelledException(); - } - } - - /** @return true - if current ImageAware is reused for displaying another image; false - otherwise */ - private boolean isViewReused() { - String currentCacheKey = engine.getLoadingUriForView(imageAware); - // Check whether memory cache key (image URI) for current ImageAware is actual. - // If ImageAware is reused for another task then current task should be cancelled. - boolean imageAwareWasReused = !memoryCacheKey.equals(currentCacheKey); - if (imageAwareWasReused) { - L.d(LOG_TASK_CANCELLED_IMAGEAWARE_REUSED, memoryCacheKey); - return true; - } - return false; - } - - /** @throws TaskCancelledException if current task was interrupted */ - private void checkTaskInterrupted() throws TaskCancelledException { - if (isTaskInterrupted()) { - throw new TaskCancelledException(); - } - } - - /** @return true - if current task was interrupted; false - otherwise */ - private boolean isTaskInterrupted() { - if (Thread.interrupted()) { - L.d(LOG_TASK_INTERRUPTED, memoryCacheKey); - return true; - } - return false; - } - - String getLoadingUri() { - return uri; - } - - static void runTask(Runnable r, boolean sync, Handler handler, ImageLoaderEngine engine) { - if (sync) { - r.run(); - } else if (handler == null) { - engine.fireCallback(r); - } else { - handler.post(r); - } - } - - /** - * Exceptions for case when task is cancelled (thread is interrupted, image view is reused for another task, view is - * collected by GC). - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.1 - */ - class TaskCancelledException extends Exception { - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ProcessAndDisplayImageTask.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ProcessAndDisplayImageTask.java deleted file mode 100644 index d09dc5a3a..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/ProcessAndDisplayImageTask.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core; - -import android.graphics.Bitmap; -import android.os.Handler; -import android.widget.ImageView; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.process.BitmapProcessor; -import com.nostra13.universalimageloader.utils.L; - -/** - * Presents process'n'display image task. Processes image {@linkplain Bitmap} and display it in {@link ImageView} using - * {@link DisplayBitmapTask}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.0 - */ -final class ProcessAndDisplayImageTask implements Runnable { - - private static final String LOG_POSTPROCESS_IMAGE = "PostProcess image before displaying [%s]"; - - private final ImageLoaderEngine engine; - private final Bitmap bitmap; - private final ImageLoadingInfo imageLoadingInfo; - private final Handler handler; - - public ProcessAndDisplayImageTask(ImageLoaderEngine engine, Bitmap bitmap, ImageLoadingInfo imageLoadingInfo, - Handler handler) { - this.engine = engine; - this.bitmap = bitmap; - this.imageLoadingInfo = imageLoadingInfo; - this.handler = handler; - } - - @Override - public void run() { - L.d(LOG_POSTPROCESS_IMAGE, imageLoadingInfo.memoryCacheKey); - - BitmapProcessor processor = imageLoadingInfo.options.getPostProcessor(); - Bitmap processedBitmap = processor.process(bitmap); - DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(processedBitmap, imageLoadingInfo, engine, - LoadedFrom.MEMORY_CACHE); - LoadAndDisplayImageTask.runTask(displayBitmapTask, imageLoadingInfo.options.isSyncLoading(), handler, engine); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ContentLengthInputStream.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ContentLengthInputStream.java deleted file mode 100644 index 316a52d06..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ContentLengthInputStream.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Decorator for {@link java.io.InputStream InputStream}. Provides possibility to return defined stream length by - * {@link #available()} method. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com), Mariotaku - * @since 1.9.1 - */ -public class ContentLengthInputStream extends InputStream { - - private final InputStream stream; - private final int length; - - public ContentLengthInputStream(InputStream stream, int length) { - this.stream = stream; - this.length = length; - } - - @Override - public int available() { - return length; - } - - @Override - public void close() throws IOException { - stream.close(); - } - - @Override - public void mark(int readLimit) { - stream.mark(readLimit); - } - - @Override - public int read() throws IOException { - return stream.read(); - } - - @Override - public int read(byte[] buffer) throws IOException { - return stream.read(buffer); - } - - @Override - public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { - return stream.read(buffer, byteOffset, byteCount); - } - - @Override - public void reset() throws IOException { - stream.reset(); - } - - @Override - public long skip(long byteCount) throws IOException { - return stream.skip(byteCount); - } - - @Override - public boolean markSupported() { - return stream.markSupported(); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FailReason.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FailReason.java deleted file mode 100644 index 061acffe1..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FailReason.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -/** - * Presents the reason why image loading and displaying was failed - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class FailReason { - - private final FailType type; - - private final Throwable cause; - - public FailReason(FailType type, Throwable cause) { - this.type = type; - this.cause = cause; - } - - /** @return {@linkplain FailType Fail type} */ - public FailType getType() { - return type; - } - - /** @return Thrown exception/error, can be null */ - public Throwable getCause() { - return cause; - } - - /** Presents type of fail while image loading */ - public static enum FailType { - /** Input/output error. Can be caused by network communication fail or error while caching image on file system. */ - IO_ERROR, - /** - * Error while - * {@linkplain android.graphics.BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options) - * decode image to Bitmap} - */ - DECODING_ERROR, - /** - * {@linkplain com.nostra13.universalimageloader.core.ImageLoader#denyNetworkDownloads(boolean) Network - * downloads are denied} and requested image wasn't cached in disk cache before. - */ - NETWORK_DENIED, - /** Not enough memory to create needed Bitmap for image */ - OUT_OF_MEMORY, - /** Unknown error was occurred while loading image */ - UNKNOWN - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FlushedInputStream.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FlushedInputStream.java deleted file mode 100644 index b2e450607..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/FlushedInputStream.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.nostra13.universalimageloader.core.assist; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Many streams obtained over slow connection show this - * problem. - */ -public class FlushedInputStream extends FilterInputStream { - - public FlushedInputStream(InputStream inputStream) { - super(inputStream); - } - - @Override - public long skip(long n) throws IOException { - long totalBytesSkipped = 0L; - while (totalBytesSkipped < n) { - long bytesSkipped = in.skip(n - totalBytesSkipped); - if (bytesSkipped == 0L) { - int by_te = read(); - if (by_te < 0) { - break; // we reached EOF - } else { - bytesSkipped = 1; // we read one byte - } - } - totalBytesSkipped += bytesSkipped; - } - return totalBytesSkipped; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageScaleType.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageScaleType.java deleted file mode 100644 index 4dfd894e0..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageScaleType.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -/** - * Type of image scaling during decoding. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.5.0 - */ -public enum ImageScaleType { - /** Image won't be scaled */ - NONE, - /** - * Image will be scaled down only if image size is greater than - * {@linkplain javax.microedition.khronos.opengles.GL10#GL_MAX_TEXTURE_SIZE maximum acceptable texture size}. - * Usually it's 2048x2048.
    - * If Bitmap is expected to display than it must not exceed this size (otherwise you'll get the exception - * "OpenGLRenderer: Bitmap too large to be uploaded into a texture".
    - * Image will be subsampled in an integer number of times (1, 2, 3, ...) to maximum texture size of device. - */ - NONE_SAFE, - /** - * Image will be reduces 2-fold until next reduce step make image smaller target size.
    - * It's fast type and it's preferable for usage in lists/grids/galleries (and other - * {@linkplain android.widget.AdapterView adapter-views}) .
    - * Relates to {@link android.graphics.BitmapFactory.Options#inSampleSize}
    - * Note: If original image size is smaller than target size then original image won't be scaled. - */ - IN_SAMPLE_POWER_OF_2, - /** - * Image will be subsampled in an integer number of times (1, 2, 3, ...). Use it if memory economy is quite - * important.
    - * Relates to {@link android.graphics.BitmapFactory.Options#inSampleSize}
    - * Note: If original image size is smaller than target size then original image won't be scaled. - */ - IN_SAMPLE_INT, - /** - * Image will scaled-down exactly to target size (scaled width or height or both will be equal to target size; - * depends on {@linkplain android.widget.ImageView.ScaleType ImageView's scale type}). Use it if memory economy is - * critically important.
    - * Note: If original image size is smaller than target size then original image won't be scaled.
    - *
    - * NOTE: For creating result Bitmap (of exact size) additional Bitmap will be created with - * {@link android.graphics.Bitmap#createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean) - * Bitmap.createBitmap(...)}.
    - * Cons: Saves memory by keeping smaller Bitmap in memory cache (comparing with IN_SAMPLE... scale types)
    - * Pros: Requires more memory in one time for creation of result Bitmap. - */ - EXACTLY, - /** - * Image will scaled exactly to target size (scaled width or height or both will be equal to target size; depends on - * {@linkplain android.widget.ImageView.ScaleType ImageView's scale type}). Use it if memory economy is critically - * important.
    - * Note: If original image size is smaller than target size then original image will be stretched to - * target size.
    - *
    - * NOTE: For creating result Bitmap (of exact size) additional Bitmap will be created with - * {@link android.graphics.Bitmap#createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean) - * Bitmap.createBitmap(...)}.
    - * Cons: Saves memory by keeping smaller Bitmap in memory cache (comparing with IN_SAMPLE... scale types)
    - * Pros: Requires more memory in one time for creation of result Bitmap. - */ - EXACTLY_STRETCHED -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageSize.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageSize.java deleted file mode 100644 index 54c97ca64..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ImageSize.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -/** - * Present width and height values - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public class ImageSize { - - private static final int TO_STRING_MAX_LENGHT = 9; // "9999x9999".length() - private static final String SEPARATOR = "x"; - - private final int width; - private final int height; - - public ImageSize(int width, int height) { - this.width = width; - this.height = height; - } - - public ImageSize(int width, int height, int rotation) { - if (rotation % 180 == 0) { - this.width = width; - this.height = height; - } else { - this.width = height; - this.height = width; - } - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - /** Scales down dimensions in sampleSize times. Returns new object. */ - public ImageSize scaleDown(int sampleSize) { - return new ImageSize(width / sampleSize, height / sampleSize); - } - - /** Scales dimensions according to incoming scale. Returns new object. */ - public ImageSize scale(float scale) { - return new ImageSize((int) (width * scale), (int) (height * scale)); - } - - @Override - public String toString() { - return new StringBuilder(TO_STRING_MAX_LENGHT).append(width).append(SEPARATOR).append(height).toString(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/LoadedFrom.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/LoadedFrom.java deleted file mode 100644 index 6889ce45a..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/LoadedFrom.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.nostra13.universalimageloader.core.assist; - -/** - * Source image loaded from. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - */ -public enum LoadedFrom { - NETWORK, DISC_CACHE, MEMORY_CACHE -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/QueueProcessingType.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/QueueProcessingType.java deleted file mode 100644 index 0bbca5868..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/QueueProcessingType.java +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -/** - * Queue processing type which will be used for display task processing - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.6.3 - */ -public enum QueueProcessingType { - FIFO, LIFO -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ViewScaleType.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ViewScaleType.java deleted file mode 100644 index c618cfba8..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/ViewScaleType.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.assist; - -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; - -/** - * Simplify {@linkplain ScaleType ImageView's scale type} to 2 types: {@link #FIT_INSIDE} and {@link #CROP} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.6.1 - */ -public enum ViewScaleType { - /** - * Scale the image uniformly (maintain the image's aspect ratio) so that at least one dimension (width or height) of - * the image will be equal to or less the corresponding dimension of the view. - */ - FIT_INSIDE, - /** - * Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the - * image will be equal to or larger than the corresponding dimension of the view. - */ - CROP; - - /** - * Defines scale type of ImageView. - * - * @param imageView {@link ImageView} - * @return {@link #FIT_INSIDE} for - *
      - *
    • {@link ScaleType#FIT_CENTER}
    • - *
    • {@link ScaleType#FIT_XY}
    • - *
    • {@link ScaleType#FIT_START}
    • - *
    • {@link ScaleType#FIT_END}
    • - *
    • {@link ScaleType#CENTER_INSIDE}
    • - *
    - * {@link #CROP} for - *
      - *
    • {@link ScaleType#CENTER}
    • - *
    • {@link ScaleType#CENTER_CROP}
    • - *
    • {@link ScaleType#MATRIX}
    • - *
    - */ - public static ViewScaleType fromImageView(ImageView imageView) { - switch (imageView.getScaleType()) { - case FIT_CENTER: - case FIT_XY: - case FIT_START: - case FIT_END: - case CENTER_INSIDE: - return FIT_INSIDE; - case MATRIX: - case CENTER: - case CENTER_CROP: - default: - return CROP; - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/BlockingDeque.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/BlockingDeque.java deleted file mode 100644 index 571eb6ca5..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/BlockingDeque.java +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain - */ - -package com.nostra13.universalimageloader.core.assist.deque; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * A {@link Deque} that additionally supports blocking operations that wait - * for the deque to become non-empty when retrieving an element, and wait for - * space to become available in the deque when storing an element. - * - *

    BlockingDeque methods come in four forms, with different ways - * of handling operations that cannot be satisfied immediately, but may be - * satisfied at some point in the future: - * one throws an exception, the second returns a special value (either - * null or false, depending on the operation), the third - * blocks the current thread indefinitely until the operation can succeed, - * and the fourth blocks for only a given maximum time limit before giving - * up. These methods are summarized in the following table: - * - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    First Element (Head)
    Throws exceptionSpecial valueBlocksTimes out
    Insert{@link #addFirst addFirst(e)}{@link #offerFirst offerFirst(e)}{@link #putFirst putFirst(e)}{@link #offerFirst offerFirst(e, time, unit)}
    Remove{@link #removeFirst removeFirst()}{@link #pollFirst pollFirst()}{@link #takeFirst takeFirst()}{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}
    Examine{@link #getFirst getFirst()}{@link #peekFirst peekFirst()}not applicablenot applicable
    Last Element (Tail)
    Throws exceptionSpecial valueBlocksTimes out
    Insert{@link #addLast addLast(e)}{@link #offerLast offerLast(e)}{@link #putLast putLast(e)}{@link #offerLast offerLast(e, time, unit)}
    Remove{@link #removeLast() removeLast()}{@link #pollLast() pollLast()}{@link #takeLast takeLast()}{@link #pollLast(long, TimeUnit) pollLast(time, unit)}
    Examine{@link #getLast getLast()}{@link #peekLast peekLast()}not applicablenot applicable
    - * - *

    Like any {@link BlockingQueue}, a BlockingDeque is thread safe, - * does not permit null elements, and may (or may not) be - * capacity-constrained. - * - *

    A BlockingDeque implementation may be used directly as a FIFO - * BlockingQueue. The methods inherited from the - * BlockingQueue interface are precisely equivalent to - * BlockingDeque methods as indicated in the following table: - * - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    BlockingQueue Method Equivalent BlockingDeque Method
    Insert
    {@link #add add(e)}{@link #addLast addLast(e)}
    {@link #offer offer(e)}{@link #offerLast offerLast(e)}
    {@link #put put(e)}{@link #putLast putLast(e)}
    {@link #offer offer(e, time, unit)}{@link #offerLast offerLast(e, time, unit)}
    Remove
    {@link #remove() remove()}{@link #removeFirst() removeFirst()}
    {@link #poll() poll()}{@link #pollFirst() pollFirst()}
    {@link #take() take()}{@link #takeFirst() takeFirst()}
    {@link #poll(long, TimeUnit) poll(time, unit)}{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}
    Examine
    {@link #element() element()}{@link #getFirst() getFirst()}
    {@link #peek() peek()}{@link #peekFirst() peekFirst()}
    - * - *

    Memory consistency effects: As with other concurrent - * collections, actions in a thread prior to placing an object into a - * {@code BlockingDeque} - * happen-before - * actions subsequent to the access or removal of that element from - * the {@code BlockingDeque} in another thread. - * - *

    This interface is a member of the - * - * Java Collections Framework. - * - * @since 1.6 - * @author Doug Lea - * @param the type of elements held in this collection - */ -public interface BlockingDeque extends BlockingQueue, Deque { - /* - * We have "diamond" multiple interface inheritance here, and that - * introduces ambiguities. Methods might end up with different - * specs depending on the branch chosen by javadoc. Thus a lot of - * methods specs here are copied from superinterfaces. - */ - - /** - * Inserts the specified element at the front of this deque if it is - * possible to do so immediately without violating capacity restrictions, - * throwing an IllegalStateException if no space is currently - * available. When using a capacity-restricted deque, it is generally - * preferable to use {@link #offerFirst offerFirst}. - * - * @param e the element to add - * @throws IllegalStateException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException {@inheritDoc} - */ - void addFirst(E e); - - /** - * Inserts the specified element at the end of this deque if it is - * possible to do so immediately without violating capacity restrictions, - * throwing an IllegalStateException if no space is currently - * available. When using a capacity-restricted deque, it is generally - * preferable to use {@link #offerLast offerLast}. - * - * @param e the element to add - * @throws IllegalStateException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException {@inheritDoc} - */ - void addLast(E e); - - /** - * Inserts the specified element at the front of this deque if it is - * possible to do so immediately without violating capacity restrictions, - * returning true upon success and false if no space is - * currently available. - * When using a capacity-restricted deque, this method is generally - * preferable to the {@link #addFirst addFirst} method, which can - * fail to insert an element only by throwing an exception. - * - * @param e the element to add - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException {@inheritDoc} - */ - boolean offerFirst(E e); - - /** - * Inserts the specified element at the end of this deque if it is - * possible to do so immediately without violating capacity restrictions, - * returning true upon success and false if no space is - * currently available. - * When using a capacity-restricted deque, this method is generally - * preferable to the {@link #addLast addLast} method, which can - * fail to insert an element only by throwing an exception. - * - * @param e the element to add - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException {@inheritDoc} - */ - boolean offerLast(E e); - - /** - * Inserts the specified element at the front of this deque, - * waiting if necessary for space to become available. - * - * @param e the element to add - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void putFirst(E e) throws InterruptedException; - - /** - * Inserts the specified element at the end of this deque, - * waiting if necessary for space to become available. - * - * @param e the element to add - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void putLast(E e) throws InterruptedException; - - /** - * Inserts the specified element at the front of this deque, - * waiting up to the specified wait time if necessary for space to - * become available. - * - * @param e the element to add - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return true if successful, or false if - * the specified waiting time elapses before space is available - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offerFirst(E e, long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Inserts the specified element at the end of this deque, - * waiting up to the specified wait time if necessary for space to - * become available. - * - * @param e the element to add - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return true if successful, or false if - * the specified waiting time elapses before space is available - * @throws InterruptedException if interrupted while waiting - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offerLast(E e, long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Retrieves and removes the first element of this deque, waiting - * if necessary until an element becomes available. - * - * @return the head of this deque - * @throws InterruptedException if interrupted while waiting - */ - E takeFirst() throws InterruptedException; - - /** - * Retrieves and removes the last element of this deque, waiting - * if necessary until an element becomes available. - * - * @return the tail of this deque - * @throws InterruptedException if interrupted while waiting - */ - E takeLast() throws InterruptedException; - - /** - * Retrieves and removes the first element of this deque, waiting - * up to the specified wait time if necessary for an element to - * become available. - * - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return the head of this deque, or null if the specified - * waiting time elapses before an element is available - * @throws InterruptedException if interrupted while waiting - */ - E pollFirst(long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Retrieves and removes the last element of this deque, waiting - * up to the specified wait time if necessary for an element to - * become available. - * - * @param timeout how long to wait before giving up, in units of - * unit - * @param unit a TimeUnit determining how to interpret the - * timeout parameter - * @return the tail of this deque, or null if the specified - * waiting time elapses before an element is available - * @throws InterruptedException if interrupted while waiting - */ - E pollLast(long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Removes the first occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element e such that - * o.equals(e) (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - * @param o element to be removed from this deque, if present - * @return true if an element was removed as a result of this call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - boolean removeFirstOccurrence(Object o); - - /** - * Removes the last occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the last element e such that - * o.equals(e) (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - * @param o element to be removed from this deque, if present - * @return true if an element was removed as a result of this call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - boolean removeLastOccurrence(Object o); - - // *** BlockingQueue methods *** - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and throwing an - * IllegalStateException if no space is currently available. - * When using a capacity-restricted deque, it is generally preferable to - * use {@link #offer offer}. - * - *

    This method is equivalent to {@link #addLast addLast}. - * - * @param e the element to add - * @throws IllegalStateException {@inheritDoc} - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean add(E e); - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and false if no space is currently - * available. When using a capacity-restricted deque, this method is - * generally preferable to the {@link #add} method, which can fail to - * insert an element only by throwing an exception. - * - *

    This method is equivalent to {@link #offerLast offerLast}. - * - * @param e the element to add - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offer(E e); - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque), waiting if necessary for - * space to become available. - * - *

    This method is equivalent to {@link #putLast putLast}. - * - * @param e the element to add - * @throws InterruptedException {@inheritDoc} - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void put(E e) throws InterruptedException; - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque), waiting up to the - * specified wait time if necessary for space to become available. - * - *

    This method is equivalent to - * {@link #offerLast offerLast}. - * - * @param e the element to add - * @return true if the element was added to this deque, else - * false - * @throws InterruptedException {@inheritDoc} - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offer(E e, long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque). - * This method differs from {@link #poll poll} only in that it - * throws an exception if this deque is empty. - * - *

    This method is equivalent to {@link #removeFirst() removeFirst}. - * - * @return the head of the queue represented by this deque - * @throws NoSuchElementException if this deque is empty - */ - E remove(); - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque), or returns - * null if this deque is empty. - * - *

    This method is equivalent to {@link #pollFirst()}. - * - * @return the head of this deque, or null if this deque is empty - */ - E poll(); - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque), waiting if - * necessary until an element becomes available. - * - *

    This method is equivalent to {@link #takeFirst() takeFirst}. - * - * @return the head of this deque - * @throws InterruptedException if interrupted while waiting - */ - E take() throws InterruptedException; - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque), waiting up to the - * specified wait time if necessary for an element to become available. - * - *

    This method is equivalent to - * {@link #pollFirst(long,TimeUnit) pollFirst}. - * - * @return the head of this deque, or null if the - * specified waiting time elapses before an element is available - * @throws InterruptedException if interrupted while waiting - */ - E poll(long timeout, TimeUnit unit) - throws InterruptedException; - - /** - * Retrieves, but does not remove, the head of the queue represented by - * this deque (in other words, the first element of this deque). - * This method differs from {@link #peek peek} only in that it throws an - * exception if this deque is empty. - * - *

    This method is equivalent to {@link #getFirst() getFirst}. - * - * @return the head of this deque - * @throws NoSuchElementException if this deque is empty - */ - E element(); - - /** - * Retrieves, but does not remove, the head of the queue represented by - * this deque (in other words, the first element of this deque), or - * returns null if this deque is empty. - * - *

    This method is equivalent to {@link #peekFirst() peekFirst}. - * - * @return the head of this deque, or null if this deque is empty - */ - E peek(); - - /** - * Removes the first occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element e such that - * o.equals(e) (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - *

    This method is equivalent to - * {@link #removeFirstOccurrence removeFirstOccurrence}. - * - * @param o element to be removed from this deque, if present - * @return true if this deque changed as a result of the call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - boolean remove(Object o); - - /** - * Returns true if this deque contains the specified element. - * More formally, returns true if and only if this deque contains - * at least one element e such that o.equals(e). - * - * @param o object to be checked for containment in this deque - * @return true if this deque contains the specified element - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null (optional) - */ - public boolean contains(Object o); - - /** - * Returns the number of elements in this deque. - * - * @return the number of elements in this deque - */ - public int size(); - - /** - * Returns an iterator over the elements in this deque in proper sequence. - * The elements will be returned in order from first (head) to last (tail). - * - * @return an iterator over the elements in this deque in proper sequence - */ - Iterator iterator(); - - // *** Stack methods *** - - /** - * Pushes an element onto the stack represented by this deque. In other - * words, inserts the element at the front of this deque unless it would - * violate capacity restrictions. - * - *

    This method is equivalent to {@link #addFirst addFirst}. - * - * @throws IllegalStateException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * @throws IllegalArgumentException {@inheritDoc} - */ - void push(E e); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/Deque.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/Deque.java deleted file mode 100644 index 1b359ffdf..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/Deque.java +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Written by Doug Lea and Josh Bloch with assistance from members of - * JCP JSR-166 Expert Group and released to the public domain, as explained - * at http://creativecommons.org/licenses/publicdomain - */ - -package com.nostra13.universalimageloader.core.assist.deque; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Queue; -import java.util.Stack; - -/** - * A linear collection that supports element insertion and removal at - * both ends. The name deque is short for "double ended queue" - * and is usually pronounced "deck". Most Deque - * implementations place no fixed limits on the number of elements - * they may contain, but this interface supports capacity-restricted - * deques as well as those with no fixed size limit. - * - *

    This interface defines methods to access the elements at both - * ends of the deque. Methods are provided to insert, remove, and - * examine the element. Each of these methods exists in two forms: - * one throws an exception if the operation fails, the other returns a - * special value (either null or false, depending on - * the operation). The latter form of the insert operation is - * designed specifically for use with capacity-restricted - * Deque implementations; in most implementations, insert - * operations cannot fail. - * - *

    The twelve methods described above are summarized in the - * following table: - * - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    First Element (Head) Last Element (Tail)
    Throws exceptionSpecial valueThrows exceptionSpecial value
    Insert{@link #addFirst addFirst(e)}{@link #offerFirst offerFirst(e)}{@link #addLast addLast(e)}{@link #offerLast offerLast(e)}
    Remove{@link #removeFirst removeFirst()}{@link #pollFirst pollFirst()}{@link #removeLast removeLast()}{@link #pollLast pollLast()}
    Examine{@link #getFirst getFirst()}{@link #peekFirst peekFirst()}{@link #getLast getLast()}{@link #peekLast peekLast()}
    - * - *

    This interface extends the {@link Queue} interface. When a deque is - * used as a queue, FIFO (First-In-First-Out) behavior results. Elements are - * added at the end of the deque and removed from the beginning. The methods - * inherited from the Queue interface are precisely equivalent to - * Deque methods as indicated in the following table: - * - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Queue Method Equivalent Deque Method
    {@link java.util.Queue#add add(e)}{@link #addLast addLast(e)}
    {@link java.util.Queue#offer offer(e)}{@link #offerLast offerLast(e)}
    {@link java.util.Queue#remove remove()}{@link #removeFirst removeFirst()}
    {@link java.util.Queue#poll poll()}{@link #pollFirst pollFirst()}
    {@link java.util.Queue#element element()}{@link #getFirst getFirst()}
    {@link java.util.Queue#peek peek()}{@link #peek peekFirst()}
    - * - *

    Deques can also be used as LIFO (Last-In-First-Out) stacks. This - * interface should be used in preference to the legacy {@link Stack} class. - * When a deque is used as a stack, elements are pushed and popped from the - * beginning of the deque. Stack methods are precisely equivalent to - * Deque methods as indicated in the table below: - * - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Stack Method Equivalent Deque Method
    {@link #push push(e)}{@link #addFirst addFirst(e)}
    {@link #pop pop()}{@link #removeFirst removeFirst()}
    {@link #peek peek()}{@link #peekFirst peekFirst()}
    - * - *

    Note that the {@link #peek peek} method works equally well when - * a deque is used as a queue or a stack; in either case, elements are - * drawn from the beginning of the deque. - * - *

    This interface provides two methods to remove interior - * elements, {@link #removeFirstOccurrence removeFirstOccurrence} and - * {@link #removeLastOccurrence removeLastOccurrence}. - * - *

    Unlike the {@link List} interface, this interface does not - * provide support for indexed access to elements. - * - *

    While Deque implementations are not strictly required - * to prohibit the insertion of null elements, they are strongly - * encouraged to do so. Users of any Deque implementations - * that do allow null elements are strongly encouraged not to - * take advantage of the ability to insert nulls. This is so because - * null is used as a special return value by various methods - * to indicated that the deque is empty. - * - *

    Deque implementations generally do not define - * element-based versions of the equals and hashCode - * methods, but instead inherit the identity-based versions from class - * Object. - * - * @author Doug Lea - * @author Josh Bloch - * @since 1.6 - * @param the type of elements held in this collection - */ - -public interface Deque extends Queue { - /** - * Inserts the specified element at the front of this deque if it is - * possible to do so immediately without violating capacity restrictions. - * When using a capacity-restricted deque, it is generally preferable to - * use method {@link #offerFirst}. - * - * @param e the element to add - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void addFirst(E e); - - /** - * Inserts the specified element at the end of this deque if it is - * possible to do so immediately without violating capacity restrictions. - * When using a capacity-restricted deque, it is generally preferable to - * use method {@link #offerLast}. - * - *

    This method is equivalent to {@link #add}. - * - * @param e the element to add - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void addLast(E e); - - /** - * Inserts the specified element at the front of this deque unless it would - * violate capacity restrictions. When using a capacity-restricted deque, - * this method is generally preferable to the {@link #addFirst} method, - * which can fail to insert an element only by throwing an exception. - * - * @param e the element to add - * @return true if the element was added to this deque, else - * false - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offerFirst(E e); - - /** - * Inserts the specified element at the end of this deque unless it would - * violate capacity restrictions. When using a capacity-restricted deque, - * this method is generally preferable to the {@link #addLast} method, - * which can fail to insert an element only by throwing an exception. - * - * @param e the element to add - * @return true if the element was added to this deque, else - * false - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offerLast(E e); - - /** - * Retrieves and removes the first element of this deque. This method - * differs from {@link #pollFirst pollFirst} only in that it throws an - * exception if this deque is empty. - * - * @return the head of this deque - * @throws NoSuchElementException if this deque is empty - */ - E removeFirst(); - - /** - * Retrieves and removes the last element of this deque. This method - * differs from {@link #pollLast pollLast} only in that it throws an - * exception if this deque is empty. - * - * @return the tail of this deque - * @throws NoSuchElementException if this deque is empty - */ - E removeLast(); - - /** - * Retrieves and removes the first element of this deque, - * or returns null if this deque is empty. - * - * @return the head of this deque, or null if this deque is empty - */ - E pollFirst(); - - /** - * Retrieves and removes the last element of this deque, - * or returns null if this deque is empty. - * - * @return the tail of this deque, or null if this deque is empty - */ - E pollLast(); - - /** - * Retrieves, but does not remove, the first element of this deque. - * - * This method differs from {@link #peekFirst peekFirst} only in that it - * throws an exception if this deque is empty. - * - * @return the head of this deque - * @throws NoSuchElementException if this deque is empty - */ - E getFirst(); - - /** - * Retrieves, but does not remove, the last element of this deque. - * This method differs from {@link #peekLast peekLast} only in that it - * throws an exception if this deque is empty. - * - * @return the tail of this deque - * @throws NoSuchElementException if this deque is empty - */ - E getLast(); - - /** - * Retrieves, but does not remove, the first element of this deque, - * or returns null if this deque is empty. - * - * @return the head of this deque, or null if this deque is empty - */ - E peekFirst(); - - /** - * Retrieves, but does not remove, the last element of this deque, - * or returns null if this deque is empty. - * - * @return the tail of this deque, or null if this deque is empty - */ - E peekLast(); - - /** - * Removes the first occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element e such that - * (o==null ? e==null : o.equals(e)) - * (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - * @param o element to be removed from this deque, if present - * @return true if an element was removed as a result of this call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements (optional) - */ - boolean removeFirstOccurrence(Object o); - - /** - * Removes the last occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the last element e such that - * (o==null ? e==null : o.equals(e)) - * (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - * @param o element to be removed from this deque, if present - * @return true if an element was removed as a result of this call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements (optional) - */ - boolean removeLastOccurrence(Object o); - - // *** Queue methods *** - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and throwing an - * IllegalStateException if no space is currently available. - * When using a capacity-restricted deque, it is generally preferable to - * use {@link #offer offer}. - * - *

    This method is equivalent to {@link #addLast}. - * - * @param e the element to add - * @return true (as specified by {@link Collection#add}) - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean add(E e); - - /** - * Inserts the specified element into the queue represented by this deque - * (in other words, at the tail of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and false if no space is currently - * available. When using a capacity-restricted deque, this method is - * generally preferable to the {@link #add} method, which can fail to - * insert an element only by throwing an exception. - * - *

    This method is equivalent to {@link #offerLast}. - * - * @param e the element to add - * @return true if the element was added to this deque, else - * false - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - boolean offer(E e); - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque). - * This method differs from {@link #poll poll} only in that it throws an - * exception if this deque is empty. - * - *

    This method is equivalent to {@link #removeFirst()}. - * - * @return the head of the queue represented by this deque - * @throws NoSuchElementException if this deque is empty - */ - E remove(); - - /** - * Retrieves and removes the head of the queue represented by this deque - * (in other words, the first element of this deque), or returns - * null if this deque is empty. - * - *

    This method is equivalent to {@link #pollFirst()}. - * - * @return the first element of this deque, or null if - * this deque is empty - */ - E poll(); - - /** - * Retrieves, but does not remove, the head of the queue represented by - * this deque (in other words, the first element of this deque). - * This method differs from {@link #peek peek} only in that it throws an - * exception if this deque is empty. - * - *

    This method is equivalent to {@link #getFirst()}. - * - * @return the head of the queue represented by this deque - * @throws NoSuchElementException if this deque is empty - */ - E element(); - - /** - * Retrieves, but does not remove, the head of the queue represented by - * this deque (in other words, the first element of this deque), or - * returns null if this deque is empty. - * - *

    This method is equivalent to {@link #peekFirst()}. - * - * @return the head of the queue represented by this deque, or - * null if this deque is empty - */ - E peek(); - - - // *** Stack methods *** - - /** - * Pushes an element onto the stack represented by this deque (in other - * words, at the head of this deque) if it is possible to do so - * immediately without violating capacity restrictions, returning - * true upon success and throwing an - * IllegalStateException if no space is currently available. - * - *

    This method is equivalent to {@link #addFirst}. - * - * @param e the element to push - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this deque - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements - * @throws IllegalArgumentException if some property of the specified - * element prevents it from being added to this deque - */ - void push(E e); - - /** - * Pops an element from the stack represented by this deque. In other - * words, removes and returns the first element of this deque. - * - *

    This method is equivalent to {@link #removeFirst()}. - * - * @return the element at the front of this deque (which is the top - * of the stack represented by this deque) - * @throws NoSuchElementException if this deque is empty - */ - E pop(); - - - // *** Collection methods *** - - /** - * Removes the first occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element e such that - * (o==null ? e==null : o.equals(e)) - * (if such an element exists). - * Returns true if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - *

    This method is equivalent to {@link #removeFirstOccurrence}. - * - * @param o element to be removed from this deque, if present - * @return true if an element was removed as a result of this call - * @throws ClassCastException if the class of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements (optional) - */ - boolean remove(Object o); - - /** - * Returns true if this deque contains the specified element. - * More formally, returns true if and only if this deque contains - * at least one element e such that - * (o==null ? e==null : o.equals(e)). - * - * @param o element whose presence in this deque is to be tested - * @return true if this deque contains the specified element - * @throws ClassCastException if the type of the specified element - * is incompatible with this deque (optional) - * @throws NullPointerException if the specified element is null and this - * deque does not permit null elements (optional) - */ - boolean contains(Object o); - - /** - * Returns the number of elements in this deque. - * - * @return the number of elements in this deque - */ - public int size(); - - /** - * Returns an iterator over the elements in this deque in proper sequence. - * The elements will be returned in order from first (head) to last (tail). - * - * @return an iterator over the elements in this deque in proper sequence - */ - Iterator iterator(); - - /** - * Returns an iterator over the elements in this deque in reverse - * sequential order. The elements will be returned in order from - * last (tail) to first (head). - * - * @return an iterator over the elements in this deque in reverse - * sequence - */ - Iterator descendingIterator(); - -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LIFOLinkedBlockingDeque.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LIFOLinkedBlockingDeque.java deleted file mode 100644 index 0a2cf02c8..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LIFOLinkedBlockingDeque.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.nostra13.universalimageloader.core.assist.deque; - -import java.util.NoSuchElementException; - -/** - * {@link LinkedBlockingDeque} using LIFO algorithm - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.6.3 - */ -public class LIFOLinkedBlockingDeque extends LinkedBlockingDeque { - - private static final long serialVersionUID = -4114786347960826192L; - - /** - * Inserts the specified element at the front of this deque if it is possible to do so immediately without violating - * capacity restrictions, returning true upon success and false if no space is currently - * available. When using a capacity-restricted deque, this method is generally preferable to the {@link #addFirst - * addFirst} method, which can fail to insert an element only by throwing an exception. - * - * @param e - * the element to add - * @throws ClassCastException - * {@inheritDoc} - * @throws NullPointerException - * if the specified element is null - * @throws IllegalArgumentException - * {@inheritDoc} - */ - @Override - public boolean offer(T e) { - return super.offerFirst(e); - } - - /** - * Retrieves and removes the first element of this deque. This method differs from {@link #pollFirst pollFirst} only - * in that it throws an exception if this deque is empty. - * - * @return the head of this deque - * @throws NoSuchElementException - * if this deque is empty - */ - @Override - public T remove() { - return super.removeFirst(); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LinkedBlockingDeque.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LinkedBlockingDeque.java deleted file mode 100644 index 75d6994fa..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/assist/deque/LinkedBlockingDeque.java +++ /dev/null @@ -1,1169 +0,0 @@ -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain - */ - -package com.nostra13.universalimageloader.core.assist.deque; - -import java.util.AbstractQueue; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -/** - * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on - * linked nodes. - * - *

    The optional capacity bound constructor argument serves as a - * way to prevent excessive expansion. The capacity, if unspecified, - * is equal to {@link Integer#MAX_VALUE}. Linked nodes are - * dynamically created upon each insertion unless this would bring the - * deque above capacity. - * - *

    Most operations run in constant time (ignoring time spent - * blocking). Exceptions include {@link #remove(Object) remove}, - * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link - * #removeLastOccurrence removeLastOccurrence}, {@link #contains - * contains}, {@link #iterator iterator.remove()}, and the bulk - * operations, all of which run in linear time. - * - *

    This class and its iterator implement all of the - * optional methods of the {@link Collection} and {@link - * Iterator} interfaces. - * - *

    This class is a member of the - * - * Java Collections Framework. - * - * @since 1.6 - * @author Doug Lea - * @param the type of elements held in this collection - */ -public class LinkedBlockingDeque - extends AbstractQueue - implements BlockingDeque, java.io.Serializable { - - /* - * Implemented as a simple doubly-linked list protected by a - * single lock and using conditions to manage blocking. - * - * To implement weakly consistent iterators, it appears we need to - * keep all Nodes GC-reachable from a predecessor dequeued Node. - * That would cause two problems: - * - allow a rogue Iterator to cause unbounded memory retention - * - cause cross-generational linking of old Nodes to new Nodes if - * a Node was tenured while live, which generational GCs have a - * hard time dealing with, causing repeated major collections. - * However, only non-deleted Nodes need to be reachable from - * dequeued Nodes, and reachability does not necessarily have to - * be of the kind understood by the GC. We use the trick of - * linking a Node that has just been dequeued to itself. Such a - * self-link implicitly means to jump to "first" (for next links) - * or "last" (for prev links). - */ - - /* - * We have "diamond" multiple interface/abstract class inheritance - * here, and that introduces ambiguities. Often we want the - * BlockingDeque javadoc combined with the AbstractQueue - * implementation, so a lot of method specs are duplicated here. - */ - - private static final long serialVersionUID = -387911632671998426L; - - /** Doubly-linked list node class */ - static final class Node { - /** - * The item, or null if this node has been removed. - */ - E item; - - /** - * One of: - * - the real predecessor Node - * - this Node, meaning the predecessor is tail - * - null, meaning there is no predecessor - */ - Node prev; - - /** - * One of: - * - the real successor Node - * - this Node, meaning the successor is head - * - null, meaning there is no successor - */ - Node next; - - Node(E x) { - item = x; - } - } - - /** - * Pointer to first node. - * Invariant: (first == null && last == null) || - * (first.prev == null && first.item != null) - */ - transient Node first; - - /** - * Pointer to last node. - * Invariant: (first == null && last == null) || - * (last.next == null && last.item != null) - */ - transient Node last; - - /** Number of items in the deque */ - private transient int count; - - /** Maximum number of items in the deque */ - private final int capacity; - - /** Main lock guarding all access */ - final ReentrantLock lock = new ReentrantLock(); - - /** Condition for waiting takes */ - private final Condition notEmpty = lock.newCondition(); - - /** Condition for waiting puts */ - private final Condition notFull = lock.newCondition(); - - /** - * Creates a {@code LinkedBlockingDeque} with a capacity of - * {@link Integer#MAX_VALUE}. - */ - public LinkedBlockingDeque() { - this(Integer.MAX_VALUE); - } - - /** - * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity. - * - * @param capacity the capacity of this deque - * @throws IllegalArgumentException if {@code capacity} is less than 1 - */ - public LinkedBlockingDeque(int capacity) { - if (capacity <= 0) throw new IllegalArgumentException(); - this.capacity = capacity; - } - - /** - * Creates a {@code LinkedBlockingDeque} with a capacity of - * {@link Integer#MAX_VALUE}, initially containing the elements of - * the given collection, added in traversal order of the - * collection's iterator. - * - * @param c the collection of elements to initially contain - * @throws NullPointerException if the specified collection or any - * of its elements are null - */ - public LinkedBlockingDeque(Collection c) { - this(Integer.MAX_VALUE); - final ReentrantLock lock = this.lock; - lock.lock(); // Never contended, but necessary for visibility - try { - for (E e : c) { - if (e == null) - throw new NullPointerException(); - if (!linkLast(new Node(e))) - throw new IllegalStateException("Deque full"); - } - } finally { - lock.unlock(); - } - } - - - // Basic linking and unlinking operations, called only while holding lock - - /** - * Links node as first element, or returns false if full. - */ - private boolean linkFirst(Node node) { - // assert lock.isHeldByCurrentThread(); - if (count >= capacity) - return false; - Node f = first; - node.next = f; - first = node; - if (last == null) - last = node; - else - f.prev = node; - ++count; - notEmpty.signal(); - return true; - } - - /** - * Links node as last element, or returns false if full. - */ - private boolean linkLast(Node node) { - // assert lock.isHeldByCurrentThread(); - if (count >= capacity) - return false; - Node l = last; - node.prev = l; - last = node; - if (first == null) - first = node; - else - l.next = node; - ++count; - notEmpty.signal(); - return true; - } - - /** - * Removes and returns first element, or null if empty. - */ - private E unlinkFirst() { - // assert lock.isHeldByCurrentThread(); - Node f = first; - if (f == null) - return null; - Node n = f.next; - E item = f.item; - f.item = null; - f.next = f; // help GC - first = n; - if (n == null) - last = null; - else - n.prev = null; - --count; - notFull.signal(); - return item; - } - - /** - * Removes and returns last element, or null if empty. - */ - private E unlinkLast() { - // assert lock.isHeldByCurrentThread(); - Node l = last; - if (l == null) - return null; - Node p = l.prev; - E item = l.item; - l.item = null; - l.prev = l; // help GC - last = p; - if (p == null) - first = null; - else - p.next = null; - --count; - notFull.signal(); - return item; - } - - /** - * Unlinks x. - */ - void unlink(Node x) { - // assert lock.isHeldByCurrentThread(); - Node p = x.prev; - Node n = x.next; - if (p == null) { - unlinkFirst(); - } else if (n == null) { - unlinkLast(); - } else { - p.next = n; - n.prev = p; - x.item = null; - // Don't mess with x's links. They may still be in use by - // an iterator. - --count; - notFull.signal(); - } - } - - // BlockingDeque methods - - /** - * @throws IllegalStateException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public void addFirst(E e) { - if (!offerFirst(e)) - throw new IllegalStateException("Deque full"); - } - - /** - * @throws IllegalStateException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public void addLast(E e) { - if (!offerLast(e)) - throw new IllegalStateException("Deque full"); - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public boolean offerFirst(E e) { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return linkFirst(node); - } finally { - lock.unlock(); - } - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public boolean offerLast(E e) { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return linkLast(node); - } finally { - lock.unlock(); - } - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public void putFirst(E e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - while (!linkFirst(node)) - notFull.await(); - } finally { - lock.unlock(); - } - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public void putLast(E e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - while (!linkLast(node)) - notFull.await(); - } finally { - lock.unlock(); - } - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public boolean offerFirst(E e, long timeout, TimeUnit unit) - throws InterruptedException { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - long nanos = unit.toNanos(timeout); - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - while (!linkFirst(node)) { - if (nanos <= 0) - return false; - nanos = notFull.awaitNanos(nanos); - } - return true; - } finally { - lock.unlock(); - } - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public boolean offerLast(E e, long timeout, TimeUnit unit) - throws InterruptedException { - if (e == null) throw new NullPointerException(); - Node node = new Node(e); - long nanos = unit.toNanos(timeout); - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - while (!linkLast(node)) { - if (nanos <= 0) - return false; - nanos = notFull.awaitNanos(nanos); - } - return true; - } finally { - lock.unlock(); - } - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E removeFirst() { - E x = pollFirst(); - if (x == null) throw new NoSuchElementException(); - return x; - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E removeLast() { - E x = pollLast(); - if (x == null) throw new NoSuchElementException(); - return x; - } - - public E pollFirst() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return unlinkFirst(); - } finally { - lock.unlock(); - } - } - - public E pollLast() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return unlinkLast(); - } finally { - lock.unlock(); - } - } - - public E takeFirst() throws InterruptedException { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - E x; - while ( (x = unlinkFirst()) == null) - notEmpty.await(); - return x; - } finally { - lock.unlock(); - } - } - - public E takeLast() throws InterruptedException { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - E x; - while ( (x = unlinkLast()) == null) - notEmpty.await(); - return x; - } finally { - lock.unlock(); - } - } - - public E pollFirst(long timeout, TimeUnit unit) - throws InterruptedException { - long nanos = unit.toNanos(timeout); - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - E x; - while ( (x = unlinkFirst()) == null) { - if (nanos <= 0) - return null; - nanos = notEmpty.awaitNanos(nanos); - } - return x; - } finally { - lock.unlock(); - } - } - - public E pollLast(long timeout, TimeUnit unit) - throws InterruptedException { - long nanos = unit.toNanos(timeout); - final ReentrantLock lock = this.lock; - lock.lockInterruptibly(); - try { - E x; - while ( (x = unlinkLast()) == null) { - if (nanos <= 0) - return null; - nanos = notEmpty.awaitNanos(nanos); - } - return x; - } finally { - lock.unlock(); - } - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E getFirst() { - E x = peekFirst(); - if (x == null) throw new NoSuchElementException(); - return x; - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E getLast() { - E x = peekLast(); - if (x == null) throw new NoSuchElementException(); - return x; - } - - public E peekFirst() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return (first == null) ? null : first.item; - } finally { - lock.unlock(); - } - } - - public E peekLast() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return (last == null) ? null : last.item; - } finally { - lock.unlock(); - } - } - - public boolean removeFirstOccurrence(Object o) { - if (o == null) return false; - final ReentrantLock lock = this.lock; - lock.lock(); - try { - for (Node p = first; p != null; p = p.next) { - if (o.equals(p.item)) { - unlink(p); - return true; - } - } - return false; - } finally { - lock.unlock(); - } - } - - public boolean removeLastOccurrence(Object o) { - if (o == null) return false; - final ReentrantLock lock = this.lock; - lock.lock(); - try { - for (Node p = last; p != null; p = p.prev) { - if (o.equals(p.item)) { - unlink(p); - return true; - } - } - return false; - } finally { - lock.unlock(); - } - } - - // BlockingQueue methods - - /** - * Inserts the specified element at the end of this deque unless it would - * violate capacity restrictions. When using a capacity-restricted deque, - * it is generally preferable to use method {@link #offer offer}. - * - *

    This method is equivalent to {@link #addLast}. - * - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws NullPointerException if the specified element is null - */ - public boolean add(E e) { - addLast(e); - return true; - } - - /** - * @throws NullPointerException if the specified element is null - */ - public boolean offer(E e) { - return offerLast(e); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public void put(E e) throws InterruptedException { - putLast(e); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws InterruptedException {@inheritDoc} - */ - public boolean offer(E e, long timeout, TimeUnit unit) - throws InterruptedException { - return offerLast(e, timeout, unit); - } - - /** - * Retrieves and removes the head of the queue represented by this deque. - * This method differs from {@link #poll poll} only in that it throws an - * exception if this deque is empty. - * - *

    This method is equivalent to {@link #removeFirst() removeFirst}. - * - * @return the head of the queue represented by this deque - * @throws NoSuchElementException if this deque is empty - */ - public E remove() { - return removeFirst(); - } - - public E poll() { - return pollFirst(); - } - - public E take() throws InterruptedException { - return takeFirst(); - } - - public E poll(long timeout, TimeUnit unit) throws InterruptedException { - return pollFirst(timeout, unit); - } - - /** - * Retrieves, but does not remove, the head of the queue represented by - * this deque. This method differs from {@link #peek peek} only in that - * it throws an exception if this deque is empty. - * - *

    This method is equivalent to {@link #getFirst() getFirst}. - * - * @return the head of the queue represented by this deque - * @throws NoSuchElementException if this deque is empty - */ - public E element() { - return getFirst(); - } - - public E peek() { - return peekFirst(); - } - - /** - * Returns the number of additional elements that this deque can ideally - * (in the absence of memory or resource constraints) accept without - * blocking. This is always equal to the initial capacity of this deque - * less the current {@code size} of this deque. - * - *

    Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting {@code remainingCapacity} - * because it may be the case that another thread is about to - * insert or remove an element. - */ - public int remainingCapacity() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return capacity - count; - } finally { - lock.unlock(); - } - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c) { - return drainTo(c, Integer.MAX_VALUE); - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - int n = Math.min(maxElements, count); - for (int i = 0; i < n; i++) { - c.add(first.item); // In this order, in case add() throws. - unlinkFirst(); - } - return n; - } finally { - lock.unlock(); - } - } - - // Stack methods - - /** - * @throws IllegalStateException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public void push(E e) { - addFirst(e); - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E pop() { - return removeFirst(); - } - - // Collection methods - - /** - * Removes the first occurrence of the specified element from this deque. - * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element {@code e} such that - * {@code o.equals(e)} (if such an element exists). - * Returns {@code true} if this deque contained the specified element - * (or equivalently, if this deque changed as a result of the call). - * - *

    This method is equivalent to - * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}. - * - * @param o element to be removed from this deque, if present - * @return {@code true} if this deque changed as a result of the call - */ - public boolean remove(Object o) { - return removeFirstOccurrence(o); - } - - /** - * Returns the number of elements in this deque. - * - * @return the number of elements in this deque - */ - public int size() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return count; - } finally { - lock.unlock(); - } - } - - /** - * Returns {@code true} if this deque contains the specified element. - * More formally, returns {@code true} if and only if this deque contains - * at least one element {@code e} such that {@code o.equals(e)}. - * - * @param o object to be checked for containment in this deque - * @return {@code true} if this deque contains the specified element - */ - public boolean contains(Object o) { - if (o == null) return false; - final ReentrantLock lock = this.lock; - lock.lock(); - try { - for (Node p = first; p != null; p = p.next) - if (o.equals(p.item)) - return true; - return false; - } finally { - lock.unlock(); - } - } - - /* - * TODO: Add support for more efficient bulk operations. - * - * We don't want to acquire the lock for every iteration, but we - * also want other threads a chance to interact with the - * collection, especially when count is close to capacity. - */ - -// /** -// * Adds all of the elements in the specified collection to this -// * queue. Attempts to addAll of a queue to itself result in -// * {@code IllegalArgumentException}. Further, the behavior of -// * this operation is undefined if the specified collection is -// * modified while the operation is in progress. -// * -// * @param c collection containing elements to be added to this queue -// * @return {@code true} if this queue changed as a result of the call -// * @throws ClassCastException {@inheritDoc} -// * @throws NullPointerException {@inheritDoc} -// * @throws IllegalArgumentException {@inheritDoc} -// * @throws IllegalStateException {@inheritDoc} -// * @see #add(Object) -// */ -// public boolean addAll(Collection c) { -// if (c == null) -// throw new NullPointerException(); -// if (c == this) -// throw new IllegalArgumentException(); -// final ReentrantLock lock = this.lock; -// lock.lock(); -// try { -// boolean modified = false; -// for (E e : c) -// if (linkLast(e)) -// modified = true; -// return modified; -// } finally { -// lock.unlock(); -// } -// } - - /** - * Returns an array containing all of the elements in this deque, in - * proper sequence (from first to last element). - * - *

    The returned array will be "safe" in that no references to it are - * maintained by this deque. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - *

    This method acts as bridge between array-based and collection-based - * APIs. - * - * @return an array containing all of the elements in this deque - */ - public Object[] toArray() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - Object[] a = new Object[count]; - int k = 0; - for (Node p = first; p != null; p = p.next) - a[k++] = p.item; - return a; - } finally { - lock.unlock(); - } - } - - /** - * Returns an array containing all of the elements in this deque, in - * proper sequence; the runtime type of the returned array is that of - * the specified array. If the deque fits in the specified array, it - * is returned therein. Otherwise, a new array is allocated with the - * runtime type of the specified array and the size of this deque. - * - *

    If this deque fits in the specified array with room to spare - * (i.e., the array has more elements than this deque), the element in - * the array immediately following the end of the deque is set to - * {@code null}. - * - *

    Like the {@link #toArray()} method, this method acts as bridge between - * array-based and collection-based APIs. Further, this method allows - * precise control over the runtime type of the output array, and may, - * under certain circumstances, be used to save allocation costs. - * - *

    Suppose {@code x} is a deque known to contain only strings. - * The following code can be used to dump the deque into a newly - * allocated array of {@code String}: - * - *

    -     *     String[] y = x.toArray(new String[0]);
    - * - * Note that {@code toArray(new Object[0])} is identical in function to - * {@code toArray()}. - * - * @param a the array into which the elements of the deque are to - * be stored, if it is big enough; otherwise, a new array of the - * same runtime type is allocated for this purpose - * @return an array containing all of the elements in this deque - * @throws ArrayStoreException if the runtime type of the specified array - * is not a supertype of the runtime type of every element in - * this deque - * @throws NullPointerException if the specified array is null - */ - @SuppressWarnings("unchecked") - public T[] toArray(T[] a) { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - if (a.length < count) - a = (T[])java.lang.reflect.Array.newInstance - (a.getClass().getComponentType(), count); - - int k = 0; - for (Node p = first; p != null; p = p.next) - a[k++] = (T)p.item; - if (a.length > k) - a[k] = null; - return a; - } finally { - lock.unlock(); - } - } - - public String toString() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - Node p = first; - if (p == null) - return "[]"; - - StringBuilder sb = new StringBuilder(); - sb.append('['); - for (;;) { - E e = p.item; - sb.append(e == this ? "(this Collection)" : e); - p = p.next; - if (p == null) - return sb.append(']').toString(); - sb.append(',').append(' '); - } - } finally { - lock.unlock(); - } - } - - /** - * Atomically removes all of the elements from this deque. - * The deque will be empty after this call returns. - */ - public void clear() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - for (Node f = first; f != null; ) { - f.item = null; - Node n = f.next; - f.prev = null; - f.next = null; - f = n; - } - first = last = null; - count = 0; - notFull.signalAll(); - } finally { - lock.unlock(); - } - } - - /** - * Returns an iterator over the elements in this deque in proper sequence. - * The elements will be returned in order from first (head) to last (tail). - * - *

    The returned iterator is a "weakly consistent" iterator that - * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, and guarantees to traverse - * elements as they existed upon construction of the iterator, and - * may (but is not guaranteed to) reflect any modifications - * subsequent to construction. - * - * @return an iterator over the elements in this deque in proper sequence - */ - public Iterator iterator() { - return new Itr(); - } - - /** - * Returns an iterator over the elements in this deque in reverse - * sequential order. The elements will be returned in order from - * last (tail) to first (head). - * - *

    The returned iterator is a "weakly consistent" iterator that - * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, and guarantees to traverse - * elements as they existed upon construction of the iterator, and - * may (but is not guaranteed to) reflect any modifications - * subsequent to construction. - * - * @return an iterator over the elements in this deque in reverse order - */ - public Iterator descendingIterator() { - return new DescendingItr(); - } - - /** - * Base class for Iterators for LinkedBlockingDeque - */ - private abstract class AbstractItr implements Iterator { - /** - * The next node to return in next() - */ - Node next; - - /** - * nextItem holds on to item fields because once we claim that - * an element exists in hasNext(), we must return item read - * under lock (in advance()) even if it was in the process of - * being removed when hasNext() was called. - */ - E nextItem; - - /** - * Node returned by most recent call to next. Needed by remove. - * Reset to null if this element is deleted by a call to remove. - */ - private Node lastRet; - - abstract Node firstNode(); - abstract Node nextNode(Node n); - - AbstractItr() { - // set to initial position - final ReentrantLock lock = LinkedBlockingDeque.this.lock; - lock.lock(); - try { - next = firstNode(); - nextItem = (next == null) ? null : next.item; - } finally { - lock.unlock(); - } - } - - /** - * Returns the successor node of the given non-null, but - * possibly previously deleted, node. - */ - private Node succ(Node n) { - // Chains of deleted nodes ending in null or self-links - // are possible if multiple interior nodes are removed. - for (;;) { - Node s = nextNode(n); - if (s == null) - return null; - else if (s.item != null) - return s; - else if (s == n) - return firstNode(); - else - n = s; - } - } - - /** - * Advances next. - */ - void advance() { - final ReentrantLock lock = LinkedBlockingDeque.this.lock; - lock.lock(); - try { - // assert next != null; - next = succ(next); - nextItem = (next == null) ? null : next.item; - } finally { - lock.unlock(); - } - } - - public boolean hasNext() { - return next != null; - } - - public E next() { - if (next == null) - throw new NoSuchElementException(); - lastRet = next; - E x = nextItem; - advance(); - return x; - } - - public void remove() { - Node n = lastRet; - if (n == null) - throw new IllegalStateException(); - lastRet = null; - final ReentrantLock lock = LinkedBlockingDeque.this.lock; - lock.lock(); - try { - if (n.item != null) - unlink(n); - } finally { - lock.unlock(); - } - } - } - - /** Forward iterator */ - private class Itr extends AbstractItr { - Node firstNode() { return first; } - Node nextNode(Node n) { return n.next; } - } - - /** Descending iterator */ - private class DescendingItr extends AbstractItr { - Node firstNode() { return last; } - Node nextNode(Node n) { return n.prev; } - } - - /** - * Save the state of this deque to a stream (that is, serialize it). - * - * @serialData The capacity (int), followed by elements (each an - * {@code Object}) in the proper order, followed by a null - * @param s the stream - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - // Write out capacity and any hidden stuff - s.defaultWriteObject(); - // Write out all elements in the proper order. - for (Node p = first; p != null; p = p.next) - s.writeObject(p.item); - // Use trailing null as sentinel - s.writeObject(null); - } finally { - lock.unlock(); - } - } - - /** - * Reconstitute this deque from a stream (that is, - * deserialize it). - * @param s the stream - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - s.defaultReadObject(); - count = 0; - first = null; - last = null; - // Read in all elements and place in queue - for (;;) { - @SuppressWarnings("unchecked") - E item = (E)s.readObject(); - if (item == null) - break; - add(item); - } - } - -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/BaseImageDecoder.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/BaseImageDecoder.java deleted file mode 100644 index 7b82ba689..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/BaseImageDecoder.java +++ /dev/null @@ -1,250 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.decode; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapFactory.Options; -import android.graphics.Matrix; -import android.media.ExifInterface; -import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme; -import com.nostra13.universalimageloader.utils.ImageSizeUtils; -import com.nostra13.universalimageloader.utils.IoUtils; -import com.nostra13.universalimageloader.utils.L; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Decodes images to {@link Bitmap}, scales them to needed size - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ImageDecodingInfo - * @since 1.8.3 - */ -public class BaseImageDecoder implements ImageDecoder { - - protected static final String LOG_SUBSAMPLE_IMAGE = "Subsample original image (%1$s) to %2$s (scale = %3$d) [%4$s]"; - protected static final String LOG_SCALE_IMAGE = "Scale subsampled image (%1$s) to %2$s (scale = %3$.5f) [%4$s]"; - protected static final String LOG_ROTATE_IMAGE = "Rotate image on %1$d\u00B0 [%2$s]"; - protected static final String LOG_FLIP_IMAGE = "Flip image horizontally [%s]"; - protected static final String ERROR_NO_IMAGE_STREAM = "No stream for image [%s]"; - protected static final String ERROR_CANT_DECODE_IMAGE = "Image can't be decoded [%s]"; - - protected final boolean loggingEnabled; - - /** - * @param loggingEnabled Whether debug logs will be written to LogCat. Usually should match {@link - * com.nostra13.universalimageloader.core.ImageLoaderConfiguration.Builder#writeDebugLogs() - * ImageLoaderConfiguration.writeDebugLogs()} - */ - public BaseImageDecoder(boolean loggingEnabled) { - this.loggingEnabled = loggingEnabled; - } - - /** - * Decodes image from URI into {@link Bitmap}. Image is scaled close to incoming {@linkplain ImageSize target size} - * during decoding (depend on incoming parameters). - * - * @param decodingInfo Needed data for decoding image - * @return Decoded bitmap - * @throws IOException if some I/O exception occurs during image reading - * @throws UnsupportedOperationException if image URI has unsupported scheme(protocol) - */ - @Override - public Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException { - Bitmap decodedBitmap; - ImageFileInfo imageInfo; - - InputStream imageStream = getImageStream(decodingInfo); - if (imageStream == null) { - L.e(ERROR_NO_IMAGE_STREAM, decodingInfo.getImageKey()); - return null; - } - try { - imageInfo = defineImageSizeAndRotation(imageStream, decodingInfo); - imageStream = resetStream(imageStream, decodingInfo); - Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, decodingInfo); - decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions); - } finally { - IoUtils.closeSilently(imageStream); - } - - if (decodedBitmap == null) { - L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey()); - } else { - decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, decodingInfo, imageInfo.exif.rotation, - imageInfo.exif.flipHorizontal); - } - return decodedBitmap; - } - - protected InputStream getImageStream(ImageDecodingInfo decodingInfo) throws IOException { - return decodingInfo.getDownloader().getStream(decodingInfo.getImageUri(), decodingInfo.getExtraForDownloader()); - } - - protected ImageFileInfo defineImageSizeAndRotation(InputStream imageStream, ImageDecodingInfo decodingInfo) - throws IOException { - Options options = new Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(imageStream, null, options); - - ExifInfo exif; - String imageUri = decodingInfo.getImageUri(); - if (decodingInfo.shouldConsiderExifParams() && canDefineExifParams(imageUri, options.outMimeType)) { - exif = defineExifOrientation(imageUri); - } else { - exif = new ExifInfo(); - } - return new ImageFileInfo(new ImageSize(options.outWidth, options.outHeight, exif.rotation), exif); - } - - private boolean canDefineExifParams(String imageUri, String mimeType) { - return "image/jpeg".equalsIgnoreCase(mimeType) && (Scheme.ofUri(imageUri) == Scheme.FILE); - } - - protected ExifInfo defineExifOrientation(String imageUri) { - int rotation = 0; - boolean flip = false; - try { - ExifInterface exif = new ExifInterface(Scheme.FILE.crop(imageUri)); - int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); - switch (exifOrientation) { - case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: - flip = true; - case ExifInterface.ORIENTATION_NORMAL: - rotation = 0; - break; - case ExifInterface.ORIENTATION_TRANSVERSE: - flip = true; - case ExifInterface.ORIENTATION_ROTATE_90: - rotation = 90; - break; - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - flip = true; - case ExifInterface.ORIENTATION_ROTATE_180: - rotation = 180; - break; - case ExifInterface.ORIENTATION_TRANSPOSE: - flip = true; - case ExifInterface.ORIENTATION_ROTATE_270: - rotation = 270; - break; - } - } catch (IOException e) { - L.w("Can't read EXIF tags from file [%s]", imageUri); - } - return new ExifInfo(rotation, flip); - } - - protected Options prepareDecodingOptions(ImageSize imageSize, ImageDecodingInfo decodingInfo) { - ImageScaleType scaleType = decodingInfo.getImageScaleType(); - int scale; - if (scaleType == ImageScaleType.NONE) { - scale = 1; - } else if (scaleType == ImageScaleType.NONE_SAFE) { - scale = ImageSizeUtils.computeMinImageSampleSize(imageSize); - } else { - ImageSize targetSize = decodingInfo.getTargetSize(); - boolean powerOf2 = scaleType == ImageScaleType.IN_SAMPLE_POWER_OF_2; - scale = ImageSizeUtils.computeImageSampleSize(imageSize, targetSize, decodingInfo.getViewScaleType(), powerOf2); - } - if (scale > 1 && loggingEnabled) { - L.d(LOG_SUBSAMPLE_IMAGE, imageSize, imageSize.scaleDown(scale), scale, decodingInfo.getImageKey()); - } - - Options decodingOptions = decodingInfo.getDecodingOptions(); - decodingOptions.inSampleSize = scale; - return decodingOptions; - } - - protected InputStream resetStream(InputStream imageStream, ImageDecodingInfo decodingInfo) throws IOException { - try { - imageStream.reset(); - } catch (IOException e) { - IoUtils.closeSilently(imageStream); - imageStream = getImageStream(decodingInfo); - } - return imageStream; - } - - protected Bitmap considerExactScaleAndOrientatiton(Bitmap subsampledBitmap, ImageDecodingInfo decodingInfo, - int rotation, boolean flipHorizontal) { - Matrix m = new Matrix(); - // Scale to exact size if need - ImageScaleType scaleType = decodingInfo.getImageScaleType(); - if (scaleType == ImageScaleType.EXACTLY || scaleType == ImageScaleType.EXACTLY_STRETCHED) { - ImageSize srcSize = new ImageSize(subsampledBitmap.getWidth(), subsampledBitmap.getHeight(), rotation); - float scale = ImageSizeUtils.computeImageScale(srcSize, decodingInfo.getTargetSize(), decodingInfo - .getViewScaleType(), scaleType == ImageScaleType.EXACTLY_STRETCHED); - if (Float.compare(scale, 1f) != 0) { - m.setScale(scale, scale); - - if (loggingEnabled) { - L.d(LOG_SCALE_IMAGE, srcSize, srcSize.scale(scale), scale, decodingInfo.getImageKey()); - } - } - } - // Flip bitmap if need - if (flipHorizontal) { - m.postScale(-1, 1); - - if (loggingEnabled) L.d(LOG_FLIP_IMAGE, decodingInfo.getImageKey()); - } - // Rotate bitmap if need - if (rotation != 0) { - m.postRotate(rotation); - - if (loggingEnabled) L.d(LOG_ROTATE_IMAGE, rotation, decodingInfo.getImageKey()); - } - - Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, subsampledBitmap.getWidth(), subsampledBitmap - .getHeight(), m, true); - if (finalBitmap != subsampledBitmap) { - subsampledBitmap.recycle(); - } - return finalBitmap; - } - - protected static class ExifInfo { - - public final int rotation; - public final boolean flipHorizontal; - - protected ExifInfo() { - this.rotation = 0; - this.flipHorizontal = false; - } - - protected ExifInfo(int rotation, boolean flipHorizontal) { - this.rotation = rotation; - this.flipHorizontal = flipHorizontal; - } - } - - protected static class ImageFileInfo { - - public final ImageSize imageSize; - public final ExifInfo exif; - - protected ImageFileInfo(ImageSize imageSize, ExifInfo exif) { - this.imageSize = imageSize; - this.exif = exif; - } - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecoder.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecoder.java deleted file mode 100644 index 69fb01842..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecoder.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright 2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.decode; - -import android.graphics.Bitmap; - -import java.io.IOException; - -/** - * Provide decoding image to result {@link Bitmap}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ImageDecodingInfo - * @since 1.8.3 - */ -public interface ImageDecoder { - - /** - * Decodes image to {@link Bitmap} according target size and other parameters. - * - * @param imageDecodingInfo - * @return - * @throws IOException - */ - Bitmap decode(ImageDecodingInfo imageDecodingInfo) throws IOException; -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecodingInfo.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecodingInfo.java deleted file mode 100644 index 9a9ca04a1..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/decode/ImageDecodingInfo.java +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.decode; - -import android.annotation.TargetApi; -import android.graphics.BitmapFactory.Options; -import android.os.Build; - -import com.nostra13.universalimageloader.core.DisplayImageOptions; -import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.core.download.ImageDownloader; - -/** - * Contains needed information for decoding image to Bitmap - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.3 - */ -public class ImageDecodingInfo { - - private final String imageKey; - private final String imageUri; - private final String originalImageUri; - private final ImageSize targetSize; - - private final ImageScaleType imageScaleType; - private final ViewScaleType viewScaleType; - - private final ImageDownloader downloader; - private final Object extraForDownloader; - - private final boolean considerExifParams; - private final Options decodingOptions; - - public ImageDecodingInfo(String imageKey, String imageUri, String originalImageUri, ImageSize targetSize, ViewScaleType viewScaleType, - ImageDownloader downloader, DisplayImageOptions displayOptions) { - this.imageKey = imageKey; - this.imageUri = imageUri; - this.originalImageUri = originalImageUri; - this.targetSize = targetSize; - - this.imageScaleType = displayOptions.getImageScaleType(); - this.viewScaleType = viewScaleType; - - this.downloader = downloader; - this.extraForDownloader = displayOptions.getExtraForDownloader(); - - considerExifParams = displayOptions.isConsiderExifParams(); - decodingOptions = new Options(); - copyOptions(displayOptions.getDecodingOptions(), decodingOptions); - } - - private void copyOptions(Options srcOptions, Options destOptions) { - destOptions.inDensity = srcOptions.inDensity; - destOptions.inDither = srcOptions.inDither; - destOptions.inInputShareable = srcOptions.inInputShareable; - destOptions.inJustDecodeBounds = srcOptions.inJustDecodeBounds; - destOptions.inPreferredConfig = srcOptions.inPreferredConfig; - destOptions.inPurgeable = srcOptions.inPurgeable; - destOptions.inSampleSize = srcOptions.inSampleSize; - destOptions.inScaled = srcOptions.inScaled; - destOptions.inScreenDensity = srcOptions.inScreenDensity; - destOptions.inTargetDensity = srcOptions.inTargetDensity; - destOptions.inTempStorage = srcOptions.inTempStorage; - if (Build.VERSION.SDK_INT >= 10) copyOptions10(srcOptions, destOptions); - if (Build.VERSION.SDK_INT >= 11) copyOptions11(srcOptions, destOptions); - } - - @TargetApi(10) - private void copyOptions10(Options srcOptions, Options destOptions) { - destOptions.inPreferQualityOverSpeed = srcOptions.inPreferQualityOverSpeed; - } - - @TargetApi(11) - private void copyOptions11(Options srcOptions, Options destOptions) { - destOptions.inBitmap = srcOptions.inBitmap; - destOptions.inMutable = srcOptions.inMutable; - } - - /** @return Original {@linkplain com.nostra13.universalimageloader.utils.MemoryCacheUtils#generateKey(String, ImageSize) image key} (used in memory cache). */ - public String getImageKey() { - return imageKey; - } - - /** @return Image URI for decoding (usually image from disk cache) */ - public String getImageUri() { - return imageUri; - } - - /** @return The original image URI which was passed to ImageLoader */ - public String getOriginalImageUri() { - return originalImageUri; - } - - /** - * @return Target size for image. Decoded bitmap should close to this size according to {@linkplain ImageScaleType - * image scale type} and {@linkplain ViewScaleType view scale type}. - */ - public ImageSize getTargetSize() { - return targetSize; - } - - /** - * @return {@linkplain ImageScaleType Scale type for image sampling and scaling}. This parameter affects result size - * of decoded bitmap. - */ - public ImageScaleType getImageScaleType() { - return imageScaleType; - } - - /** @return {@linkplain ViewScaleType View scale type}. This parameter affects result size of decoded bitmap. */ - public ViewScaleType getViewScaleType() { - return viewScaleType; - } - - /** @return Downloader for image loading */ - public ImageDownloader getDownloader() { - return downloader; - } - - /** @return Auxiliary object for downloader */ - public Object getExtraForDownloader() { - return extraForDownloader; - } - - /** @return true - if EXIF params of image should be considered; false - otherwise */ - public boolean shouldConsiderExifParams() { - return considerExifParams; - } - - /** @return Decoding options */ - public Options getDecodingOptions() { - return decodingOptions; - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/BitmapDisplayer.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/BitmapDisplayer.java deleted file mode 100644 index 1149111ec..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/BitmapDisplayer.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.display; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; - -/** - * Displays {@link Bitmap} in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware}. Implementations can - * apply some changes to Bitmap or any animation for displaying Bitmap.
    - * Implementations have to be thread-safe. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see com.nostra13.universalimageloader.core.imageaware.ImageAware - * @see com.nostra13.universalimageloader.core.assist.LoadedFrom - * @since 1.5.6 - */ -public interface BitmapDisplayer { - /** - * Displays bitmap in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware}. - * NOTE: This method is called on UI thread so it's strongly recommended not to do any heavy work in it. - * - * @param bitmap Source bitmap - * @param imageAware {@linkplain com.nostra13.universalimageloader.core.imageaware.ImageAware Image aware view} to - * display Bitmap - * @param loadedFrom Source of loaded image - */ - void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/FadeInBitmapDisplayer.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/FadeInBitmapDisplayer.java deleted file mode 100644 index 686f0fd1f..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/FadeInBitmapDisplayer.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich, Daniel Martí - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.display; - -import android.graphics.Bitmap; -import android.view.View; -import android.view.animation.AlphaAnimation; -import android.view.animation.DecelerateInterpolator; -import android.widget.ImageView; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; - -/** - * Displays image with "fade in" animation - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com), Daniel Martí - * @since 1.6.4 - */ -public class FadeInBitmapDisplayer implements BitmapDisplayer { - - private final int durationMillis; - - private final boolean animateFromNetwork; - private final boolean animateFromDisk; - private final boolean animateFromMemory; - - /** - * @param durationMillis Duration of "fade-in" animation (in milliseconds) - */ - public FadeInBitmapDisplayer(int durationMillis) { - this(durationMillis, true, true, true); - } - - /** - * @param durationMillis Duration of "fade-in" animation (in milliseconds) - * @param animateFromNetwork Whether animation should be played if image is loaded from network - * @param animateFromDisk Whether animation should be played if image is loaded from disk cache - * @param animateFromMemory Whether animation should be played if image is loaded from memory cache - */ - public FadeInBitmapDisplayer(int durationMillis, boolean animateFromNetwork, boolean animateFromDisk, - boolean animateFromMemory) { - this.durationMillis = durationMillis; - this.animateFromNetwork = animateFromNetwork; - this.animateFromDisk = animateFromDisk; - this.animateFromMemory = animateFromMemory; - } - - @Override - public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { - imageAware.setImageBitmap(bitmap); - - if ((animateFromNetwork && loadedFrom == LoadedFrom.NETWORK) || - (animateFromDisk && loadedFrom == LoadedFrom.DISC_CACHE) || - (animateFromMemory && loadedFrom == LoadedFrom.MEMORY_CACHE)) { - animate(imageAware.getWrappedView(), durationMillis); - } - } - - /** - * Animates {@link ImageView} with "fade-in" effect - * - * @param imageView {@link ImageView} which display image in - * @param durationMillis The length of the animation in milliseconds - */ - public static void animate(View imageView, int durationMillis) { - if (imageView != null) { - AlphaAnimation fadeImage = new AlphaAnimation(0, 1); - fadeImage.setDuration(durationMillis); - fadeImage.setInterpolator(new DecelerateInterpolator()); - imageView.startAnimation(fadeImage); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedBitmapDisplayer.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedBitmapDisplayer.java deleted file mode 100644 index c4dd8d5f8..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedBitmapDisplayer.java +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.display; - -import android.graphics.*; -import android.graphics.drawable.Drawable; - -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; - -/** - * Can display bitmap with rounded corners. This implementation works only with ImageViews wrapped - * in ImageViewAware. - *
    - * This implementation is inspired by - * - * Romain Guy's article. It rounds images using custom drawable drawing. Original bitmap isn't changed. - *
    - *
    - * If this implementation doesn't meet your needs then consider - * RoundedImageView or - * CircularImageView projects for usage. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.5.6 - */ -public class RoundedBitmapDisplayer implements BitmapDisplayer { - - protected final int cornerRadius; - protected final int margin; - - public RoundedBitmapDisplayer(int cornerRadiusPixels) { - this(cornerRadiusPixels, 0); - } - - public RoundedBitmapDisplayer(int cornerRadiusPixels, int marginPixels) { - this.cornerRadius = cornerRadiusPixels; - this.margin = marginPixels; - } - - @Override - public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { - if (!(imageAware instanceof ImageViewAware)) { - throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected."); - } - - imageAware.setImageDrawable(new RoundedDrawable(bitmap, cornerRadius, margin)); - } - - public static class RoundedDrawable extends Drawable { - - protected final float cornerRadius; - protected final int margin; - - protected final RectF mRect = new RectF(), - mBitmapRect; - protected final BitmapShader bitmapShader; - protected final Paint paint; - - public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) { - this.cornerRadius = cornerRadius; - this.margin = margin; - - bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - mBitmapRect = new RectF (margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin); - - paint = new Paint(); - paint.setAntiAlias(true); - paint.setShader(bitmapShader); - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin); - - // Resize the original bitmap to fit the new bound - Matrix shaderMatrix = new Matrix(); - shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL); - bitmapShader.setLocalMatrix(shaderMatrix); - - } - - @Override - public void draw(Canvas canvas) { - canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setAlpha(int alpha) { - paint.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter cf) { - paint.setColorFilter(cf); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedVignetteBitmapDisplayer.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedVignetteBitmapDisplayer.java deleted file mode 100644 index bea59d354..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/RoundedVignetteBitmapDisplayer.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * Copyright 2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.display; - -import android.graphics.*; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; -import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; - -/** - * Can display bitmap with rounded corners and vignette effect. This implementation works only with ImageViews wrapped - * in ImageViewAware. - *
    - * This implementation is inspired by - * - * Romain Guy's article. It rounds images using custom drawable drawing. Original bitmap isn't changed. - *
    - *
    - * If this implementation doesn't meet your needs then consider - * this project for usage. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.1 - */ -public class RoundedVignetteBitmapDisplayer extends RoundedBitmapDisplayer { - - public RoundedVignetteBitmapDisplayer(int cornerRadiusPixels, int marginPixels) { - super(cornerRadiusPixels, marginPixels); - } - - @Override - public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { - if (!(imageAware instanceof ImageViewAware)) { - throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected."); - } - - imageAware.setImageDrawable(new RoundedVignetteDrawable(bitmap, cornerRadius, margin)); - } - - protected static class RoundedVignetteDrawable extends RoundedDrawable { - - RoundedVignetteDrawable(Bitmap bitmap, int cornerRadius, int margin) { - super(bitmap, cornerRadius, margin); - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - RadialGradient vignette = new RadialGradient( - mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f, - new int[]{0, 0, 0x7f000000}, new float[]{0.0f, 0.7f, 1.0f}, - Shader.TileMode.CLAMP); - - Matrix oval = new Matrix(); - oval.setScale(1.0f, 0.7f); - vignette.setLocalMatrix(oval); - - paint.setShader(new ComposeShader(bitmapShader, vignette, PorterDuff.Mode.SRC_OVER)); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/SimpleBitmapDisplayer.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/SimpleBitmapDisplayer.java deleted file mode 100644 index 8aae7de6b..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/display/SimpleBitmapDisplayer.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.display; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.core.assist.LoadedFrom; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; - -/** - * Just displays {@link Bitmap} in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.5.6 - */ -public final class SimpleBitmapDisplayer implements BitmapDisplayer { - @Override - public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { - imageAware.setImageBitmap(bitmap); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/BaseImageDownloader.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/BaseImageDownloader.java deleted file mode 100644 index f050eebc6..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/BaseImageDownloader.java +++ /dev/null @@ -1,293 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.download; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.media.ThumbnailUtils; -import android.net.Uri; -import android.os.Build; -import android.provider.ContactsContract; -import android.provider.MediaStore; -import android.webkit.MimeTypeMap; -import com.nostra13.universalimageloader.core.DisplayImageOptions; -import com.nostra13.universalimageloader.core.assist.ContentLengthInputStream; -import com.nostra13.universalimageloader.utils.IoUtils; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; - -/** - * Provides retrieving of {@link InputStream} of image by URI from network or file system or app resources.
    - * {@link URLConnection} is used to retrieve image stream from network. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.0 - */ -public class BaseImageDownloader implements ImageDownloader { - /** {@value} */ - public static final int DEFAULT_HTTP_CONNECT_TIMEOUT = 5 * 1000; // milliseconds - /** {@value} */ - public static final int DEFAULT_HTTP_READ_TIMEOUT = 20 * 1000; // milliseconds - - /** {@value} */ - protected static final int BUFFER_SIZE = 32 * 1024; // 32 Kb - /** {@value} */ - protected static final String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%"; - - protected static final int MAX_REDIRECT_COUNT = 5; - - protected static final String CONTENT_CONTACTS_URI_PREFIX = "content://com.android.contacts/"; - - private static final String ERROR_UNSUPPORTED_SCHEME = "UIL doesn't support scheme(protocol) by default [%s]. " + "You should implement this support yourself (BaseImageDownloader.getStreamFromOtherSource(...))"; - - protected final Context context; - protected final int connectTimeout; - protected final int readTimeout; - - public BaseImageDownloader(Context context) { - this(context, DEFAULT_HTTP_CONNECT_TIMEOUT, DEFAULT_HTTP_READ_TIMEOUT); - } - - public BaseImageDownloader(Context context, int connectTimeout, int readTimeout) { - this.context = context.getApplicationContext(); - this.connectTimeout = connectTimeout; - this.readTimeout = readTimeout; - } - - @Override - public InputStream getStream(String imageUri, Object extra) throws IOException { - switch (Scheme.ofUri(imageUri)) { - case HTTP: - case HTTPS: - return getStreamFromNetwork(imageUri, extra); - case FILE: - return getStreamFromFile(imageUri, extra); - case CONTENT: - return getStreamFromContent(imageUri, extra); - case ASSETS: - return getStreamFromAssets(imageUri, extra); - case DRAWABLE: - return getStreamFromDrawable(imageUri, extra); - case UNKNOWN: - default: - return getStreamFromOtherSource(imageUri, extra); - } - } - - /** - * Retrieves {@link InputStream} of image by URI (image is located in the network). - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws IOException if some I/O error occurs during network request or if no InputStream could be created for - * URL. - */ - protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException { - HttpURLConnection conn = createConnection(imageUri, extra); - - int redirectCount = 0; - while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) { - conn = createConnection(conn.getHeaderField("Location"), extra); - redirectCount++; - } - - InputStream imageStream; - try { - imageStream = conn.getInputStream(); - } catch (IOException e) { - // Read all data to allow reuse connection (http://bit.ly/1ad35PY) - IoUtils.readAndCloseStream(conn.getErrorStream()); - throw e; - } - if (!shouldBeProcessed(conn)) { - IoUtils.closeSilently(imageStream); - throw new IOException("Image request failed with response code " + conn.getResponseCode()); - } - - return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength()); - } - - /** - * @param conn Opened request connection (response code is available) - * @return true - if data from connection is correct and should be read and processed; - * false - if response contains irrelevant data and shouldn't be processed - * @throws IOException - */ - protected boolean shouldBeProcessed(HttpURLConnection conn) throws IOException { - return conn.getResponseCode() == 200; - } - - /** - * Create {@linkplain HttpURLConnection HTTP connection} for incoming URL - * - * @param url URL to connect to - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@linkplain HttpURLConnection Connection} for incoming URL. Connection isn't established so it still configurable. - * @throws IOException if some I/O error occurs during network request or if no InputStream could be created for - * URL. - */ - protected HttpURLConnection createConnection(String url, Object extra) throws IOException { - String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS); - HttpURLConnection conn = (HttpURLConnection) new URL(encodedUrl).openConnection(); - conn.setConnectTimeout(connectTimeout); - conn.setReadTimeout(readTimeout); - return conn; - } - - /** - * Retrieves {@link InputStream} of image by URI (image is located on the local file system or SD card). - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws IOException if some I/O error occurs reading from file system - */ - protected InputStream getStreamFromFile(String imageUri, Object extra) throws IOException { - String filePath = Scheme.FILE.crop(imageUri); - if (isVideoFileUri(imageUri)) { - return getVideoThumbnailStream(filePath); - } else { - BufferedInputStream imageStream = new BufferedInputStream(new FileInputStream(filePath), BUFFER_SIZE); - return new ContentLengthInputStream(imageStream, (int) new File(filePath).length()); - } - } - - @TargetApi(Build.VERSION_CODES.FROYO) - private InputStream getVideoThumbnailStream(String filePath) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { - Bitmap bitmap = ThumbnailUtils - .createVideoThumbnail(filePath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND); - if (bitmap != null) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bitmap.compress(CompressFormat.PNG, 0, bos); - return new ByteArrayInputStream(bos.toByteArray()); - } - } - return null; - } - - /** - * Retrieves {@link InputStream} of image by URI (image is accessed using {@link ContentResolver}). - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws FileNotFoundException if the provided URI could not be opened - */ - protected InputStream getStreamFromContent(String imageUri, Object extra) throws FileNotFoundException { - ContentResolver res = context.getContentResolver(); - - Uri uri = Uri.parse(imageUri); - if (isVideoContentUri(uri)) { // video thumbnail - Long origId = Long.valueOf(uri.getLastPathSegment()); - Bitmap bitmap = MediaStore.Video.Thumbnails - .getThumbnail(res, origId, MediaStore.Images.Thumbnails.MINI_KIND, null); - if (bitmap != null) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bitmap.compress(CompressFormat.PNG, 0, bos); - return new ByteArrayInputStream(bos.toByteArray()); - } - } else if (imageUri.startsWith(CONTENT_CONTACTS_URI_PREFIX)) { // contacts photo - return getContactPhotoStream(uri); - } - - return res.openInputStream(uri); - } - - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - protected InputStream getContactPhotoStream(Uri uri) { - ContentResolver res = context.getContentResolver(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return ContactsContract.Contacts.openContactPhotoInputStream(res, uri, true); - } else { - return ContactsContract.Contacts.openContactPhotoInputStream(res, uri); - } - } - - /** - * Retrieves {@link InputStream} of image by URI (image is located in assets of application). - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws IOException if some I/O error occurs file reading - */ - protected InputStream getStreamFromAssets(String imageUri, Object extra) throws IOException { - String filePath = Scheme.ASSETS.crop(imageUri); - return context.getAssets().open(filePath); - } - - /** - * Retrieves {@link InputStream} of image by URI (image is located in drawable resources of application). - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - */ - protected InputStream getStreamFromDrawable(String imageUri, Object extra) { - String drawableIdString = Scheme.DRAWABLE.crop(imageUri); - int drawableId = Integer.parseInt(drawableIdString); - return context.getResources().openRawResource(drawableId); - } - - /** - * Retrieves {@link InputStream} of image by URI from other source with unsupported scheme. Should be overriden by - * successors to implement image downloading from special sources.
    - * This method is called only if image URI has unsupported scheme. Throws {@link UnsupportedOperationException} by - * default. - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws IOException if some I/O error occurs - * @throws UnsupportedOperationException if image URI has unsupported scheme(protocol) - */ - protected InputStream getStreamFromOtherSource(String imageUri, Object extra) throws IOException { - throw new UnsupportedOperationException(String.format(ERROR_UNSUPPORTED_SCHEME, imageUri)); - } - - private boolean isVideoContentUri(Uri uri) { - String mimeType = context.getContentResolver().getType(uri); - return mimeType != null && mimeType.startsWith("video/"); - } - - private boolean isVideoFileUri(String uri) { - String extension = MimeTypeMap.getFileExtensionFromUrl(uri); - String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - return mimeType != null && mimeType.startsWith("video/"); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/ImageDownloader.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/ImageDownloader.java deleted file mode 100644 index 3fa0fb5cc..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/download/ImageDownloader.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.download; - -import com.nostra13.universalimageloader.core.DisplayImageOptions; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -/** - * Provides retrieving of {@link InputStream} of image by URI.
    - * Implementations have to be thread-safe. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.4.0 - */ -public interface ImageDownloader { - /** - * Retrieves {@link InputStream} of image by URI. - * - * @param imageUri Image URI - * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) - * DisplayImageOptions.extraForDownloader(Object)}; can be null - * @return {@link InputStream} of image - * @throws IOException if some I/O error occurs during getting image stream - * @throws UnsupportedOperationException if image URI has unsupported scheme(protocol) - */ - InputStream getStream(String imageUri, Object extra) throws IOException; - - /** Represents supported schemes(protocols) of URI. Provides convenient methods for work with schemes and URIs. */ - public enum Scheme { - HTTP("http"), HTTPS("https"), FILE("file"), CONTENT("content"), ASSETS("assets"), DRAWABLE("drawable"), UNKNOWN(""); - - private String scheme; - private String uriPrefix; - - Scheme(String scheme) { - this.scheme = scheme; - uriPrefix = scheme + "://"; - } - - /** - * Defines scheme of incoming URI - * - * @param uri URI for scheme detection - * @return Scheme of incoming URI - */ - public static Scheme ofUri(String uri) { - if (uri != null) { - for (Scheme s : values()) { - if (s.belongsTo(uri)) { - return s; - } - } - } - return UNKNOWN; - } - - private boolean belongsTo(String uri) { - return uri.toLowerCase(Locale.US).startsWith(uriPrefix); - } - - /** Appends scheme to incoming path */ - public String wrap(String path) { - return uriPrefix + path; - } - - /** Removed scheme part ("scheme://") from incoming URI */ - public String crop(String uri) { - if (!belongsTo(uri)) { - throw new IllegalArgumentException(String.format("URI [%1$s] doesn't have expected scheme [%2$s]", uri, scheme)); - } - return uri.substring(uriPrefix.length()); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageAware.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageAware.java deleted file mode 100644 index ba1f4cb83..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageAware.java +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.imageaware; - -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.view.View; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; - -/** - * Represents image aware view which provides all needed properties and behavior for image processing and displaying - * through {@link com.nostra13.universalimageloader.core.ImageLoader ImageLoader}. - * It can wrap any Android {@link android.view.View View} which can be accessed by {@link #getWrappedView()}. Wrapped - * view is returned in {@link com.nostra13.universalimageloader.core.listener.ImageLoadingListener ImageLoadingListener}'s - * callbacks. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see ViewAware - * @see ImageViewAware - * @see NonViewAware - * @since 1.9.0 - */ -public interface ImageAware { - /** - * Returns width of image aware view. This value is used to define scale size for original image. - * Can return 0 if width is undefined.
    - * Is called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - */ - int getWidth(); - - /** - * Returns height of image aware view. This value is used to define scale size for original image. - * Can return 0 if height is undefined.
    - * Is called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - */ - int getHeight(); - - /** - * Returns {@linkplain com.nostra13.universalimageloader.core.assist.ViewScaleType scale type} which is used for - * scaling image for this image aware view. Must NOT return null. - */ - ViewScaleType getScaleType(); - - /** - * Returns wrapped Android {@link android.view.View View}. Can return null if no view is wrapped or view was - * collected by GC.
    - * Is called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - */ - View getWrappedView(); - - /** - * Returns a flag whether image aware view is collected by GC or whatsoever. If so then ImageLoader stop processing - * of task for this image aware view and fires - * {@link com.nostra13.universalimageloader.core.listener.ImageLoadingListener#onLoadingCancelled(String, - * android.view.View) ImageLoadingListener#onLoadingCancelled(String, View)} callback.
    - * Mey be called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - * - * @return true - if view is collected by GC and ImageLoader should stop processing this image aware view; - * false - otherwise - */ - boolean isCollected(); - - /** - * Returns ID of image aware view. Point of ID is similar to Object's hashCode. This ID should be unique for every - * image view instance and should be the same for same instances. This ID identifies processing task in ImageLoader - * so ImageLoader won't process two image aware views with the same ID in one time. When ImageLoader get new task - * it cancels old task with this ID (if any) and starts new task. - *

    - * It's reasonable to return hash code of wrapped view (if any) to prevent displaying non-actual images in view - * because of view re-using. - */ - int getId(); - - /** - * Sets image drawable into this image aware view.
    - * Displays drawable in this image aware view - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions.Builder#showImageForEmptyUri( - *android.graphics.drawable.Drawable) for empty Uri}, - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions.Builder#showImageOnLoading( - *android.graphics.drawable.Drawable) on loading} or - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions.Builder#showImageOnFail( - *android.graphics.drawable.Drawable) on loading fail}. These drawables can be specified in - * {@linkplain com.nostra13.universalimageloader.core.DisplayImageOptions display options}.
    - * Also can be called in {@link com.nostra13.universalimageloader.core.display.BitmapDisplayer BitmapDisplayer}.< br /> - * Is called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - * - * @return true if drawable was set successfully; false - otherwise - */ - boolean setImageDrawable(Drawable drawable); - - /** - * Sets image bitmap into this image aware view.
    - * Displays loaded and decoded image {@link android.graphics.Bitmap} in this image view aware. - * Actually it's used only in - * {@link com.nostra13.universalimageloader.core.display.BitmapDisplayer BitmapDisplayer}.< br /> - * Is called on UI thread if ImageLoader was called on UI thread. Otherwise - on background thread. - * - * @return true if bitmap was set successfully; false - otherwise - */ - boolean setImageBitmap(Bitmap bitmap); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageViewAware.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageViewAware.java deleted file mode 100644 index 418f6b0a4..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ImageViewAware.java +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.imageaware; - -import android.graphics.Bitmap; -import android.graphics.drawable.AnimationDrawable; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.widget.ImageView; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.utils.L; - -import java.lang.reflect.Field; - -/** - * Wrapper for Android {@link android.widget.ImageView ImageView}. Keeps weak reference of ImageView to prevent memory - * leaks. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.0 - */ -public class ImageViewAware extends ViewAware { - - /** - * Constructor.
    - * References {@link #ImageViewAware(android.widget.ImageView, boolean) ImageViewAware(imageView, true)}. - * - * @param imageView {@link android.widget.ImageView ImageView} to work with - */ - public ImageViewAware(ImageView imageView) { - super(imageView); - } - - /** - * Constructor - * - * @param imageView {@link android.widget.ImageView ImageView} to work with - * @param checkActualViewSize true - then {@link #getWidth()} and {@link #getHeight()} will check actual - * size of ImageView. It can cause known issues like - * this. - * But it helps to save memory because memory cache keeps bitmaps of actual (less in - * general) size. - *

    - * false - then {@link #getWidth()} and {@link #getHeight()} will NOT - * consider actual size of ImageView, just layout parameters.
    If you set 'false' - * it's recommended 'android:layout_width' and 'android:layout_height' (or - * 'android:maxWidth' and 'android:maxHeight') are set with concrete values. It helps to - * save memory. - *

    - */ - public ImageViewAware(ImageView imageView, boolean checkActualViewSize) { - super(imageView, checkActualViewSize); - } - - /** - * {@inheritDoc} - *
    - * 3) Get maxWidth. - */ - @Override - public int getWidth() { - int width = super.getWidth(); - if (width <= 0) { - ImageView imageView = (ImageView) viewRef.get(); - if (imageView != null) { - width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check maxWidth parameter - } - } - return width; - } - - /** - * {@inheritDoc} - *
    - * 3) Get maxHeight - */ - @Override - public int getHeight() { - int height = super.getHeight(); - if (height <= 0) { - ImageView imageView = (ImageView) viewRef.get(); - if (imageView != null) { - height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check maxHeight parameter - } - } - return height; - } - - @Override - public ViewScaleType getScaleType() { - ImageView imageView = (ImageView) viewRef.get(); - if (imageView != null) { - return ViewScaleType.fromImageView(imageView); - } - return super.getScaleType(); - } - - @Override - public ImageView getWrappedView() { - return (ImageView) super.getWrappedView(); - } - - @Override - protected void setImageDrawableInto(Drawable drawable, View view) { - ((ImageView) view).setImageDrawable(drawable); - if (drawable instanceof AnimationDrawable) { - ((AnimationDrawable)drawable).start(); - } - } - - @Override - protected void setImageBitmapInto(Bitmap bitmap, View view) { - ((ImageView) view).setImageBitmap(bitmap); - } - - private static int getImageViewFieldValue(Object object, String fieldName) { - int value = 0; - try { - Field field = ImageView.class.getDeclaredField(fieldName); - field.setAccessible(true); - int fieldValue = (Integer) field.get(object); - if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) { - value = fieldValue; - } - } catch (Exception e) { - L.e(e); - } - return value; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/NonViewAware.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/NonViewAware.java deleted file mode 100644 index 1975bdfa3..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/NonViewAware.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.imageaware; - -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; -import android.view.View; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; - -/** - * ImageAware which provides needed info for processing of original image but do nothing for displaying image. It's - * used when user need just load and decode image and get it in {@linkplain - * com.nostra13.universalimageloader.core.listener.ImageLoadingListener#onLoadingComplete(String, android.view.View, - * android.graphics.Bitmap) callback}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.0 - */ -public class NonViewAware implements ImageAware { - - protected final String imageUri; - protected final ImageSize imageSize; - protected final ViewScaleType scaleType; - - public NonViewAware(ImageSize imageSize, ViewScaleType scaleType) { - this(null, imageSize, scaleType); - } - - public NonViewAware(String imageUri, ImageSize imageSize, ViewScaleType scaleType) { - if (imageSize == null) throw new IllegalArgumentException("imageSize must not be null"); - if (scaleType == null) throw new IllegalArgumentException("scaleType must not be null"); - - this.imageUri = imageUri; - this.imageSize = imageSize; - this.scaleType = scaleType; - } - - @Override - public int getWidth() { - return imageSize.getWidth(); - } - - @Override - public int getHeight() { - return imageSize.getHeight(); - } - - @Override - public ViewScaleType getScaleType() { - return scaleType; - } - - @Override - public View getWrappedView() { - return null; - } - - @Override - public boolean isCollected() { - return false; - } - - @Override - public int getId() { - return TextUtils.isEmpty(imageUri) ? super.hashCode() : imageUri.hashCode(); - } - - @Override - public boolean setImageDrawable(Drawable drawable) { // Do nothing - return true; - } - - @Override - public boolean setImageBitmap(Bitmap bitmap) { // Do nothing - return true; - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ViewAware.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ViewAware.java deleted file mode 100644 index af6871531..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/imageaware/ViewAware.java +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.imageaware; - -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.os.Looper; -import android.view.View; -import android.view.ViewGroup; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.utils.L; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; - -/** - * Wrapper for Android {@link android.view.View View}. Keeps weak reference of View to prevent memory leaks. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.2 - */ -public abstract class ViewAware implements ImageAware { - - public static final String WARN_CANT_SET_DRAWABLE = "Can't set a drawable into view. You should call ImageLoader on UI thread for it."; - public static final String WARN_CANT_SET_BITMAP = "Can't set a bitmap into view. You should call ImageLoader on UI thread for it."; - - protected Reference viewRef; - protected boolean checkActualViewSize; - - /** - * Constructor.
    - * References {@link #ViewAware(android.view.View, boolean) ImageViewAware(imageView, true)}. - * - * @param view {@link android.view.View View} to work with - */ - public ViewAware(View view) { - this(view, true); - } - - /** - * Constructor - * - * @param view {@link android.view.View View} to work with - * @param checkActualViewSize true - then {@link #getWidth()} and {@link #getHeight()} will check actual - * size of View. It can cause known issues like - * this. - * But it helps to save memory because memory cache keeps bitmaps of actual (less in - * general) size. - *

    - * false - then {@link #getWidth()} and {@link #getHeight()} will NOT - * consider actual size of View, just layout parameters.
    If you set 'false' - * it's recommended 'android:layout_width' and 'android:layout_height' (or - * 'android:maxWidth' and 'android:maxHeight') are set with concrete values. It helps to - * save memory. - */ - public ViewAware(View view, boolean checkActualViewSize) { - if (view == null) throw new IllegalArgumentException("view must not be null"); - - this.viewRef = new WeakReference(view); - this.checkActualViewSize = checkActualViewSize; - } - - /** - * {@inheritDoc} - *

    - * Width is defined by target {@link android.view.View view} parameters, configuration - * parameters or device display dimensions.
    - * Size computing algorithm (go by steps until get non-zero value):
    - * 1) Get the actual drawn getWidth() of the View
    - * 2) Get layout_width - */ - @Override - public int getWidth() { - View view = viewRef.get(); - if (view != null) { - final ViewGroup.LayoutParams params = view.getLayoutParams(); - int width = 0; - if (checkActualViewSize && params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) { - width = view.getWidth(); // Get actual image width - } - if (width <= 0 && params != null) width = params.width; // Get layout width parameter - return width; - } - return 0; - } - - /** - * {@inheritDoc} - *

    - * Height is defined by target {@link android.view.View view} parameters, configuration - * parameters or device display dimensions.
    - * Size computing algorithm (go by steps until get non-zero value):
    - * 1) Get the actual drawn getHeight() of the View
    - * 2) Get layout_height - */ - @Override - public int getHeight() { - View view = viewRef.get(); - if (view != null) { - final ViewGroup.LayoutParams params = view.getLayoutParams(); - int height = 0; - if (checkActualViewSize && params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) { - height = view.getHeight(); // Get actual image height - } - if (height <= 0 && params != null) height = params.height; // Get layout height parameter - return height; - } - return 0; - } - - @Override - public ViewScaleType getScaleType() { - return ViewScaleType.CROP; - } - - @Override - public View getWrappedView() { - return viewRef.get(); - } - - @Override - public boolean isCollected() { - return viewRef.get() == null; - } - - @Override - public int getId() { - View view = viewRef.get(); - return view == null ? super.hashCode() : view.hashCode(); - } - - @Override - public boolean setImageDrawable(Drawable drawable) { - if (Looper.myLooper() == Looper.getMainLooper()) { - View view = viewRef.get(); - if (view != null) { - setImageDrawableInto(drawable, view); - return true; - } - } else { - L.w(WARN_CANT_SET_DRAWABLE); - } - return false; - } - - @Override - public boolean setImageBitmap(Bitmap bitmap) { - if (Looper.myLooper() == Looper.getMainLooper()) { - View view = viewRef.get(); - if (view != null) { - setImageBitmapInto(bitmap, view); - return true; - } - } else { - L.w(WARN_CANT_SET_BITMAP); - } - return false; - } - - /** - * Should set drawable into incoming view. Incoming view is guaranteed not null.
    - * This method is called on UI thread. - */ - protected abstract void setImageDrawableInto(Drawable drawable, View view); - - /** - * Should set Bitmap into incoming view. Incoming view is guaranteed not null.< br /> - * This method is called on UI thread. - */ - protected abstract void setImageBitmapInto(Bitmap bitmap, View view); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingListener.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingListener.java deleted file mode 100644 index 7be04fbcf..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingListener.java +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.listener; - -import android.graphics.Bitmap; -import android.view.View; -import com.nostra13.universalimageloader.core.assist.FailReason; - -/** - * Listener for image loading process.
    - * You can use {@link SimpleImageLoadingListener} for implementing only needed methods. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @see SimpleImageLoadingListener - * @see com.nostra13.universalimageloader.core.assist.FailReason - * @since 1.0.0 - */ -public interface ImageLoadingListener { - - /** - * Is called when image loading task was started - * - * @param imageUri Loading image URI - * @param view View for image - */ - void onLoadingStarted(String imageUri, View view); - - /** - * Is called when an error was occurred during image loading - * - * @param imageUri Loading image URI - * @param view View for image. Can be null. - * @param failReason {@linkplain com.nostra13.universalimageloader.core.assist.FailReason The reason} why image - * loading was failed - */ - void onLoadingFailed(String imageUri, View view, FailReason failReason); - - /** - * Is called when image is loaded successfully (and displayed in View if one was specified) - * - * @param imageUri Loaded image URI - * @param view View for image. Can be null. - * @param loadedImage Bitmap of loaded and decoded image - */ - void onLoadingComplete(String imageUri, View view, Bitmap loadedImage); - - /** - * Is called when image loading task was cancelled because View for image was reused in newer task - * - * @param imageUri Loading image URI - * @param view View for image. Can be null. - */ - void onLoadingCancelled(String imageUri, View view); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingProgressListener.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingProgressListener.java deleted file mode 100644 index c9ce6848c..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/ImageLoadingProgressListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright 2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.listener; - -import android.view.View; - -/** - * Listener for image loading progress. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.9.1 - */ -public interface ImageLoadingProgressListener { - - /** - * Is called when image loading progress changed. - * - * @param imageUri Image URI - * @param view View for image. Can be null. - * @param current Downloaded size in bytes - * @param total Total size in bytes - */ - void onProgressUpdate(String imageUri, View view, int current, int total); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/PauseOnScrollListener.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/PauseOnScrollListener.java deleted file mode 100644 index 870822f65..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/PauseOnScrollListener.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.listener; - -import android.widget.AbsListView; -import android.widget.AbsListView.OnScrollListener; -import android.widget.GridView; -import android.widget.ListView; -import com.nostra13.universalimageloader.core.ImageLoader; - -/** - * Listener-helper for {@linkplain AbsListView list views} ({@link ListView}, {@link GridView}) which can - * {@linkplain ImageLoader#pause() pause ImageLoader's tasks} while list view is scrolling (touch scrolling and/or - * fling). It prevents redundant loadings.
    - * Set it to your list view's {@link AbsListView#setOnScrollListener(OnScrollListener) setOnScrollListener(...)}.
    - * This listener can wrap your custom {@linkplain OnScrollListener listener}. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.7.0 - */ -public class PauseOnScrollListener implements OnScrollListener { - - private ImageLoader imageLoader; - - private final boolean pauseOnScroll; - private final boolean pauseOnFling; - private final OnScrollListener externalListener; - - /** - * Constructor - * - * @param imageLoader {@linkplain ImageLoader} instance for controlling - * @param pauseOnScroll Whether {@linkplain ImageLoader#pause() pause ImageLoader} during touch scrolling - * @param pauseOnFling Whether {@linkplain ImageLoader#pause() pause ImageLoader} during fling - */ - public PauseOnScrollListener(ImageLoader imageLoader, boolean pauseOnScroll, boolean pauseOnFling) { - this(imageLoader, pauseOnScroll, pauseOnFling, null); - } - - /** - * Constructor - * - * @param imageLoader {@linkplain ImageLoader} instance for controlling - * @param pauseOnScroll Whether {@linkplain ImageLoader#pause() pause ImageLoader} during touch scrolling - * @param pauseOnFling Whether {@linkplain ImageLoader#pause() pause ImageLoader} during fling - * @param customListener Your custom {@link OnScrollListener} for {@linkplain AbsListView list view} which also - * will be get scroll events - */ - public PauseOnScrollListener(ImageLoader imageLoader, boolean pauseOnScroll, boolean pauseOnFling, - OnScrollListener customListener) { - this.imageLoader = imageLoader; - this.pauseOnScroll = pauseOnScroll; - this.pauseOnFling = pauseOnFling; - externalListener = customListener; - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - switch (scrollState) { - case OnScrollListener.SCROLL_STATE_IDLE: - imageLoader.resume(); - break; - case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: - if (pauseOnScroll) { - imageLoader.pause(); - } - break; - case OnScrollListener.SCROLL_STATE_FLING: - if (pauseOnFling) { - imageLoader.pause(); - } - break; - } - if (externalListener != null) { - externalListener.onScrollStateChanged(view, scrollState); - } - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if (externalListener != null) { - externalListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/SimpleImageLoadingListener.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/SimpleImageLoadingListener.java deleted file mode 100644 index 3e42223d5..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/listener/SimpleImageLoadingListener.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.listener; - -import android.graphics.Bitmap; -import android.view.View; -import com.nostra13.universalimageloader.core.assist.FailReason; - -/** - * A convenient class to extend when you only want to listen for a subset of all the image loading events. This - * implements all methods in the {@link com.nostra13.universalimageloader.core.listener.ImageLoadingListener} but does - * nothing. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.4.0 - */ -public class SimpleImageLoadingListener implements ImageLoadingListener { - @Override - public void onLoadingStarted(String imageUri, View view) { - // Empty implementation - } - - @Override - public void onLoadingFailed(String imageUri, View view, FailReason failReason) { - // Empty implementation - } - - @Override - public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - // Empty implementation - } - - @Override - public void onLoadingCancelled(String imageUri, View view) { - // Empty implementation - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/process/BitmapProcessor.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/process/BitmapProcessor.java deleted file mode 100644 index 962605dbd..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/core/process/BitmapProcessor.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2013 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.core.process; - -import android.graphics.Bitmap; -import com.nostra13.universalimageloader.core.DisplayImageOptions; - -/** - * Makes some processing on {@link Bitmap}. Implementations can apply any changes to original {@link Bitmap}.
    - * Implementations have to be thread-safe. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.0 - */ -public interface BitmapProcessor { - /** - * Makes some processing of incoming bitmap.
    - * This method is executing on additional thread (not on UI thread).
    - * Note: If this processor is used as {@linkplain DisplayImageOptions.Builder#preProcessor(BitmapProcessor) - * pre-processor} then don't forget {@linkplain Bitmap#recycle() to recycle} incoming bitmap if you return a new - * created one. - * - * @param bitmap Original {@linkplain Bitmap bitmap} - * @return Processed {@linkplain Bitmap bitmap} - */ - Bitmap process(Bitmap bitmap); -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/DiskCacheUtils.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/DiskCacheUtils.java deleted file mode 100644 index 3b17fd7d4..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/DiskCacheUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import com.nostra13.universalimageloader.cache.disc.DiskCache; - -import java.io.File; - -/** - * Utility for convenient work with disk cache.
    - * NOTE: This utility works with file system so avoid using it on application main thread. - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.0 - */ -public final class DiskCacheUtils { - - private DiskCacheUtils() { - } - - /** Returns {@link File} of cached image or null if image was not cached in disk cache */ - public static File findInCache(String imageUri, DiskCache diskCache) { - File image = diskCache.get(imageUri); - return image != null && image.exists() ? image : null; - } - - /** - * Removed cached image file from disk cache (if image was cached in disk cache before) - * - * @return true - if cached image file existed and was deleted; false - otherwise. - */ - public static boolean removeFromCache(String imageUri, DiskCache diskCache) { - File image = diskCache.get(imageUri); - return image != null && image.exists() && image.delete(); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/ImageSizeUtils.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/ImageSizeUtils.java deleted file mode 100644 index d899b8d83..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/ImageSizeUtils.java +++ /dev/null @@ -1,215 +0,0 @@ -/******************************************************************************* - * Copyright 2013-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import android.graphics.BitmapFactory; -import android.opengl.GLES10; -import com.nostra13.universalimageloader.core.assist.ImageSize; -import com.nostra13.universalimageloader.core.assist.ViewScaleType; -import com.nostra13.universalimageloader.core.imageaware.ImageAware; - -import javax.microedition.khronos.opengles.GL10; - -/** - * Provides calculations with image sizes, scales - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.8.3 - */ -public final class ImageSizeUtils { - - private static final int DEFAULT_MAX_BITMAP_DIMENSION = 2048; - - private static ImageSize maxBitmapSize; - - static { - int[] maxTextureSize = new int[1]; - GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); - int maxBitmapDimension = Math.max(maxTextureSize[0], DEFAULT_MAX_BITMAP_DIMENSION); - maxBitmapSize = new ImageSize(maxBitmapDimension, maxBitmapDimension); - } - - private ImageSizeUtils() { - } - - /** - * Defines target size for image aware view. Size is defined by target - * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware view} parameters, configuration - * parameters or device display dimensions.
    - */ - public static ImageSize defineTargetSizeForView(ImageAware imageAware, ImageSize maxImageSize) { - int width = imageAware.getWidth(); - if (width <= 0) width = maxImageSize.getWidth(); - - int height = imageAware.getHeight(); - if (height <= 0) height = maxImageSize.getHeight(); - - return new ImageSize(width, height); - } - - /** - * Computes sample size for downscaling image size (srcSize) to view size (targetSize). This sample - * size is used during - * {@linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options) - * decoding image} to bitmap.
    - *
    - * Examples:
    - *

    - *

    -	 * srcSize(100x100), targetSize(10x10), powerOf2Scale = true -> sampleSize = 8
    -	 * srcSize(100x100), targetSize(10x10), powerOf2Scale = false -> sampleSize = 10
    -	 *
    -	 * srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> sampleSize = 5
    -	 * srcSize(100x100), targetSize(20x40), viewScaleType = CROP       -> sampleSize = 2
    -	 * 
    - *

    - *
    - * The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded - * bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 - * the number of pixels. Any value <= 1 is treated the same as 1. - * - * @param srcSize Original (image) size - * @param targetSize Target (view) size - * @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view - * @param powerOf2Scale true - if sample size be a power of 2 (1, 2, 4, 8, ...) - * @return Computed sample size - */ - public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType, - boolean powerOf2Scale) { - final int srcWidth = srcSize.getWidth(); - final int srcHeight = srcSize.getHeight(); - final int targetWidth = targetSize.getWidth(); - final int targetHeight = targetSize.getHeight(); - - int scale = 1; - - switch (viewScaleType) { - case FIT_INSIDE: - if (powerOf2Scale) { - final int halfWidth = srcWidth / 2; - final int halfHeight = srcHeight / 2; - while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // || - scale *= 2; - } - } else { - scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max - } - break; - case CROP: - if (powerOf2Scale) { - final int halfWidth = srcWidth / 2; - final int halfHeight = srcHeight / 2; - while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // && - scale *= 2; - } - } else { - scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min - } - break; - } - - if (scale < 1) { - scale = 1; - } - scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale); - - return scale; - } - - private static int considerMaxTextureSize(int srcWidth, int srcHeight, int scale, boolean powerOf2) { - final int maxWidth = maxBitmapSize.getWidth(); - final int maxHeight = maxBitmapSize.getHeight(); - while ((srcWidth / scale) > maxWidth || (srcHeight / scale) > maxHeight) { - if (powerOf2) { - scale *= 2; - } else { - scale++; - } - } - return scale; - } - - /** - * Computes minimal sample size for downscaling image so result image size won't exceed max acceptable OpenGL - * texture size.
    - * We can't create Bitmap in memory with size exceed max texture size (usually this is 2048x2048) so this method - * calculate minimal sample size which should be applied to image to fit into these limits. - * - * @param srcSize Original image size - * @return Minimal sample size - */ - public static int computeMinImageSampleSize(ImageSize srcSize) { - final int srcWidth = srcSize.getWidth(); - final int srcHeight = srcSize.getHeight(); - final int targetWidth = maxBitmapSize.getWidth(); - final int targetHeight = maxBitmapSize.getHeight(); - - final int widthScale = (int) Math.ceil((float) srcWidth / targetWidth); - final int heightScale = (int) Math.ceil((float) srcHeight / targetHeight); - - return Math.max(widthScale, heightScale); // max - } - - /** - * Computes scale of target size (targetSize) to source size (srcSize).
    - *
    - * Examples:
    - *

    - *

    -	 * srcSize(40x40), targetSize(10x10) -> scale = 0.25
    -	 *
    -	 * srcSize(10x10), targetSize(20x20), stretch = false -> scale = 1
    -	 * srcSize(10x10), targetSize(20x20), stretch = true  -> scale = 2
    -	 *
    -	 * srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> scale = 0.2
    -	 * srcSize(100x100), targetSize(20x40), viewScaleType = CROP       -> scale = 0.4
    -	 * 
    - * - * @param srcSize Source (image) size - * @param targetSize Target (view) size - * @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view - * @param stretch Whether source size should be stretched if target size is larger than source size. If false - * then result scale value can't be greater than 1. - * @return Computed scale - */ - public static float computeImageScale(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType, - boolean stretch) { - final int srcWidth = srcSize.getWidth(); - final int srcHeight = srcSize.getHeight(); - final int targetWidth = targetSize.getWidth(); - final int targetHeight = targetSize.getHeight(); - - final float widthScale = (float) srcWidth / targetWidth; - final float heightScale = (float) srcHeight / targetHeight; - - final int destWidth; - final int destHeight; - if ((viewScaleType == ViewScaleType.FIT_INSIDE && widthScale >= heightScale) || (viewScaleType == ViewScaleType.CROP && widthScale < heightScale)) { - destWidth = targetWidth; - destHeight = (int) (srcHeight / widthScale); - } else { - destWidth = (int) (srcWidth / heightScale); - destHeight = targetHeight; - } - - float scale = 1; - if ((!stretch && destWidth < srcWidth && destHeight < srcHeight) || (stretch && destWidth != srcWidth && destHeight != srcHeight)) { - scale = (float) destWidth / srcWidth; - } - - return scale; - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/IoUtils.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/IoUtils.java deleted file mode 100644 index 498f3c2fc..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/IoUtils.java +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Provides I/O operations - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public final class IoUtils { - - /** {@value} */ - public static final int DEFAULT_BUFFER_SIZE = 32 * 1024; // 32 KB - /** {@value} */ - public static final int DEFAULT_IMAGE_TOTAL_SIZE = 500 * 1024; // 500 Kb - /** {@value} */ - public static final int CONTINUE_LOADING_PERCENTAGE = 75; - - private IoUtils() { - } - - /** - * Copies stream, fires progress events by listener, can be interrupted by listener. Uses buffer size = - * {@value #DEFAULT_BUFFER_SIZE} bytes. - * - * @param is Input stream - * @param os Output stream - * @param listener null-ok; Listener of copying progress and controller of copying interrupting - * @return true - if stream copied successfully; false - if copying was interrupted by listener - * @throws IOException - */ - public static boolean copyStream(InputStream is, OutputStream os, CopyListener listener) throws IOException { - return copyStream(is, os, listener, DEFAULT_BUFFER_SIZE); - } - - /** - * Copies stream, fires progress events by listener, can be interrupted by listener. - * - * @param is Input stream - * @param os Output stream - * @param listener null-ok; Listener of copying progress and controller of copying interrupting - * @param bufferSize Buffer size for copying, also represents a step for firing progress listener callback, i.e. - * progress event will be fired after every copied bufferSize bytes - * @return true - if stream copied successfully; false - if copying was interrupted by listener - * @throws IOException - */ - public static boolean copyStream(InputStream is, OutputStream os, CopyListener listener, int bufferSize) - throws IOException { - int current = 0; - int total = is.available(); - if (total <= 0) { - total = DEFAULT_IMAGE_TOTAL_SIZE; - } - - final byte[] bytes = new byte[bufferSize]; - int count; - if (shouldStopLoading(listener, current, total)) return false; - while ((count = is.read(bytes, 0, bufferSize)) != -1) { - os.write(bytes, 0, count); - current += count; - if (shouldStopLoading(listener, current, total)) return false; - } - os.flush(); - return true; - } - - private static boolean shouldStopLoading(CopyListener listener, int current, int total) { - if (listener != null) { - boolean shouldContinue = listener.onBytesCopied(current, total); - if (!shouldContinue) { - if (100 * current / total < CONTINUE_LOADING_PERCENTAGE) { - return true; // if loaded more than 75% then continue loading anyway - } - } - } - return false; - } - - /** - * Reads all data from stream and close it silently - * - * @param is Input stream - */ - public static void readAndCloseStream(InputStream is) { - final byte[] bytes = new byte[DEFAULT_BUFFER_SIZE]; - try { - while (is.read(bytes, 0, DEFAULT_BUFFER_SIZE) != -1); - } catch (IOException ignored) { - } finally { - closeSilently(is); - } - } - - public static void closeSilently(Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (Exception ignored) { - } - } - } - - /** Listener and controller for copy process */ - public static interface CopyListener { - /** - * @param current Loaded bytes - * @param total Total bytes for loading - * @return true - if copying should be continued; false - if copying should be interrupted - */ - boolean onBytesCopied(int current, int total); - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/L.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/L.java deleted file mode 100644 index 427b8671e..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/L.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import android.util.Log; -import com.nostra13.universalimageloader.core.ImageLoader; - -/** - * "Less-word" analog of Android {@link android.util.Log logger} - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.6.4 - */ -public final class L { - - private static final String LOG_FORMAT = "%1$s\n%2$s"; - private static volatile boolean writeDebugLogs = false; - private static volatile boolean writeLogs = true; - - private L() { - } - - /** - * Enables logger (if {@link #disableLogging()} was called before) - * - * @deprecated Use {@link #writeLogs(boolean) writeLogs(true)} instead - */ - @Deprecated - public static void enableLogging() { - writeLogs(true); - } - - /** - * Disables logger, no logs will be passed to LogCat, all log methods will do nothing - * - * @deprecated Use {@link #writeLogs(boolean) writeLogs(false)} instead - */ - @Deprecated - public static void disableLogging() { - writeLogs(false); - } - - /** - * Enables/disables detail logging of {@link ImageLoader} work. - * Consider {@link com.nostra13.universalimageloader.utils.L#disableLogging()} to disable - * ImageLoader logging completely (even error logs)
    - * Debug logs are disabled by default. - */ - public static void writeDebugLogs(boolean writeDebugLogs) { - L.writeDebugLogs = writeDebugLogs; - } - - /** Enables/disables logging of {@link ImageLoader} completely (even error logs). */ - public static void writeLogs(boolean writeLogs) { - L.writeLogs = writeLogs; - } - - public static void d(String message, Object... args) { - if (writeDebugLogs) { - log(Log.DEBUG, null, message, args); - } - } - - public static void i(String message, Object... args) { - log(Log.INFO, null, message, args); - } - - public static void w(String message, Object... args) { - log(Log.WARN, null, message, args); - } - - public static void e(Throwable ex) { - log(Log.ERROR, ex, null); - } - - public static void e(String message, Object... args) { - log(Log.ERROR, null, message, args); - } - - public static void e(Throwable ex, String message, Object... args) { - log(Log.ERROR, ex, message, args); - } - - private static void log(int priority, Throwable ex, String message, Object... args) { - if (!writeLogs) return; - if (args.length > 0) { - message = String.format(message, args); - } - - String log; - if (ex == null) { - log = message; - } else { - String logMessage = message == null ? ex.getMessage() : message; - String logBody = Log.getStackTraceString(ex); - log = String.format(LOG_FORMAT, logMessage, logBody); - } - Log.println(priority, ImageLoader.TAG, log); - } -} \ No newline at end of file diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/MemoryCacheUtils.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/MemoryCacheUtils.java deleted file mode 100644 index 39bed8799..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/MemoryCacheUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import android.graphics.Bitmap; - -import com.nostra13.universalimageloader.cache.memory.MemoryCache; -import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; -import com.nostra13.universalimageloader.core.assist.ImageSize; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -/** - * Utility for generating of keys for memory cache, key comparing and other work with memory cache - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.6.3 - */ -public final class MemoryCacheUtils { - - private static final String URI_AND_SIZE_SEPARATOR = "_"; - private static final String WIDTH_AND_HEIGHT_SEPARATOR = "x"; - - private MemoryCacheUtils() { - } - - /** - * Generates key for memory cache for incoming image (URI + size).
    - * Pattern for cache key - [imageUri]_[width]x[height]. - */ - public static String generateKey(String imageUri, ImageSize targetSize) { - return new StringBuilder(imageUri).append(URI_AND_SIZE_SEPARATOR).append(targetSize.getWidth()).append(WIDTH_AND_HEIGHT_SEPARATOR).append(targetSize.getHeight()).toString(); - } - - public static Comparator createFuzzyKeyComparator() { - return new Comparator() { - @Override - public int compare(String key1, String key2) { - String imageUri1 = key1.substring(0, key1.lastIndexOf(URI_AND_SIZE_SEPARATOR)); - String imageUri2 = key2.substring(0, key2.lastIndexOf(URI_AND_SIZE_SEPARATOR)); - return imageUri1.compareTo(imageUri2); - } - }; - } - - /** - * Searches all bitmaps in memory cache which are corresponded to incoming URI.
    - * Note: Memory cache can contain multiple sizes of the same image if only you didn't set - * {@link ImageLoaderConfiguration.Builder#denyCacheImageMultipleSizesInMemory() - * denyCacheImageMultipleSizesInMemory()} option in {@linkplain ImageLoaderConfiguration configuration} - */ - public static List findCachedBitmapsForImageUri(String imageUri, MemoryCache memoryCache) { - List values = new ArrayList(); - for (String key : memoryCache.keys()) { - if (key.startsWith(imageUri)) { - values.add(memoryCache.get(key)); - } - } - return values; - } - - /** - * Searches all keys in memory cache which are corresponded to incoming URI.
    - * Note: Memory cache can contain multiple sizes of the same image if only you didn't set - * {@link ImageLoaderConfiguration.Builder#denyCacheImageMultipleSizesInMemory() - * denyCacheImageMultipleSizesInMemory()} option in {@linkplain ImageLoaderConfiguration configuration} - */ - public static List findCacheKeysForImageUri(String imageUri, MemoryCache memoryCache) { - List values = new ArrayList(); - for (String key : memoryCache.keys()) { - if (key.startsWith(imageUri)) { - values.add(key); - } - } - return values; - } - - /** - * Removes from memory cache all images for incoming URI.
    - * Note: Memory cache can contain multiple sizes of the same image if only you didn't set - * {@link ImageLoaderConfiguration.Builder#denyCacheImageMultipleSizesInMemory() - * denyCacheImageMultipleSizesInMemory()} option in {@linkplain ImageLoaderConfiguration configuration} - */ - public static void removeFromCache(String imageUri, MemoryCache memoryCache) { - List keysToRemove = new ArrayList(); - for (String key : memoryCache.keys()) { - if (key.startsWith(imageUri)) { - keysToRemove.add(key); - } - } - for (String keyToRemove : keysToRemove) { - memoryCache.remove(keyToRemove); - } - } -} diff --git a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/StorageUtils.java b/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/StorageUtils.java deleted file mode 100644 index 13026495f..000000000 --- a/extern/UniversalImageLoader/library/src/com/nostra13/universalimageloader/utils/StorageUtils.java +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************* - * Copyright 2011-2014 Sergey Tarasevich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package com.nostra13.universalimageloader.utils; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Environment; - -import java.io.File; -import java.io.IOException; - -import static android.os.Environment.MEDIA_MOUNTED; - -/** - * Provides application storage paths - * - * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) - * @since 1.0.0 - */ -public final class StorageUtils { - - private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE"; - private static final String INDIVIDUAL_DIR_NAME = "uil-images"; - - private StorageUtils() { - } - - /** - * Returns application cache directory. Cache directory will be created on SD card - * ("/Android/data/[app_package_name]/cache") if card is mounted and app has appropriate permission. Else - - * Android defines cache directory on device's file system. - * - * @param context Application context - * @return Cache {@link File directory}.
    - * NOTE: Can be null in some unpredictable cases (if SD card is unmounted and - * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null). - */ - public static File getCacheDirectory(Context context) { - return getCacheDirectory(context, true); - } - - /** - * Returns application cache directory. Cache directory will be created on SD card - * ("/Android/data/[app_package_name]/cache") (if card is mounted and app has appropriate permission) or - * on device's file system depending incoming parameters. - * - * @param context Application context - * @param preferExternal Whether prefer external location for cache - * @return Cache {@link File directory}.
    - * NOTE: Can be null in some unpredictable cases (if SD card is unmounted and - * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null). - */ - public static File getCacheDirectory(Context context, boolean preferExternal) { - File appCacheDir = null; - String externalStorageState; - try { - externalStorageState = Environment.getExternalStorageState(); - } catch (NullPointerException e) { // (sh)it happens (Issue #660) - externalStorageState = ""; - } catch (IncompatibleClassChangeError e) { // (sh)it happens too (Issue #989) - externalStorageState = ""; - } - if (preferExternal && MEDIA_MOUNTED.equals(externalStorageState) && hasExternalStoragePermission(context)) { - appCacheDir = getExternalCacheDir(context); - } - if (appCacheDir == null) { - appCacheDir = context.getCacheDir(); - } - if (appCacheDir == null) { - String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/"; - L.w("Can't define system cache directory! '%s' will be used.", cacheDirPath); - appCacheDir = new File(cacheDirPath); - } - return appCacheDir; - } - - /** - * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be - * created on SD card ("/Android/data/[app_package_name]/cache/uil-images") if card is mounted and app has - * appropriate permission. Else - Android defines cache directory on device's file system. - * - * @param context Application context - * @return Cache {@link File directory} - */ - public static File getIndividualCacheDirectory(Context context) { - return getIndividualCacheDirectory(context, INDIVIDUAL_DIR_NAME); - } - - /** - * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be - * created on SD card ("/Android/data/[app_package_name]/cache/uil-images") if card is mounted and app has - * appropriate permission. Else - Android defines cache directory on device's file system. - * - * @param context Application context - * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images") - * @return Cache {@link File directory} - */ - public static File getIndividualCacheDirectory(Context context, String cacheDir) { - File appCacheDir = getCacheDirectory(context); - File individualCacheDir = new File(appCacheDir, cacheDir); - if (!individualCacheDir.exists()) { - if (!individualCacheDir.mkdir()) { - individualCacheDir = appCacheDir; - } - } - return individualCacheDir; - } - - /** - * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card - * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system. - * - * @param context Application context - * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images") - * @return Cache {@link File directory} - */ - public static File getOwnCacheDirectory(Context context, String cacheDir) { - File appCacheDir = null; - if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) { - appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir); - } - if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) { - appCacheDir = context.getCacheDir(); - } - return appCacheDir; - } - - /** - * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card - * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system. - * - * @param context Application context - * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images") - * @return Cache {@link File directory} - */ - public static File getOwnCacheDirectory(Context context, String cacheDir, boolean preferExternal) { - File appCacheDir = null; - if (preferExternal && MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) { - appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir); - } - if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) { - appCacheDir = context.getCacheDir(); - } - return appCacheDir; - } - - private static File getExternalCacheDir(Context context) { - File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"); - File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache"); - if (!appCacheDir.exists()) { - if (!appCacheDir.mkdirs()) { - L.w("Unable to create external cache directory"); - return null; - } - try { - new File(appCacheDir, ".nomedia").createNewFile(); - } catch (IOException e) { - L.i("Can't create \".nomedia\" file in application external cache directory"); - } - } - return appCacheDir; - } - - private static boolean hasExternalStoragePermission(Context context) { - int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION); - return perm == PackageManager.PERMISSION_GRANTED; - } -} diff --git a/extern/UniversalImageLoader/settings.gradle b/extern/UniversalImageLoader/settings.gradle deleted file mode 100644 index d8f14a134..000000000 --- a/extern/UniversalImageLoader/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':library' diff --git a/extern/libsuperuser/LICENSE b/extern/libsuperuser/LICENSE deleted file mode 100644 index ade750b16..000000000 --- a/extern/libsuperuser/LICENSE +++ /dev/null @@ -1,177 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/extern/libsuperuser/build.gradle b/extern/libsuperuser/build.gradle deleted file mode 100644 index f3de435d5..000000000 --- a/extern/libsuperuser/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -buildscript { - repositories { - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/extern/libsuperuser/libsuperuser/.classpath b/extern/libsuperuser/libsuperuser/.classpath deleted file mode 100644 index b76ec6cd4..000000000 --- a/extern/libsuperuser/libsuperuser/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/extern/libsuperuser/libsuperuser/.project b/extern/libsuperuser/libsuperuser/.project deleted file mode 100644 index 8f20a24e9..000000000 --- a/extern/libsuperuser/libsuperuser/.project +++ /dev/null @@ -1,38 +0,0 @@ - - - libsuperuser - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.saikoa.dexguard.eclipse.adt.ApkBuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/extern/libsuperuser/libsuperuser/AndroidManifest.xml b/extern/libsuperuser/libsuperuser/AndroidManifest.xml deleted file mode 100644 index 2a7f3830e..000000000 --- a/extern/libsuperuser/libsuperuser/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/extern/libsuperuser/libsuperuser/build.gradle b/extern/libsuperuser/libsuperuser/build.gradle deleted file mode 100644 index 8987b1ebe..000000000 --- a/extern/libsuperuser/libsuperuser/build.gradle +++ /dev/null @@ -1,56 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 21 - buildToolsVersion "23.0.1" - - defaultConfig { - minSdkVersion 4 - targetSdkVersion 21 - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_6 - } -} - -version = "1.0.0." + (new Date()).format('yyyyMMddHHmm') -group = "eu.chainfire" - -dependencies { -} - -task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' -} - -task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -artifacts { - archives javadocJar - archives sourcesJar -} - -task findConventions << { - println project.getConvention() -} diff --git a/extern/libsuperuser/libsuperuser/project.properties b/extern/libsuperuser/libsuperuser/project.properties deleted file mode 100644 index 93c8c3c08..000000000 --- a/extern/libsuperuser/libsuperuser/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-21 -android.library=true diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Application.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Application.java deleted file mode 100644 index 095c7209b..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Application.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -import android.content.Context; -import android.os.Handler; -import android.widget.Toast; - -/** - * Base application class to extend from, solving some issues with - * toasts and AsyncTasks you are likely to run into - */ -public class Application extends android.app.Application { - /** - * Shows a toast message - * - * @param context Any context belonging to this application - * @param message The message to show - */ - public static void toast(Context context, String message) { - // this is a static method so it is easier to call, - // as the context checking and casting is done for you - - if (context == null) return; - - if (!(context instanceof Application)) { - context = context.getApplicationContext(); - } - - if (context instanceof Application) { - final Context c = context; - final String m = message; - - ((Application)context).runInApplicationThread(new Runnable() { - @Override - public void run() { - Toast.makeText(c, m, Toast.LENGTH_LONG).show(); - } - }); - } - } - - private static Handler mApplicationHandler = new Handler(); - - /** - * Run a runnable in the main application thread - * - * @param r Runnable to run - */ - public void runInApplicationThread(Runnable r) { - mApplicationHandler.post(r); - } - - @Override - public void onCreate() { - super.onCreate(); - - try { - // workaround bug in AsyncTask, can show up (for example) when you toast from a service - // this makes sure AsyncTask's internal handler is created from the right (main) thread - Class.forName("android.os.AsyncTask"); - } catch (ClassNotFoundException e) { - // will never happen - } - } -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Debug.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Debug.java deleted file mode 100644 index 6116c9abb..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Debug.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -import android.os.Looper; -import android.util.Log; - -/** - * Utility class for logging and debug features that (by default) does nothing when not in debug mode - */ -public class Debug { - - // ----- DEBUGGING ----- - - private static boolean debug = BuildConfig.DEBUG; - - /** - *

    Enable or disable debug mode

    - * - *

    By default, debug mode is enabled for development - * builds and disabled for exported APKs - see - * BuildConfig.DEBUG

    - * - * @param enable Enable debug mode ? - */ - public static void setDebug(boolean enable) { - debug = enable; - } - - /** - *

    Is debug mode enabled ?

    - * - * @return Debug mode enabled - */ - public static boolean getDebug() { - return debug; - } - - // ----- LOGGING ----- - - public interface OnLogListener { - void onLog(int type, String typeIndicator, String message); - } - - public static final String TAG = "libsuperuser"; - - public static final int LOG_GENERAL = 0x0001; - public static final int LOG_COMMAND = 0x0002; - public static final int LOG_OUTPUT = 0x0004; - - public static final int LOG_NONE = 0x0000; - public static final int LOG_ALL = 0xFFFF; - - private static int logTypes = LOG_ALL; - - private static OnLogListener logListener = null; - - /** - *

    Log a message (internal)

    - * - *

    Current debug and enabled logtypes decide what gets logged - - * even if a custom callback is registered

    - * - * @param type Type of message to log - * @param typeIndicator String indicator for message type - * @param message The message to log - */ - private static void logCommon(int type, String typeIndicator, String message) { - if (debug && ((logTypes & type) == type)) { - if (logListener != null) { - logListener.onLog(type, typeIndicator, message); - } else { - Log.d(TAG, "[" + TAG + "][" + typeIndicator + "]" + (!message.startsWith("[") && !message.startsWith(" ") ? " " : "") + message); - } - } - } - - /** - *

    Log a "general" message

    - * - *

    These messages are infrequent and mostly occur at startup/shutdown or on error

    - * - * @param message The message to log - */ - public static void log(String message) { - logCommon(LOG_GENERAL, "G", message); - } - - /** - *

    Log a "per-command" message

    - * - *

    This could produce a lot of output if the client runs many commands in the session

    - * - * @param message The message to log - */ - public static void logCommand(String message) { - logCommon(LOG_COMMAND, "C", message); - } - - /** - *

    Log a line of stdout/stderr output

    - * - *

    This could produce a lot of output if the shell commands are noisy

    - * - * @param message The message to log - */ - public static void logOutput(String message) { - logCommon(LOG_OUTPUT, "O", message); - } - - /** - *

    Enable or disable logging specific types of message

    - * - *

    You may | (or) LOG_* constants together. Note that - * debug mode must also be enabled for actual logging to - * occur.

    - * - * @param type LOG_* constants - * @param enable Enable or disable - */ - public static void setLogTypeEnabled(int type, boolean enable) { - if (enable) { - logTypes |= type; - } else { - logTypes &= ~type; - } - } - - /** - *

    Is logging for specific types of messages enabled ?

    - * - *

    You may | (or) LOG_* constants together, to learn if - * all passed message types are enabled for logging. Note - * that debug mode must also be enabled for actual logging - * to occur.

    - * - * @param type LOG_* constants - */ - public static boolean getLogTypeEnabled(int type) { - return ((logTypes & type) == type); - } - - /** - *

    Is logging for specific types of messages enabled ?

    - * - *

    You may | (or) LOG_* constants together, to learn if - * all message types are enabled for logging. Takes - * debug mode into account for the result.

    - * - * @param type LOG_* constants - */ - public static boolean getLogTypeEnabledEffective(int type) { - return getDebug() && getLogTypeEnabled(type); - } - - /** - *

    Register a custom log handler

    - * - *

    Replaces the log method (write to logcat) with your own - * handler. Whether your handler gets called is still dependent - * on debug mode and message types being enabled for logging.

    - * - * @param onLogListener Custom log listener or NULL to revert to default - */ - public static void setOnLogListener(OnLogListener onLogListener) { - logListener = onLogListener; - } - - /** - *

    Get the currently registered custom log handler

    - * - * @return Current custom log handler or NULL if none is present - */ - public static OnLogListener getOnLogListener() { - return logListener; - } - - // ----- SANITY CHECKS ----- - - private static boolean sanityChecks = true; - - /** - *

    Enable or disable sanity checks

    - * - *

    Enables or disables the library crashing when su is called - * from the main thread.

    - * - * @param enable Enable or disable - */ - public static void setSanityChecksEnabled(boolean enable) { - sanityChecks = enable; - } - - /** - *

    Are sanity checks enabled ?

    - * - *

    Note that debug mode must also be enabled for actual - * sanity checks to occur.

    - * - * @return True if enabled - */ - public static boolean getSanityChecksEnabled() { - return sanityChecks; - } - - /** - *

    Are sanity checks enabled ?

    - * - *

    Takes debug mode into account for the result.

    - * - * @return True if enabled - */ - public static boolean getSanityChecksEnabledEffective() { - return getDebug() && getSanityChecksEnabled(); - } - - /** - *

    Are we running on the main thread ?

    - * - * @return Running on main thread ? - */ - public static boolean onMainThread() { - return ((Looper.myLooper() != null) && (Looper.myLooper() == Looper.getMainLooper())); - } - -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/HideOverlaysReceiver.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/HideOverlaysReceiver.java deleted file mode 100644 index 4b4ce5a8d..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/HideOverlaysReceiver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -/** - *

    - * Base receiver to extend to catch notifications when overlays should be - * hidden. - *

    - *

    - * Tapjacking protection in SuperSU prevents some dialogs from receiving user - * input when overlays are present. For security reasons this notification is - * only sent to apps that have previously been granted root access, so even if - * your app does not require root, you still need to request - * it, and the user must grant it. - *

    - *

    - * Note that the word overlay as used here should be interpreted as "any view or - * window possibly obscuring SuperSU dialogs". - *

    - */ -public abstract class HideOverlaysReceiver extends BroadcastReceiver { - public static final String ACTION_HIDE_OVERLAYS = "eu.chainfire.supersu.action.HIDE_OVERLAYS"; - public static final String CATEGORY_HIDE_OVERLAYS = Intent.CATEGORY_INFO; - public static final String EXTRA_HIDE_OVERLAYS = "eu.chainfire.supersu.extra.HIDE"; - - @Override - public final void onReceive(Context context, Intent intent) { - if (intent.hasExtra(EXTRA_HIDE_OVERLAYS)) { - onHideOverlays(intent.getBooleanExtra(EXTRA_HIDE_OVERLAYS, false)); - } - } - - /** - * Called when overlays should be hidden or may be shown - * again. - * - * @param hide Should overlays be hidden? - */ - public abstract void onHideOverlays(boolean hide); -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Shell.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Shell.java deleted file mode 100644 index 742363a87..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/Shell.java +++ /dev/null @@ -1,1756 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import android.os.Handler; -import android.os.Looper; - -import eu.chainfire.libsuperuser.StreamGobbler.OnLineListener; - -/** - * Class providing functionality to execute commands in a (root) shell - */ -public class Shell { - /** - *

    - * Runs commands using the supplied shell, and returns the output, or null - * in case of errors. - *

    - *

    - * This method is deprecated and only provided for backwards compatibility. - * Use {@link #run(String, String[], String[], boolean)} instead, and see - * that same method for usage notes. - *

    - * - * @param shell The shell to use for executing the commands - * @param commands The commands to execute - * @param wantSTDERR Return STDERR in the output ? - * @return Output of the commands, or null in case of an error - */ - @Deprecated - public static List run(String shell, String[] commands, boolean wantSTDERR) { - return run(shell, commands, null, wantSTDERR); - } - - /** - *

    - * Runs commands using the supplied shell, and returns the output, or null - * in case of errors. - *

    - *

    - * Note that due to compatibility with older Android versions, wantSTDERR is - * not implemented using redirectErrorStream, but rather appended to the - * output. STDOUT and STDERR are thus not guaranteed to be in the correct - * order in the output. - *

    - *

    - * Note as well that this code will intentionally crash when run in debug - * mode from the main thread of the application. You should always execute - * shell commands from a background thread. - *

    - *

    - * When in debug mode, the code will also excessively log the commands - * passed to and the output returned from the shell. - *

    - *

    - * Though this function uses background threads to gobble STDOUT and STDERR - * so a deadlock does not occur if the shell produces massive output, the - * output is still stored in a List<String>, and as such doing - * something like 'ls -lR /' will probably have you run out of - * memory. - *

    - * - * @param shell The shell to use for executing the commands - * @param commands The commands to execute - * @param environment List of all environment variables (in 'key=value' - * format) or null for defaults - * @param wantSTDERR Return STDERR in the output ? - * @return Output of the commands, or null in case of an error - */ - public static List run(String shell, String[] commands, String[] environment, - boolean wantSTDERR) { - String shellUpper = shell.toUpperCase(Locale.ENGLISH); - - if (Debug.getSanityChecksEnabledEffective() && Debug.onMainThread()) { - // check if we're running in the main thread, and if so, crash if - // we're in debug mode, to let the developer know attention is - // needed here. - - Debug.log(ShellOnMainThreadException.EXCEPTION_COMMAND); - throw new ShellOnMainThreadException(ShellOnMainThreadException.EXCEPTION_COMMAND); - } - Debug.logCommand(String.format("[%s%%] START", shellUpper)); - - List res = Collections.synchronizedList(new ArrayList()); - - try { - // Combine passed environment with system environment - if (environment != null) { - Map newEnvironment = new HashMap(); - newEnvironment.putAll(System.getenv()); - int split; - for (String entry : environment) { - if ((split = entry.indexOf("=")) >= 0) { - newEnvironment.put(entry.substring(0, split), entry.substring(split + 1)); - } - } - int i = 0; - environment = new String[newEnvironment.size()]; - for (Map.Entry entry : newEnvironment.entrySet()) { - environment[i] = entry.getKey() + "=" + entry.getValue(); - i++; - } - } - - // setup our process, retrieve STDIN stream, and STDOUT/STDERR - // gobblers - Process process = Runtime.getRuntime().exec(shell, environment); - DataOutputStream STDIN = new DataOutputStream(process.getOutputStream()); - StreamGobbler STDOUT = new StreamGobbler(shellUpper + "-", process.getInputStream(), - res); - StreamGobbler STDERR = new StreamGobbler(shellUpper + "*", process.getErrorStream(), - wantSTDERR ? res : null); - - // start gobbling and write our commands to the shell - STDOUT.start(); - STDERR.start(); - try { - for (String write : commands) { - Debug.logCommand(String.format("[%s+] %s", shellUpper, write)); - STDIN.write((write + "\n").getBytes("UTF-8")); - STDIN.flush(); - } - STDIN.write("exit\n".getBytes("UTF-8")); - STDIN.flush(); - } catch (IOException e) { - if (e.getMessage().contains("EPIPE")) { - // method most horrid to catch broken pipe, in which case we - // do nothing. the command is not a shell, the shell closed - // STDIN, the script already contained the exit command, etc. - // these cases we want the output instead of returning null - } else { - // other issues we don't know how to handle, leads to - // returning null - throw e; - } - } - - // wait for our process to finish, while we gobble away in the - // background - process.waitFor(); - - // make sure our threads are done gobbling, our streams are closed, - // and the process is destroyed - while the latter two shouldn't be - // needed in theory, and may even produce warnings, in "normal" Java - // they are required for guaranteed cleanup of resources, so lets be - // safe and do this on Android as well - try { - STDIN.close(); - } catch (IOException e) { - // might be closed already - } - STDOUT.join(); - STDERR.join(); - process.destroy(); - - // in case of su, 255 usually indicates access denied - if (SU.isSU(shell) && (process.exitValue() == 255)) { - res = null; - } - } catch (IOException e) { - // shell probably not found - res = null; - } catch (InterruptedException e) { - // this should really be re-thrown - res = null; - } - - Debug.logCommand(String.format("[%s%%] END", shell.toUpperCase(Locale.ENGLISH))); - return res; - } - - protected static String[] availableTestCommands = new String[] { - "echo -BOC-", - "id" - }; - - /** - * See if the shell is alive, and if so, check the UID - * - * @param ret Standard output from running availableTestCommands - * @param checkForRoot true if we are expecting this shell to be running as - * root - * @return true on success, false on error - */ - protected static boolean parseAvailableResult(List ret, boolean checkForRoot) { - if (ret == null) - return false; - - // this is only one of many ways this can be done - boolean echo_seen = false; - - for (String line : ret) { - if (line.contains("uid=")) { - // id command is working, let's see if we are actually root - return !checkForRoot || line.contains("uid=0"); - } else if (line.contains("-BOC-")) { - // if we end up here, at least the su command starts some kind - // of shell, - // let's hope it has root privileges - no way to know without - // additional - // native binaries - echo_seen = true; - } - } - - return echo_seen; - } - - /** - * This class provides utility functions to easily execute commands using SH - */ - public static class SH { - /** - * Runs command and return output - * - * @param command The command to run - * @return Output of the command, or null in case of an error - */ - public static List run(String command) { - return Shell.run("sh", new String[] { - command - }, null, false); - } - - /** - * Runs commands and return output - * - * @param commands The commands to run - * @return Output of the commands, or null in case of an error - */ - public static List run(List commands) { - return Shell.run("sh", commands.toArray(new String[commands.size()]), null, false); - } - - /** - * Runs commands and return output - * - * @param commands The commands to run - * @return Output of the commands, or null in case of an error - */ - public static List run(String[] commands) { - return Shell.run("sh", commands, null, false); - } - } - - /** - * This class provides utility functions to easily execute commands using SU - * (root shell), as well as detecting whether or not root is available, and - * if so which version. - */ - public static class SU { - private static Boolean isSELinuxEnforcing = null; - private static String[] suVersion = new String[] { - null, null - }; - - /** - * Runs command as root (if available) and return output - * - * @param command The command to run - * @return Output of the command, or null if root isn't available or in - * case of an error - */ - public static List run(String command) { - return Shell.run("su", new String[] { - command - }, null, false); - } - - /** - * Runs commands as root (if available) and return output - * - * @param commands The commands to run - * @return Output of the commands, or null if root isn't available or in - * case of an error - */ - public static List run(List commands) { - return Shell.run("su", commands.toArray(new String[commands.size()]), null, false); - } - - /** - * Runs commands as root (if available) and return output - * - * @param commands The commands to run - * @return Output of the commands, or null if root isn't available or in - * case of an error - */ - public static List run(String[] commands) { - return Shell.run("su", commands, null, false); - } - - /** - * Detects whether or not superuser access is available, by checking the - * output of the "id" command if available, checking if a shell runs at - * all otherwise - * - * @return True if superuser access available - */ - public static boolean available() { - // this is only one of many ways this can be done - - List ret = run(Shell.availableTestCommands); - return Shell.parseAvailableResult(ret, true); - } - - /** - *

    - * Detects the version of the su binary installed (if any), if supported - * by the binary. Most binaries support two different version numbers, - * the public version that is displayed to users, and an internal - * version number that is used for version number comparisons. Returns - * null if su not available or retrieving the version isn't supported. - *

    - *

    - * Note that su binary version and GUI (APK) version can be completely - * different. - *

    - *

    - * This function caches its result to improve performance on multiple - * calls - *

    - * - * @param internal Request human-readable version or application - * internal version - * @return String containing the su version or null - */ - public static synchronized String version(boolean internal) { - int idx = internal ? 0 : 1; - if (suVersion[idx] == null) { - String version = null; - - List ret = Shell.run( - internal ? "su -V" : "su -v", - new String[] { "exit" }, - null, - false - ); - - if (ret != null) { - for (String line : ret) { - if (!internal) { - if (!line.trim().equals("")) { - version = line; - break; - } - } else { - try { - if (Integer.parseInt(line) > 0) { - version = line; - break; - } - } catch (NumberFormatException e) { - // should be parsable, try next line otherwise - } - } - } - } - - suVersion[idx] = version; - } - return suVersion[idx]; - } - - /** - * Attempts to deduce if the shell command refers to a su shell - * - * @param shell Shell command to run - * @return Shell command appears to be su - */ - public static boolean isSU(String shell) { - // Strip parameters - int pos = shell.indexOf(' '); - if (pos >= 0) { - shell = shell.substring(0, pos); - } - - // Strip path - pos = shell.lastIndexOf('/'); - if (pos >= 0) { - shell = shell.substring(pos + 1); - } - - return shell.equals("su"); - } - - /** - * Constructs a shell command to start a su shell using the supplied uid - * and SELinux context. This is can be an expensive operation, consider - * caching the result. - * - * @param uid Uid to use (0 == root) - * @param context (SELinux) context name to use or null - * @return Shell command - */ - public static String shell(int uid, String context) { - // su[ --context ][ ] - String shell = "su"; - - if ((context != null) && isSELinuxEnforcing()) { - String display = version(false); - String internal = version(true); - - // We only know the format for SuperSU v1.90+ right now - if ((display != null) && - (internal != null) && - (display.endsWith("SUPERSU")) && - (Integer.valueOf(internal) >= 190)) { - shell = String.format(Locale.ENGLISH, "%s --context %s", shell, context); - } - } - - // Most su binaries support the "su " format, but in case - // they don't, lets skip it for the default 0 (root) case - if (uid > 0) { - shell = String.format(Locale.ENGLISH, "%s %d", shell, uid); - } - - return shell; - } - - /** - * Constructs a shell command to start a su shell connected to mount - * master daemon, to perform public mounts on Android 4.3+ (or 4.2+ in - * SELinux enforcing mode) - * - * @return Shell command - */ - public static String shellMountMaster() { - if (android.os.Build.VERSION.SDK_INT >= 17) { - return "su --mount-master"; - } - return "su"; - } - - /** - * Detect if SELinux is set to enforcing, caches result - * - * @return true if SELinux set to enforcing, or false in the case of - * permissive or not present - */ - public static synchronized boolean isSELinuxEnforcing() { - if (isSELinuxEnforcing == null) { - Boolean enforcing = null; - - // First known firmware with SELinux built-in was a 4.2 (17) - // leak - if (android.os.Build.VERSION.SDK_INT >= 17) { - // Detect enforcing through sysfs, not always present - File f = new File("/sys/fs/selinux/enforce"); - if (f.exists()) { - try { - InputStream is = new FileInputStream("/sys/fs/selinux/enforce"); - try { - enforcing = (is.read() == '1'); - } finally { - is.close(); - } - } catch (Exception e) { - // we might not be allowed to read, thanks SELinux - } - } - - // 4.4+ builds are enforcing by default, take the gamble - if (enforcing == null) { - enforcing = (android.os.Build.VERSION.SDK_INT >= 19); - } - } - - if (enforcing == null) { - enforcing = false; - } - - isSELinuxEnforcing = enforcing; - } - return isSELinuxEnforcing; - } - - /** - *

    - * Clears results cached by isSELinuxEnforcing() and version(boolean - * internal) calls. - *

    - *

    - * Most apps should never need to call this, as neither enforcing status - * nor su version is likely to change on a running device - though it is - * not impossible. - *

    - */ - public static synchronized void clearCachedResults() { - isSELinuxEnforcing = null; - suVersion[0] = null; - suVersion[1] = null; - } - } - - private interface OnResult { - // for any onCommandResult callback - int WATCHDOG_EXIT = -1; - int SHELL_DIED = -2; - - // for Interactive.open() callbacks only - int SHELL_EXEC_FAILED = -3; - int SHELL_WRONG_UID = -4; - int SHELL_RUNNING = 0; - } - - /** - * Command result callback, notifies the recipient of the completion of a - * command block, including the (last) exit code, and the full output - */ - public interface OnCommandResultListener extends OnResult { - /** - *

    - * Command result callback - *

    - *

    - * Depending on how and on which thread the shell was created, this - * callback may be executed on one of the gobbler threads. In that case, - * it is important the callback returns as quickly as possible, as - * delays in this callback may pause the native process or even result - * in a deadlock - *

    - *

    - * See {@link Shell.Interactive} for threading details - *

    - * - * @param commandCode Value previously supplied to addCommand - * @param exitCode Exit code of the last command in the block - * @param output All output generated by the command block - */ - void onCommandResult(int commandCode, int exitCode, List output); - } - - /** - * Command per line callback for parsing the output line by line without - * buffering It also notifies the recipient of the completion of a command - * block, including the (last) exit code. - */ - public interface OnCommandLineListener extends OnResult, OnLineListener { - /** - *

    - * Command result callback - *

    - *

    - * Depending on how and on which thread the shell was created, this - * callback may be executed on one of the gobbler threads. In that case, - * it is important the callback returns as quickly as possible, as - * delays in this callback may pause the native process or even result - * in a deadlock - *

    - *

    - * See {@link Shell.Interactive} for threading details - *

    - * - * @param commandCode Value previously supplied to addCommand - * @param exitCode Exit code of the last command in the block - */ - void onCommandResult(int commandCode, int exitCode); - } - - /** - * Internal class to store command block properties - */ - private static class Command { - private static int commandCounter = 0; - - private final String[] commands; - private final int code; - private final OnCommandResultListener onCommandResultListener; - private final OnCommandLineListener onCommandLineListener; - private final String marker; - - public Command(String[] commands, int code, - OnCommandResultListener onCommandResultListener, - OnCommandLineListener onCommandLineListener) { - this.commands = commands; - this.code = code; - this.onCommandResultListener = onCommandResultListener; - this.onCommandLineListener = onCommandLineListener; - this.marker = UUID.randomUUID().toString() + String.format("-%08x", ++commandCounter); - } - } - - /** - * Builder class for {@link Shell.Interactive} - */ - public static class Builder { - private Handler handler = null; - private boolean autoHandler = true; - private String shell = "sh"; - private boolean wantSTDERR = false; - private List commands = new LinkedList(); - private Map environment = new HashMap(); - private OnLineListener onSTDOUTLineListener = null; - private OnLineListener onSTDERRLineListener = null; - private int watchdogTimeout = 0; - - /** - *

    - * Set a custom handler that will be used to post all callbacks to - *

    - *

    - * See {@link Shell.Interactive} for further details on threading and - * handlers - *

    - * - * @param handler Handler to use - * @return This Builder object for method chaining - */ - public Builder setHandler(Handler handler) { - this.handler = handler; - return this; - } - - /** - *

    - * Automatically create a handler if possible ? Default to true - *

    - *

    - * See {@link Shell.Interactive} for further details on threading and - * handlers - *

    - * - * @param autoHandler Auto-create handler ? - * @return This Builder object for method chaining - */ - public Builder setAutoHandler(boolean autoHandler) { - this.autoHandler = autoHandler; - return this; - } - - /** - * Set shell binary to use. Usually "sh" or "su", do not use a full path - * unless you have a good reason to - * - * @param shell Shell to use - * @return This Builder object for method chaining - */ - public Builder setShell(String shell) { - this.shell = shell; - return this; - } - - /** - * Convenience function to set "sh" as used shell - * - * @return This Builder object for method chaining - */ - public Builder useSH() { - return setShell("sh"); - } - - /** - * Convenience function to set "su" as used shell - * - * @return This Builder object for method chaining - */ - public Builder useSU() { - return setShell("su"); - } - - /** - * Set if error output should be appended to command block result output - * - * @param wantSTDERR Want error output ? - * @return This Builder object for method chaining - */ - public Builder setWantSTDERR(boolean wantSTDERR) { - this.wantSTDERR = wantSTDERR; - return this; - } - - /** - * Add or update an environment variable - * - * @param key Key of the environment variable - * @param value Value of the environment variable - * @return This Builder object for method chaining - */ - public Builder addEnvironment(String key, String value) { - environment.put(key, value); - return this; - } - - /** - * Add or update environment variables - * - * @param addEnvironment Map of environment variables - * @return This Builder object for method chaining - */ - public Builder addEnvironment(Map addEnvironment) { - environment.putAll(addEnvironment); - return this; - } - - /** - * Add a command to execute - * - * @param command Command to execute - * @return This Builder object for method chaining - */ - public Builder addCommand(String command) { - return addCommand(command, 0, null); - } - - /** - *

    - * Add a command to execute, with a callback to be called on completion - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param command Command to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - * @return This Builder object for method chaining - */ - public Builder addCommand(String command, int code, - OnCommandResultListener onCommandResultListener) { - return addCommand(new String[] { - command - }, code, onCommandResultListener); - } - - /** - * Add commands to execute - * - * @param commands Commands to execute - * @return This Builder object for method chaining - */ - public Builder addCommand(List commands) { - return addCommand(commands, 0, null); - } - - /** - *

    - * Add commands to execute, with a callback to be called on completion - * (of all commands) - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - * (of all commands) - * @return This Builder object for method chaining - */ - public Builder addCommand(List commands, int code, - OnCommandResultListener onCommandResultListener) { - return addCommand(commands.toArray(new String[commands.size()]), code, - onCommandResultListener); - } - - /** - * Add commands to execute - * - * @param commands Commands to execute - * @return This Builder object for method chaining - */ - public Builder addCommand(String[] commands) { - return addCommand(commands, 0, null); - } - - /** - *

    - * Add commands to execute, with a callback to be called on completion - * (of all commands) - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - * (of all commands) - * @return This Builder object for method chaining - */ - public Builder addCommand(String[] commands, int code, - OnCommandResultListener onCommandResultListener) { - this.commands.add(new Command(commands, code, onCommandResultListener, null)); - return this; - } - - /** - *

    - * Set a callback called for every line output to STDOUT by the shell - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param onLineListener Callback to be called for each line - * @return This Builder object for method chaining - */ - public Builder setOnSTDOUTLineListener(OnLineListener onLineListener) { - this.onSTDOUTLineListener = onLineListener; - return this; - } - - /** - *

    - * Set a callback called for every line output to STDERR by the shell - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param onLineListener Callback to be called for each line - * @return This Builder object for method chaining - */ - public Builder setOnSTDERRLineListener(OnLineListener onLineListener) { - this.onSTDERRLineListener = onLineListener; - return this; - } - - /** - *

    - * Enable command timeout callback - *

    - *

    - * This will invoke the onCommandResult() callback with exitCode - * WATCHDOG_EXIT if a command takes longer than watchdogTimeout seconds - * to complete. - *

    - *

    - * If a watchdog timeout occurs, it generally means that the Interactive - * session is out of sync with the shell process. The caller should - * close the current session and open a new one. - *

    - * - * @param watchdogTimeout Timeout, in seconds; 0 to disable - * @return This Builder object for method chaining - */ - public Builder setWatchdogTimeout(int watchdogTimeout) { - this.watchdogTimeout = watchdogTimeout; - return this; - } - - /** - *

    - * Enable/disable reduced logcat output - *

    - *

    - * Note that this is a global setting - *

    - * - * @param useMinimal true for reduced output, false for full output - * @return This Builder object for method chaining - */ - public Builder setMinimalLogging(boolean useMinimal) { - Debug.setLogTypeEnabled(Debug.LOG_COMMAND | Debug.LOG_OUTPUT, !useMinimal); - return this; - } - - /** - * Construct a {@link Shell.Interactive} instance, and start the shell - */ - public Interactive open() { - return new Interactive(this, null); - } - - /** - * Construct a {@link Shell.Interactive} instance, try to start the - * shell, and call onCommandResultListener to report success or failure - * - * @param onCommandResultListener Callback to return shell open status - */ - public Interactive open(OnCommandResultListener onCommandResultListener) { - return new Interactive(this, onCommandResultListener); - } - } - - /** - *

    - * An interactive shell - initially created with {@link Shell.Builder} - - * that executes blocks of commands you supply in the background, optionally - * calling callbacks as each block completes. - *

    - *

    - * STDERR output can be supplied as well, but due to compatibility with - * older Android versions, wantSTDERR is not implemented using - * redirectErrorStream, but rather appended to the output. STDOUT and STDERR - * are thus not guaranteed to be in the correct order in the output. - *

    - *

    - * Note as well that the close() and waitForIdle() methods will - * intentionally crash when run in debug mode from the main thread of the - * application. Any blocking call should be run from a background thread. - *

    - *

    - * When in debug mode, the code will also excessively log the commands - * passed to and the output returned from the shell. - *

    - *

    - * Though this function uses background threads to gobble STDOUT and STDERR - * so a deadlock does not occur if the shell produces massive output, the - * output is still stored in a List<String>, and as such doing - * something like 'ls -lR /' will probably have you run out of - * memory when using a {@link Shell.OnCommandResultListener}. A work-around - * is to not supply this callback, but using (only) - * {@link Shell.Builder#setOnSTDOUTLineListener(OnLineListener)}. This way, - * an internal buffer will not be created and wasting your memory. - *

    - *

    Callbacks, threads and handlers

    - *

    - * On which thread the callbacks execute is dependent on your - * initialization. You can supply a custom Handler using - * {@link Shell.Builder#setHandler(Handler)} if needed. If you do not supply - * a custom Handler - unless you set - * {@link Shell.Builder#setAutoHandler(boolean)} to false - a Handler will - * be auto-created if the thread used for instantiation of the object has a - * Looper. - *

    - *

    - * If no Handler was supplied and it was also not auto-created, all - * callbacks will be called from either the STDOUT or STDERR gobbler - * threads. These are important threads that should be blocked as little as - * possible, as blocking them may in rare cases pause the native process or - * even create a deadlock. - *

    - *

    - * The main thread must certainly have a Looper, thus if you call - * {@link Shell.Builder#open()} from the main thread, a handler will (by - * default) be auto-created, and all the callbacks will be called on the - * main thread. While this is often convenient and easy to code with, you - * should be aware that if your callbacks are 'expensive' to execute, this - * may negatively impact UI performance. - *

    - *

    - * Background threads usually do not have a Looper, so calling - * {@link Shell.Builder#open()} from such a background thread will (by - * default) result in all the callbacks being executed in one of the gobbler - * threads. You will have to make sure the code you execute in these - * callbacks is thread-safe. - *

    - */ - public static class Interactive { - private final Handler handler; - private final boolean autoHandler; - private final String shell; - private final boolean wantSTDERR; - private final List commands; - private final Map environment; - private final OnLineListener onSTDOUTLineListener; - private final OnLineListener onSTDERRLineListener; - private int watchdogTimeout; - - private Process process = null; - private DataOutputStream STDIN = null; - private StreamGobbler STDOUT = null; - private StreamGobbler STDERR = null; - private ScheduledThreadPoolExecutor watchdog = null; - - private volatile boolean running = false; - private volatile boolean idle = true; // read/write only synchronized - private volatile boolean closed = true; - private volatile int callbacks = 0; - private volatile int watchdogCount; - - private final Object idleSync = new Object(); - private final Object callbackSync = new Object(); - - private volatile int lastExitCode = 0; - private volatile String lastMarkerSTDOUT = null; - private volatile String lastMarkerSTDERR = null; - private volatile Command command = null; - private volatile List buffer = null; - - /** - * The only way to create an instance: Shell.Builder::open() - * - * @param builder Builder class to take values from - */ - private Interactive(final Builder builder, - final OnCommandResultListener onCommandResultListener) { - autoHandler = builder.autoHandler; - shell = builder.shell; - wantSTDERR = builder.wantSTDERR; - commands = builder.commands; - environment = builder.environment; - onSTDOUTLineListener = builder.onSTDOUTLineListener; - onSTDERRLineListener = builder.onSTDERRLineListener; - watchdogTimeout = builder.watchdogTimeout; - - // If a looper is available, we offload the callbacks from the - // gobbling threads - // to whichever thread created us. Would normally do this in open(), - // but then we could not declare handler as final - if ((Looper.myLooper() != null) && (builder.handler == null) && autoHandler) { - handler = new Handler(); - } else { - handler = builder.handler; - } - - if (onCommandResultListener != null) { - // Allow up to 60 seconds for SuperSU/Superuser dialog, then enable - // the user-specified timeout for all subsequent operations - watchdogTimeout = 60; - commands.add(0, new Command(Shell.availableTestCommands, 0, new OnCommandResultListener() { - public void onCommandResult(int commandCode, int exitCode, List output) { - if ((exitCode == OnCommandResultListener.SHELL_RUNNING) && - !Shell.parseAvailableResult(output, Shell.SU.isSU(shell))) { - // shell is up, but it's brain-damaged - exitCode = OnCommandResultListener.SHELL_WRONG_UID; - } - watchdogTimeout = builder.watchdogTimeout; - onCommandResultListener.onCommandResult(0, exitCode, output); - } - }, null)); - } - - if (!open() && (onCommandResultListener != null)) { - onCommandResultListener.onCommandResult(0, - OnCommandResultListener.SHELL_EXEC_FAILED, null); - } - } - - @Override - protected void finalize() throws Throwable { - if (!closed && Debug.getSanityChecksEnabledEffective()) { - // waste of resources - Debug.log(ShellNotClosedException.EXCEPTION_NOT_CLOSED); - throw new ShellNotClosedException(); - } - super.finalize(); - } - - /** - * Add a command to execute - * - * @param command Command to execute - */ - public void addCommand(String command) { - addCommand(command, 0, (OnCommandResultListener) null); - } - - /** - *

    - * Add a command to execute, with a callback to be called on completion - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param command Command to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - */ - public void addCommand(String command, int code, - OnCommandResultListener onCommandResultListener) { - addCommand(new String[] { - command - }, code, onCommandResultListener); - } - - /** - *

    - * Add a command to execute, with a callback. This callback gobbles the - * output line by line without buffering it and also returns the result - * code on completion. - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param command Command to execute - * @param code User-defined value passed back to the callback - * @param onCommandLineListener Callback - */ - public void addCommand(String command, int code, OnCommandLineListener onCommandLineListener) { - addCommand(new String[] { - command - }, code, onCommandLineListener); - } - - /** - * Add commands to execute - * - * @param commands Commands to execute - */ - public void addCommand(List commands) { - addCommand(commands, 0, (OnCommandResultListener) null); - } - - /** - *

    - * Add commands to execute, with a callback to be called on completion - * (of all commands) - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - * (of all commands) - */ - public void addCommand(List commands, int code, - OnCommandResultListener onCommandResultListener) { - addCommand(commands.toArray(new String[commands.size()]), code, onCommandResultListener); - } - - /** - *

    - * Add commands to execute, with a callback. This callback gobbles the - * output line by line without buffering it and also returns the result - * code on completion. - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandLineListener Callback - */ - public void addCommand(List commands, int code, - OnCommandLineListener onCommandLineListener) { - addCommand(commands.toArray(new String[commands.size()]), code, onCommandLineListener); - } - - /** - * Add commands to execute - * - * @param commands Commands to execute - */ - public void addCommand(String[] commands) { - addCommand(commands, 0, (OnCommandResultListener) null); - } - - /** - *

    - * Add commands to execute, with a callback to be called on completion - * (of all commands) - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandResultListener Callback to be called on completion - * (of all commands) - */ - public synchronized void addCommand(String[] commands, int code, - OnCommandResultListener onCommandResultListener) { - this.commands.add(new Command(commands, code, onCommandResultListener, null)); - runNextCommand(); - } - - /** - *

    - * Add commands to execute, with a callback. This callback gobbles the - * output line by line without buffering it and also returns the result - * code on completion. - *

    - *

    - * The thread on which the callback executes is dependent on various - * factors, see {@link Shell.Interactive} for further details - *

    - * - * @param commands Commands to execute - * @param code User-defined value passed back to the callback - * @param onCommandLineListener Callback - */ - public synchronized void addCommand(String[] commands, int code, - OnCommandLineListener onCommandLineListener) { - this.commands.add(new Command(commands, code, null, onCommandLineListener)); - runNextCommand(); - } - - /** - * Run the next command if any and if ready, signals idle state if no - * commands left - */ - private void runNextCommand() { - runNextCommand(true); - } - - /** - * Called from a ScheduledThreadPoolExecutor timer thread every second - * when there is an outstanding command - */ - private synchronized void handleWatchdog() { - final int exitCode; - - if (watchdog == null) - return; - if (watchdogTimeout == 0) - return; - - if (!isRunning()) { - exitCode = OnCommandResultListener.SHELL_DIED; - Debug.log(String.format("[%s%%] SHELL_DIED", shell.toUpperCase(Locale.ENGLISH))); - } else if (watchdogCount++ < watchdogTimeout) { - return; - } else { - exitCode = OnCommandResultListener.WATCHDOG_EXIT; - Debug.log(String.format("[%s%%] WATCHDOG_EXIT", shell.toUpperCase(Locale.ENGLISH))); - } - - if (handler != null) { - postCallback(command, exitCode, buffer); - } - - // prevent multiple callbacks for the same command - command = null; - buffer = null; - idle = true; - - watchdog.shutdown(); - watchdog = null; - kill(); - } - - /** - * Start the periodic timer when a command is submitted - */ - private void startWatchdog() { - if (watchdogTimeout == 0) { - return; - } - watchdogCount = 0; - watchdog = new ScheduledThreadPoolExecutor(1); - watchdog.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - handleWatchdog(); - } - }, 1, 1, TimeUnit.SECONDS); - } - - /** - * Disable the watchdog timer upon command completion - */ - private void stopWatchdog() { - if (watchdog != null) { - watchdog.shutdownNow(); - watchdog = null; - } - } - - /** - * Run the next command if any and if ready - * - * @param notifyIdle signals idle state if no commands left ? - */ - private void runNextCommand(boolean notifyIdle) { - // must always be called from a synchronized method - - boolean running = isRunning(); - if (!running) - idle = true; - - if (running && idle && (commands.size() > 0)) { - Command command = commands.get(0); - commands.remove(0); - - buffer = null; - lastExitCode = 0; - lastMarkerSTDOUT = null; - lastMarkerSTDERR = null; - - if (command.commands.length > 0) { - try { - if (command.onCommandResultListener != null) { - // no reason to store the output if we don't have an - // OnCommandResultListener - // user should catch the output with an - // OnLineListener in this case - buffer = Collections.synchronizedList(new ArrayList()); - } - - idle = false; - this.command = command; - startWatchdog(); - for (String write : command.commands) { - Debug.logCommand(String.format("[%s+] %s", - shell.toUpperCase(Locale.ENGLISH), write)); - STDIN.write((write + "\n").getBytes("UTF-8")); - } - STDIN.write(("echo " + command.marker + " $?\n").getBytes("UTF-8")); - STDIN.write(("echo " + command.marker + " >&2\n").getBytes("UTF-8")); - STDIN.flush(); - } catch (IOException e) { - // STDIN might have closed - } - } else { - runNextCommand(false); - } - } else if (!running) { - // our shell died for unknown reasons - abort all submissions - while (commands.size() > 0) { - postCallback(commands.remove(0), OnCommandResultListener.SHELL_DIED, null); - } - } - - if (idle && notifyIdle) { - synchronized (idleSync) { - idleSync.notifyAll(); - } - } - } - - /** - * Processes a STDOUT/STDERR line containing an end/exitCode marker - */ - private synchronized void processMarker() { - if (command.marker.equals(lastMarkerSTDOUT) - && (command.marker.equals(lastMarkerSTDERR))) { - postCallback(command, lastExitCode, buffer); - stopWatchdog(); - command = null; - buffer = null; - idle = true; - runNextCommand(); - } - } - - /** - * Process a normal STDOUT/STDERR line - * - * @param line Line to process - * @param listener Callback to call or null - */ - private synchronized void processLine(String line, OnLineListener listener) { - if (listener != null) { - if (handler != null) { - final String fLine = line; - final OnLineListener fListener = listener; - - startCallback(); - handler.post(new Runnable() { - @Override - public void run() { - try { - fListener.onLine(fLine); - } finally { - endCallback(); - } - } - }); - } else { - listener.onLine(line); - } - } - } - - /** - * Add line to internal buffer - * - * @param line Line to add - */ - private synchronized void addBuffer(String line) { - if (buffer != null) { - buffer.add(line); - } - } - - /** - * Increase callback counter - */ - private void startCallback() { - synchronized (callbackSync) { - callbacks++; - } - } - - /** - * Schedule a callback to run on the appropriate thread - */ - private void postCallback(final Command fCommand, final int fExitCode, - final List fOutput) { - if (fCommand.onCommandResultListener == null && fCommand.onCommandLineListener == null) { - return; - } - if (handler == null) { - if ((fCommand.onCommandResultListener != null) && (fOutput != null)) - fCommand.onCommandResultListener.onCommandResult(fCommand.code, fExitCode, - fOutput); - if (fCommand.onCommandLineListener != null) - fCommand.onCommandLineListener.onCommandResult(fCommand.code, fExitCode); - return; - } - startCallback(); - handler.post(new Runnable() { - @Override - public void run() { - try { - if ((fCommand.onCommandResultListener != null) && (fOutput != null)) - fCommand.onCommandResultListener.onCommandResult(fCommand.code, - fExitCode, fOutput); - if (fCommand.onCommandLineListener != null) - fCommand.onCommandLineListener - .onCommandResult(fCommand.code, fExitCode); - } finally { - endCallback(); - } - } - }); - } - - /** - * Decrease callback counter, signals callback complete state when - * dropped to 0 - */ - private void endCallback() { - synchronized (callbackSync) { - callbacks--; - if (callbacks == 0) { - callbackSync.notifyAll(); - } - } - } - - /** - * Internal call that launches the shell, starts gobbling, and starts - * executing commands. See {@link Shell.Interactive} - * - * @return Opened successfully ? - */ - private synchronized boolean open() { - Debug.log(String.format("[%s%%] START", shell.toUpperCase(Locale.ENGLISH))); - - try { - // setup our process, retrieve STDIN stream, and STDOUT/STDERR - // gobblers - if (environment.size() == 0) { - process = Runtime.getRuntime().exec(shell); - } else { - Map newEnvironment = new HashMap(); - newEnvironment.putAll(System.getenv()); - newEnvironment.putAll(environment); - int i = 0; - String[] env = new String[newEnvironment.size()]; - for (Map.Entry entry : newEnvironment.entrySet()) { - env[i] = entry.getKey() + "=" + entry.getValue(); - i++; - } - process = Runtime.getRuntime().exec(shell, env); - } - - STDIN = new DataOutputStream(process.getOutputStream()); - STDOUT = new StreamGobbler(shell.toUpperCase(Locale.ENGLISH) + "-", - process.getInputStream(), new OnLineListener() { - @Override - public void onLine(String line) { - synchronized (Interactive.this) { - if (command == null) { - return; - } - if (line.startsWith(command.marker)) { - try { - lastExitCode = Integer.valueOf( - line.substring(command.marker.length() + 1), 10); - } catch (Exception e) { - // this really shouldn't happen - e.printStackTrace(); - } - lastMarkerSTDOUT = command.marker; - processMarker(); - } else { - addBuffer(line); - processLine(line, onSTDOUTLineListener); - processLine(line, command.onCommandLineListener); - } - } - } - }); - STDERR = new StreamGobbler(shell.toUpperCase(Locale.ENGLISH) + "*", - process.getErrorStream(), new OnLineListener() { - @Override - public void onLine(String line) { - synchronized (Interactive.this) { - if (command == null) { - return; - } - if (line.startsWith(command.marker)) { - lastMarkerSTDERR = command.marker; - processMarker(); - } else { - if (wantSTDERR) - addBuffer(line); - processLine(line, onSTDERRLineListener); - } - } - } - }); - - // start gobbling and write our commands to the shell - STDOUT.start(); - STDERR.start(); - - running = true; - closed = false; - - runNextCommand(); - - return true; - } catch (IOException e) { - // shell probably not found - return false; - } - } - - /** - * Close shell and clean up all resources. Call this when you are done - * with the shell. If the shell is not idle (all commands completed) you - * should not call this method from the main UI thread because it may - * block for a long time. This method will intentionally crash your app - * (if in debug mode) if you try to do this anyway. - */ - public void close() { - boolean _idle = isIdle(); // idle must be checked synchronized - - synchronized (this) { - if (!running) - return; - running = false; - closed = true; - } - - // This method should not be called from the main thread unless the - // shell is idle and can be cleaned up with (minimal) waiting. Only - // throw in debug mode. - if (!_idle && Debug.getSanityChecksEnabledEffective() && Debug.onMainThread()) { - Debug.log(ShellOnMainThreadException.EXCEPTION_NOT_IDLE); - throw new ShellOnMainThreadException(ShellOnMainThreadException.EXCEPTION_NOT_IDLE); - } - - if (!_idle) - waitForIdle(); - - try { - try { - STDIN.write(("exit\n").getBytes("UTF-8")); - STDIN.flush(); - } catch (IOException e) { - if (e.getMessage().contains("EPIPE")) { - // we're not running a shell, the shell closed STDIN, - // the script already contained the exit command, etc. - } else { - throw e; - } - } - - // wait for our process to finish, while we gobble away in the - // background - process.waitFor(); - - // make sure our threads are done gobbling, our streams are - // closed, and the process is destroyed - while the latter two - // shouldn't be needed in theory, and may even produce warnings, - // in "normal" Java they are required for guaranteed cleanup of - // resources, so lets be safe and do this on Android as well - try { - STDIN.close(); - } catch (IOException e) { - // STDIN going missing is no reason to abort - } - STDOUT.join(); - STDERR.join(); - stopWatchdog(); - process.destroy(); - } catch (IOException e) { - // various unforseen IO errors may still occur - } catch (InterruptedException e) { - // this should really be re-thrown - } - - Debug.log(String.format("[%s%%] END", shell.toUpperCase(Locale.ENGLISH))); - } - - /** - * Try to clean up as much as possible from a shell that's gotten itself - * wedged. Hopefully the StreamGobblers will croak on their own when the - * other side of the pipe is closed. - */ - public synchronized void kill() { - running = false; - closed = true; - - try { - STDIN.close(); - } catch (IOException e) { - // in case it was closed - } - try { - process.destroy(); - } catch (Exception e) { - // in case it was already destroyed or can't be - } - } - - /** - * Is our shell still running ? - * - * @return Shell running ? - */ - public boolean isRunning() { - if (process == null) { - return false; - } - try { - process.exitValue(); - return false; - } catch (IllegalThreadStateException e) { - // if this is thrown, we're still running - } - return true; - } - - /** - * Have all commands completed executing ? - * - * @return Shell idle ? - */ - public synchronized boolean isIdle() { - if (!isRunning()) { - idle = true; - synchronized (idleSync) { - idleSync.notifyAll(); - } - } - return idle; - } - - /** - *

    - * Wait for idle state. As this is a blocking call, you should not call - * it from the main UI thread. If you do so and debug mode is enabled, - * this method will intentionally crash your app. - *

    - *

    - * If not interrupted, this method will not return until all commands - * have finished executing. Note that this does not necessarily mean - * that all the callbacks have fired yet. - *

    - *

    - * If no Handler is used, all callbacks will have been executed when - * this method returns. If a Handler is used, and this method is called - * from a different thread than associated with the Handler's Looper, - * all callbacks will have been executed when this method returns as - * well. If however a Handler is used but this method is called from the - * same thread as associated with the Handler's Looper, there is no way - * to know. - *

    - *

    - * In practice this means that in most simple cases all callbacks will - * have completed when this method returns, but if you actually depend - * on this behavior, you should make certain this is indeed the case. - *

    - *

    - * See {@link Shell.Interactive} for further details on threading and - * handlers - *

    - * - * @return True if wait complete, false if wait interrupted - */ - public boolean waitForIdle() { - if (Debug.getSanityChecksEnabledEffective() && Debug.onMainThread()) { - Debug.log(ShellOnMainThreadException.EXCEPTION_WAIT_IDLE); - throw new ShellOnMainThreadException(ShellOnMainThreadException.EXCEPTION_WAIT_IDLE); - } - - if (isRunning()) { - synchronized (idleSync) { - while (!idle) { - try { - idleSync.wait(); - } catch (InterruptedException e) { - return false; - } - } - } - - if ((handler != null) && - (handler.getLooper() != null) && - (handler.getLooper() != Looper.myLooper())) { - // If the callbacks are posted to a different thread than - // this one, we can wait until all callbacks have called - // before returning. If we don't use a Handler at all, the - // callbacks are already called before we get here. If we do - // use a Handler but we use the same Looper, waiting here - // would actually block the callbacks from being called - - synchronized (callbackSync) { - while (callbacks > 0) { - try { - callbackSync.wait(); - } catch (InterruptedException e) { - return false; - } - } - } - } - } - - return true; - } - - /** - * Are we using a Handler to post callbacks ? - * - * @return Handler used ? - */ - public boolean hasHandler() { - return (handler != null); - } - } -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellNotClosedException.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellNotClosedException.java deleted file mode 100644 index 2a44083ec..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellNotClosedException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -/** - * Exception class used to notify developer that a shell was not close()d - */ -@SuppressWarnings("serial") -public class ShellNotClosedException extends RuntimeException { - public static final String EXCEPTION_NOT_CLOSED = "Application did not close() interactive shell"; - - public ShellNotClosedException() { - super(EXCEPTION_NOT_CLOSED); - } -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellOnMainThreadException.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellOnMainThreadException.java deleted file mode 100644 index 69732e3b3..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/ShellOnMainThreadException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -/** - * Exception class used to crash application when shell commands are executed - * from the main thread, and we are in debug mode. - */ -@SuppressWarnings("serial") -public class ShellOnMainThreadException extends RuntimeException { - public static final String EXCEPTION_COMMAND = "Application attempted to run a shell command from the main thread"; - public static final String EXCEPTION_NOT_IDLE = "Application attempted to wait for a non-idle shell to close on the main thread"; - public static final String EXCEPTION_WAIT_IDLE = "Application attempted to wait for a shell to become idle on the main thread"; - - public ShellOnMainThreadException(String message) { - super(message); - } -} diff --git a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/StreamGobbler.java b/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/StreamGobbler.java deleted file mode 100644 index 4ce669742..000000000 --- a/extern/libsuperuser/libsuperuser/src/eu/chainfire/libsuperuser/StreamGobbler.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.chainfire.libsuperuser; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.List; - -/** - * Thread utility class continuously reading from an InputStream - */ -public class StreamGobbler extends Thread { - /** - * Line callback interface - */ - public interface OnLineListener { - /** - *

    Line callback

    - * - *

    This callback should process the line as quickly as possible. - * Delays in this callback may pause the native process or even - * result in a deadlock

    - * - * @param line String that was gobbled - */ - void onLine(String line); - } - - private String shell = null; - private BufferedReader reader = null; - private List writer = null; - private OnLineListener listener = null; - - /** - *

    StreamGobbler constructor

    - * - *

    We use this class because shell STDOUT and STDERR should be read as quickly as - * possible to prevent a deadlock from occurring, or Process.waitFor() never - * returning (as the buffer is full, pausing the native process)

    - * - * @param shell Name of the shell - * @param inputStream InputStream to read from - * @param outputList List to write to, or null - */ - public StreamGobbler(String shell, InputStream inputStream, List outputList) { - this.shell = shell; - reader = new BufferedReader(new InputStreamReader(inputStream)); - writer = outputList; - } - - /** - *

    StreamGobbler constructor

    - * - *

    We use this class because shell STDOUT and STDERR should be read as quickly as - * possible to prevent a deadlock from occurring, or Process.waitFor() never - * returning (as the buffer is full, pausing the native process)

    - * - * @param shell Name of the shell - * @param inputStream InputStream to read from - * @param onLineListener OnLineListener callback - */ - public StreamGobbler(String shell, InputStream inputStream, OnLineListener onLineListener) { - this.shell = shell; - reader = new BufferedReader(new InputStreamReader(inputStream)); - listener = onLineListener; - } - - @Override - public void run() { - // keep reading the InputStream until it ends (or an error occurs) - try { - String line; - while ((line = reader.readLine()) != null) { - Debug.logOutput(String.format("[%s] %s", shell, line)); - if (writer != null) writer.add(line); - if (listener != null) listener.onLine(line); - } - } catch (IOException e) { - // reader probably closed, expected exit condition - } - - // make sure our stream is closed and resources will be freed - try { - reader.close(); - } catch (IOException e) { - // read already closed - } - } -} diff --git a/extern/libsuperuser/settings.gradle b/extern/libsuperuser/settings.gradle deleted file mode 100644 index 32aef3ac0..000000000 --- a/extern/libsuperuser/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':libsuperuser', ':libsuperuser_example' diff --git a/extern/zxing-core/build.gradle b/extern/zxing-core/build.gradle deleted file mode 100644 index 4d4a19643..000000000 --- a/extern/zxing-core/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -apply plugin: 'java' - -sourceCompatibility = 1.7 diff --git a/extern/zxing-core/src/main/java/com/google/zxing/BarcodeFormat.java b/extern/zxing-core/src/main/java/com/google/zxing/BarcodeFormat.java deleted file mode 100644 index 7f6a0ef58..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/BarcodeFormat.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Enumerates barcode formats known to this package. Please keep alphabetized. - * - * @author Sean Owen - */ -public enum BarcodeFormat { - - /** Aztec 2D barcode format. */ - AZTEC, - - /** CODABAR 1D format. */ - CODABAR, - - /** Code 39 1D format. */ - CODE_39, - - /** Code 93 1D format. */ - CODE_93, - - /** Code 128 1D format. */ - CODE_128, - - /** Data Matrix 2D barcode format. */ - DATA_MATRIX, - - /** EAN-8 1D format. */ - EAN_8, - - /** EAN-13 1D format. */ - EAN_13, - - /** ITF (Interleaved Two of Five) 1D format. */ - ITF, - - /** MaxiCode 2D barcode format. */ - MAXICODE, - - /** PDF417 format. */ - PDF_417, - - /** QR Code 2D barcode format. */ - QR_CODE, - - /** RSS 14 */ - RSS_14, - - /** RSS EXPANDED */ - RSS_EXPANDED, - - /** UPC-A 1D format. */ - UPC_A, - - /** UPC-E 1D format. */ - UPC_E, - - /** UPC/EAN extension format. Not a stand-alone format. */ - UPC_EAN_EXTENSION - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/Binarizer.java b/extern/zxing-core/src/main/java/com/google/zxing/Binarizer.java deleted file mode 100644 index 02af0832f..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/Binarizer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.common.BitArray; -import com.google.zxing.common.BitMatrix; - -/** - * This class hierarchy provides a set of methods to convert luminance data to 1 bit data. - * It allows the algorithm to vary polymorphically, for example allowing a very expensive - * thresholding technique for servers and a fast one for mobile. It also permits the implementation - * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public abstract class Binarizer { - - private final LuminanceSource source; - - protected Binarizer(LuminanceSource source) { - this.source = source; - } - - public final LuminanceSource getLuminanceSource() { - return source; - } - - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * For callers which only examine one row of pixels at a time, the same BitArray should be reused - * and passed in with each call for performance. However it is legal to keep more than one row - * at a time if needed. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - public abstract BitArray getBlackRow(int y, BitArray row) throws NotFoundException; - - /** - * Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive - * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - * may not apply sharpening. Therefore, a row from this matrix may not be identical to one - * fetched using getBlackRow(), so don't mix and match between them. - * - * @return The 2D array of bits for the image (true means black). - * @throws NotFoundException if image can't be binarized to make a matrix - */ - public abstract BitMatrix getBlackMatrix() throws NotFoundException; - - /** - * Creates a new object with the same type as this Binarizer implementation, but with pristine - * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache - * of 1 bit data. See Effective Java for why we can't use Java's clone() method. - * - * @param source The LuminanceSource this Binarizer will operate on. - * @return A new concrete Binarizer implementation object. - */ - public abstract Binarizer createBinarizer(LuminanceSource source); - - public final int getWidth() { - return source.getWidth(); - } - - public final int getHeight() { - return source.getHeight(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/BinaryBitmap.java b/extern/zxing-core/src/main/java/com/google/zxing/BinaryBitmap.java deleted file mode 100644 index c1ef8a13e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/BinaryBitmap.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.common.BitArray; -import com.google.zxing.common.BitMatrix; - -/** - * This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects - * accept a BinaryBitmap and attempt to decode it. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class BinaryBitmap { - - private final Binarizer binarizer; - private BitMatrix matrix; - - public BinaryBitmap(Binarizer binarizer) { - if (binarizer == null) { - throw new IllegalArgumentException("Binarizer must be non-null."); - } - this.binarizer = binarizer; - } - - /** - * @return The width of the bitmap. - */ - public int getWidth() { - return binarizer.getWidth(); - } - - /** - * @return The height of the bitmap. - */ - public int getHeight() { - return binarizer.getHeight(); - } - - /** - * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - * cached data. Callers should assume this method is expensive and call it as seldom as possible. - * This method is intended for decoding 1D barcodes and may choose to apply sharpening. - * - * @param y The row to fetch, which must be in [0, bitmap height) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * If used, the Binarizer will call BitArray.clear(). Always use the returned object. - * @return The array of bits for this row (true means black). - * @throws NotFoundException if row can't be binarized - */ - public BitArray getBlackRow(int y, BitArray row) throws NotFoundException { - return binarizer.getBlackRow(y, row); - } - - /** - * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive - * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - * may not apply sharpening. Therefore, a row from this matrix may not be identical to one - * fetched using getBlackRow(), so don't mix and match between them. - * - * @return The 2D array of bits for the image (true means black). - * @throws NotFoundException if image can't be binarized to make a matrix - */ - public BitMatrix getBlackMatrix() throws NotFoundException { - // The matrix is created on demand the first time it is requested, then cached. There are two - // reasons for this: - // 1. This work will never be done if the caller only installs 1D Reader objects, or if a - // 1D Reader finds a barcode before the 2D Readers run. - // 2. This work will only be done once even if the caller installs multiple 2D Readers. - if (matrix == null) { - matrix = binarizer.getBlackMatrix(); - } - return matrix; - } - - /** - * @return Whether this bitmap can be cropped. - */ - public boolean isCropSupported() { - return binarizer.getLuminanceSource().isCropSupported(); - } - - /** - * Returns a new object with cropped image data. Implementations may keep a reference to the - * original data rather than a copy. Only callable if isCropSupported() is true. - * - * @param left The left coordinate, which must be in [0,getWidth()) - * @param top The top coordinate, which must be in [0,getHeight()) - * @param width The width of the rectangle to crop. - * @param height The height of the rectangle to crop. - * @return A cropped version of this object. - */ - public BinaryBitmap crop(int left, int top, int width, int height) { - LuminanceSource newSource = binarizer.getLuminanceSource().crop(left, top, width, height); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - /** - * @return Whether this bitmap supports counter-clockwise rotation. - */ - public boolean isRotateSupported() { - return binarizer.getLuminanceSource().isRotateSupported(); - } - - /** - * Returns a new object with rotated image data by 90 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public BinaryBitmap rotateCounterClockwise() { - LuminanceSource newSource = binarizer.getLuminanceSource().rotateCounterClockwise(); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - /** - * Returns a new object with rotated image data by 45 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public BinaryBitmap rotateCounterClockwise45() { - LuminanceSource newSource = binarizer.getLuminanceSource().rotateCounterClockwise45(); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - @Override - public String toString() { - try { - return getBlackMatrix().toString(); - } catch (NotFoundException e) { - return ""; - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/ChecksumException.java b/extern/zxing-core/src/main/java/com/google/zxing/ChecksumException.java deleted file mode 100644 index c5acbe3ee..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/ChecksumException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Thrown when a barcode was successfully detected and decoded, but - * was not returned because its checksum feature failed. - * - * @author Sean Owen - */ -public final class ChecksumException extends ReaderException { - - private static final ChecksumException INSTANCE = new ChecksumException(); - static { - INSTANCE.setStackTrace(NO_TRACE); // since it's meaningless - } - - private ChecksumException() { - // do nothing - } - - private ChecksumException(Throwable cause) { - super(cause); - } - - public static ChecksumException getChecksumInstance() { - return isStackTrace ? new ChecksumException() : INSTANCE; - } - - public static ChecksumException getChecksumInstance(Throwable cause) { - return isStackTrace ? new ChecksumException(cause) : INSTANCE; - } -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/DecodeHintType.java b/extern/zxing-core/src/main/java/com/google/zxing/DecodeHintType.java deleted file mode 100644 index a6658695e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/DecodeHintType.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import java.util.List; - -/** - * Encapsulates a type of hint that a caller may pass to a barcode reader to help it - * more quickly or accurately decode it. It is up to implementations to decide what, - * if anything, to do with the information that is supplied. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - * @see Reader#decode(BinaryBitmap,java.util.Map) - */ -public enum DecodeHintType { - - /** - * Unspecified, application-specific hint. Maps to an unspecified {@link Object}. - */ - OTHER(Object.class), - - /** - * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - PURE_BARCODE(Void.class), - - /** - * Image is known to be of one of a few possible formats. - * Maps to a {@link List} of {@link BarcodeFormat}s. - */ - POSSIBLE_FORMATS(List.class), - - /** - * Spend more time to try to find a barcode; optimize for accuracy, not speed. - * Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - TRY_HARDER(Void.class), - - /** - * Specifies what character encoding to use when decoding, where applicable (type String) - */ - CHARACTER_SET(String.class), - - /** - * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}. - */ - ALLOWED_LENGTHS(int[].class), - - /** - * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_CODE_39_CHECK_DIGIT(Void.class), - - /** - * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; - * use {@link Boolean#TRUE}. - */ - ASSUME_GS1(Void.class), - - /** - * If true, return the start and end digits in a Codabar barcode instead of stripping them. They - * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them - * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}. - */ - RETURN_CODABAR_START_END(Void.class), - - /** - * The caller needs to be notified via callback when a possible {@link ResultPoint} - * is found. Maps to a {@link ResultPointCallback}. - */ - NEED_RESULT_POINT_CALLBACK(ResultPointCallback.class), - - - /** - * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5]. - * If it is optional to have an extension, do not set this hint. If this is set, - * and a UPC or EAN barcode is found but an extension is not, then no result will be returned - * at all. - */ - ALLOWED_EAN_EXTENSIONS(int[].class), - - // End of enumeration values. - ; - - /** - * Data type the hint is expecting. - * Among the possible values the {@link Void} stands out as being used for - * hints that do not expect a value to be supplied (flag hints). Such hints - * will possibly have their value ignored, or replaced by a - * {@link Boolean#TRUE}. Hint suppliers should probably use - * {@link Boolean#TRUE} as directed by the actual hint documentation. - */ - private final Class valueType; - - DecodeHintType(Class valueType) { - this.valueType = valueType; - } - - public Class getValueType() { - return valueType; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/Dimension.java b/extern/zxing-core/src/main/java/com/google/zxing/Dimension.java deleted file mode 100644 index b3a2486e6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/Dimension.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Simply encapsulates a width and height. - */ -public final class Dimension { - - private final int width; - private final int height; - - public Dimension(int width, int height) { - if (width < 0 || height < 0) { - throw new IllegalArgumentException(); - } - this.width = width; - this.height = height; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - @Override - public boolean equals(Object other) { - if (other instanceof Dimension) { - Dimension d = (Dimension) other; - return width == d.width && height == d.height; - } - return false; - } - - @Override - public int hashCode() { - return width * 32713 + height; - } - - @Override - public String toString() { - return width + "x" + height; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/EncodeHintType.java b/extern/zxing-core/src/main/java/com/google/zxing/EncodeHintType.java deleted file mode 100644 index ff97b21aa..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/EncodeHintType.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * These are a set of hints that you may pass to Writers to specify their behavior. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public enum EncodeHintType { - - /** - * Specifies what degree of error correction to use, for example in QR Codes. - * Type depends on the encoder. For example for QR codes it's type - * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. - * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words. - * For PDF417 it is of type {@link Integer}, valid values being 0 to 8. - * Note: an Aztec symbol should have a minimum of 25% EC words. - */ - ERROR_CORRECTION, - - /** - * Specifies what character encoding to use where applicable (type {@link String}) - */ - CHARACTER_SET, - - /** - * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint}) - */ - DATA_MATRIX_SHAPE, - - /** - * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated use width/height params in - * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)} - */ - @Deprecated - MIN_SIZE, - - /** - * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now. - * - * @deprecated without replacement - */ - @Deprecated - MAX_SIZE, - - /** - * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - * by format; for example it controls margin before and after the barcode horizontally for - * most 1D formats. (Type {@link Integer}). - */ - MARGIN, - - /** - * Specifies whether to use compact mode for PDF417 (type {@link Boolean}). - */ - PDF417_COMPACT, - - /** - * Specifies what compaction mode to use for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Compaction Compaction}). - */ - PDF417_COMPACTION, - - /** - * Specifies the minimum and maximum number of rows and columns for PDF417 (type - * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}). - */ - PDF417_DIMENSIONS, - - /** - * Specifies the required number of layers for an Aztec code: - * a negative number (-1, -2, -3, -4) specifies a compact Aztec code - * 0 indicates to use the minimum number of layers (the default) - * a positive number (1, 2, .. 32) specifies a normaol (non-compact) Aztec code - */ - AZTEC_LAYERS, -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/FormatException.java b/extern/zxing-core/src/main/java/com/google/zxing/FormatException.java deleted file mode 100644 index b046b822d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/FormatException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Thrown when a barcode was successfully detected, but some aspect of - * the content did not conform to the barcode's format rules. This could have - * been due to a mis-detection. - * - * @author Sean Owen - */ -public final class FormatException extends ReaderException { - - private static final FormatException INSTANCE = new FormatException(); - static { - INSTANCE.setStackTrace(NO_TRACE); // since it's meaningless - } - - private FormatException() { - } - - private FormatException(Throwable cause) { - super(cause); - } - - public static FormatException getFormatInstance() { - return isStackTrace ? new FormatException() : INSTANCE; - } - - public static FormatException getFormatInstance(Throwable cause) { - return isStackTrace ? new FormatException(cause) : INSTANCE; - } -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/InvertedLuminanceSource.java b/extern/zxing-core/src/main/java/com/google/zxing/InvertedLuminanceSource.java deleted file mode 100644 index edaa119bd..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/InvertedLuminanceSource.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes - * white and vice versa, and each value becomes (255-value). - * - * @author Sean Owen - */ -public final class InvertedLuminanceSource extends LuminanceSource { - - private final LuminanceSource delegate; - - public InvertedLuminanceSource(LuminanceSource delegate) { - super(delegate.getWidth(), delegate.getHeight()); - this.delegate = delegate; - } - - @Override - public byte[] getRow(int y, byte[] row) { - row = delegate.getRow(y, row); - int width = getWidth(); - for (int i = 0; i < width; i++) { - row[i] = (byte) (255 - (row[i] & 0xFF)); - } - return row; - } - - @Override - public byte[] getMatrix() { - byte[] matrix = delegate.getMatrix(); - int length = getWidth() * getHeight(); - byte[] invertedMatrix = new byte[length]; - for (int i = 0; i < length; i++) { - invertedMatrix[i] = (byte) (255 - (matrix[i] & 0xFF)); - } - return invertedMatrix; - } - - @Override - public boolean isCropSupported() { - return delegate.isCropSupported(); - } - - @Override - public LuminanceSource crop(int left, int top, int width, int height) { - return new InvertedLuminanceSource(delegate.crop(left, top, width, height)); - } - - @Override - public boolean isRotateSupported() { - return delegate.isRotateSupported(); - } - - /** - * @return original delegate {@link LuminanceSource} since invert undoes itself - */ - @Override - public LuminanceSource invert() { - return delegate; - } - - @Override - public LuminanceSource rotateCounterClockwise() { - return new InvertedLuminanceSource(delegate.rotateCounterClockwise()); - } - - @Override - public LuminanceSource rotateCounterClockwise45() { - return new InvertedLuminanceSource(delegate.rotateCounterClockwise45()); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/LuminanceSource.java b/extern/zxing-core/src/main/java/com/google/zxing/LuminanceSource.java deleted file mode 100644 index 1946d023c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/LuminanceSource.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * The purpose of this class hierarchy is to abstract different bitmap implementations across - * platforms into a standard interface for requesting greyscale luminance values. The interface - * only provides immutable methods; therefore crop and rotation create copies. This is to ensure - * that one Reader does not modify the original luminance source and leave it in an unknown state - * for other Readers in the chain. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public abstract class LuminanceSource { - - private final int width; - private final int height; - - protected LuminanceSource(int width, int height) { - this.width = width; - this.height = height; - } - - /** - * Fetches one row of luminance data from the underlying platform's bitmap. Values range from - * 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have - * to bitwise and with 0xff for each value. It is preferable for implementations of this method - * to only fetch this row rather than the whole image, since no 2D Readers may be installed and - * getMatrix() may never be called. - * - * @param y The row to fetch, which must be in [0,getHeight()) - * @param row An optional preallocated array. If null or too small, it will be ignored. - * Always use the returned object, and ignore the .length of the array. - * @return An array containing the luminance data. - */ - public abstract byte[] getRow(int y, byte[] row); - - /** - * Fetches luminance data for the underlying bitmap. Values should be fetched using: - * {@code int luminance = array[y * width + x] & 0xff} - * - * @return A row-major 2D array of luminance values. Do not use result.length as it may be - * larger than width * height bytes on some platforms. Do not modify the contents - * of the result. - */ - public abstract byte[] getMatrix(); - - /** - * @return The width of the bitmap. - */ - public final int getWidth() { - return width; - } - - /** - * @return The height of the bitmap. - */ - public final int getHeight() { - return height; - } - - /** - * @return Whether this subclass supports cropping. - */ - public boolean isCropSupported() { - return false; - } - - /** - * Returns a new object with cropped image data. Implementations may keep a reference to the - * original data rather than a copy. Only callable if isCropSupported() is true. - * - * @param left The left coordinate, which must be in [0,getWidth()) - * @param top The top coordinate, which must be in [0,getHeight()) - * @param width The width of the rectangle to crop. - * @param height The height of the rectangle to crop. - * @return A cropped version of this object. - */ - public LuminanceSource crop(int left, int top, int width, int height) { - throw new UnsupportedOperationException("This luminance source does not support cropping."); - } - - /** - * @return Whether this subclass supports counter-clockwise rotation. - */ - public boolean isRotateSupported() { - return false; - } - - /** - * @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes - * white and vice versa, and each value becomes (255-value). - */ - public LuminanceSource invert() { - return new InvertedLuminanceSource(this); - } - - /** - * Returns a new object with rotated image data by 90 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public LuminanceSource rotateCounterClockwise() { - throw new UnsupportedOperationException("This luminance source does not support rotation by 90 degrees."); - } - - /** - * Returns a new object with rotated image data by 45 degrees counterclockwise. - * Only callable if {@link #isRotateSupported()} is true. - * - * @return A rotated version of this object. - */ - public LuminanceSource rotateCounterClockwise45() { - throw new UnsupportedOperationException("This luminance source does not support rotation by 45 degrees."); - } - - @Override - public final String toString() { - byte[] row = new byte[width]; - StringBuilder result = new StringBuilder(height * (width + 1)); - for (int y = 0; y < height; y++) { - row = getRow(y, row); - for (int x = 0; x < width; x++) { - int luminance = row[x] & 0xFF; - char c; - if (luminance < 0x40) { - c = '#'; - } else if (luminance < 0x80) { - c = '+'; - } else if (luminance < 0xC0) { - c = '.'; - } else { - c = ' '; - } - result.append(c); - } - result.append('\n'); - } - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatReader.java b/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatReader.java deleted file mode 100644 index fe6f4ce5a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatReader.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.aztec.AztecReader; -import com.google.zxing.datamatrix.DataMatrixReader; -import com.google.zxing.maxicode.MaxiCodeReader; -import com.google.zxing.oned.MultiFormatOneDReader; -import com.google.zxing.pdf417.PDF417Reader; -import com.google.zxing.qrcode.QRCodeReader; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - * MultiFormatReader is a convenience class and the main entry point into the library for most uses. - * By default it attempts to decode all barcode formats that the library supports. Optionally, you - * can provide a hints object to request different behavior, for example only decoding QR codes. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class MultiFormatReader implements Reader { - - private Map hints; - private Reader[] readers; - - /** - * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it - * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. - * Use setHints() followed by decodeWithState() for continuous scan applications. - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException { - setHints(null); - return decodeInternal(image); - } - - /** - * Decode an image using the hints provided. Does not honor existing state. - * - * @param image The pixel data to decode - * @param hints The hints to use, clearing the previous state. - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - @Override - public Result decode(BinaryBitmap image, Map hints) throws NotFoundException { - setHints(hints); - return decodeInternal(image); - } - - /** - * Decode an image using the state set up by calling setHints() previously. Continuous scan - * clients will get a large speed increase by using this instead of decode(). - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - public Result decodeWithState(BinaryBitmap image) throws NotFoundException { - // Make sure to set up the default state so we don't crash - if (readers == null) { - setHints(null); - } - return decodeInternal(image); - } - - /** - * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls - * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This - * is important for performance in continuous scan clients. - * - * @param hints The set of hints to use for subsequent calls to decode(image) - */ - public void setHints(Map hints) { - this.hints = hints; - - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - @SuppressWarnings("unchecked") - Collection formats = - hints == null ? null : (Collection) hints.get(DecodeHintType.POSSIBLE_FORMATS); - Collection readers = new ArrayList<>(); - if (formats != null) { - boolean addOneDReader = - formats.contains(BarcodeFormat.UPC_A) || - formats.contains(BarcodeFormat.UPC_E) || - formats.contains(BarcodeFormat.EAN_13) || - formats.contains(BarcodeFormat.EAN_8) || - formats.contains(BarcodeFormat.CODABAR) || - formats.contains(BarcodeFormat.CODE_39) || - formats.contains(BarcodeFormat.CODE_93) || - formats.contains(BarcodeFormat.CODE_128) || - formats.contains(BarcodeFormat.ITF) || - formats.contains(BarcodeFormat.RSS_14) || - formats.contains(BarcodeFormat.RSS_EXPANDED); - // Put 1D readers upfront in "normal" mode - if (addOneDReader && !tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - if (formats.contains(BarcodeFormat.QR_CODE)) { - readers.add(new QRCodeReader()); - } - if (formats.contains(BarcodeFormat.DATA_MATRIX)) { - readers.add(new DataMatrixReader()); - } - if (formats.contains(BarcodeFormat.AZTEC)) { - readers.add(new AztecReader()); - } - if (formats.contains(BarcodeFormat.PDF_417)) { - readers.add(new PDF417Reader()); - } - if (formats.contains(BarcodeFormat.MAXICODE)) { - readers.add(new MaxiCodeReader()); - } - // At end in "try harder" mode - if (addOneDReader && tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - } - if (readers.isEmpty()) { - if (!tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - - readers.add(new QRCodeReader()); - readers.add(new DataMatrixReader()); - readers.add(new AztecReader()); - readers.add(new PDF417Reader()); - readers.add(new MaxiCodeReader()); - - if (tryHarder) { - readers.add(new MultiFormatOneDReader(hints)); - } - } - this.readers = readers.toArray(new Reader[readers.size()]); - } - - @Override - public void reset() { - if (readers != null) { - for (Reader reader : readers) { - reader.reset(); - } - } - } - - private Result decodeInternal(BinaryBitmap image) throws NotFoundException { - if (readers != null) { - for (Reader reader : readers) { - try { - return reader.decode(image, hints); - } catch (ReaderException re) { - // continue - } - } - } - throw NotFoundException.getNotFoundInstance(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatWriter.java deleted file mode 100644 index c980eb666..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/MultiFormatWriter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.aztec.AztecWriter; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.datamatrix.DataMatrixWriter; -import com.google.zxing.oned.CodaBarWriter; -import com.google.zxing.oned.Code128Writer; -import com.google.zxing.oned.Code39Writer; -import com.google.zxing.oned.EAN13Writer; -import com.google.zxing.oned.EAN8Writer; -import com.google.zxing.oned.ITFWriter; -import com.google.zxing.oned.UPCAWriter; -import com.google.zxing.pdf417.PDF417Writer; -import com.google.zxing.qrcode.QRCodeWriter; - -import java.util.Map; - -/** - * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat - * requested and encodes the barcode with the supplied contents. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class MultiFormatWriter implements Writer { - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height) throws WriterException { - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, int height, - Map hints) throws WriterException { - - Writer writer; - switch (format) { - case EAN_8: - writer = new EAN8Writer(); - break; - case EAN_13: - writer = new EAN13Writer(); - break; - case UPC_A: - writer = new UPCAWriter(); - break; - case QR_CODE: - writer = new QRCodeWriter(); - break; - case CODE_39: - writer = new Code39Writer(); - break; - case CODE_128: - writer = new Code128Writer(); - break; - case ITF: - writer = new ITFWriter(); - break; - case PDF_417: - writer = new PDF417Writer(); - break; - case CODABAR: - writer = new CodaBarWriter(); - break; - case DATA_MATRIX: - writer = new DataMatrixWriter(); - break; - case AZTEC: - writer = new AztecWriter(); - break; - default: - throw new IllegalArgumentException("No encoder available for format " + format); - } - return writer.encode(contents, format, width, height, hints); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/NotFoundException.java b/extern/zxing-core/src/main/java/com/google/zxing/NotFoundException.java deleted file mode 100644 index 863526af4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/NotFoundException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Thrown when a barcode was not found in the image. It might have been - * partially detected but could not be confirmed. - * - * @author Sean Owen - */ -public final class NotFoundException extends ReaderException { - - private static final NotFoundException INSTANCE = new NotFoundException(); - static { - INSTANCE.setStackTrace(NO_TRACE); // since it's meaningless - } - - private NotFoundException() { - // do nothing - } - - public static NotFoundException getNotFoundInstance() { - return INSTANCE; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/PlanarYUVLuminanceSource.java b/extern/zxing-core/src/main/java/com/google/zxing/PlanarYUVLuminanceSource.java deleted file mode 100644 index 2049e5930..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/PlanarYUVLuminanceSource.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * This object extends LuminanceSource around an array of YUV data returned from the camera driver, - * with the option to crop to a rectangle within the full data. This can be used to exclude - * superfluous pixels around the perimeter and speed up decoding. - * - * It works for any pixel format where the Y channel is planar and appears first, including - * YCbCr_420_SP and YCbCr_422_SP. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class PlanarYUVLuminanceSource extends LuminanceSource { - - private static final int THUMBNAIL_SCALE_FACTOR = 2; - - private final byte[] yuvData; - private final int dataWidth; - private final int dataHeight; - private final int left; - private final int top; - - public PlanarYUVLuminanceSource(byte[] yuvData, - int dataWidth, - int dataHeight, - int left, - int top, - int width, - int height, - boolean reverseHorizontal) { - super(width, height); - - if (left + width > dataWidth || top + height > dataHeight) { - throw new IllegalArgumentException("Crop rectangle does not fit within image data."); - } - - this.yuvData = yuvData; - this.dataWidth = dataWidth; - this.dataHeight = dataHeight; - this.left = left; - this.top = top; - if (reverseHorizontal) { - reverseHorizontal(width, height); - } - } - - @Override - public byte[] getRow(int y, byte[] row) { - if (y < 0 || y >= getHeight()) { - throw new IllegalArgumentException("Requested row is outside the image: " + y); - } - int width = getWidth(); - if (row == null || row.length < width) { - row = new byte[width]; - } - int offset = (y + top) * dataWidth + left; - System.arraycopy(yuvData, offset, row, 0, width); - return row; - } - - @Override - public byte[] getMatrix() { - int width = getWidth(); - int height = getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width == dataWidth && height == dataHeight) { - return yuvData; - } - - int area = width * height; - byte[] matrix = new byte[area]; - int inputOffset = top * dataWidth + left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width == dataWidth) { - System.arraycopy(yuvData, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - byte[] yuv = yuvData; - for (int y = 0; y < height; y++) { - int outputOffset = y * width; - System.arraycopy(yuv, inputOffset, matrix, outputOffset, width); - inputOffset += dataWidth; - } - return matrix; - } - - @Override - public boolean isCropSupported() { - return true; - } - - @Override - public LuminanceSource crop(int left, int top, int width, int height) { - return new PlanarYUVLuminanceSource(yuvData, - dataWidth, - dataHeight, - this.left + left, - this.top + top, - width, - height, - false); - } - - public int[] renderThumbnail() { - int width = getWidth() / THUMBNAIL_SCALE_FACTOR; - int height = getHeight() / THUMBNAIL_SCALE_FACTOR; - int[] pixels = new int[width * height]; - byte[] yuv = yuvData; - int inputOffset = top * dataWidth + left; - - for (int y = 0; y < height; y++) { - int outputOffset = y * width; - for (int x = 0; x < width; x++) { - int grey = yuv[inputOffset + x * THUMBNAIL_SCALE_FACTOR] & 0xff; - pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101); - } - inputOffset += dataWidth * THUMBNAIL_SCALE_FACTOR; - } - return pixels; - } - - /** - * @return width of image from {@link #renderThumbnail()} - */ - public int getThumbnailWidth() { - return getWidth() / THUMBNAIL_SCALE_FACTOR; - } - - /** - * @return height of image from {@link #renderThumbnail()} - */ - public int getThumbnailHeight() { - return getHeight() / THUMBNAIL_SCALE_FACTOR; - } - - private void reverseHorizontal(int width, int height) { - byte[] yuvData = this.yuvData; - for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) { - int middle = rowStart + width / 2; - for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { - byte temp = yuvData[x1]; - yuvData[x1] = yuvData[x2]; - yuvData[x2] = temp; - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/RGBLuminanceSource.java b/extern/zxing-core/src/main/java/com/google/zxing/RGBLuminanceSource.java deleted file mode 100644 index 7c70b35ca..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/RGBLuminanceSource.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * This class is used to help decode images from files which arrive as RGB data from - * an ARGB pixel array. It does not support rotation. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Betaminos - */ -public final class RGBLuminanceSource extends LuminanceSource { - - private final byte[] luminances; - private final int dataWidth; - private final int dataHeight; - private final int left; - private final int top; - - public RGBLuminanceSource(int width, int height, int[] pixels) { - super(width, height); - - dataWidth = width; - dataHeight = height; - left = 0; - top = 0; - - // In order to measure pure decoding speed, we convert the entire image to a greyscale array - // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app. - luminances = new byte[width * height]; - for (int y = 0; y < height; y++) { - int offset = y * width; - for (int x = 0; x < width; x++) { - int pixel = pixels[offset + x]; - int r = (pixel >> 16) & 0xff; - int g = (pixel >> 8) & 0xff; - int b = pixel & 0xff; - if (r == g && g == b) { - // Image is already greyscale, so pick any channel. - luminances[offset + x] = (byte) r; - } else { - // Calculate luminance cheaply, favoring green. - luminances[offset + x] = (byte) ((r + 2 * g + b) / 4); - } - } - } - } - - private RGBLuminanceSource(byte[] pixels, - int dataWidth, - int dataHeight, - int left, - int top, - int width, - int height) { - super(width, height); - if (left + width > dataWidth || top + height > dataHeight) { - throw new IllegalArgumentException("Crop rectangle does not fit within image data."); - } - this.luminances = pixels; - this.dataWidth = dataWidth; - this.dataHeight = dataHeight; - this.left = left; - this.top = top; - } - - @Override - public byte[] getRow(int y, byte[] row) { - if (y < 0 || y >= getHeight()) { - throw new IllegalArgumentException("Requested row is outside the image: " + y); - } - int width = getWidth(); - if (row == null || row.length < width) { - row = new byte[width]; - } - int offset = (y + top) * dataWidth + left; - System.arraycopy(luminances, offset, row, 0, width); - return row; - } - - @Override - public byte[] getMatrix() { - int width = getWidth(); - int height = getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width == dataWidth && height == dataHeight) { - return luminances; - } - - int area = width * height; - byte[] matrix = new byte[area]; - int inputOffset = top * dataWidth + left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width == dataWidth) { - System.arraycopy(luminances, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - byte[] rgb = luminances; - for (int y = 0; y < height; y++) { - int outputOffset = y * width; - System.arraycopy(rgb, inputOffset, matrix, outputOffset, width); - inputOffset += dataWidth; - } - return matrix; - } - - @Override - public boolean isCropSupported() { - return true; - } - - @Override - public LuminanceSource crop(int left, int top, int width, int height) { - return new RGBLuminanceSource(luminances, - dataWidth, - dataHeight, - this.left + left, - this.top + top, - width, - height); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/Reader.java deleted file mode 100644 index bd3732e02..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/Reader.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import java.util.Map; - -/** - * Implementations of this interface can decode an image of a barcode in some format into - * the String it encodes. For example, {@link com.google.zxing.qrcode.QRCodeReader} can - * decode a QR code. The decoder may optionally receive hints from the caller which may help - * it decode more quickly or accurately. - * - * See {@link com.google.zxing.MultiFormatReader}, which attempts to determine what barcode - * format is present within the image as well, and then decodes it accordingly. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ -public interface Reader { - - /** - * Locates and decodes a barcode in some format within an image. - * - * @param image image of barcode to decode - * @return String which the barcode encodes - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException; - - /** - * Locates and decodes a barcode in some format within an image. This method also accepts - * hints, each possibly associated to some data, which may help the implementation decode. - * - * @param image image of barcode to decode - * @param hints passed as a {@link java.util.Map} from {@link com.google.zxing.DecodeHintType} - * to arbitrary data. The - * meaning of the data depends upon the hint type. The implementation may or may not do - * anything with these hints. - * @return String which the barcode encodes - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, ChecksumException, FormatException; - - /** - * Resets any internal state the implementation has after a decode, to prepare it - * for reuse. - */ - void reset(); - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/ReaderException.java b/extern/zxing-core/src/main/java/com/google/zxing/ReaderException.java deleted file mode 100644 index 5f2c12e43..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/ReaderException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * The general exception class throw when something goes wrong during decoding of a barcode. - * This includes, but is not limited to, failing checksums / error correction algorithms, being - * unable to locate finder timing patterns, and so on. - * - * @author Sean Owen - */ -public abstract class ReaderException extends Exception { - - // disable stack traces when not running inside test units - protected static final boolean isStackTrace = - System.getProperty("surefire.test.class.path") != null; - protected static final StackTraceElement[] NO_TRACE = new StackTraceElement[0]; - - ReaderException() { - // do nothing - } - - ReaderException(Throwable cause) { - super(cause); - } - - // Prevent stack traces from being taken - // srowen says: huh, my IDE is saying this is not an override. native methods can't be overridden? - // This, at least, does not hurt. Because we use a singleton pattern here, it doesn't matter anyhow. - @Override - public final Throwable fillInStackTrace() { - return null; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/Result.java b/extern/zxing-core/src/main/java/com/google/zxing/Result.java deleted file mode 100644 index 7c98006de..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/Result.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import java.util.EnumMap; -import java.util.Map; - -/** - *

    Encapsulates the result of decoding a barcode within an image.

    - * - * @author Sean Owen - */ -public final class Result { - - private final String text; - private final byte[] rawBytes; - private ResultPoint[] resultPoints; - private final BarcodeFormat format; - private Map resultMetadata; - private final long timestamp; - - public Result(String text, - byte[] rawBytes, - ResultPoint[] resultPoints, - BarcodeFormat format) { - this(text, rawBytes, resultPoints, format, System.currentTimeMillis()); - } - - public Result(String text, - byte[] rawBytes, - ResultPoint[] resultPoints, - BarcodeFormat format, - long timestamp) { - this.text = text; - this.rawBytes = rawBytes; - this.resultPoints = resultPoints; - this.format = format; - this.resultMetadata = null; - this.timestamp = timestamp; - } - - /** - * @return raw text encoded by the barcode - */ - public String getText() { - return text; - } - - /** - * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null} - */ - public byte[] getRawBytes() { - return rawBytes; - } - - /** - * @return points related to the barcode in the image. These are typically points - * identifying finder patterns or the corners of the barcode. The exact meaning is - * specific to the type of barcode that was decoded. - */ - public ResultPoint[] getResultPoints() { - return resultPoints; - } - - /** - * @return {@link BarcodeFormat} representing the format of the barcode that was decoded - */ - public BarcodeFormat getBarcodeFormat() { - return format; - } - - /** - * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be - * {@code null}. This contains optional metadata about what was detected about the barcode, - * like orientation. - */ - public Map getResultMetadata() { - return resultMetadata; - } - - public void putMetadata(ResultMetadataType type, Object value) { - if (resultMetadata == null) { - resultMetadata = new EnumMap<>(ResultMetadataType.class); - } - resultMetadata.put(type, value); - } - - public void putAllMetadata(Map metadata) { - if (metadata != null) { - if (resultMetadata == null) { - resultMetadata = metadata; - } else { - resultMetadata.putAll(metadata); - } - } - } - - public void addResultPoints(ResultPoint[] newPoints) { - ResultPoint[] oldPoints = resultPoints; - if (oldPoints == null) { - resultPoints = newPoints; - } else if (newPoints != null && newPoints.length > 0) { - ResultPoint[] allPoints = new ResultPoint[oldPoints.length + newPoints.length]; - System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length); - System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length); - resultPoints = allPoints; - } - } - - public long getTimestamp() { - return timestamp; - } - - @Override - public String toString() { - return text; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/ResultMetadataType.java b/extern/zxing-core/src/main/java/com/google/zxing/ResultMetadataType.java deleted file mode 100644 index eac968b1e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/ResultMetadataType.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Represents some type of metadata about the result of the decoding that the decoder - * wishes to communicate back to the caller. - * - * @author Sean Owen - */ -public enum ResultMetadataType { - - /** - * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. - */ - OTHER, - - /** - * Denotes the likely approximate orientation of the barcode in the image. This value - * is given as degrees rotated clockwise from the normal, upright orientation. - * For example a 1D barcode which was found by reading top-to-bottom would be - * said to have orientation "90". This key maps to an {@link Integer} whose - * value is in the range [0,360). - */ - ORIENTATION, - - /** - *

    2D barcode formats typically encode text, but allow for a sort of 'byte mode' - * which is sometimes used to encode binary data. While {@link Result} makes available - * the complete raw bytes in the barcode for these formats, it does not offer the bytes - * from the byte segments alone.

    - * - *

    This maps to a {@link java.util.List} of byte arrays corresponding to the - * raw bytes in the byte segments in the barcode, in order.

    - */ - BYTE_SEGMENTS, - - /** - * Error correction level used, if applicable. The value type depends on the - * format, but is typically a String. - */ - ERROR_CORRECTION_LEVEL, - - /** - * For some periodicals, indicates the issue number as an {@link Integer}. - */ - ISSUE_NUMBER, - - /** - * For some products, indicates the suggested retail price in the barcode as a - * formatted {@link String}. - */ - SUGGESTED_PRICE , - - /** - * For some products, the possible country of manufacture as a {@link String} denoting the - * ISO country code. Some map to multiple possible countries, like "US/CA". - */ - POSSIBLE_COUNTRY, - - /** - * For some products, the extension text - */ - UPC_EAN_EXTENSION, - - /** - * PDF417-specific metadata - */ - PDF417_EXTRA_METADATA, - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * sequence number is given with it. - */ - STRUCTURED_APPEND_SEQUENCE, - - /** - * If the code format supports structured append and the current scanned code is part of one then the - * parity is given with it. - */ - STRUCTURED_APPEND_PARITY, - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/ResultPoint.java b/extern/zxing-core/src/main/java/com/google/zxing/ResultPoint.java deleted file mode 100644 index 920cd24c5..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/ResultPoint.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.common.detector.MathUtils; - -/** - *

    Encapsulates a point of interest in an image containing a barcode. Typically, this - * would be the location of a finder pattern or the corner of the barcode, for example.

    - * - * @author Sean Owen - */ -public class ResultPoint { - - private final float x; - private final float y; - - public ResultPoint(float x, float y) { - this.x = x; - this.y = y; - } - - public final float getX() { - return x; - } - - public final float getY() { - return y; - } - - @Override - public final boolean equals(Object other) { - if (other instanceof ResultPoint) { - ResultPoint otherPoint = (ResultPoint) other; - return x == otherPoint.x && y == otherPoint.y; - } - return false; - } - - @Override - public final int hashCode() { - return 31 * Float.floatToIntBits(x) + Float.floatToIntBits(y); - } - - @Override - public final String toString() { - StringBuilder result = new StringBuilder(25); - result.append('('); - result.append(x); - result.append(','); - result.append(y); - result.append(')'); - return result.toString(); - } - - /** - * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC - * and BC is less than AC, and the angle between BC and BA is less than 180 degrees. - * - * @param patterns array of three {@code ResultPoint} to order - */ - public static void orderBestPatterns(ResultPoint[] patterns) { - - // Find distances between pattern centers - float zeroOneDistance = distance(patterns[0], patterns[1]); - float oneTwoDistance = distance(patterns[1], patterns[2]); - float zeroTwoDistance = distance(patterns[0], patterns[2]); - - ResultPoint pointA; - ResultPoint pointB; - ResultPoint pointC; - // Assume one closest to other two is B; A and C will just be guesses at first - if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) { - pointB = patterns[0]; - pointA = patterns[1]; - pointC = patterns[2]; - } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) { - pointB = patterns[1]; - pointA = patterns[0]; - pointC = patterns[2]; - } else { - pointB = patterns[2]; - pointA = patterns[0]; - pointC = patterns[1]; - } - - // Use cross product to figure out whether A and C are correct or flipped. - // This asks whether BC x BA has a positive z component, which is the arrangement - // we want for A, B, C. If it's negative, then we've got it flipped around and - // should swap A and C. - if (crossProductZ(pointA, pointB, pointC) < 0.0f) { - ResultPoint temp = pointA; - pointA = pointC; - pointC = temp; - } - - patterns[0] = pointA; - patterns[1] = pointB; - patterns[2] = pointC; - } - - - /** - * @param pattern1 first pattern - * @param pattern2 second pattern - * @return distance between two points - */ - public static float distance(ResultPoint pattern1, ResultPoint pattern2) { - return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y); - } - - /** - * Returns the z component of the cross product between vectors BC and BA. - */ - private static float crossProductZ(ResultPoint pointA, - ResultPoint pointB, - ResultPoint pointC) { - float bX = pointB.x; - float bY = pointB.y; - return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX)); - } - - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/ResultPointCallback.java b/extern/zxing-core/src/main/java/com/google/zxing/ResultPointCallback.java deleted file mode 100644 index 0c85410bc..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/ResultPointCallback.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * Callback which is invoked when a possible result point (significant - * point in the barcode image such as a corner) is found. - * - * @see DecodeHintType#NEED_RESULT_POINT_CALLBACK - */ -public interface ResultPointCallback { - - void foundPossibleResultPoint(ResultPoint point); - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/Writer.java deleted file mode 100644 index f405fd844..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/Writer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * The base class for all objects which encode/generate a barcode image. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public interface Writer { - - /** - * Encode a barcode using the default settings. - * - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - throws WriterException; - - /** - * @param contents The contents to encode in the barcode - * @param format The barcode format to generate - * @param width The preferred width in pixels - * @param height The preferred height in pixels - * @param hints Additional parameters to supply to the encoder - * @return {@link BitMatrix} representing encoded barcode image - * @throws WriterException if contents cannot be encoded legally in a format - */ - BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) - throws WriterException; - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/WriterException.java b/extern/zxing-core/src/main/java/com/google/zxing/WriterException.java deleted file mode 100644 index c61800b93..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/WriterException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing; - -/** - * A base class which covers the range of exceptions which may occur when encoding a barcode using - * the Writer framework. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class WriterException extends Exception { - - public WriterException() { - } - - public WriterException(String message) { - super(message); - } - - public WriterException(Throwable cause) { - super(cause); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecDetectorResult.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecDetectorResult.java deleted file mode 100644 index f262e0e6d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecDetectorResult.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec; - -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DetectorResult; - -public final class AztecDetectorResult extends DetectorResult { - - private final boolean compact; - private final int nbDatablocks; - private final int nbLayers; - - public AztecDetectorResult(BitMatrix bits, - ResultPoint[] points, - boolean compact, - int nbDatablocks, - int nbLayers) { - super(bits, points); - this.compact = compact; - this.nbDatablocks = nbDatablocks; - this.nbLayers = nbLayers; - } - - public int getNbLayers() { - return nbLayers; - } - - public int getNbDatablocks() { - return nbDatablocks; - } - - public boolean isCompact() { - return compact; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecReader.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecReader.java deleted file mode 100644 index d56e3f6c6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecReader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.aztec.decoder.Decoder; -import com.google.zxing.aztec.detector.Detector; -import com.google.zxing.common.DecoderResult; - -import java.util.List; -import java.util.Map; - -/** - * This implementation can detect and decode Aztec codes in an image. - * - * @author David Olivier - */ -public final class AztecReader implements Reader { - - /** - * Locates and decodes a Data Matrix code in an image. - * - * @return a String representing the content encoded by the Data Matrix code - * @throws NotFoundException if a Data Matrix code cannot be found - * @throws FormatException if a Data Matrix code cannot be decoded - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, FormatException { - return decode(image, null); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, FormatException { - - NotFoundException notFoundException = null; - FormatException formatException = null; - Detector detector = new Detector(image.getBlackMatrix()); - ResultPoint[] points = null; - DecoderResult decoderResult = null; - try { - AztecDetectorResult detectorResult = detector.detect(false); - points = detectorResult.getPoints(); - decoderResult = new Decoder().decode(detectorResult); - } catch (NotFoundException e) { - notFoundException = e; - } catch (FormatException e) { - formatException = e; - } - if (decoderResult == null) { - try { - AztecDetectorResult detectorResult = detector.detect(true); - points = detectorResult.getPoints(); - decoderResult = new Decoder().decode(detectorResult); - } catch (NotFoundException | FormatException e) { - if (notFoundException != null) { - throw notFoundException; - } - if (formatException != null) { - throw formatException; - } - throw e; - } - } - - if (hints != null) { - ResultPointCallback rpcb = (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - if (rpcb != null) { - for (ResultPoint point : points) { - rpcb.foundPossibleResultPoint(point); - } - } - } - - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.AZTEC); - - List byteSegments = decoderResult.getByteSegments(); - if (byteSegments != null) { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - String ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - - return result; - } - - @Override - public void reset() { - // do nothing - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecWriter.java deleted file mode 100644 index afa73ef83..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/AztecWriter.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.aztec.encoder.AztecCode; -import com.google.zxing.aztec.encoder.Encoder; -import com.google.zxing.common.BitMatrix; - -import java.nio.charset.Charset; -import java.util.Map; - -public final class AztecWriter implements Writer { - - private static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) { - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map hints) { - String charset = hints == null ? null : (String) hints.get(EncodeHintType.CHARACTER_SET); - Number eccPercent = hints == null ? null : (Number) hints.get(EncodeHintType.ERROR_CORRECTION); - Number layers = hints == null ? null : (Number) hints.get(EncodeHintType.AZTEC_LAYERS); - return encode(contents, - format, - width, - height, - charset == null ? DEFAULT_CHARSET : Charset.forName(charset), - eccPercent == null ? Encoder.DEFAULT_EC_PERCENT : eccPercent.intValue(), - layers == null ? Encoder.DEFAULT_AZTEC_LAYERS : layers.intValue()); - } - - private static BitMatrix encode(String contents, BarcodeFormat format, - int width, int height, - Charset charset, int eccPercent, int layers) { - if (format != BarcodeFormat.AZTEC) { - throw new IllegalArgumentException("Can only encode AZTEC, but got " + format); - } - AztecCode aztec = Encoder.encode(contents.getBytes(charset), eccPercent, layers); - return renderResult(aztec, width, height); - } - - private static BitMatrix renderResult(AztecCode code, int width, int height) { - BitMatrix input = code.getMatrix(); - if (input == null) { - throw new IllegalStateException(); - } - int inputWidth = input.getWidth(); - int inputHeight = input.getHeight(); - int outputWidth = Math.max(width, inputWidth); - int outputHeight = Math.max(height, inputHeight); - - int multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight); - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - int topPadding = (outputHeight - (inputHeight * multiple)) / 2; - - BitMatrix output = new BitMatrix(outputWidth, outputHeight); - - for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) { - // Write the contents of this row of the barcode - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { - if (input.get(inputX, inputY)) { - output.setRegion(outputX, outputY, multiple, multiple); - } - } - } - return output; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java deleted file mode 100644 index d0304a9a1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.aztec.AztecDetectorResult; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonDecoder; -import com.google.zxing.common.reedsolomon.ReedSolomonException; - -import java.util.Arrays; - -/** - *

    The main class which implements Aztec Code decoding -- as opposed to locating and extracting - * the Aztec Code from an image.

    - * - * @author David Olivier - */ -public final class Decoder { - - private enum Table { - UPPER, - LOWER, - MIXED, - DIGIT, - PUNCT, - BINARY - } - - private static final String[] UPPER_TABLE = { - "CTRL_PS", " ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", - "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "CTRL_LL", "CTRL_ML", "CTRL_DL", "CTRL_BS" - }; - - private static final String[] LOWER_TABLE = { - "CTRL_PS", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", - "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "CTRL_US", "CTRL_ML", "CTRL_DL", "CTRL_BS" - }; - - private static final String[] MIXED_TABLE = { - "CTRL_PS", " ", "\1", "\2", "\3", "\4", "\5", "\6", "\7", "\b", "\t", "\n", - "\13", "\f", "\r", "\33", "\34", "\35", "\36", "\37", "@", "\\", "^", "_", - "`", "|", "~", "\177", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS" - }; - - private static final String[] PUNCT_TABLE = { - "", "\r", "\r\n", ". ", ", ", ": ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", - "*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "[", "]", "{", "}", "CTRL_UL" - }; - - private static final String[] DIGIT_TABLE = { - "CTRL_PS", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", "CTRL_UL", "CTRL_US" - }; - - private AztecDetectorResult ddata; - - public DecoderResult decode(AztecDetectorResult detectorResult) throws FormatException { - ddata = detectorResult; - BitMatrix matrix = detectorResult.getBits(); - boolean[] rawbits = extractBits(matrix); - boolean[] correctedBits = correctBits(rawbits); - String result = getEncodedData(correctedBits); - return new DecoderResult(null, result, null, null); - } - - // This method is used for testing the high-level encoder - public static String highLevelDecode(boolean[] correctedBits) { - return getEncodedData(correctedBits); - } - - /** - * Gets the string encoded in the aztec code bits - * - * @return the decoded string - */ - private static String getEncodedData(boolean[] correctedBits) { - int endIndex = correctedBits.length; - Table latchTable = Table.UPPER; // table most recently latched to - Table shiftTable = Table.UPPER; // table to use for the next read - StringBuilder result = new StringBuilder(20); - int index = 0; - while (index < endIndex) { - if (shiftTable == Table.BINARY) { - if (endIndex - index < 5) { - break; - } - int length = readCode(correctedBits, index, 5); - index += 5; - if (length == 0) { - if (endIndex - index < 11) { - break; - } - length = readCode(correctedBits, index, 11) + 31; - index += 11; - } - for (int charCount = 0; charCount < length; charCount++) { - if (endIndex - index < 8) { - index = endIndex; // Force outer loop to exit - break; - } - int code = readCode(correctedBits, index, 8); - result.append((char) code); - index += 8; - } - // Go back to whatever mode we had been in - shiftTable = latchTable; - } else { - int size = shiftTable == Table.DIGIT ? 4 : 5; - if (endIndex - index < size) { - break; - } - int code = readCode(correctedBits, index, size); - index += size; - String str = getCharacter(shiftTable, code); - if (str.startsWith("CTRL_")) { - // Table changes - shiftTable = getTable(str.charAt(5)); - if (str.charAt(6) == 'L') { - latchTable = shiftTable; - } - } else { - result.append(str); - // Go back to whatever mode we had been in - shiftTable = latchTable; - } - } - } - return result.toString(); - } - - /** - * gets the table corresponding to the char passed - */ - private static Table getTable(char t) { - switch (t) { - case 'L': - return Table.LOWER; - case 'P': - return Table.PUNCT; - case 'M': - return Table.MIXED; - case 'D': - return Table.DIGIT; - case 'B': - return Table.BINARY; - case 'U': - default: - return Table.UPPER; - } - } - - /** - * Gets the character (or string) corresponding to the passed code in the given table - * - * @param table the table used - * @param code the code of the character - */ - private static String getCharacter(Table table, int code) { - switch (table) { - case UPPER: - return UPPER_TABLE[code]; - case LOWER: - return LOWER_TABLE[code]; - case MIXED: - return MIXED_TABLE[code]; - case PUNCT: - return PUNCT_TABLE[code]; - case DIGIT: - return DIGIT_TABLE[code]; - default: - // Should not reach here. - throw new IllegalStateException("Bad table"); - } - } - - /** - *

    Performs RS error correction on an array of bits.

    - * - * @return the corrected array - * @throws FormatException if the input contains too many errors - */ - private boolean[] correctBits(boolean[] rawbits) throws FormatException { - GenericGF gf; - int codewordSize; - - if (ddata.getNbLayers() <= 2) { - codewordSize = 6; - gf = GenericGF.AZTEC_DATA_6; - } else if (ddata.getNbLayers() <= 8) { - codewordSize = 8; - gf = GenericGF.AZTEC_DATA_8; - } else if (ddata.getNbLayers() <= 22) { - codewordSize = 10; - gf = GenericGF.AZTEC_DATA_10; - } else { - codewordSize = 12; - gf = GenericGF.AZTEC_DATA_12; - } - - int numDataCodewords = ddata.getNbDatablocks(); - int numCodewords = rawbits.length / codewordSize; - if (numCodewords < numDataCodewords) { - throw FormatException.getFormatInstance(); - } - int offset = rawbits.length % codewordSize; - int numECCodewords = numCodewords - numDataCodewords; - - int[] dataWords = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++, offset += codewordSize) { - dataWords[i] = readCode(rawbits, offset, codewordSize); - } - - try { - ReedSolomonDecoder rsDecoder = new ReedSolomonDecoder(gf); - rsDecoder.decode(dataWords, numECCodewords); - } catch (ReedSolomonException ex) { - throw FormatException.getFormatInstance(ex); - } - - // Now perform the unstuffing operation. - // First, count how many bits are going to be thrown out as stuffing - int mask = (1 << codewordSize) - 1; - int stuffedBits = 0; - for (int i = 0; i < numDataCodewords; i++) { - int dataWord = dataWords[i]; - if (dataWord == 0 || dataWord == mask) { - throw FormatException.getFormatInstance(); - } else if (dataWord == 1 || dataWord == mask - 1) { - stuffedBits++; - } - } - // Now, actually unpack the bits and remove the stuffing - boolean[] correctedBits = new boolean[numDataCodewords * codewordSize - stuffedBits]; - int index = 0; - for (int i = 0; i < numDataCodewords; i++) { - int dataWord = dataWords[i]; - if (dataWord == 1 || dataWord == mask - 1) { - // next codewordSize-1 bits are all zeros or all ones - Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1); - index += codewordSize - 1; - } else { - for (int bit = codewordSize - 1; bit >= 0; --bit) { - correctedBits[index++] = (dataWord & (1 << bit)) != 0; - } - } - } - return correctedBits; - } - - /** - * Gets the array of bits from an Aztec Code matrix - * - * @return the array of bits - */ - boolean[] extractBits(BitMatrix matrix) { - boolean compact = ddata.isCompact(); - int layers = ddata.getNbLayers(); - int baseMatrixSize = compact ? 11 + layers * 4 : 14 + layers * 4; // not including alignment lines - int[] alignmentMap = new int[baseMatrixSize]; - boolean[] rawbits = new boolean[totalBitsInLayer(layers, compact)]; - - if (compact) { - for (int i = 0; i < alignmentMap.length; i++) { - alignmentMap[i] = i; - } - } else { - int matrixSize = baseMatrixSize + 1 + 2 * ((baseMatrixSize / 2 - 1) / 15); - int origCenter = baseMatrixSize / 2; - int center = matrixSize / 2; - for (int i = 0; i < origCenter; i++) { - int newOffset = i + i / 15; - alignmentMap[origCenter - i - 1] = center - newOffset - 1; - alignmentMap[origCenter + i] = center + newOffset + 1; - } - } - for (int i = 0, rowOffset = 0; i < layers; i++) { - int rowSize = compact ? (layers - i) * 4 + 9 : (layers - i) * 4 + 12; - // The top-left most point of this layer is (not including alignment lines) - int low = i * 2; - // The bottom-right most point of this layer is (not including alignment lines) - int high = baseMatrixSize - 1 - low; - // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows - for (int j = 0; j < rowSize; j++) { - int columnOffset = j * 2; - for (int k = 0; k < 2; k++) { - // left column - rawbits[rowOffset + columnOffset + k] = - matrix.get(alignmentMap[low + k], alignmentMap[low + j]); - // bottom row - rawbits[rowOffset + 2 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[low + j], alignmentMap[high - k]); - // right column - rawbits[rowOffset + 4 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[high - k], alignmentMap[high - j]); - // top row - rawbits[rowOffset + 6 * rowSize + columnOffset + k] = - matrix.get(alignmentMap[high - j], alignmentMap[low + k]); - } - } - rowOffset += rowSize * 8; - } - return rawbits; - } - - /** - * Reads a code of given length and at given index in an array of bits - */ - private static int readCode(boolean[] rawbits, int startIndex, int length) { - int res = 0; - for (int i = startIndex; i < startIndex + length; i++) { - res <<= 1; - if (rawbits[i]) { - res |= 0x01; - } - } - return res; - } - - private static int totalBitsInLayer(int layers, boolean compact) { - return ((compact ? 88 : 112) + 16 * layers) * layers; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/detector/Detector.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/detector/Detector.java deleted file mode 100644 index 5cc5c3669..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/detector/Detector.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.detector; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.aztec.AztecDetectorResult; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.GridSampler; -import com.google.zxing.common.detector.MathUtils; -import com.google.zxing.common.detector.WhiteRectangleDetector; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonDecoder; -import com.google.zxing.common.reedsolomon.ReedSolomonException; - -/** - * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code - * is rotated or skewed, or partially obscured. - * - * @author David Olivier - * @author Frank Yellin - */ -public final class Detector { - - private final BitMatrix image; - - private boolean compact; - private int nbLayers; - private int nbDataBlocks; - private int nbCenterLayers; - private int shift; - - public Detector(BitMatrix image) { - this.image = image; - } - - public AztecDetectorResult detect() throws NotFoundException { - return detect(false); - } - - /** - * Detects an Aztec Code in an image. - * - * @param isMirror if true, image is a mirror-image of original - * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code - * @throws NotFoundException if no Aztec Code can be found - */ - public AztecDetectorResult detect(boolean isMirror) throws NotFoundException { - - // 1. Get the center of the aztec matrix - Point pCenter = getMatrixCenter(); - - // 2. Get the center points of the four diagonal points just outside the bull's eye - // [topRight, bottomRight, bottomLeft, topLeft] - ResultPoint[] bullsEyeCorners = getBullsEyeCorners(pCenter); - - if (isMirror) { - ResultPoint temp = bullsEyeCorners[0]; - bullsEyeCorners[0] = bullsEyeCorners[2]; - bullsEyeCorners[2] = temp; - } - - // 3. Get the size of the matrix and other parameters from the bull's eye - extractParameters(bullsEyeCorners); - - // 4. Sample the grid - BitMatrix bits = sampleGrid(image, - bullsEyeCorners[shift % 4], - bullsEyeCorners[(shift + 1) % 4], - bullsEyeCorners[(shift + 2) % 4], - bullsEyeCorners[(shift + 3) % 4]); - - // 5. Get the corners of the matrix. - ResultPoint[] corners = getMatrixCornerPoints(bullsEyeCorners); - - return new AztecDetectorResult(bits, corners, compact, nbDataBlocks, nbLayers); - } - - /** - * Extracts the number of data layers and data blocks from the layer around the bull's eye. - * - * @param bullsEyeCorners the array of bull's eye corners - * @throws NotFoundException in case of too many errors or invalid parameters - */ - private void extractParameters(ResultPoint[] bullsEyeCorners) throws NotFoundException { - if (!isValid(bullsEyeCorners[0]) || !isValid(bullsEyeCorners[1]) || - !isValid(bullsEyeCorners[2]) || !isValid(bullsEyeCorners[3])) { - throw NotFoundException.getNotFoundInstance(); - } - int length = 2 * nbCenterLayers; - // Get the bits around the bull's eye - int[] sides = { - sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length), // Right side - sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom - sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length), // Left side - sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top - }; - - // bullsEyeCorners[shift] is the corner of the bulls'eye that has three - // orientation marks. - // sides[shift] is the row/column that goes from the corner with three - // orientation marks to the corner with two. - shift = getRotation(sides, length); - - // Flatten the parameter bits into a single 28- or 40-bit long - long parameterData = 0; - for (int i = 0; i < 4; i++) { - int side = sides[(shift + i) % 4]; - if (compact) { - // Each side of the form ..XXXXXXX. where Xs are parameter data - parameterData <<= 7; - parameterData += (side >> 1) & 0x7F; - } else { - // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data - parameterData <<= 10; - parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F); - } - } - - // Corrects parameter data using RS. Returns just the data portion - // without the error correction. - int correctedData = getCorrectedParameterData(parameterData, compact); - - if (compact) { - // 8 bits: 2 bits layers and 6 bits data blocks - nbLayers = (correctedData >> 6) + 1; - nbDataBlocks = (correctedData & 0x3F) + 1; - } else { - // 16 bits: 5 bits layers and 11 bits data blocks - nbLayers = (correctedData >> 11) + 1; - nbDataBlocks = (correctedData & 0x7FF) + 1; - } - } - - private static final int[] EXPECTED_CORNER_BITS = { - 0xee0, // 07340 XXX .XX X.. ... - 0x1dc, // 00734 ... XXX .XX X.. - 0x83b, // 04073 X.. ... XXX .XX - 0x707, // 03407 .XX X.. ... XXX - }; - - private static int getRotation(int[] sides, int length) throws NotFoundException { - // In a normal pattern, we expect to See - // ** .* D A - // * * - // - // . * - // .. .. C B - // - // Grab the 3 bits from each of the sides the form the locator pattern and concatenate - // into a 12-bit integer. Start with the bit at A - int cornerBits = 0; - for (int side : sides) { - // XX......X where X's are orientation marks - int t = ((side >> (length - 2)) << 1) + (side & 1); - cornerBits = (cornerBits << 3) + t; - } - // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are - // together. cornerBits is now: - // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D - cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1); - // The result shift indicates which element of BullsEyeCorners[] goes into the top-left - // corner. Since the four rotation values have a Hamming distance of 8, we - // can easily tolerate two errors. - for (int shift = 0; shift < 4; shift++) { - if (Integer.bitCount(cornerBits ^ EXPECTED_CORNER_BITS[shift]) <= 2) { - return shift; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Corrects the parameter bits using Reed-Solomon algorithm. - * - * @param parameterData parameter bits - * @param compact true if this is a compact Aztec code - * @throws NotFoundException if the array contains too many errors - */ - private static int getCorrectedParameterData(long parameterData, boolean compact) throws NotFoundException { - int numCodewords; - int numDataCodewords; - - if (compact) { - numCodewords = 7; - numDataCodewords = 2; - } else { - numCodewords = 10; - numDataCodewords = 4; - } - - int numECCodewords = numCodewords - numDataCodewords; - int[] parameterWords = new int[numCodewords]; - for (int i = numCodewords - 1; i >= 0; --i) { - parameterWords[i] = (int) parameterData & 0xF; - parameterData >>= 4; - } - try { - ReedSolomonDecoder rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); - rsDecoder.decode(parameterWords, numECCodewords); - } catch (ReedSolomonException ignored) { - throw NotFoundException.getNotFoundInstance(); - } - // Toss the error correction. Just return the data as an integer - int result = 0; - for (int i = 0; i < numDataCodewords; i++) { - result = (result << 4) + parameterWords[i]; - } - return result; - } - - /** - * Finds the corners of a bull-eye centered on the passed point. - * This returns the centers of the diagonal points just outside the bull's eye - * Returns [topRight, bottomRight, bottomLeft, topLeft] - * - * @param pCenter Center point - * @return The corners of the bull-eye - * @throws NotFoundException If no valid bull-eye can be found - */ - private ResultPoint[] getBullsEyeCorners(Point pCenter) throws NotFoundException { - - Point pina = pCenter; - Point pinb = pCenter; - Point pinc = pCenter; - Point pind = pCenter; - - boolean color = true; - - for (nbCenterLayers = 1; nbCenterLayers < 9; nbCenterLayers++) { - Point pouta = getFirstDifferent(pina, color, 1, -1); - Point poutb = getFirstDifferent(pinb, color, 1, 1); - Point poutc = getFirstDifferent(pinc, color, -1, 1); - Point poutd = getFirstDifferent(pind, color, -1, -1); - - //d a - // - //c b - - if (nbCenterLayers > 2) { - float q = distance(poutd, pouta) * nbCenterLayers / (distance(pind, pina) * (nbCenterLayers + 2)); - if (q < 0.75 || q > 1.25 || !isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) { - break; - } - } - - pina = pouta; - pinb = poutb; - pinc = poutc; - pind = poutd; - - color = !color; - } - - if (nbCenterLayers != 5 && nbCenterLayers != 7) { - throw NotFoundException.getNotFoundInstance(); - } - - compact = nbCenterLayers == 5; - - // Expand the square by .5 pixel in each direction so that we're on the border - // between the white square and the black square - ResultPoint pinax = new ResultPoint(pina.getX() + 0.5f, pina.getY() - 0.5f); - ResultPoint pinbx = new ResultPoint(pinb.getX() + 0.5f, pinb.getY() + 0.5f); - ResultPoint pincx = new ResultPoint(pinc.getX() - 0.5f, pinc.getY() + 0.5f); - ResultPoint pindx = new ResultPoint(pind.getX() - 0.5f, pind.getY() - 0.5f); - - // Expand the square so that its corners are the centers of the points - // just outside the bull's eye. - return expandSquare(new ResultPoint[]{pinax, pinbx, pincx, pindx}, - 2 * nbCenterLayers - 3, - 2 * nbCenterLayers); - } - - /** - * Finds a candidate center point of an Aztec code from an image - * - * @return the center point - */ - private Point getMatrixCenter() { - - ResultPoint pointA; - ResultPoint pointB; - ResultPoint pointC; - ResultPoint pointD; - - //Get a white rectangle that can be the border of the matrix in center bull's eye or - try { - - ResultPoint[] cornerPoints = new WhiteRectangleDetector(image).detect(); - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - - } catch (NotFoundException e) { - - // This exception can be in case the initial rectangle is white - // In that case, surely in the bull's eye, we try to expand the rectangle. - int cx = image.getWidth() / 2; - int cy = image.getHeight() / 2; - pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - - } - - //Compute the center of the rectangle - int cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0f); - int cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0f); - - // Redetermine the white rectangle starting from previously computed center. - // This will ensure that we end up with a white rectangle in center bull's eye - // in order to compute a more accurate center. - try { - ResultPoint[] cornerPoints = new WhiteRectangleDetector(image, 15, cx, cy).detect(); - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - } catch (NotFoundException e) { - // This exception can be in case the initial rectangle is white - // In that case we try to expand the rectangle. - pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - } - - // Recompute the center of the rectangle - cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0f); - cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0f); - - return new Point(cx, cy); - } - - /** - * Gets the Aztec code corners from the bull's eye corners and the parameters. - * - * @param bullsEyeCorners the array of bull's eye corners - * @return the array of aztec code corners - */ - private ResultPoint[] getMatrixCornerPoints(ResultPoint[] bullsEyeCorners) { - return expandSquare(bullsEyeCorners, 2 * nbCenterLayers, getDimension()); - } - - /** - * Creates a BitMatrix by sampling the provided image. - * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the - * diagonal just outside the bull's eye. - */ - private BitMatrix sampleGrid(BitMatrix image, - ResultPoint topLeft, - ResultPoint topRight, - ResultPoint bottomRight, - ResultPoint bottomLeft) throws NotFoundException { - - GridSampler sampler = GridSampler.getInstance(); - int dimension = getDimension(); - - float low = dimension / 2.0f - nbCenterLayers; - float high = dimension / 2.0f + nbCenterLayers; - - return sampler.sampleGrid(image, - dimension, - dimension, - low, low, // topleft - high, low, // topright - high, high, // bottomright - low, high, // bottomleft - topLeft.getX(), topLeft.getY(), - topRight.getX(), topRight.getY(), - bottomRight.getX(), bottomRight.getY(), - bottomLeft.getX(), bottomLeft.getY()); - } - - /** - * Samples a line. - * - * @param p1 start point (inclusive) - * @param p2 end point (exclusive) - * @param size number of bits - * @return the array of bits as an int (first bit is high-order bit of result) - */ - private int sampleLine(ResultPoint p1, ResultPoint p2, int size) { - int result = 0; - - float d = distance(p1, p2); - float moduleSize = d / size; - float px = p1.getX(); - float py = p1.getY(); - float dx = moduleSize * (p2.getX() - p1.getX()) / d; - float dy = moduleSize * (p2.getY() - p1.getY()) / d; - for (int i = 0; i < size; i++) { - if (image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) { - result |= 1 << (size - i - 1); - } - } - return result; - } - - /** - * @return true if the border of the rectangle passed in parameter is compound of white points only - * or black points only - */ - private boolean isWhiteOrBlackRectangle(Point p1, - Point p2, - Point p3, - Point p4) { - - int corr = 3; - - p1 = new Point(p1.getX() - corr, p1.getY() + corr); - p2 = new Point(p2.getX() - corr, p2.getY() - corr); - p3 = new Point(p3.getX() + corr, p3.getY() - corr); - p4 = new Point(p4.getX() + corr, p4.getY() + corr); - - int cInit = getColor(p4, p1); - - if (cInit == 0) { - return false; - } - - int c = getColor(p1, p2); - - if (c != cInit) { - return false; - } - - c = getColor(p2, p3); - - if (c != cInit) { - return false; - } - - c = getColor(p3, p4); - - return c == cInit; - - } - - /** - * Gets the color of a segment - * - * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else - */ - private int getColor(Point p1, Point p2) { - float d = distance(p1, p2); - float dx = (p2.getX() - p1.getX()) / d; - float dy = (p2.getY() - p1.getY()) / d; - int error = 0; - - float px = p1.getX(); - float py = p1.getY(); - - boolean colorModel = image.get(p1.getX(), p1.getY()); - - for (int i = 0; i < d; i++) { - px += dx; - py += dy; - if (image.get(MathUtils.round(px), MathUtils.round(py)) != colorModel) { - error++; - } - } - - float errRatio = error / d; - - if (errRatio > 0.1f && errRatio < 0.9f) { - return 0; - } - - return (errRatio <= 0.1f) == colorModel ? 1 : -1; - } - - /** - * Gets the coordinate of the first point with a different color in the given direction - */ - private Point getFirstDifferent(Point init, boolean color, int dx, int dy) { - int x = init.getX() + dx; - int y = init.getY() + dy; - - while (isValid(x, y) && image.get(x, y) == color) { - x += dx; - y += dy; - } - - x -= dx; - y -= dy; - - while (isValid(x, y) && image.get(x, y) == color) { - x += dx; - } - x -= dx; - - while (isValid(x, y) && image.get(x, y) == color) { - y += dy; - } - y -= dy; - - return new Point(x, y); - } - - /** - * Expand the square represented by the corner points by pushing out equally in all directions - * - * @param cornerPoints the corners of the square, which has the bull's eye at its center - * @param oldSide the original length of the side of the square in the target bit matrix - * @param newSide the new length of the size of the square in the target bit matrix - * @return the corners of the expanded square - */ - private static ResultPoint[] expandSquare(ResultPoint[] cornerPoints, float oldSide, float newSide) { - float ratio = newSide / (2 * oldSide); - float dx = cornerPoints[0].getX() - cornerPoints[2].getX(); - float dy = cornerPoints[0].getY() - cornerPoints[2].getY(); - float centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0f; - float centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0f; - - ResultPoint result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); - ResultPoint result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - dx = cornerPoints[1].getX() - cornerPoints[3].getX(); - dy = cornerPoints[1].getY() - cornerPoints[3].getY(); - centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0f; - centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0f; - ResultPoint result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); - ResultPoint result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - return new ResultPoint[]{result0, result1, result2, result3}; - } - - private boolean isValid(int x, int y) { - return x >= 0 && x < image.getWidth() && y > 0 && y < image.getHeight(); - } - - private boolean isValid(ResultPoint point) { - int x = MathUtils.round(point.getX()); - int y = MathUtils.round(point.getY()); - return isValid(x, y); - } - - private static float distance(Point a, Point b) { - return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); - } - - private static float distance(ResultPoint a, ResultPoint b) { - return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY()); - } - - private int getDimension() { - if (compact) { - return 4 * nbLayers + 11; - } - if (nbLayers <= 4) { - return 4 * nbLayers + 15; - } - return 4 * nbLayers + 2 * ((nbLayers - 4) / 8 + 1) + 15; - } - - static final class Point { - private final int x; - private final int y; - - ResultPoint toResultPoint() { - return new ResultPoint(getX(), getY()); - } - - Point(int x, int y) { - this.x = x; - this.y = y; - } - - int getX() { - return x; - } - - int getY() { - return y; - } - - @Override - public String toString() { - return "<" + x + ' ' + y + '>'; - } - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/AztecCode.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/AztecCode.java deleted file mode 100644 index e813b6bfa..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/AztecCode.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitMatrix; - -/** - * Aztec 2D code representation - * - * @author Rustam Abdullaev - */ -public final class AztecCode { - - private boolean compact; - private int size; - private int layers; - private int codeWords; - private BitMatrix matrix; - - /** - * @return {@code true} if compact instead of full mode - */ - public boolean isCompact() { - return compact; - } - - public void setCompact(boolean compact) { - this.compact = compact; - } - - /** - * @return size in pixels (width and height) - */ - public int getSize() { - return size; - } - - public void setSize(int size) { - this.size = size; - } - - /** - * @return number of levels - */ - public int getLayers() { - return layers; - } - - public void setLayers(int layers) { - this.layers = layers; - } - - /** - * @return number of data codewords - */ - public int getCodeWords() { - return codeWords; - } - - public void setCodeWords(int codeWords) { - this.codeWords = codeWords; - } - - /** - * @return the symbol image - */ - public BitMatrix getMatrix() { - return matrix; - } - - public void setMatrix(BitMatrix matrix) { - this.matrix = matrix; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/BinaryShiftToken.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/BinaryShiftToken.java deleted file mode 100644 index 637ba63a5..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/BinaryShiftToken.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitArray; - -final class BinaryShiftToken extends Token { - - private final short binaryShiftStart; - private final short binaryShiftByteCount; - - BinaryShiftToken(Token previous, - int binaryShiftStart, - int binaryShiftByteCount) { - super(previous); - this.binaryShiftStart = (short) binaryShiftStart; - this.binaryShiftByteCount = (short) binaryShiftByteCount; - } - - @Override - public void appendTo(BitArray bitArray, byte[] text) { - for (int i = 0; i < binaryShiftByteCount; i++) { - if (i == 0 || (i == 31 && binaryShiftByteCount <= 62)) { - // We need a header before the first character, and before - // character 31 when the total byte code is <= 62 - bitArray.appendBits(31, 5); // BINARY_SHIFT - if (binaryShiftByteCount > 62) { - bitArray.appendBits(binaryShiftByteCount - 31, 16); - } else if (i == 0) { - // 1 <= binaryShiftByteCode <= 62 - bitArray.appendBits(Math.min(binaryShiftByteCount, 31), 5); - } else { - // 32 <= binaryShiftCount <= 62 and i == 31 - bitArray.appendBits(binaryShiftByteCount - 31, 5); - } - } - bitArray.appendBits(text[binaryShiftStart + i], 8); - } - } - - @Override - public String toString() { - return "<" + binaryShiftStart + "::" + (binaryShiftStart + binaryShiftByteCount - 1) + '>'; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Encoder.java deleted file mode 100644 index 3a3655411..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Encoder.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitArray; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonEncoder; - -/** - * Generates Aztec 2D barcodes. - * - * @author Rustam Abdullaev - */ -public final class Encoder { - - public static final int DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words - public static final int DEFAULT_AZTEC_LAYERS = 0; - private static final int MAX_NB_BITS = 32; - private static final int MAX_NB_BITS_COMPACT = 4; - - private static final int[] WORD_SIZE = { - 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 - }; - - private Encoder() { - } - - /** - * Encodes the given binary content as an Aztec symbol - * - * @param data input data string - * @return Aztec symbol matrix with metadata - */ - public static AztecCode encode(byte[] data) { - return encode(data, DEFAULT_EC_PERCENT, DEFAULT_AZTEC_LAYERS); - } - - /** - * Encodes the given binary content as an Aztec symbol - * - * @param data input data string - * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008, - * a minimum of 23% + 3 words is recommended) - * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers - * @return Aztec symbol matrix with metadata - */ - public static AztecCode encode(byte[] data, int minECCPercent, int userSpecifiedLayers) { - // High-level encode - BitArray bits = new HighLevelEncoder(data).encode(); - - // stuff bits and choose symbol size - int eccBits = bits.getSize() * minECCPercent / 100 + 11; - int totalSizeBits = bits.getSize() + eccBits; - boolean compact; - int layers; - int totalBitsInLayer; - int wordSize; - BitArray stuffedBits; - if (userSpecifiedLayers != DEFAULT_AZTEC_LAYERS) { - compact = userSpecifiedLayers < 0; - layers = Math.abs(userSpecifiedLayers); - if (layers > (compact ? MAX_NB_BITS_COMPACT : MAX_NB_BITS)) { - throw new IllegalArgumentException( - String.format("Illegal value %s for layers", userSpecifiedLayers)); - } - totalBitsInLayer = totalBitsInLayer(layers, compact); - wordSize = WORD_SIZE[layers]; - int usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize); - stuffedBits = stuffBits(bits, wordSize); - if (stuffedBits.getSize() + eccBits > usableBitsInLayers) { - throw new IllegalArgumentException("Data to large for user specified layer"); - } - if (compact && stuffedBits.getSize() > wordSize * 64) { - // Compact format only allows 64 data words, though C4 can hold more words than that - throw new IllegalArgumentException("Data to large for user specified layer"); - } - } else { - wordSize = 0; - stuffedBits = null; - // We look at the possible table sizes in the order Compact1, Compact2, Compact3, - // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1) - // is the same size, but has more data. - for (int i = 0; ; i++) { - if (i > MAX_NB_BITS) { - throw new IllegalArgumentException("Data too large for an Aztec code"); - } - compact = i <= 3; - layers = compact ? i + 1 : i; - totalBitsInLayer = totalBitsInLayer(layers, compact); - if (totalSizeBits > totalBitsInLayer) { - continue; - } - // [Re]stuff the bits if this is the first opportunity, or if the - // wordSize has changed - if (wordSize != WORD_SIZE[layers]) { - wordSize = WORD_SIZE[layers]; - stuffedBits = stuffBits(bits, wordSize); - } - int usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize); - if (compact && stuffedBits.getSize() > wordSize * 64) { - // Compact format only allows 64 data words, though C4 can hold more words than that - continue; - } - if (stuffedBits.getSize() + eccBits <= usableBitsInLayers) { - break; - } - } - } - BitArray messageBits = generateCheckWords(stuffedBits, totalBitsInLayer, wordSize); - - // generate mode message - int messageSizeInWords = stuffedBits.getSize() / wordSize; - BitArray modeMessage = generateModeMessage(compact, layers, messageSizeInWords); - - // allocate symbol - int baseMatrixSize = compact ? 11 + layers * 4 : 14 + layers * 4; // not including alignment lines - int[] alignmentMap = new int[baseMatrixSize]; - int matrixSize; - if (compact) { - // no alignment marks in compact mode, alignmentMap is a no-op - matrixSize = baseMatrixSize; - for (int i = 0; i < alignmentMap.length; i++) { - alignmentMap[i] = i; - } - } else { - matrixSize = baseMatrixSize + 1 + 2 * ((baseMatrixSize / 2 - 1) / 15); - int origCenter = baseMatrixSize / 2; - int center = matrixSize / 2; - for (int i = 0; i < origCenter; i++) { - int newOffset = i + i / 15; - alignmentMap[origCenter - i - 1] = center - newOffset - 1; - alignmentMap[origCenter + i] = center + newOffset + 1; - } - } - BitMatrix matrix = new BitMatrix(matrixSize); - - // draw data bits - for (int i = 0, rowOffset = 0; i < layers; i++) { - int rowSize = compact ? (layers - i) * 4 + 9 : (layers - i) * 4 + 12; - for (int j = 0; j < rowSize; j++) { - int columnOffset = j * 2; - for (int k = 0; k < 2; k++) { - if (messageBits.get(rowOffset + columnOffset + k)) { - matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]); - } - if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) { - matrix.set(alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]); - } - if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) { - matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]); - } - if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) { - matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]); - } - } - } - rowOffset += rowSize * 8; - } - - // draw mode message - drawModeMessage(matrix, compact, matrixSize, modeMessage); - - // draw alignment marks - if (compact) { - drawBullsEye(matrix, matrixSize / 2, 5); - } else { - drawBullsEye(matrix, matrixSize / 2, 7); - for (int i = 0, j = 0; i < baseMatrixSize / 2 - 1; i += 15, j += 16) { - for (int k = (matrixSize / 2) & 1; k < matrixSize; k += 2) { - matrix.set(matrixSize / 2 - j, k); - matrix.set(matrixSize / 2 + j, k); - matrix.set(k, matrixSize / 2 - j); - matrix.set(k, matrixSize / 2 + j); - } - } - } - - AztecCode aztec = new AztecCode(); - aztec.setCompact(compact); - aztec.setSize(matrixSize); - aztec.setLayers(layers); - aztec.setCodeWords(messageSizeInWords); - aztec.setMatrix(matrix); - return aztec; - } - - private static void drawBullsEye(BitMatrix matrix, int center, int size) { - for (int i = 0; i < size; i += 2) { - for (int j = center - i; j <= center + i; j++) { - matrix.set(j, center - i); - matrix.set(j, center + i); - matrix.set(center - i, j); - matrix.set(center + i, j); - } - } - matrix.set(center - size, center - size); - matrix.set(center - size + 1, center - size); - matrix.set(center - size, center - size + 1); - matrix.set(center + size, center - size); - matrix.set(center + size, center - size + 1); - matrix.set(center + size, center + size - 1); - } - - static BitArray generateModeMessage(boolean compact, int layers, int messageSizeInWords) { - BitArray modeMessage = new BitArray(); - if (compact) { - modeMessage.appendBits(layers - 1, 2); - modeMessage.appendBits(messageSizeInWords - 1, 6); - modeMessage = generateCheckWords(modeMessage, 28, 4); - } else { - modeMessage.appendBits(layers - 1, 5); - modeMessage.appendBits(messageSizeInWords - 1, 11); - modeMessage = generateCheckWords(modeMessage, 40, 4); - } - return modeMessage; - } - - private static void drawModeMessage(BitMatrix matrix, boolean compact, int matrixSize, BitArray modeMessage) { - int center = matrixSize / 2; - if (compact) { - for (int i = 0; i < 7; i++) { - int offset = center - 3 + i; - if (modeMessage.get(i)) { - matrix.set(offset, center - 5); - } - if (modeMessage.get(i + 7)) { - matrix.set(center + 5, offset); - } - if (modeMessage.get(20 - i)) { - matrix.set(offset, center + 5); - } - if (modeMessage.get(27 - i)) { - matrix.set(center - 5, offset); - } - } - } else { - for (int i = 0; i < 10; i++) { - int offset = center - 5 + i + i / 5; - if (modeMessage.get(i)) { - matrix.set(offset, center - 7); - } - if (modeMessage.get(i + 10)) { - matrix.set(center + 7, offset); - } - if (modeMessage.get(29 - i)) { - matrix.set(offset, center + 7); - } - if (modeMessage.get(39 - i)) { - matrix.set(center - 7, offset); - } - } - } - } - - private static BitArray generateCheckWords(BitArray bitArray, int totalBits, int wordSize) { - // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed - int messageSizeInWords = bitArray.getSize() / wordSize; - ReedSolomonEncoder rs = new ReedSolomonEncoder(getGF(wordSize)); - int totalWords = totalBits / wordSize; - int[] messageWords = bitsToWords(bitArray, wordSize, totalWords); - rs.encode(messageWords, totalWords - messageSizeInWords); - int startPad = totalBits % wordSize; - BitArray messageBits = new BitArray(); - messageBits.appendBits(0, startPad); - for (int messageWord : messageWords) { - messageBits.appendBits(messageWord, wordSize); - } - return messageBits; - } - - private static int[] bitsToWords(BitArray stuffedBits, int wordSize, int totalWords) { - int[] message = new int[totalWords]; - int i; - int n; - for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) { - int value = 0; - for (int j = 0; j < wordSize; j++) { - value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0; - } - message[i] = value; - } - return message; - } - - private static GenericGF getGF(int wordSize) { - switch (wordSize) { - case 4: - return GenericGF.AZTEC_PARAM; - case 6: - return GenericGF.AZTEC_DATA_6; - case 8: - return GenericGF.AZTEC_DATA_8; - case 10: - return GenericGF.AZTEC_DATA_10; - case 12: - return GenericGF.AZTEC_DATA_12; - default: - throw new IllegalArgumentException("Unsupported word size " + wordSize); - } - } - - static BitArray stuffBits(BitArray bits, int wordSize) { - BitArray out = new BitArray(); - - int n = bits.getSize(); - int mask = (1 << wordSize) - 2; - for (int i = 0; i < n; i += wordSize) { - int word = 0; - for (int j = 0; j < wordSize; j++) { - if (i + j >= n || bits.get(i + j)) { - word |= 1 << (wordSize - 1 - j); - } - } - if ((word & mask) == mask) { - out.appendBits(word & mask, wordSize); - i--; - } else if ((word & mask) == 0) { - out.appendBits(word | 1, wordSize); - i--; - } else { - out.appendBits(word, wordSize); - } - } - return out; - } - - private static int totalBitsInLayer(int layers, boolean compact) { - return ((compact ? 88 : 112) + 16 * layers) * layers; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/HighLevelEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/HighLevelEncoder.java deleted file mode 100644 index bd867e31c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/HighLevelEncoder.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * This produces nearly optimal encodings of text into the first-level of - * encoding used by Aztec code. - * - * It uses a dynamic algorithm. For each prefix of the string, it determines - * a set of encodings that could lead to this prefix. We repeatedly add a - * character and generate a new set of optimal encodings until we have read - * through the entire input. - * - * @author Frank Yellin - * @author Rustam Abdullaev - */ -public final class HighLevelEncoder { - - static final String[] MODE_NAMES = {"UPPER", "LOWER", "DIGIT", "MIXED", "PUNCT"}; - - static final int MODE_UPPER = 0; // 5 bits - static final int MODE_LOWER = 1; // 5 bits - static final int MODE_DIGIT = 2; // 4 bits - static final int MODE_MIXED = 3; // 5 bits - static final int MODE_PUNCT = 4; // 5 bits - - // The Latch Table shows, for each pair of Modes, the optimal method for - // getting from one mode to another. In the worst possible case, this can - // be up to 14 bits. In the best possible case, we are already there! - // The high half-word of each entry gives the number of bits. - // The low half-word of each entry are the actual bits necessary to change - static final int[][] LATCH_TABLE = { - { - 0, - (5 << 16) + 28, // UPPER -> LOWER - (5 << 16) + 30, // UPPER -> DIGIT - (5 << 16) + 29, // UPPER -> MIXED - (10 << 16) + (29 << 5) + 30, // UPPER -> MIXED -> PUNCT - }, - { - (9 << 16) + (30 << 4) + 14, // LOWER -> DIGIT -> UPPER - 0, - (5 << 16) + 30, // LOWER -> DIGIT - (5 << 16) + 29, // LOWER -> MIXED - (10 << 16) + (29 << 5) + 30, // LOWER -> MIXED -> PUNCT - }, - { - (4 << 16) + 14, // DIGIT -> UPPER - (9 << 16) + (14 << 5) + 28, // DIGIT -> UPPER -> LOWER - 0, - (9 << 16) + (14 << 5) + 29, // DIGIT -> UPPER -> MIXED - (14 << 16) + (14 << 10) + (29 << 5) + 30, - // DIGIT -> UPPER -> MIXED -> PUNCT - }, - { - (5 << 16) + 29, // MIXED -> UPPER - (5 << 16) + 28, // MIXED -> LOWER - (10 << 16) + (29 << 5) + 30, // MIXED -> UPPER -> DIGIT - 0, - (5 << 16) + 30, // MIXED -> PUNCT - }, - { - (5 << 16) + 31, // PUNCT -> UPPER - (10 << 16) + (31 << 5) + 28, // PUNCT -> UPPER -> LOWER - (10 << 16) + (31 << 5) + 30, // PUNCT -> UPPER -> DIGIT - (10 << 16) + (31 << 5) + 29, // PUNCT -> UPPER -> MIXED - 0, - }, - }; - - // A reverse mapping from [mode][char] to the encoding for that character - // in that mode. An entry of 0 indicates no mapping exists. - private static final int[][] CHAR_MAP = new int[5][256]; - static { - CHAR_MAP[MODE_UPPER][' '] = 1; - for (int c = 'A'; c <= 'Z'; c++) { - CHAR_MAP[MODE_UPPER][c] = c - 'A' + 2; - } - CHAR_MAP[MODE_LOWER][' '] = 1; - for (int c = 'a'; c <= 'z'; c++) { - CHAR_MAP[MODE_LOWER][c] = c - 'a' + 2; - } - CHAR_MAP[MODE_DIGIT][' '] = 1; - for (int c = '0'; c <= '9'; c++) { - CHAR_MAP[MODE_DIGIT][c] = c - '0' + 2; - } - CHAR_MAP[MODE_DIGIT][','] = 12; - CHAR_MAP[MODE_DIGIT]['.'] = 13; - int[] mixedTable = { - '\0', ' ', '\1', '\2', '\3', '\4', '\5', '\6', '\7', '\b', '\t', '\n', - '\13', '\f', '\r', '\33', '\34', '\35', '\36', '\37', '@', '\\', '^', - '_', '`', '|', '~', '\177' - }; - for (int i = 0; i < mixedTable.length; i++) { - CHAR_MAP[MODE_MIXED][mixedTable[i]] = i; - } - int[] punctTable = { - '\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', - '[', ']', '{', '}' - }; - for (int i = 0; i < punctTable.length; i++) { - if (punctTable[i] > 0) { - CHAR_MAP[MODE_PUNCT][punctTable[i]] = i; - } - } - } - - // A map showing the available shift codes. (The shifts to BINARY are not - // shown - static final int[][] SHIFT_TABLE = new int[6][6]; // mode shift codes, per table - static { - for (int[] table : SHIFT_TABLE) { - Arrays.fill(table, -1); - } - SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0; - - SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0; - SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28; - - SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0; - - SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0; - SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15; - } - - private final byte[] text; - - public HighLevelEncoder(byte[] text) { - this.text = text; - } - - /** - * @return text represented by this encoder encoded as a {@link BitArray} - */ - public BitArray encode() { - Collection states = Collections.singletonList(State.INITIAL_STATE); - for (int index = 0; index < text.length; index++) { - int pairCode; - int nextChar = index + 1 < text.length ? text[index + 1] : 0; - switch (text[index]) { - case '\r': - pairCode = nextChar == '\n' ? 2 : 0; - break; - case '.' : - pairCode = nextChar == ' ' ? 3 : 0; - break; - case ',' : - pairCode = nextChar == ' ' ? 4 : 0; - break; - case ':' : - pairCode = nextChar == ' ' ? 5 : 0; - break; - default: - pairCode = 0; - } - if (pairCode > 0) { - // We have one of the four special PUNCT pairs. Treat them specially. - // Get a new set of states for the two new characters. - states = updateStateListForPair(states, index, pairCode); - index++; - } else { - // Get a new set of states for the new character. - states = updateStateListForChar(states, index); - } - } - // We are left with a set of states. Find the shortest one. - State minState = Collections.min(states, new Comparator() { - @Override - public int compare(State a, State b) { - return a.getBitCount() - b.getBitCount(); - } - }); - // Convert it to a bit array, and return. - return minState.toBitArray(text); - } - - // We update a set of states for a new character by updating each state - // for the new character, merging the results, and then removing the - // non-optimal states. - private Collection updateStateListForChar(Iterable states, int index) { - Collection result = new LinkedList<>(); - for (State state : states) { - updateStateForChar(state, index, result); - } - return simplifyStates(result); - } - - // Return a set of states that represent the possible ways of updating this - // state for the next character. The resulting set of states are added to - // the "result" list. - private void updateStateForChar(State state, int index, Collection result) { - char ch = (char) (text[index] & 0xFF); - boolean charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0; - State stateNoBinary = null; - for (int mode = 0; mode <= MODE_PUNCT; mode++) { - int charInMode = CHAR_MAP[mode][ch]; - if (charInMode > 0) { - if (stateNoBinary == null) { - // Only create stateNoBinary the first time it's required. - stateNoBinary = state.endBinaryShift(index); - } - // Try generating the character by latching to its mode - if (!charInCurrentTable || mode == state.getMode() || mode == MODE_DIGIT) { - // If the character is in the current table, we don't want to latch to - // any other mode except possibly digit (which uses only 4 bits). Any - // other latch would be equally successful *after* this character, and - // so wouldn't save any bits. - State latchState = stateNoBinary.latchAndAppend(mode, charInMode); - result.add(latchState); - } - // Try generating the character by switching to its mode. - if (!charInCurrentTable && SHIFT_TABLE[state.getMode()][mode] >= 0) { - // It never makes sense to temporarily shift to another mode if the - // character exists in the current mode. That can never save bits. - State shiftState = stateNoBinary.shiftAndAppend(mode, charInMode); - result.add(shiftState); - } - } - } - if (state.getBinaryShiftByteCount() > 0 || CHAR_MAP[state.getMode()][ch] == 0) { - // It's never worthwhile to go into binary shift mode if you're not already - // in binary shift mode, and the character exists in your current mode. - // That can never save bits over just outputting the char in the current mode. - State binaryState = state.addBinaryShiftChar(index); - result.add(binaryState); - } - } - - private static Collection updateStateListForPair(Iterable states, int index, int pairCode) { - Collection result = new LinkedList<>(); - for (State state : states) { - updateStateForPair(state, index, pairCode, result); - } - return simplifyStates(result); - } - - private static void updateStateForPair(State state, int index, int pairCode, Collection result) { - State stateNoBinary = state.endBinaryShift(index); - // Possibility 1. Latch to MODE_PUNCT, and then append this code - result.add(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode)); - if (state.getMode() != MODE_PUNCT) { - // Possibility 2. Shift to MODE_PUNCT, and then append this code. - // Every state except MODE_PUNCT (handled above) can shift - result.add(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode)); - } - if (pairCode == 3 || pairCode == 4) { - // both characters are in DIGITS. Sometimes better to just add two digits - State digitState = stateNoBinary - .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT - .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT - result.add(digitState); - } - if (state.getBinaryShiftByteCount() > 0) { - // It only makes sense to do the characters as binary if we're already - // in binary mode. - State binaryState = state.addBinaryShiftChar(index).addBinaryShiftChar(index + 1); - result.add(binaryState); - } - } - - private static Collection simplifyStates(Iterable states) { - List result = new LinkedList<>(); - for (State newState : states) { - boolean add = true; - for (Iterator iterator = result.iterator(); iterator.hasNext();) { - State oldState = iterator.next(); - if (oldState.isBetterThanOrEqualTo(newState)) { - add = false; - break; - } - if (newState.isBetterThanOrEqualTo(oldState)) { - iterator.remove(); - } - } - if (add) { - result.add(newState); - } - } - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/SimpleToken.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/SimpleToken.java deleted file mode 100644 index 047d962ad..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/SimpleToken.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitArray; - -final class SimpleToken extends Token { - - // For normal words, indicates value and bitCount - private final short value; - private final short bitCount; - - SimpleToken(Token previous, int value, int bitCount) { - super(previous); - this.value = (short) value; - this.bitCount = (short) bitCount; - } - - @Override - void appendTo(BitArray bitArray, byte[] text) { - bitArray.appendBits(value, bitCount); - } - - @Override - public String toString() { - int value = this.value & ((1 << bitCount) - 1); - value |= 1 << bitCount; - return '<' + Integer.toBinaryString(value | (1 << bitCount)).substring(1) + '>'; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/State.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/State.java deleted file mode 100644 index 927da63a9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/State.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import java.util.Deque; -import java.util.LinkedList; - -import com.google.zxing.common.BitArray; - -/** - * State represents all information about a sequence necessary to generate the current output. - * Note that a state is immutable. - */ -final class State { - - static final State INITIAL_STATE = new State(Token.EMPTY, HighLevelEncoder.MODE_UPPER, 0, 0); - - // The current mode of the encoding (or the mode to which we'll return if - // we're in Binary Shift mode. - private final int mode; - // The list of tokens that we output. If we are in Binary Shift mode, this - // token list does *not* yet included the token for those bytes - private final Token token; - // If non-zero, the number of most recent bytes that should be output - // in Binary Shift mode. - private final int binaryShiftByteCount; - // The total number of bits generated (including Binary Shift). - private final int bitCount; - - private State(Token token, int mode, int binaryBytes, int bitCount) { - this.token = token; - this.mode = mode; - this.binaryShiftByteCount = binaryBytes; - this.bitCount = bitCount; - // Make sure we match the token - //int binaryShiftBitCount = (binaryShiftByteCount * 8) + - // (binaryShiftByteCount == 0 ? 0 : - // binaryShiftByteCount <= 31 ? 10 : - // binaryShiftByteCount <= 62 ? 20 : 21); - //assert this.bitCount == token.getTotalBitCount() + binaryShiftBitCount; - } - - int getMode() { - return mode; - } - - Token getToken() { - return token; - } - - int getBinaryShiftByteCount() { - return binaryShiftByteCount; - } - - int getBitCount() { - return bitCount; - } - - // Create a new state representing this state with a latch to a (not - // necessary different) mode, and then a code. - State latchAndAppend(int mode, int value) { - //assert binaryShiftByteCount == 0; - int bitCount = this.bitCount; - Token token = this.token; - if (mode != this.mode) { - int latch = HighLevelEncoder.LATCH_TABLE[this.mode][mode]; - token = token.add(latch & 0xFFFF, latch >> 16); - bitCount += latch >> 16; - } - int latchModeBitCount = mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5; - token = token.add(value, latchModeBitCount); - return new State(token, mode, 0, bitCount + latchModeBitCount); - } - - // Create a new state representing this state, with a temporary shift - // to a different mode to output a single value. - State shiftAndAppend(int mode, int value) { - //assert binaryShiftByteCount == 0 && this.mode != mode; - Token token = this.token; - int thisModeBitCount = this.mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5; - // Shifts exist only to UPPER and PUNCT, both with tokens size 5. - token = token.add(HighLevelEncoder.SHIFT_TABLE[this.mode][mode], thisModeBitCount); - token = token.add(value, 5); - return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5); - } - - // Create a new state representing this state, but an additional character - // output in Binary Shift mode. - State addBinaryShiftChar(int index) { - Token token = this.token; - int mode = this.mode; - int bitCount = this.bitCount; - if (this.mode == HighLevelEncoder.MODE_PUNCT || this.mode == HighLevelEncoder.MODE_DIGIT) { - //assert binaryShiftByteCount == 0; - int latch = HighLevelEncoder.LATCH_TABLE[mode][HighLevelEncoder.MODE_UPPER]; - token = token.add(latch & 0xFFFF, latch >> 16); - bitCount += latch >> 16; - mode = HighLevelEncoder.MODE_UPPER; - } - int deltaBitCount = - (binaryShiftByteCount == 0 || binaryShiftByteCount == 31) ? 18 : - (binaryShiftByteCount == 62) ? 9 : 8; - State result = new State(token, mode, binaryShiftByteCount + 1, bitCount + deltaBitCount); - if (result.binaryShiftByteCount == 2047 + 31) { - // The string is as long as it's allowed to be. We should end it. - result = result.endBinaryShift(index + 1); - } - return result; - } - - // Create the state identical to this one, but we are no longer in - // Binary Shift mode. - State endBinaryShift(int index) { - if (binaryShiftByteCount == 0) { - return this; - } - Token token = this.token; - token = token.addBinaryShift(index - binaryShiftByteCount, binaryShiftByteCount); - //assert token.getTotalBitCount() == this.bitCount; - return new State(token, mode, 0, this.bitCount); - } - - // Returns true if "this" state is better (or equal) to be in than "that" - // state under all possible circumstances. - boolean isBetterThanOrEqualTo(State other) { - int mySize = this.bitCount + (HighLevelEncoder.LATCH_TABLE[this.mode][other.mode] >> 16); - if (other.binaryShiftByteCount > 0 && - (this.binaryShiftByteCount == 0 || this.binaryShiftByteCount > other.binaryShiftByteCount)) { - mySize += 10; // Cost of entering Binary Shift mode. - } - return mySize <= other.bitCount; - } - - BitArray toBitArray(byte[] text) { - // Reverse the tokens, so that they are in the order that they should - // be output - Deque symbols = new LinkedList<>(); - for (Token token = endBinaryShift(text.length).token; token != null; token = token.getPrevious()) { - symbols.addFirst(token); - } - BitArray bitArray = new BitArray(); - // Add each token to the result. - for (Token symbol : symbols) { - symbol.appendTo(bitArray, text); - } - //assert bitArray.getSize() == this.bitCount; - return bitArray; - } - - @Override - public String toString() { - return String.format("%s bits=%d bytes=%d", HighLevelEncoder.MODE_NAMES[mode], bitCount, binaryShiftByteCount); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Token.java b/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Token.java deleted file mode 100644 index 62d336e9c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/aztec/encoder/Token.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.aztec.encoder; - -import com.google.zxing.common.BitArray; - -abstract class Token { - - static final Token EMPTY = new SimpleToken(null, 0, 0); - - private final Token previous; - - Token(Token previous) { - this.previous = previous; - } - - final Token getPrevious() { - return previous; - } - - final Token add(int value, int bitCount) { - return new SimpleToken(this, value, bitCount); - } - - final Token addBinaryShift(int start, int byteCount) { - //int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21); - return new BinaryShiftToken(this, start, byteCount); - } - - abstract void appendTo(BitArray bitArray, byte[] text); - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AbstractDoCoMoResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/AbstractDoCoMoResultParser.java deleted file mode 100644 index 3d2c1d2a7..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AbstractDoCoMoResultParser.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - *

    See - * - * DoCoMo's documentation about the result types represented by subclasses of this class.

    - * - *

    Thanks to Jeff Griffin for proposing rewrite of these classes that relies less - * on exception-based mechanisms during parsing.

    - * - * @author Sean Owen - */ -abstract class AbstractDoCoMoResultParser extends ResultParser { - - static String[] matchDoCoMoPrefixedField(String prefix, String rawText, boolean trim) { - return matchPrefixedField(prefix, rawText, ';', trim); - } - - static String matchSingleDoCoMoPrefixedField(String prefix, String rawText, boolean trim) { - return matchSinglePrefixedField(prefix, rawText, ';', trim); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookAUResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookAUResultParser.java deleted file mode 100644 index cf7f96e87..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookAUResultParser.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.ArrayList; -import java.util.List; - -/** - * Implements KDDI AU's address book format. See - * - * http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html. - * (Thanks to Yuzo for translating!) - * - * @author Sean Owen - */ -public final class AddressBookAUResultParser extends ResultParser { - - @Override - public AddressBookParsedResult parse(Result result) { - String rawText = getMassagedText(result); - // MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF - if (!rawText.contains("MEMORY") || !rawText.contains("\r\n")) { - return null; - } - - // NAME1 and NAME2 have specific uses, namely written name and pronunciation, respectively. - // Therefore we treat them specially instead of as an array of names. - String name = matchSinglePrefixedField("NAME1:", rawText, '\r', true); - String pronunciation = matchSinglePrefixedField("NAME2:", rawText, '\r', true); - - String[] phoneNumbers = matchMultipleValuePrefix("TEL", 3, rawText, true); - String[] emails = matchMultipleValuePrefix("MAIL", 3, rawText, true); - String note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false); - String address = matchSinglePrefixedField("ADD:", rawText, '\r', true); - String[] addresses = address == null ? null : new String[] {address}; - return new AddressBookParsedResult(maybeWrap(name), - null, - pronunciation, - phoneNumbers, - null, - emails, - null, - null, - note, - addresses, - null, - null, - null, - null, - null, - null); - } - - private static String[] matchMultipleValuePrefix(String prefix, - int max, - String rawText, - boolean trim) { - List values = null; - for (int i = 1; i <= max; i++) { - String value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', trim); - if (value == null) { - break; - } - if (values == null) { - values = new ArrayList<>(max); // lazy init - } - values.add(value); - } - if (values == null) { - return null; - } - return values.toArray(new String[values.size()]); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookDoCoMoResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookDoCoMoResultParser.java deleted file mode 100644 index cb2e19b26..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookDoCoMoResultParser.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - * Implements the "MECARD" address book entry format. - * - * Supported keys: N, SOUND, TEL, EMAIL, NOTE, ADR, BDAY, URL, plus ORG - * Unsupported keys: TEL-AV, NICKNAME - * - * Except for TEL, multiple values for keys are also not supported; - * the first one found takes precedence. - * - * Our understanding of the MECARD format is based on this document: - * - * http://www.mobicode.org.tw/files/OMIA%20Mobile%20Bar%20Code%20Standard%20v3.2.1.doc - * - * @author Sean Owen - */ -public final class AddressBookDoCoMoResultParser extends AbstractDoCoMoResultParser { - - @Override - public AddressBookParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("MECARD:")) { - return null; - } - String[] rawName = matchDoCoMoPrefixedField("N:", rawText, true); - if (rawName == null) { - return null; - } - String name = parseName(rawName[0]); - String pronunciation = matchSingleDoCoMoPrefixedField("SOUND:", rawText, true); - String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText, true); - String[] emails = matchDoCoMoPrefixedField("EMAIL:", rawText, true); - String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false); - String[] addresses = matchDoCoMoPrefixedField("ADR:", rawText, true); - String birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText, true); - if (!isStringOfDigits(birthday, 8)) { - // No reason to throw out the whole card because the birthday is formatted wrong. - birthday = null; - } - String[] urls = matchDoCoMoPrefixedField("URL:", rawText, true); - - // Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well - // honor it when found in the wild. - String org = matchSingleDoCoMoPrefixedField("ORG:", rawText, true); - - return new AddressBookParsedResult(maybeWrap(name), - null, - pronunciation, - phoneNumbers, - null, - emails, - null, - null, - note, - addresses, - null, - org, - birthday, - null, - urls, - null); - } - - private static String parseName(String name) { - int comma = name.indexOf((int) ','); - if (comma >= 0) { - // Format may be last,first; switch it around - return name.substring(comma + 1) + ' ' + name.substring(0, comma); - } - return name; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookParsedResult.java deleted file mode 100644 index 291ebfccf..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/AddressBookParsedResult.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Sean Owen - */ -public final class AddressBookParsedResult extends ParsedResult { - - private final String[] names; - private final String[] nicknames; - private final String pronunciation; - private final String[] phoneNumbers; - private final String[] phoneTypes; - private final String[] emails; - private final String[] emailTypes; - private final String instantMessenger; - private final String note; - private final String[] addresses; - private final String[] addressTypes; - private final String org; - private final String birthday; - private final String title; - private final String[] urls; - private final String[] geo; - - public AddressBookParsedResult(String[] names, - String[] phoneNumbers, - String[] phoneTypes, - String[] emails, - String[] emailTypes, - String[] addresses, - String[] addressTypes) { - this(names, - null, - null, - phoneNumbers, - phoneTypes, - emails, - emailTypes, - null, - null, - addresses, - addressTypes, - null, - null, - null, - null, - null); - } - - public AddressBookParsedResult(String[] names, - String[] nicknames, - String pronunciation, - String[] phoneNumbers, - String[] phoneTypes, - String[] emails, - String[] emailTypes, - String instantMessenger, - String note, - String[] addresses, - String[] addressTypes, - String org, - String birthday, - String title, - String[] urls, - String[] geo) { - super(ParsedResultType.ADDRESSBOOK); - this.names = names; - this.nicknames = nicknames; - this.pronunciation = pronunciation; - this.phoneNumbers = phoneNumbers; - this.phoneTypes = phoneTypes; - this.emails = emails; - this.emailTypes = emailTypes; - this.instantMessenger = instantMessenger; - this.note = note; - this.addresses = addresses; - this.addressTypes = addressTypes; - this.org = org; - this.birthday = birthday; - this.title = title; - this.urls = urls; - this.geo = geo; - } - - public String[] getNames() { - return names; - } - - public String[] getNicknames() { - return nicknames; - } - - /** - * In Japanese, the name is written in kanji, which can have multiple readings. Therefore a hint - * is often provided, called furigana, which spells the name phonetically. - * - * @return The pronunciation of the getNames() field, often in hiragana or katakana. - */ - public String getPronunciation() { - return pronunciation; - } - - public String[] getPhoneNumbers() { - return phoneNumbers; - } - - /** - * @return optional descriptions of the type of each phone number. It could be like "HOME", but, - * there is no guaranteed or standard format. - */ - public String[] getPhoneTypes() { - return phoneTypes; - } - - public String[] getEmails() { - return emails; - } - - /** - * @return optional descriptions of the type of each e-mail. It could be like "WORK", but, - * there is no guaranteed or standard format. - */ - public String[] getEmailTypes() { - return emailTypes; - } - - public String getInstantMessenger() { - return instantMessenger; - } - - public String getNote() { - return note; - } - - public String[] getAddresses() { - return addresses; - } - - /** - * @return optional descriptions of the type of each e-mail. It could be like "WORK", but, - * there is no guaranteed or standard format. - */ - public String[] getAddressTypes() { - return addressTypes; - } - - public String getTitle() { - return title; - } - - public String getOrg() { - return org; - } - - public String[] getURLs() { - return urls; - } - - /** - * @return birthday formatted as yyyyMMdd (e.g. 19780917) - */ - public String getBirthday() { - return birthday; - } - - /** - * @return a location as a latitude/longitude pair - */ - public String[] getGeo() { - return geo; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(100); - maybeAppend(names, result); - maybeAppend(nicknames, result); - maybeAppend(pronunciation, result); - maybeAppend(title, result); - maybeAppend(org, result); - maybeAppend(addresses, result); - maybeAppend(phoneNumbers, result); - maybeAppend(emails, result); - maybeAppend(instantMessenger, result); - maybeAppend(urls, result); - maybeAppend(birthday, result); - maybeAppend(geo, result); - maybeAppend(note, result); - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/BizcardResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/BizcardResultParser.java deleted file mode 100644 index 1d588d4c2..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/BizcardResultParser.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.ArrayList; -import java.util.List; - -/** - * Implements the "BIZCARD" address book entry format, though this has been - * largely reverse-engineered from examples observed in the wild -- still - * looking for a definitive reference. - * - * @author Sean Owen - */ -public final class BizcardResultParser extends AbstractDoCoMoResultParser { - - // Yes, we extend AbstractDoCoMoResultParser since the format is very much - // like the DoCoMo MECARD format, but this is not technically one of - // DoCoMo's proposed formats - - @Override - public AddressBookParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("BIZCARD:")) { - return null; - } - String firstName = matchSingleDoCoMoPrefixedField("N:", rawText, true); - String lastName = matchSingleDoCoMoPrefixedField("X:", rawText, true); - String fullName = buildName(firstName, lastName); - String title = matchSingleDoCoMoPrefixedField("T:", rawText, true); - String org = matchSingleDoCoMoPrefixedField("C:", rawText, true); - String[] addresses = matchDoCoMoPrefixedField("A:", rawText, true); - String phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText, true); - String phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText, true); - String phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText, true); - String email = matchSingleDoCoMoPrefixedField("E:", rawText, true); - - return new AddressBookParsedResult(maybeWrap(fullName), - null, - null, - buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3), - null, - maybeWrap(email), - null, - null, - null, - addresses, - null, - org, - null, - title, - null, - null); - } - - private static String[] buildPhoneNumbers(String number1, - String number2, - String number3) { - List numbers = new ArrayList<>(3); - if (number1 != null) { - numbers.add(number1); - } - if (number2 != null) { - numbers.add(number2); - } - if (number3 != null) { - numbers.add(number3); - } - int size = numbers.size(); - if (size == 0) { - return null; - } - return numbers.toArray(new String[size]); - } - - private static String buildName(String firstName, String lastName) { - if (firstName == null) { - return lastName; - } else { - return lastName == null ? firstName : firstName + ' ' + lastName; - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/BookmarkDoCoMoResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/BookmarkDoCoMoResultParser.java deleted file mode 100644 index a729239d8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/BookmarkDoCoMoResultParser.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - * @author Sean Owen - */ -public final class BookmarkDoCoMoResultParser extends AbstractDoCoMoResultParser { - - @Override - public URIParsedResult parse(Result result) { - String rawText = result.getText(); - if (!rawText.startsWith("MEBKM:")) { - return null; - } - String title = matchSingleDoCoMoPrefixedField("TITLE:", rawText, true); - String[] rawUri = matchDoCoMoPrefixedField("URL:", rawText, true); - if (rawUri == null) { - return null; - } - String uri = rawUri[0]; - return URIResultParser.isBasicallyValidURI(uri) ? new URIParsedResult(uri, title) : null; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/CalendarParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/CalendarParsedResult.java deleted file mode 100644 index 48b92a6bc..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/CalendarParsedResult.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Locale; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Sean Owen - */ -public final class CalendarParsedResult extends ParsedResult { - - private static final Pattern RFC2445_DURATION = - Pattern.compile("P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?"); - private static final long[] RFC2445_DURATION_FIELD_UNITS = { - 7 * 24 * 60 * 60 * 1000L, // 1 week - 24 * 60 * 60 * 1000L, // 1 day - 60 * 60 * 1000L, // 1 hour - 60 * 1000L, // 1 minute - 1000L, // 1 second - }; - - private static final Pattern DATE_TIME = Pattern.compile("[0-9]{8}(T[0-9]{6}Z?)?"); - - private final String summary; - private final Date start; - private final boolean startAllDay; - private final Date end; - private final boolean endAllDay; - private final String location; - private final String organizer; - private final String[] attendees; - private final String description; - private final double latitude; - private final double longitude; - - public CalendarParsedResult(String summary, - String startString, - String endString, - String durationString, - String location, - String organizer, - String[] attendees, - String description, - double latitude, - double longitude) { - super(ParsedResultType.CALENDAR); - this.summary = summary; - - try { - this.start = parseDate(startString); - } catch (ParseException pe) { - throw new IllegalArgumentException(pe.toString()); - } - - if (endString == null) { - long durationMS = parseDurationMS(durationString); - end = durationMS < 0L ? null : new Date(start.getTime() + durationMS); - } else { - try { - this.end = parseDate(endString); - } catch (ParseException pe) { - throw new IllegalArgumentException(pe.toString()); - } - } - - this.startAllDay = startString.length() == 8; - this.endAllDay = endString != null && endString.length() == 8; - - this.location = location; - this.organizer = organizer; - this.attendees = attendees; - this.description = description; - this.latitude = latitude; - this.longitude = longitude; - } - - public String getSummary() { - return summary; - } - - /** - * @return start time - */ - public Date getStart() { - return start; - } - - /** - * @return true if start time was specified as a whole day - */ - public boolean isStartAllDay() { - return startAllDay; - } - - /** - * @return event end {@link Date}, or {@code null} if event has no duration - * @see #getStart() - */ - public Date getEnd() { - return end; - } - - /** - * @return true if end time was specified as a whole day - */ - public boolean isEndAllDay() { - return endAllDay; - } - - public String getLocation() { - return location; - } - - public String getOrganizer() { - return organizer; - } - - public String[] getAttendees() { - return attendees; - } - - public String getDescription() { - return description; - } - - public double getLatitude() { - return latitude; - } - - public double getLongitude() { - return longitude; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(100); - maybeAppend(summary, result); - maybeAppend(format(startAllDay, start), result); - maybeAppend(format(endAllDay, end), result); - maybeAppend(location, result); - maybeAppend(organizer, result); - maybeAppend(attendees, result); - maybeAppend(description, result); - return result.toString(); - } - - /** - * Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021) - * or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC). - * - * @param when The string to parse - * @throws ParseException if not able to parse as a date - */ - private static Date parseDate(String when) throws ParseException { - if (!DATE_TIME.matcher(when).matches()) { - throw new ParseException(when, 0); - } - if (when.length() == 8) { - // Show only year/month/day - return buildDateFormat().parse(when); - } else { - // The when string can be local time, or UTC if it ends with a Z - Date date; - if (when.length() == 16 && when.charAt(15) == 'Z') { - date = buildDateTimeFormat().parse(when.substring(0, 15)); - Calendar calendar = new GregorianCalendar(); - long milliseconds = date.getTime(); - // Account for time zone difference - milliseconds += calendar.get(Calendar.ZONE_OFFSET); - // Might need to correct for daylight savings time, but use target time since - // now might be in DST but not then, or vice versa - calendar.setTime(new Date(milliseconds)); - milliseconds += calendar.get(Calendar.DST_OFFSET); - date = new Date(milliseconds); - } else { - date = buildDateTimeFormat().parse(when); - } - return date; - } - } - - private static String format(boolean allDay, Date date) { - if (date == null) { - return null; - } - DateFormat format = allDay - ? DateFormat.getDateInstance(DateFormat.MEDIUM) - : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); - return format.format(date); - } - - private static long parseDurationMS(CharSequence durationString) { - if (durationString == null) { - return -1L; - } - Matcher m = RFC2445_DURATION.matcher(durationString); - if (!m.matches()) { - return -1L; - } - long durationMS = 0L; - for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) { - String fieldValue = m.group(i + 1); - if (fieldValue != null) { - durationMS += RFC2445_DURATION_FIELD_UNITS[i] * Integer.parseInt(fieldValue); - } - } - return durationMS; - } - - private static DateFormat buildDateFormat() { - DateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); - // For dates without a time, for purposes of interacting with Android, the resulting timestamp - // needs to be midnight of that day in GMT. See: - // http://code.google.com/p/android/issues/detail?id=8330 - format.setTimeZone(TimeZone.getTimeZone("GMT")); - return format; - } - - private static DateFormat buildDateTimeFormat() { - return new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ENGLISH); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressParsedResult.java deleted file mode 100644 index 06c4075a4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressParsedResult.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Sean Owen - */ -public final class EmailAddressParsedResult extends ParsedResult { - - private final String[] tos; - private final String[] ccs; - private final String[] bccs; - private final String subject; - private final String body; - - EmailAddressParsedResult(String to) { - this(new String[] {to}, null, null, null, null); - } - - EmailAddressParsedResult(String[] tos, - String[] ccs, - String[] bccs, - String subject, - String body) { - super(ParsedResultType.EMAIL_ADDRESS); - this.tos = tos; - this.ccs = ccs; - this.bccs = bccs; - this.subject = subject; - this.body = body; - } - - /** - * @return first elements of {@link #getTos()} or {@code null} if none - * @deprecated use {@link #getTos()} - */ - @Deprecated - public String getEmailAddress() { - return tos == null || tos.length == 0 ? null : tos[0]; - } - - public String[] getTos() { - return tos; - } - - public String[] getCCs() { - return ccs; - } - - public String[] getBCCs() { - return bccs; - } - - public String getSubject() { - return subject; - } - - public String getBody() { - return body; - } - - /** - * @return "mailto:" - * @deprecated without replacement - */ - @Deprecated - public String getMailtoURI() { - return "mailto:"; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(30); - maybeAppend(tos, result); - maybeAppend(ccs, result); - maybeAppend(bccs, result); - maybeAppend(subject, result); - maybeAppend(body, result); - return result.toString(); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressResultParser.java deleted file mode 100644 index d66adf1dd..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailAddressResultParser.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Represents a result that encodes an e-mail address, either as a plain address - * like "joe@example.org" or a mailto: URL like "mailto:joe@example.org". - * - * @author Sean Owen - */ -public final class EmailAddressResultParser extends ResultParser { - - private static final Pattern COMMA = Pattern.compile(","); - - @Override - public EmailAddressParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (rawText.startsWith("mailto:") || rawText.startsWith("MAILTO:")) { - // If it starts with mailto:, assume it is definitely trying to be an email address - String hostEmail = rawText.substring(7); - int queryStart = hostEmail.indexOf('?'); - if (queryStart >= 0) { - hostEmail = hostEmail.substring(0, queryStart); - } - hostEmail = urlDecode(hostEmail); - String[] tos = null; - if (!hostEmail.isEmpty()) { - tos = COMMA.split(hostEmail); - } - Map nameValues = parseNameValuePairs(rawText); - String[] ccs = null; - String[] bccs = null; - String subject = null; - String body = null; - if (nameValues != null) { - if (tos == null) { - String tosString = nameValues.get("to"); - if (tosString != null) { - tos = COMMA.split(tosString); - } - } - String ccString = nameValues.get("cc"); - if (ccString != null) { - ccs = COMMA.split(ccString); - } - String bccString = nameValues.get("bcc"); - if (bccString != null) { - bccs = COMMA.split(bccString); - } - subject = nameValues.get("subject"); - body = nameValues.get("body"); - } - return new EmailAddressParsedResult(tos, ccs, bccs, subject, body); - } else { - if (!EmailDoCoMoResultParser.isBasicallyValidEmailAddress(rawText)) { - return null; - } - return new EmailAddressParsedResult(rawText); - } - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailDoCoMoResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailDoCoMoResultParser.java deleted file mode 100644 index fc4c28485..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/EmailDoCoMoResultParser.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.regex.Pattern; - -/** - * Implements the "MATMSG" email message entry format. - * - * Supported keys: TO, SUB, BODY - * - * @author Sean Owen - */ -public final class EmailDoCoMoResultParser extends AbstractDoCoMoResultParser { - - private static final Pattern ATEXT_ALPHANUMERIC = Pattern.compile("[a-zA-Z0-9@.!#$%&'*+\\-/=?^_`{|}~]+"); - - @Override - public EmailAddressParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("MATMSG:")) { - return null; - } - String[] tos = matchDoCoMoPrefixedField("TO:", rawText, true); - if (tos == null) { - return null; - } - for (String to : tos) { - if (!isBasicallyValidEmailAddress(to)) { - return null; - } - } - String subject = matchSingleDoCoMoPrefixedField("SUB:", rawText, false); - String body = matchSingleDoCoMoPrefixedField("BODY:", rawText, false); - return new EmailAddressParsedResult(tos, null, null, subject, body); - } - - /** - * This implements only the most basic checking for an email address's validity -- that it contains - * an '@' and contains no characters disallowed by RFC 2822. This is an overly lenient definition of - * validity. We want to generally be lenient here since this class is only intended to encapsulate what's - * in a barcode, not "judge" it. - */ - static boolean isBasicallyValidEmailAddress(String email) { - return email != null && ATEXT_ALPHANUMERIC.matcher(email).matches() && email.indexOf('@') >= 0; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductParsedResult.java deleted file mode 100644 index 6053100d4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductParsedResult.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.client.result; - -import java.util.Map; - -/** - * @author Antonio Manuel Benjumea Conde, Servinform, S.A. - * @author Agustín Delgado, Servinform, S.A. - */ -public final class ExpandedProductParsedResult extends ParsedResult { - - public static final String KILOGRAM = "KG"; - public static final String POUND = "LB"; - - private final String rawText; - private final String productID; - private final String sscc; - private final String lotNumber; - private final String productionDate; - private final String packagingDate; - private final String bestBeforeDate; - private final String expirationDate; - private final String weight; - private final String weightType; - private final String weightIncrement; - private final String price; - private final String priceIncrement; - private final String priceCurrency; - // For AIS that not exist in this object - private final Map uncommonAIs; - - public ExpandedProductParsedResult(String rawText, - String productID, - String sscc, - String lotNumber, - String productionDate, - String packagingDate, - String bestBeforeDate, - String expirationDate, - String weight, - String weightType, - String weightIncrement, - String price, - String priceIncrement, - String priceCurrency, - Map uncommonAIs) { - super(ParsedResultType.PRODUCT); - this.rawText = rawText; - this.productID = productID; - this.sscc = sscc; - this.lotNumber = lotNumber; - this.productionDate = productionDate; - this.packagingDate = packagingDate; - this.bestBeforeDate = bestBeforeDate; - this.expirationDate = expirationDate; - this.weight = weight; - this.weightType = weightType; - this.weightIncrement = weightIncrement; - this.price = price; - this.priceIncrement = priceIncrement; - this.priceCurrency = priceCurrency; - this.uncommonAIs = uncommonAIs; - } - - @Override - public boolean equals(Object o){ - if (!(o instanceof ExpandedProductParsedResult)) { - return false; - } - - ExpandedProductParsedResult other = (ExpandedProductParsedResult)o; - - return equalsOrNull(productID, other.productID) - && equalsOrNull(sscc, other.sscc) - && equalsOrNull(lotNumber, other.lotNumber) - && equalsOrNull(productionDate, other.productionDate) - && equalsOrNull(bestBeforeDate, other.bestBeforeDate) - && equalsOrNull(expirationDate, other.expirationDate) - && equalsOrNull(weight, other.weight) - && equalsOrNull(weightType, other.weightType) - && equalsOrNull(weightIncrement, other.weightIncrement) - && equalsOrNull(price, other.price) - && equalsOrNull(priceIncrement, other.priceIncrement) - && equalsOrNull(priceCurrency, other.priceCurrency) - && equalsOrNull(uncommonAIs, other.uncommonAIs); - } - - private static boolean equalsOrNull(Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals(o2); - } - - @Override - public int hashCode(){ - int hash = 0; - hash ^= hashNotNull(productID); - hash ^= hashNotNull(sscc); - hash ^= hashNotNull(lotNumber); - hash ^= hashNotNull(productionDate); - hash ^= hashNotNull(bestBeforeDate); - hash ^= hashNotNull(expirationDate); - hash ^= hashNotNull(weight); - hash ^= hashNotNull(weightType); - hash ^= hashNotNull(weightIncrement); - hash ^= hashNotNull(price); - hash ^= hashNotNull(priceIncrement); - hash ^= hashNotNull(priceCurrency); - hash ^= hashNotNull(uncommonAIs); - return hash; - } - - private static int hashNotNull(Object o) { - return o == null ? 0 : o.hashCode(); - } - - public String getRawText() { - return rawText; - } - - public String getProductID() { - return productID; - } - - public String getSscc() { - return sscc; - } - - public String getLotNumber() { - return lotNumber; - } - - public String getProductionDate() { - return productionDate; - } - - public String getPackagingDate() { - return packagingDate; - } - - public String getBestBeforeDate() { - return bestBeforeDate; - } - - public String getExpirationDate() { - return expirationDate; - } - - public String getWeight() { - return weight; - } - - public String getWeightType() { - return weightType; - } - - public String getWeightIncrement() { - return weightIncrement; - } - - public String getPrice() { - return price; - } - - public String getPriceIncrement() { - return priceIncrement; - } - - public String getPriceCurrency() { - return priceCurrency; - } - - public Map getUncommonAIs() { - return uncommonAIs; - } - - @Override - public String getDisplayResult() { - return String.valueOf(rawText); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductResultParser.java deleted file mode 100644 index a64aec275..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ExpandedProductResultParser.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.client.result; - -import java.util.HashMap; -import java.util.Map; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; - -/** - * Parses strings of digits that represent a RSS Extended code. - * - * @author Antonio Manuel Benjumea Conde, Servinform, S.A. - * @author Agustín Delgado, Servinform, S.A. - */ -public final class ExpandedProductResultParser extends ResultParser { - - @Override - public ExpandedProductParsedResult parse(Result result) { - BarcodeFormat format = result.getBarcodeFormat(); - if (format != BarcodeFormat.RSS_EXPANDED) { - // ExtendedProductParsedResult NOT created. Not a RSS Expanded barcode - return null; - } - String rawText = getMassagedText(result); - - String productID = null; - String sscc = null; - String lotNumber = null; - String productionDate = null; - String packagingDate = null; - String bestBeforeDate = null; - String expirationDate = null; - String weight = null; - String weightType = null; - String weightIncrement = null; - String price = null; - String priceIncrement = null; - String priceCurrency = null; - Map uncommonAIs = new HashMap<>(); - - int i = 0; - - while (i < rawText.length()) { - String ai = findAIvalue(i, rawText); - if (ai == null) { - // Error. Code doesn't match with RSS expanded pattern - // ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern - return null; - } - i += ai.length() + 2; - String value = findValue(i, rawText); - i += value.length(); - - switch (ai) { - case "00": - sscc = value; - break; - case "01": - productID = value; - break; - case "10": - lotNumber = value; - break; - case "11": - productionDate = value; - break; - case "13": - packagingDate = value; - break; - case "15": - bestBeforeDate = value; - break; - case "17": - expirationDate = value; - break; - case "3100": - case "3101": - case "3102": - case "3103": - case "3104": - case "3105": - case "3106": - case "3107": - case "3108": - case "3109": - weight = value; - weightType = ExpandedProductParsedResult.KILOGRAM; - weightIncrement = ai.substring(3); - break; - case "3200": - case "3201": - case "3202": - case "3203": - case "3204": - case "3205": - case "3206": - case "3207": - case "3208": - case "3209": - weight = value; - weightType = ExpandedProductParsedResult.POUND; - weightIncrement = ai.substring(3); - break; - case "3920": - case "3921": - case "3922": - case "3923": - price = value; - priceIncrement = ai.substring(3); - break; - case "3930": - case "3931": - case "3932": - case "3933": - if (value.length() < 4) { - // The value must have more of 3 symbols (3 for currency and - // 1 at least for the price) - // ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern - return null; - } - price = value.substring(3); - priceCurrency = value.substring(0, 3); - priceIncrement = ai.substring(3); - break; - default: - // No match with common AIs - uncommonAIs.put(ai, value); - break; - } - } - - return new ExpandedProductParsedResult(rawText, - productID, - sscc, - lotNumber, - productionDate, - packagingDate, - bestBeforeDate, - expirationDate, - weight, - weightType, - weightIncrement, - price, - priceIncrement, - priceCurrency, - uncommonAIs); - } - - private static String findAIvalue(int i, String rawText) { - char c = rawText.charAt(i); - // First character must be a open parenthesis.If not, ERROR - if (c != '(') { - return null; - } - - CharSequence rawTextAux = rawText.substring(i + 1); - - StringBuilder buf = new StringBuilder(); - for (int index = 0; index < rawTextAux.length(); index++) { - char currentChar = rawTextAux.charAt(index); - if (currentChar == ')') { - return buf.toString(); - } else if (currentChar >= '0' && currentChar <= '9') { - buf.append(currentChar); - } else { - return null; - } - } - return buf.toString(); - } - - private static String findValue(int i, String rawText) { - StringBuilder buf = new StringBuilder(); - String rawTextAux = rawText.substring(i); - - for (int index = 0; index < rawTextAux.length(); index++) { - char c = rawTextAux.charAt(index); - if (c == '(') { - // We look for a new AI. If it doesn't exist (ERROR), we coninue - // with the iteration - if (findAIvalue(index, rawTextAux) == null) { - buf.append('('); - } else { - break; - } - } else { - buf.append(c); - } - } - return buf.toString(); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoParsedResult.java deleted file mode 100644 index 6eaad1ebb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoParsedResult.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Sean Owen - */ -public final class GeoParsedResult extends ParsedResult { - - private final double latitude; - private final double longitude; - private final double altitude; - private final String query; - - GeoParsedResult(double latitude, double longitude, double altitude, String query) { - super(ParsedResultType.GEO); - this.latitude = latitude; - this.longitude = longitude; - this.altitude = altitude; - this.query = query; - } - - public String getGeoURI() { - StringBuilder result = new StringBuilder(); - result.append("geo:"); - result.append(latitude); - result.append(','); - result.append(longitude); - if (altitude > 0) { - result.append(','); - result.append(altitude); - } - if (query != null) { - result.append('?'); - result.append(query); - } - return result.toString(); - } - - /** - * @return latitude in degrees - */ - public double getLatitude() { - return latitude; - } - - /** - * @return longitude in degrees - */ - public double getLongitude() { - return longitude; - } - - /** - * @return altitude in meters. If not specified, in the geo URI, returns 0.0 - */ - public double getAltitude() { - return altitude; - } - - /** - * @return query string associated with geo URI or null if none exists - */ - public String getQuery() { - return query; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(20); - result.append(latitude); - result.append(", "); - result.append(longitude); - if (altitude > 0.0) { - result.append(", "); - result.append(altitude); - result.append('m'); - } - if (query != null) { - result.append(" ("); - result.append(query); - result.append(')'); - } - return result.toString(); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoResultParser.java deleted file mode 100644 index fb9cb07d4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/GeoResultParser.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Parses a "geo:" URI result, which specifies a location on the surface of - * the Earth as well as an optional altitude above the surface. See - * - * http://tools.ietf.org/html/draft-mayrhofer-geo-uri-00. - * - * @author Sean Owen - */ -public final class GeoResultParser extends ResultParser { - - private static final Pattern GEO_URL_PATTERN = - Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE); - - @Override - public GeoParsedResult parse(Result result) { - CharSequence rawText = getMassagedText(result); - Matcher matcher = GEO_URL_PATTERN.matcher(rawText); - if (!matcher.matches()) { - return null; - } - - String query = matcher.group(4); - - double latitude; - double longitude; - double altitude; - try { - latitude = Double.parseDouble(matcher.group(1)); - if (latitude > 90.0 || latitude < -90.0) { - return null; - } - longitude = Double.parseDouble(matcher.group(2)); - if (longitude > 180.0 || longitude < -180.0) { - return null; - } - if (matcher.group(3) == null) { - altitude = 0.0; - } else { - altitude = Double.parseDouble(matcher.group(3)); - if (altitude < 0.0) { - return null; - } - } - } catch (NumberFormatException ignored) { - return null; - } - return new GeoParsedResult(latitude, longitude, altitude, query); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNParsedResult.java deleted file mode 100644 index 51b63ff82..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNParsedResult.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author jbreiden@google.com (Jeff Breidenbach) - */ -public final class ISBNParsedResult extends ParsedResult { - - private final String isbn; - - ISBNParsedResult(String isbn) { - super(ParsedResultType.ISBN); - this.isbn = isbn; - } - - public String getISBN() { - return isbn; - } - - @Override - public String getDisplayResult() { - return isbn; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNResultParser.java deleted file mode 100644 index e957dd02b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ISBNResultParser.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; - -/** - * Parses strings of digits that represent a ISBN. - * - * @author jbreiden@google.com (Jeff Breidenbach) - */ -public final class ISBNResultParser extends ResultParser { - - /** - * See ISBN-13 For Dummies - */ - @Override - public ISBNParsedResult parse(Result result) { - BarcodeFormat format = result.getBarcodeFormat(); - if (format != BarcodeFormat.EAN_13) { - return null; - } - String rawText = getMassagedText(result); - int length = rawText.length(); - if (length != 13) { - return null; - } - if (!rawText.startsWith("978") && !rawText.startsWith("979")) { - return null; - } - - return new ISBNParsedResult(rawText); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResult.java deleted file mode 100644 index 17660e2e6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResult.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - *

    Abstract class representing the result of decoding a barcode, as more than - * a String -- as some type of structured data. This might be a subclass which represents - * a URL, or an e-mail address. {@link ResultParser#parseResult(com.google.zxing.Result)} will turn a raw - * decoded string into the most appropriate type of structured representation.

    - * - *

    Thanks to Jeff Griffin for proposing rewrite of these classes that relies less - * on exception-based mechanisms during parsing.

    - * - * @author Sean Owen - */ -public abstract class ParsedResult { - - private final ParsedResultType type; - - protected ParsedResult(ParsedResultType type) { - this.type = type; - } - - public final ParsedResultType getType() { - return type; - } - - public abstract String getDisplayResult(); - - @Override - public final String toString() { - return getDisplayResult(); - } - - public static void maybeAppend(String value, StringBuilder result) { - if (value != null && !value.isEmpty()) { - // Don't add a newline before the first value - if (result.length() > 0) { - result.append('\n'); - } - result.append(value); - } - } - - public static void maybeAppend(String[] values, StringBuilder result) { - if (values != null) { - for (String value : values) { - maybeAppend(value, result); - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResultType.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResultType.java deleted file mode 100644 index c74d54594..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ParsedResultType.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * Represents the type of data encoded by a barcode -- from plain text, to a - * URI, to an e-mail address, etc. - * - * @author Sean Owen - */ -public enum ParsedResultType { - - ADDRESSBOOK, - EMAIL_ADDRESS, - PRODUCT, - URI, - TEXT, - GEO, - TEL, - SMS, - CALENDAR, - WIFI, - ISBN, - VIN, - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductParsedResult.java deleted file mode 100644 index 95cfad016..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductParsedResult.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class ProductParsedResult extends ParsedResult { - - private final String productID; - private final String normalizedProductID; - - ProductParsedResult(String productID) { - this(productID, productID); - } - - ProductParsedResult(String productID, String normalizedProductID) { - super(ParsedResultType.PRODUCT); - this.productID = productID; - this.normalizedProductID = normalizedProductID; - } - - public String getProductID() { - return productID; - } - - public String getNormalizedProductID() { - return normalizedProductID; - } - - @Override - public String getDisplayResult() { - return productID; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductResultParser.java deleted file mode 100644 index bed1a7dc1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ProductResultParser.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; -import com.google.zxing.oned.UPCEReader; - -/** - * Parses strings of digits that represent a UPC code. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class ProductResultParser extends ResultParser { - - // Treat all UPC and EAN variants as UPCs, in the sense that they are all product barcodes. - @Override - public ProductParsedResult parse(Result result) { - BarcodeFormat format = result.getBarcodeFormat(); - if (!(format == BarcodeFormat.UPC_A || format == BarcodeFormat.UPC_E || - format == BarcodeFormat.EAN_8 || format == BarcodeFormat.EAN_13)) { - return null; - } - String rawText = getMassagedText(result); - if (!isStringOfDigits(rawText, rawText.length())) { - return null; - } - // Not actually checking the checksum again here - - String normalizedProductID; - // Expand UPC-E for purposes of searching - if (format == BarcodeFormat.UPC_E && rawText.length() == 8) { - normalizedProductID = UPCEReader.convertUPCEtoUPCA(rawText); - } else { - normalizedProductID = rawText; - } - - return new ProductParsedResult(rawText, normalizedProductID); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/ResultParser.java deleted file mode 100644 index c86f1f7fc..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/ResultParser.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -/** - *

    Abstract class representing the result of decoding a barcode, as more than - * a String -- as some type of structured data. This might be a subclass which represents - * a URL, or an e-mail address. {@link #parseResult(Result)} will turn a raw - * decoded string into the most appropriate type of structured representation.

    - * - *

    Thanks to Jeff Griffin for proposing rewrite of these classes that relies less - * on exception-based mechanisms during parsing.

    - * - * @author Sean Owen - */ -public abstract class ResultParser { - - private static final ResultParser[] PARSERS = { - new BookmarkDoCoMoResultParser(), - new AddressBookDoCoMoResultParser(), - new EmailDoCoMoResultParser(), - new AddressBookAUResultParser(), - new VCardResultParser(), - new BizcardResultParser(), - new VEventResultParser(), - new EmailAddressResultParser(), - new SMTPResultParser(), - new TelResultParser(), - new SMSMMSResultParser(), - new SMSTOMMSTOResultParser(), - new GeoResultParser(), - new WifiResultParser(), - new URLTOResultParser(), - new URIResultParser(), - new ISBNResultParser(), - new ProductResultParser(), - new ExpandedProductResultParser(), - new VINResultParser(), - }; - - private static final Pattern DIGITS = Pattern.compile("\\d+"); - private static final Pattern AMPERSAND = Pattern.compile("&"); - private static final Pattern EQUALS = Pattern.compile("="); - private static final String BYTE_ORDER_MARK = "\ufeff"; - - /** - * Attempts to parse the raw {@link Result}'s contents as a particular type - * of information (email, URL, etc.) and return a {@link ParsedResult} encapsulating - * the result of parsing. - * - * @param theResult the raw {@link Result} to parse - * @return {@link ParsedResult} encapsulating the parsing result - */ - public abstract ParsedResult parse(Result theResult); - - protected static String getMassagedText(Result result) { - String text = result.getText(); - if (text.startsWith(BYTE_ORDER_MARK)) { - text = text.substring(1); - } - return text; - } - - public static ParsedResult parseResult(Result theResult) { - for (ResultParser parser : PARSERS) { - ParsedResult result = parser.parse(theResult); - if (result != null) { - return result; - } - } - return new TextParsedResult(theResult.getText(), null); - } - - protected static void maybeAppend(String value, StringBuilder result) { - if (value != null) { - result.append('\n'); - result.append(value); - } - } - - protected static void maybeAppend(String[] value, StringBuilder result) { - if (value != null) { - for (String s : value) { - result.append('\n'); - result.append(s); - } - } - } - - protected static String[] maybeWrap(String value) { - return value == null ? null : new String[] { value }; - } - - protected static String unescapeBackslash(String escaped) { - int backslash = escaped.indexOf('\\'); - if (backslash < 0) { - return escaped; - } - int max = escaped.length(); - StringBuilder unescaped = new StringBuilder(max - 1); - unescaped.append(escaped.toCharArray(), 0, backslash); - boolean nextIsEscaped = false; - for (int i = backslash; i < max; i++) { - char c = escaped.charAt(i); - if (nextIsEscaped || c != '\\') { - unescaped.append(c); - nextIsEscaped = false; - } else { - nextIsEscaped = true; - } - } - return unescaped.toString(); - } - - protected static int parseHexDigit(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'a' && c <= 'f') { - return 10 + (c - 'a'); - } - if (c >= 'A' && c <= 'F') { - return 10 + (c - 'A'); - } - return -1; - } - - protected static boolean isStringOfDigits(CharSequence value, int length) { - return value != null && length > 0 && length == value.length() && DIGITS.matcher(value).matches(); - } - - protected static boolean isSubstringOfDigits(CharSequence value, int offset, int length) { - if (value == null || length <= 0) { - return false; - } - int max = offset + length; - return value.length() >= max && DIGITS.matcher(value.subSequence(offset, max)).matches(); - } - - static Map parseNameValuePairs(String uri) { - int paramStart = uri.indexOf('?'); - if (paramStart < 0) { - return null; - } - Map result = new HashMap<>(3); - for (String keyValue : AMPERSAND.split(uri.substring(paramStart + 1))) { - appendKeyValue(keyValue, result); - } - return result; - } - - private static void appendKeyValue(CharSequence keyValue, Map result) { - String[] keyValueTokens = EQUALS.split(keyValue, 2); - if (keyValueTokens.length == 2) { - String key = keyValueTokens[0]; - String value = keyValueTokens[1]; - try { - value = urlDecode(value); - result.put(key, value); - } catch (IllegalArgumentException iae) { - // continue; invalid data such as an escape like %0t - } - } - } - - static String urlDecode(String encoded) { - try { - return URLDecoder.decode(encoded, "UTF-8"); - } catch (UnsupportedEncodingException uee) { - throw new IllegalStateException(uee); // can't happen - } - } - - static String[] matchPrefixedField(String prefix, String rawText, char endChar, boolean trim) { - List matches = null; - int i = 0; - int max = rawText.length(); - while (i < max) { - i = rawText.indexOf(prefix, i); - if (i < 0) { - break; - } - i += prefix.length(); // Skip past this prefix we found to start - int start = i; // Found the start of a match here - boolean more = true; - while (more) { - i = rawText.indexOf(endChar, i); - if (i < 0) { - // No terminating end character? uh, done. Set i such that loop terminates and break - i = rawText.length(); - more = false; - } else if (countPrecedingBackslashes(rawText, i) % 2 != 0) { - // semicolon was escaped (odd count of preceding backslashes) so continue - i++; - } else { - // found a match - if (matches == null) { - matches = new ArrayList<>(3); // lazy init - } - String element = unescapeBackslash(rawText.substring(start, i)); - if (trim) { - element = element.trim(); - } - if (!element.isEmpty()) { - matches.add(element); - } - i++; - more = false; - } - } - } - if (matches == null || matches.isEmpty()) { - return null; - } - return matches.toArray(new String[matches.size()]); - } - - private static int countPrecedingBackslashes(CharSequence s, int pos) { - int count = 0; - for (int i = pos - 1; i >= 0; i--) { - if (s.charAt(i) == '\\') { - count++; - } else { - break; - } - } - return count; - } - - static String matchSinglePrefixedField(String prefix, String rawText, char endChar, boolean trim) { - String[] matches = matchPrefixedField(prefix, rawText, endChar, trim); - return matches == null ? null : matches[0]; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSMMSResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSMMSResultParser.java deleted file mode 100644 index a8d65d315..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSMMSResultParser.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - *

    Parses an "sms:" URI result, which specifies a number to SMS. - * See RFC 5724 on this.

    - * - *

    This class supports "via" syntax for numbers, which is not part of the spec. - * For example "+12125551212;via=+12124440101" may appear as a number. - * It also supports a "subject" query parameter, which is not mentioned in the spec. - * These are included since they were mentioned in earlier IETF drafts and might be - * used.

    - * - *

    This actually also parses URIs starting with "mms:" and treats them all the same way, - * and effectively converts them to an "sms:" URI for purposes of forwarding to the platform.

    - * - * @author Sean Owen - */ -public final class SMSMMSResultParser extends ResultParser { - - @Override - public SMSParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!(rawText.startsWith("sms:") || rawText.startsWith("SMS:") || - rawText.startsWith("mms:") || rawText.startsWith("MMS:"))) { - return null; - } - - // Check up front if this is a URI syntax string with query arguments - Map nameValuePairs = parseNameValuePairs(rawText); - String subject = null; - String body = null; - boolean querySyntax = false; - if (nameValuePairs != null && !nameValuePairs.isEmpty()) { - subject = nameValuePairs.get("subject"); - body = nameValuePairs.get("body"); - querySyntax = true; - } - - // Drop sms, query portion - int queryStart = rawText.indexOf('?', 4); - String smsURIWithoutQuery; - // If it's not query syntax, the question mark is part of the subject or message - if (queryStart < 0 || !querySyntax) { - smsURIWithoutQuery = rawText.substring(4); - } else { - smsURIWithoutQuery = rawText.substring(4, queryStart); - } - - int lastComma = -1; - int comma; - List numbers = new ArrayList<>(1); - List vias = new ArrayList<>(1); - while ((comma = smsURIWithoutQuery.indexOf(',', lastComma + 1)) > lastComma) { - String numberPart = smsURIWithoutQuery.substring(lastComma + 1, comma); - addNumberVia(numbers, vias, numberPart); - lastComma = comma; - } - addNumberVia(numbers, vias, smsURIWithoutQuery.substring(lastComma + 1)); - - return new SMSParsedResult(numbers.toArray(new String[numbers.size()]), - vias.toArray(new String[vias.size()]), - subject, - body); - } - - private static void addNumberVia(Collection numbers, - Collection vias, - String numberPart) { - int numberEnd = numberPart.indexOf(';'); - if (numberEnd < 0) { - numbers.add(numberPart); - vias.add(null); - } else { - numbers.add(numberPart.substring(0, numberEnd)); - String maybeVia = numberPart.substring(numberEnd + 1); - String via; - if (maybeVia.startsWith("via=")) { - via = maybeVia.substring(4); - } else { - via = null; - } - vias.add(via); - } - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSParsedResult.java deleted file mode 100644 index 69c806c84..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSParsedResult.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Sean Owen - */ -public final class SMSParsedResult extends ParsedResult { - - private final String[] numbers; - private final String[] vias; - private final String subject; - private final String body; - - public SMSParsedResult(String number, - String via, - String subject, - String body) { - super(ParsedResultType.SMS); - this.numbers = new String[] {number}; - this.vias = new String[] {via}; - this.subject = subject; - this.body = body; - } - - public SMSParsedResult(String[] numbers, - String[] vias, - String subject, - String body) { - super(ParsedResultType.SMS); - this.numbers = numbers; - this.vias = vias; - this.subject = subject; - this.body = body; - } - - public String getSMSURI() { - StringBuilder result = new StringBuilder(); - result.append("sms:"); - boolean first = true; - for (int i = 0; i < numbers.length; i++) { - if (first) { - first = false; - } else { - result.append(','); - } - result.append(numbers[i]); - if (vias != null && vias[i] != null) { - result.append(";via="); - result.append(vias[i]); - } - } - boolean hasBody = body != null; - boolean hasSubject = subject != null; - if (hasBody || hasSubject) { - result.append('?'); - if (hasBody) { - result.append("body="); - result.append(body); - } - if (hasSubject) { - if (hasBody) { - result.append('&'); - } - result.append("subject="); - result.append(subject); - } - } - return result.toString(); - } - - public String[] getNumbers() { - return numbers; - } - - public String[] getVias() { - return vias; - } - - public String getSubject() { - return subject; - } - - public String getBody() { - return body; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(100); - maybeAppend(numbers, result); - maybeAppend(subject, result); - maybeAppend(body, result); - return result.toString(); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSTOMMSTOResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSTOMMSTOResultParser.java deleted file mode 100644 index 076056587..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMSTOMMSTOResultParser.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - *

    Parses an "smsto:" URI result, whose format is not standardized but appears to be like: - * {@code smsto:number(:body)}.

    - * - *

    This actually also parses URIs starting with "smsto:", "mmsto:", "SMSTO:", and - * "MMSTO:", and treats them all the same way, and effectively converts them to an "sms:" URI - * for purposes of forwarding to the platform.

    - * - * @author Sean Owen - */ -public final class SMSTOMMSTOResultParser extends ResultParser { - - @Override - public SMSParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!(rawText.startsWith("smsto:") || rawText.startsWith("SMSTO:") || - rawText.startsWith("mmsto:") || rawText.startsWith("MMSTO:"))) { - return null; - } - // Thanks to dominik.wild for suggesting this enhancement to support - // smsto:number:body URIs - String number = rawText.substring(6); - String body = null; - int bodyStart = number.indexOf(':'); - if (bodyStart >= 0) { - body = number.substring(bodyStart + 1); - number = number.substring(0, bodyStart); - } - return new SMSParsedResult(number, null, null, body); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMTPResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMTPResultParser.java deleted file mode 100644 index 3279cebc4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/SMTPResultParser.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - *

    Parses an "smtp:" URI result, whose format is not standardized but appears to be like: - * {@code smtp[:subject[:body]]}.

    - * - * @author Sean Owen - */ -public final class SMTPResultParser extends ResultParser { - - @Override - public EmailAddressParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!(rawText.startsWith("smtp:") || rawText.startsWith("SMTP:"))) { - return null; - } - String emailAddress = rawText.substring(5); - String subject = null; - String body = null; - int colon = emailAddress.indexOf(':'); - if (colon >= 0) { - subject = emailAddress.substring(colon + 1); - emailAddress = emailAddress.substring(0, colon); - colon = subject.indexOf(':'); - if (colon >= 0) { - body = subject.substring(colon + 1); - subject = subject.substring(0, colon); - } - } - return new EmailAddressParsedResult(new String[] {emailAddress}, - null, - null, - subject, - body); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelParsedResult.java deleted file mode 100644 index 8b6c6f879..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelParsedResult.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Sean Owen - */ -public final class TelParsedResult extends ParsedResult { - - private final String number; - private final String telURI; - private final String title; - - public TelParsedResult(String number, String telURI, String title) { - super(ParsedResultType.TEL); - this.number = number; - this.telURI = telURI; - this.title = title; - } - - public String getNumber() { - return number; - } - - public String getTelURI() { - return telURI; - } - - public String getTitle() { - return title; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(20); - maybeAppend(number, result); - maybeAppend(title, result); - return result.toString(); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelResultParser.java deleted file mode 100644 index e4bca1fba..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TelResultParser.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - * Parses a "tel:" URI result, which specifies a phone number. - * - * @author Sean Owen - */ -public final class TelResultParser extends ResultParser { - - @Override - public TelParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("tel:") && !rawText.startsWith("TEL:")) { - return null; - } - // Normalize "TEL:" to "tel:" - String telURI = rawText.startsWith("TEL:") ? "tel:" + rawText.substring(4) : rawText; - // Drop tel, query portion - int queryStart = rawText.indexOf('?', 4); - String number = queryStart < 0 ? rawText.substring(4) : rawText.substring(4, queryStart); - return new TelParsedResult(number, telURI, null); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TextParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/TextParsedResult.java deleted file mode 100644 index 9cc408ec6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/TextParsedResult.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * A simple result type encapsulating a string that has no further - * interpretation. - * - * @author Sean Owen - */ -public final class TextParsedResult extends ParsedResult { - - private final String text; - private final String language; - - public TextParsedResult(String text, String language) { - super(ParsedResultType.TEXT); - this.text = text; - this.language = language; - } - - public String getText() { - return text; - } - - public String getLanguage() { - return language; - } - - @Override - public String getDisplayResult() { - return text; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIParsedResult.java deleted file mode 100644 index b360de92e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIParsedResult.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import java.util.regex.Pattern; - -/** - * @author Sean Owen - */ -public final class URIParsedResult extends ParsedResult { - - private static final Pattern USER_IN_HOST = Pattern.compile(":/*([^/@]+)@[^/]+"); - - private final String uri; - private final String title; - - public URIParsedResult(String uri, String title) { - super(ParsedResultType.URI); - this.uri = massageURI(uri); - this.title = title; - } - - public String getURI() { - return uri; - } - - public String getTitle() { - return title; - } - - /** - * @return true if the URI contains suspicious patterns that may suggest it intends to - * mislead the user about its true nature. At the moment this looks for the presence - * of user/password syntax in the host/authority portion of a URI which may be used - * in attempts to make the URI's host appear to be other than it is. Example: - * http://yourbank.com@phisher.com This URI connects to phisher.com but may appear - * to connect to yourbank.com at first glance. - */ - public boolean isPossiblyMaliciousURI() { - return USER_IN_HOST.matcher(uri).find(); - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(30); - maybeAppend(title, result); - maybeAppend(uri, result); - return result.toString(); - } - - /** - * Transforms a string that represents a URI into something more proper, by adding or canonicalizing - * the protocol. - */ - private static String massageURI(String uri) { - uri = uri.trim(); - int protocolEnd = uri.indexOf(':'); - if (protocolEnd < 0 || isColonFollowedByPortNumber(uri, protocolEnd)) { - // No protocol, or found a colon, but it looks like it is after the host, so the protocol is still missing, - // so assume http - uri = "http://" + uri; - } - return uri; - } - - private static boolean isColonFollowedByPortNumber(String uri, int protocolEnd) { - int start = protocolEnd + 1; - int nextSlash = uri.indexOf('/', start); - if (nextSlash < 0) { - nextSlash = uri.length(); - } - return ResultParser.isSubstringOfDigits(uri, start, nextSlash - start); - } - - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIResultParser.java deleted file mode 100644 index 2b0feefa4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URIResultParser.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Tries to parse results that are a URI of some kind. - * - * @author Sean Owen - */ -public final class URIResultParser extends ResultParser { - - // See http://www.ietf.org/rfc/rfc2396.txt - private static final Pattern URL_WITH_PROTOCOL_PATTERN = Pattern.compile("[a-zA-Z][a-zA-Z0-9+-.]+:"); - private static final Pattern URL_WITHOUT_PROTOCOL_PATTERN = Pattern.compile( - "([a-zA-Z0-9\\-]+\\.)+[a-zA-Z]{2,}" + // host name elements - "(:\\d{1,5})?" + // maybe port - "(/|\\?|$)"); // query, path or nothing - - @Override - public URIParsedResult parse(Result result) { - String rawText = getMassagedText(result); - // We specifically handle the odd "URL" scheme here for simplicity and add "URI" for fun - // Assume anything starting this way really means to be a URI - if (rawText.startsWith("URL:") || rawText.startsWith("URI:")) { - return new URIParsedResult(rawText.substring(4).trim(), null); - } - rawText = rawText.trim(); - return isBasicallyValidURI(rawText) ? new URIParsedResult(rawText, null) : null; - } - - static boolean isBasicallyValidURI(String uri) { - if (uri.contains(" ")) { - // Quick hack check for a common case - return false; - } - Matcher m = URL_WITH_PROTOCOL_PATTERN.matcher(uri); - if (m.find() && m.start() == 0) { // match at start only - return true; - } - m = URL_WITHOUT_PROTOCOL_PATTERN.matcher(uri); - return m.find() && m.start() == 0; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URLTOResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/URLTOResultParser.java deleted file mode 100644 index fd259007e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/URLTOResultParser.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - * Parses the "URLTO" result format, which is of the form "URLTO:[title]:[url]". - * This seems to be used sometimes, but I am not able to find documentation - * on its origin or official format? - * - * @author Sean Owen - */ -public final class URLTOResultParser extends ResultParser { - - @Override - public URIParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("urlto:") && !rawText.startsWith("URLTO:")) { - return null; - } - int titleEnd = rawText.indexOf(':', 6); - if (titleEnd < 0) { - return null; - } - String title = titleEnd <= 6 ? null : rawText.substring(6, titleEnd); - String uri = rawText.substring(titleEnd + 1); - return new URIParsedResult(uri, title); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VCardResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/VCardResultParser.java deleted file mode 100644 index 98078b3fb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VCardResultParser.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Parses contact information formatted according to the VCard (2.1) format. This is not a complete - * implementation but should parse information as commonly encoded in 2D barcodes. - * - * @author Sean Owen - */ -public final class VCardResultParser extends ResultParser { - - private static final Pattern BEGIN_VCARD = Pattern.compile("BEGIN:VCARD", Pattern.CASE_INSENSITIVE); - private static final Pattern VCARD_LIKE_DATE = Pattern.compile("\\d{4}-?\\d{2}-?\\d{2}"); - private static final Pattern CR_LF_SPACE_TAB = Pattern.compile("\r\n[ \t]"); - private static final Pattern NEWLINE_ESCAPE = Pattern.compile("\\\\[nN]"); - private static final Pattern VCARD_ESCAPES = Pattern.compile("\\\\([,;\\\\])"); - private static final Pattern EQUALS = Pattern.compile("="); - private static final Pattern SEMICOLON = Pattern.compile(";"); - private static final Pattern UNESCAPED_SEMICOLONS = Pattern.compile("(?> names = matchVCardPrefixedField("FN", rawText, true, false); - if (names == null) { - // If no display names found, look for regular name fields and format them - names = matchVCardPrefixedField("N", rawText, true, false); - formatNames(names); - } - List nicknameString = matchSingleVCardPrefixedField("NICKNAME", rawText, true, false); - String[] nicknames = nicknameString == null ? null : COMMA.split(nicknameString.get(0)); - List> phoneNumbers = matchVCardPrefixedField("TEL", rawText, true, false); - List> emails = matchVCardPrefixedField("EMAIL", rawText, true, false); - List note = matchSingleVCardPrefixedField("NOTE", rawText, false, false); - List> addresses = matchVCardPrefixedField("ADR", rawText, true, true); - List org = matchSingleVCardPrefixedField("ORG", rawText, true, true); - List birthday = matchSingleVCardPrefixedField("BDAY", rawText, true, false); - if (birthday != null && !isLikeVCardDate(birthday.get(0))) { - birthday = null; - } - List title = matchSingleVCardPrefixedField("TITLE", rawText, true, false); - List> urls = matchVCardPrefixedField("URL", rawText, true, false); - List instantMessenger = matchSingleVCardPrefixedField("IMPP", rawText, true, false); - List geoString = matchSingleVCardPrefixedField("GEO", rawText, true, false); - String[] geo = geoString == null ? null : SEMICOLON_OR_COMMA.split(geoString.get(0)); - if (geo != null && geo.length != 2) { - geo = null; - } - return new AddressBookParsedResult(toPrimaryValues(names), - nicknames, - null, - toPrimaryValues(phoneNumbers), - toTypes(phoneNumbers), - toPrimaryValues(emails), - toTypes(emails), - toPrimaryValue(instantMessenger), - toPrimaryValue(note), - toPrimaryValues(addresses), - toTypes(addresses), - toPrimaryValue(org), - toPrimaryValue(birthday), - toPrimaryValue(title), - toPrimaryValues(urls), - geo); - } - - static List> matchVCardPrefixedField(CharSequence prefix, - String rawText, - boolean trim, - boolean parseFieldDivider) { - List> matches = null; - int i = 0; - int max = rawText.length(); - - while (i < max) { - - // At start or after newline, match prefix, followed by optional metadata - // (led by ;) ultimately ending in colon - Matcher matcher = Pattern.compile("(?:^|\n)" + prefix + "(?:;([^:]*))?:", - Pattern.CASE_INSENSITIVE).matcher(rawText); - if (i > 0) { - i--; // Find from i-1 not i since looking at the preceding character - } - if (!matcher.find(i)) { - break; - } - i = matcher.end(0); // group 0 = whole pattern; end(0) is past final colon - - String metadataString = matcher.group(1); // group 1 = metadata substring - List metadata = null; - boolean quotedPrintable = false; - String quotedPrintableCharset = null; - if (metadataString != null) { - for (String metadatum : SEMICOLON.split(metadataString)) { - if (metadata == null) { - metadata = new ArrayList<>(1); - } - metadata.add(metadatum); - String[] metadatumTokens = EQUALS.split(metadatum, 2); - if (metadatumTokens.length > 1) { - String key = metadatumTokens[0]; - String value = metadatumTokens[1]; - if ("ENCODING".equalsIgnoreCase(key) && "QUOTED-PRINTABLE".equalsIgnoreCase(value)) { - quotedPrintable = true; - } else if ("CHARSET".equalsIgnoreCase(key)) { - quotedPrintableCharset = value; - } - } - } - } - - int matchStart = i; // Found the start of a match here - - while ((i = rawText.indexOf((int) '\n', i)) >= 0) { // Really, end in \r\n - if (i < rawText.length() - 1 && // But if followed by tab or space, - (rawText.charAt(i+1) == ' ' || // this is only a continuation - rawText.charAt(i+1) == '\t')) { - i += 2; // Skip \n and continutation whitespace - } else if (quotedPrintable && // If preceded by = in quoted printable - ((i >= 1 && rawText.charAt(i-1) == '=') || // this is a continuation - (i >= 2 && rawText.charAt(i-2) == '='))) { - i++; // Skip \n - } else { - break; - } - } - - if (i < 0) { - // No terminating end character? uh, done. Set i such that loop terminates and break - i = max; - } else if (i > matchStart) { - // found a match - if (matches == null) { - matches = new ArrayList<>(1); // lazy init - } - if (i >= 1 && rawText.charAt(i-1) == '\r') { - i--; // Back up over \r, which really should be there - } - String element = rawText.substring(matchStart, i); - if (trim) { - element = element.trim(); - } - if (quotedPrintable) { - element = decodeQuotedPrintable(element, quotedPrintableCharset); - if (parseFieldDivider) { - element = UNESCAPED_SEMICOLONS.matcher(element).replaceAll("\n").trim(); - } - } else { - if (parseFieldDivider) { - element = UNESCAPED_SEMICOLONS.matcher(element).replaceAll("\n").trim(); - } - element = CR_LF_SPACE_TAB.matcher(element).replaceAll(""); - element = NEWLINE_ESCAPE.matcher(element).replaceAll("\n"); - element = VCARD_ESCAPES.matcher(element).replaceAll("$1"); - } - if (metadata == null) { - List match = new ArrayList<>(1); - match.add(element); - matches.add(match); - } else { - metadata.add(0, element); - matches.add(metadata); - } - i++; - } else { - i++; - } - - } - - return matches; - } - - private static String decodeQuotedPrintable(CharSequence value, String charset) { - int length = value.length(); - StringBuilder result = new StringBuilder(length); - ByteArrayOutputStream fragmentBuffer = new ByteArrayOutputStream(); - for (int i = 0; i < length; i++) { - char c = value.charAt(i); - switch (c) { - case '\r': - case '\n': - break; - case '=': - if (i < length - 2) { - char nextChar = value.charAt(i+1); - if (nextChar != '\r' && nextChar != '\n') { - char nextNextChar = value.charAt(i+2); - int firstDigit = parseHexDigit(nextChar); - int secondDigit = parseHexDigit(nextNextChar); - if (firstDigit >= 0 && secondDigit >= 0) { - fragmentBuffer.write((firstDigit << 4) + secondDigit); - } // else ignore it, assume it was incorrectly encoded - i += 2; - } - } - break; - default: - maybeAppendFragment(fragmentBuffer, charset, result); - result.append(c); - } - } - maybeAppendFragment(fragmentBuffer, charset, result); - return result.toString(); - } - - private static void maybeAppendFragment(ByteArrayOutputStream fragmentBuffer, - String charset, - StringBuilder result) { - if (fragmentBuffer.size() > 0) { - byte[] fragmentBytes = fragmentBuffer.toByteArray(); - String fragment; - if (charset == null) { - fragment = new String(fragmentBytes, Charset.forName("UTF-8")); - } else { - try { - fragment = new String(fragmentBytes, charset); - } catch (UnsupportedEncodingException e) { - fragment = new String(fragmentBytes, Charset.forName("UTF-8")); - } - } - fragmentBuffer.reset(); - result.append(fragment); - } - } - - static List matchSingleVCardPrefixedField(CharSequence prefix, - String rawText, - boolean trim, - boolean parseFieldDivider) { - List> values = matchVCardPrefixedField(prefix, rawText, trim, parseFieldDivider); - return values == null || values.isEmpty() ? null : values.get(0); - } - - private static String toPrimaryValue(List list) { - return list == null || list.isEmpty() ? null : list.get(0); - } - - private static String[] toPrimaryValues(Collection> lists) { - if (lists == null || lists.isEmpty()) { - return null; - } - List result = new ArrayList<>(lists.size()); - for (List list : lists) { - String value = list.get(0); - if (value != null && !value.isEmpty()) { - result.add(value); - } - } - return result.toArray(new String[lists.size()]); - } - - private static String[] toTypes(Collection> lists) { - if (lists == null || lists.isEmpty()) { - return null; - } - List result = new ArrayList<>(lists.size()); - for (List list : lists) { - String type = null; - for (int i = 1; i < list.size(); i++) { - String metadatum = list.get(i); - int equals = metadatum.indexOf('='); - if (equals < 0) { - // take the whole thing as a usable label - type = metadatum; - break; - } - if ("TYPE".equalsIgnoreCase(metadatum.substring(0, equals))) { - type = metadatum.substring(equals + 1); - break; - } - } - result.add(type); - } - return result.toArray(new String[lists.size()]); - } - - private static boolean isLikeVCardDate(CharSequence value) { - return value == null || VCARD_LIKE_DATE.matcher(value).matches(); - } - - /** - * Formats name fields of the form "Public;John;Q.;Reverend;III" into a form like - * "Reverend John Q. Public III". - * - * @param names name values to format, in place - */ - private static void formatNames(Iterable> names) { - if (names != null) { - for (List list : names) { - String name = list.get(0); - String[] components = new String[5]; - int start = 0; - int end; - int componentIndex = 0; - while (componentIndex < components.length - 1 && (end = name.indexOf(';', start)) >= 0) { - components[componentIndex] = name.substring(start, end); - componentIndex++; - start = end + 1; - } - components[componentIndex] = name.substring(start); - StringBuilder newName = new StringBuilder(100); - maybeAppendComponent(components, 3, newName); - maybeAppendComponent(components, 1, newName); - maybeAppendComponent(components, 2, newName); - maybeAppendComponent(components, 0, newName); - maybeAppendComponent(components, 4, newName); - list.set(0, newName.toString().trim()); - } - } - } - - private static void maybeAppendComponent(String[] components, int i, StringBuilder newName) { - if (components[i] != null && !components[i].isEmpty()) { - if (newName.length() > 0) { - newName.append(' '); - } - newName.append(components[i]); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VEventResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/VEventResultParser.java deleted file mode 100644 index f6b2f398c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VEventResultParser.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -import java.util.List; - -/** - * Partially implements the iCalendar format's "VEVENT" format for specifying a - * calendar event. See RFC 2445. This supports SUMMARY, LOCATION, GEO, DTSTART and DTEND fields. - * - * @author Sean Owen - */ -public final class VEventResultParser extends ResultParser { - - @Override - public CalendarParsedResult parse(Result result) { - String rawText = getMassagedText(result); - int vEventStart = rawText.indexOf("BEGIN:VEVENT"); - if (vEventStart < 0) { - return null; - } - - String summary = matchSingleVCardPrefixedField("SUMMARY", rawText, true); - String start = matchSingleVCardPrefixedField("DTSTART", rawText, true); - if (start == null) { - return null; - } - String end = matchSingleVCardPrefixedField("DTEND", rawText, true); - String duration = matchSingleVCardPrefixedField("DURATION", rawText, true); - String location = matchSingleVCardPrefixedField("LOCATION", rawText, true); - String organizer = stripMailto(matchSingleVCardPrefixedField("ORGANIZER", rawText, true)); - - String[] attendees = matchVCardPrefixedField("ATTENDEE", rawText, true); - if (attendees != null) { - for (int i = 0; i < attendees.length; i++) { - attendees[i] = stripMailto(attendees[i]); - } - } - String description = matchSingleVCardPrefixedField("DESCRIPTION", rawText, true); - - String geoString = matchSingleVCardPrefixedField("GEO", rawText, true); - double latitude; - double longitude; - if (geoString == null) { - latitude = Double.NaN; - longitude = Double.NaN; - } else { - int semicolon = geoString.indexOf(';'); - if (semicolon < 0) { - return null; - } - try { - latitude = Double.parseDouble(geoString.substring(0, semicolon)); - longitude = Double.parseDouble(geoString.substring(semicolon + 1)); - } catch (NumberFormatException ignored) { - return null; - } - } - - try { - return new CalendarParsedResult(summary, - start, - end, - duration, - location, - organizer, - attendees, - description, - latitude, - longitude); - } catch (IllegalArgumentException ignored) { - return null; - } - } - - private static String matchSingleVCardPrefixedField(CharSequence prefix, - String rawText, - boolean trim) { - List values = VCardResultParser.matchSingleVCardPrefixedField(prefix, rawText, trim, false); - return values == null || values.isEmpty() ? null : values.get(0); - } - - private static String[] matchVCardPrefixedField(CharSequence prefix, String rawText, boolean trim) { - List> values = VCardResultParser.matchVCardPrefixedField(prefix, rawText, trim, false); - if (values == null || values.isEmpty()) { - return null; - } - int size = values.size(); - String[] result = new String[size]; - for (int i = 0; i < size; i++) { - result[i] = values.get(i).get(0); - } - return result; - } - - private static String stripMailto(String s) { - if (s != null && (s.startsWith("mailto:") || s.startsWith("MAILTO:"))) { - s = s.substring(7); - } - return s; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINParsedResult.java deleted file mode 100644 index dddd7d022..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINParsedResult.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2014 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.google.zxing.client.result; - - -public final class VINParsedResult extends ParsedResult { - - private final String vin; - private final String worldManufacturerID; - private final String vehicleDescriptorSection; - private final String vehicleIdentifierSection; - private final String countryCode; - private final String vehicleAttributes; - private final int modelYear; - private final char plantCode; - private final String sequentialNumber; - - public VINParsedResult(String vin, - String worldManufacturerID, - String vehicleDescriptorSection, - String vehicleIdentifierSection, - String countryCode, - String vehicleAttributes, - int modelYear, - char plantCode, - String sequentialNumber) { - super(ParsedResultType.VIN); - this.vin = vin; - this.worldManufacturerID = worldManufacturerID; - this.vehicleDescriptorSection = vehicleDescriptorSection; - this.vehicleIdentifierSection = vehicleIdentifierSection; - this.countryCode = countryCode; - this.vehicleAttributes = vehicleAttributes; - this.modelYear = modelYear; - this.plantCode = plantCode; - this.sequentialNumber = sequentialNumber; - } - - public String getVIN() { - return vin; - } - - public String getWorldManufacturerID() { - return worldManufacturerID; - } - - public String getVehicleDescriptorSection() { - return vehicleDescriptorSection; - } - - public String getVehicleIdentifierSection() { - return vehicleIdentifierSection; - } - - public String getCountryCode() { - return countryCode; - } - - public String getVehicleAttributes() { - return vehicleAttributes; - } - - public int getModelYear() { - return modelYear; - } - - public char getPlantCode() { - return plantCode; - } - - public String getSequentialNumber() { - return sequentialNumber; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(50); - result.append(worldManufacturerID).append(' '); - result.append(vehicleDescriptorSection).append(' '); - result.append(vehicleIdentifierSection).append('\n'); - if (countryCode != null) { - result.append(countryCode).append(' '); - } - result.append(modelYear).append(' '); - result.append(plantCode).append(' '); - result.append(sequentialNumber).append('\n'); - return result.toString(); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINResultParser.java deleted file mode 100644 index 0d1314cb6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/VINResultParser.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2014 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; - -import java.util.regex.Pattern; - -/** - * Detects a result that is likely a vehicle identification number. - * - * @author Sean Owen - */ -public final class VINResultParser extends ResultParser { - - private static final Pattern IOQ = Pattern.compile("[IOQ]"); - private static final Pattern AZ09 = Pattern.compile("[A-Z0-9]{17}"); - - @Override - public VINParsedResult parse(Result result) { - if (result.getBarcodeFormat() != BarcodeFormat.CODE_39) { - return null; - } - String rawText = result.getText(); - rawText = IOQ.matcher(rawText).replaceAll("").trim(); - if (!AZ09.matcher(rawText).matches()) { - return null; - } - try { - if (!checkChecksum(rawText)) { - return null; - } - String wmi = rawText.substring(0, 3); - return new VINParsedResult(rawText, - wmi, - rawText.substring(3, 9), - rawText.substring(9, 17), - countryCode(wmi), - rawText.substring(3, 8), - modelYear(rawText.charAt(9)), - rawText.charAt(10), - rawText.substring(11)); - } catch (IllegalArgumentException iae) { - return null; - } - } - - private static boolean checkChecksum(CharSequence vin) { - int sum = 0; - for (int i = 0; i < vin.length(); i++) { - sum += vinPositionWeight(i + 1) * vinCharValue(vin.charAt(i)); - } - char checkChar = vin.charAt(8); - char expectedCheckChar = checkChar(sum % 11); - return checkChar == expectedCheckChar; - } - - private static int vinCharValue(char c) { - if (c >= 'A' && c <= 'I') { - return (c - 'A') + 1; - } - if (c >= 'J' && c <= 'R') { - return (c - 'J') + 1; - } - if (c >= 'S' && c <= 'Z') { - return (c - 'S') + 2; - } - if (c >= '0' && c <= '9') { - return c - '0'; - } - throw new IllegalArgumentException(); - } - - private static int vinPositionWeight(int position) { - if (position >= 1 && position <= 7) { - return 9 - position; - } - if (position == 8) { - return 10; - } - if (position == 9) { - return 0; - } - if (position >= 10 && position <= 17) { - return 19 - position; - } - throw new IllegalArgumentException(); - } - - private static char checkChar(int remainder) { - if (remainder < 10) { - return (char) ('0' + remainder); - } - if (remainder == 10) { - return 'X'; - } - throw new IllegalArgumentException(); - } - - private static int modelYear(char c) { - if (c >= 'E' && c <= 'H') { - return (c - 'E') + 1984; - } - if (c >= 'J' && c <= 'N') { - return (c - 'J') + 1988; - } - if (c == 'P') { - return 1993; - } - if (c >= 'R' && c <= 'T') { - return (c - 'R') + 1994; - } - if (c >= 'V' && c <= 'Y') { - return (c - 'V') + 1997; - } - if (c >= '1' && c <= '9') { - return (c - '1') + 2001; - } - if (c >= 'A' && c <= 'D') { - return (c - 'A') + 2010; - } - throw new IllegalArgumentException(); - } - - private static String countryCode(CharSequence wmi) { - char c1 = wmi.charAt(0); - char c2 = wmi.charAt(1); - switch (c1) { - case '1': - case '4': - case '5': - return "US"; - case '2': - return "CA"; - case '3': - if (c2 >= 'A' && c2 <= 'W') { - return "MX"; - } - break; - case '9': - if ((c2 >= 'A' && c2 <= 'E') || (c2 >= '3' && c2 <= '9')) { - return "BR"; - } - break; - case 'J': - if (c2 >= 'A' && c2 <= 'T') { - return "JP"; - } - break; - case 'K': - if (c2 >= 'L' && c2 <= 'R') { - return "KO"; - } - break; - case 'L': - return "CN"; - case 'M': - if (c2 >= 'A' && c2 <= 'E') { - return "IN"; - } - break; - case 'S': - if (c2 >= 'A' && c2 <= 'M') { - return "UK"; - } - if (c2 >= 'N' && c2 <= 'T') { - return "DE"; - } - break; - case 'V': - if (c2 >= 'F' && c2 <= 'R') { - return "FR"; - } - if (c2 >= 'S' && c2 <= 'W') { - return "ES"; - } - break; - case 'W': - return "DE"; - case 'X': - if (c2 == '0' || (c2 >= '3' && c2 <= '9')) { - return "RU"; - } - break; - case 'Z': - if (c2 >= 'A' && c2 <= 'R') { - return "IT"; - } - break; - } - return null; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiParsedResult.java deleted file mode 100644 index 39dec351d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiParsedResult.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -/** - * @author Vikram Aggarwal - */ -public final class WifiParsedResult extends ParsedResult { - - private final String ssid; - private final String networkEncryption; - private final String password; - private final boolean hidden; - - public WifiParsedResult(String networkEncryption, String ssid, String password) { - this(networkEncryption, ssid, password, false); - } - - public WifiParsedResult(String networkEncryption, String ssid, String password, boolean hidden) { - super(ParsedResultType.WIFI); - this.ssid = ssid; - this.networkEncryption = networkEncryption; - this.password = password; - this.hidden = hidden; - } - - public String getSsid() { - return ssid; - } - - public String getNetworkEncryption() { - return networkEncryption; - } - - public String getPassword() { - return password; - } - - public boolean isHidden() { - return hidden; - } - - @Override - public String getDisplayResult() { - StringBuilder result = new StringBuilder(80); - maybeAppend(ssid, result); - maybeAppend(networkEncryption, result); - maybeAppend(password, result); - maybeAppend(Boolean.toString(hidden), result); - return result.toString(); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiResultParser.java b/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiResultParser.java deleted file mode 100644 index b62151c72..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/client/result/WifiResultParser.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.client.result; - -import com.google.zxing.Result; - -/** - *

    Parses a WIFI configuration string. Strings will be of the form:

    - * - *

    {@code WIFI:T:[network type];S:[network SSID];P:[network password];H:[hidden?];;}

    - * - *

    The fields can appear in any order. Only "S:" is required.

    - * - * @author Vikram Aggarwal - * @author Sean Owen - */ -public final class WifiResultParser extends ResultParser { - - @Override - public WifiParsedResult parse(Result result) { - String rawText = getMassagedText(result); - if (!rawText.startsWith("WIFI:")) { - return null; - } - String ssid = matchSinglePrefixedField("S:", rawText, ';', false); - if (ssid == null || ssid.isEmpty()) { - return null; - } - String pass = matchSinglePrefixedField("P:", rawText, ';', false); - String type = matchSinglePrefixedField("T:", rawText, ';', false); - if (type == null) { - type = "nopass"; - } - boolean hidden = Boolean.parseBoolean(matchSinglePrefixedField("H:", rawText, ';', false)); - return new WifiParsedResult(type, ssid, pass, hidden); - } -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/BitArray.java b/extern/zxing-core/src/main/java/com/google/zxing/common/BitArray.java deleted file mode 100644 index 0af7dd72c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/BitArray.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import java.util.Arrays; - -/** - *

    A simple, fast array of bits, represented compactly by an array of ints internally.

    - * - * @author Sean Owen - */ -public final class BitArray implements Cloneable { - - private int[] bits; - private int size; - - public BitArray() { - this.size = 0; - this.bits = new int[1]; - } - - public BitArray(int size) { - this.size = size; - this.bits = makeArray(size); - } - - // For testing only - BitArray(int[] bits, int size) { - this.bits = bits; - this.size = size; - } - - public int getSize() { - return size; - } - - public int getSizeInBytes() { - return (size + 7) / 8; - } - - private void ensureCapacity(int size) { - if (size > bits.length * 32) { - int[] newBits = makeArray(size); - System.arraycopy(bits, 0, newBits, 0, bits.length); - this.bits = newBits; - } - } - - /** - * @param i bit to get - * @return true iff bit i is set - */ - public boolean get(int i) { - return (bits[i / 32] & (1 << (i & 0x1F))) != 0; - } - - /** - * Sets bit i. - * - * @param i bit to set - */ - public void set(int i) { - bits[i / 32] |= 1 << (i & 0x1F); - } - - /** - * Flips bit i. - * - * @param i bit to set - */ - public void flip(int i) { - bits[i / 32] ^= 1 << (i & 0x1F); - } - - /** - * @param from first bit to check - * @return index of first bit that is set, starting from the given index, or size if none are set - * at or beyond this given index - * @see #getNextUnset(int) - */ - public int getNextSet(int from) { - if (from >= size) { - return size; - } - int bitsOffset = from / 32; - int currentBits = bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) { - if (++bitsOffset == bits.length) { - return size; - } - currentBits = bits[bitsOffset]; - } - int result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /** - * @param from index to start looking for unset bit - * @return index of next unset bit, or {@code size} if none are unset until the end - * @see #getNextSet(int) - */ - public int getNextUnset(int from) { - if (from >= size) { - return size; - } - int bitsOffset = from / 32; - int currentBits = ~bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) { - if (++bitsOffset == bits.length) { - return size; - } - currentBits = ~bits[bitsOffset]; - } - int result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /** - * Sets a block of 32 bits, starting at bit i. - * - * @param i first bit to set - * @param newBits the new value of the next 32 bits. Note again that the least-significant bit - * corresponds to bit i, the next-least-significant to i+1, and so on. - */ - public void setBulk(int i, int newBits) { - bits[i / 32] = newBits; - } - - /** - * Sets a range of bits. - * - * @param start start of range, inclusive. - * @param end end of range, exclusive - */ - public void setRange(int start, int end) { - if (end < start) { - throw new IllegalArgumentException(); - } - if (end == start) { - return; - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start / 32; - int lastInt = end / 32; - for (int i = firstInt; i <= lastInt; i++) { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) { - mask = -1; - } else { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) { - mask |= 1 << j; - } - } - bits[i] |= mask; - } - } - - /** - * Clears all bits (sets to false). - */ - public void clear() { - int max = bits.length; - for (int i = 0; i < max; i++) { - bits[i] = 0; - } - } - - /** - * Efficient method to check if a range of bits is set, or not set. - * - * @param start start of range, inclusive. - * @param end end of range, exclusive - * @param value if true, checks that bits in range are set, otherwise checks that they are not set - * @return true iff all bits are set or not set in range, according to value argument - * @throws IllegalArgumentException if end is less than or equal to start - */ - public boolean isRange(int start, int end, boolean value) { - if (end < start) { - throw new IllegalArgumentException(); - } - if (end == start) { - return true; // empty range matches - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start / 32; - int lastInt = end / 32; - for (int i = firstInt; i <= lastInt; i++) { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) { - mask = -1; - } else { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) { - mask |= 1 << j; - } - } - - // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is, - // equals the mask, or we're looking for 0s and the masked portion is not all 0s - if ((bits[i] & mask) != (value ? mask : 0)) { - return false; - } - } - return true; - } - - public void appendBit(boolean bit) { - ensureCapacity(size + 1); - if (bit) { - bits[size / 32] |= 1 << (size & 0x1F); - } - size++; - } - - /** - * Appends the least-significant bits, from value, in order from most-significant to - * least-significant. For example, appending 6 bits from 0x000001E will append the bits - * 0, 1, 1, 1, 1, 0 in that order. - * - * @param value {@code int} containing bits to append - * @param numBits bits from value to append - */ - public void appendBits(int value, int numBits) { - if (numBits < 0 || numBits > 32) { - throw new IllegalArgumentException("Num bits must be between 0 and 32"); - } - ensureCapacity(size + numBits); - for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) { - appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1); - } - } - - public void appendBitArray(BitArray other) { - int otherSize = other.size; - ensureCapacity(size + otherSize); - for (int i = 0; i < otherSize; i++) { - appendBit(other.get(i)); - } - } - - public void xor(BitArray other) { - if (bits.length != other.bits.length) { - throw new IllegalArgumentException("Sizes don't match"); - } - for (int i = 0; i < bits.length; i++) { - // The last byte could be incomplete (i.e. not have 8 bits in - // it) but there is no problem since 0 XOR 0 == 0. - bits[i] ^= other.bits[i]; - } - } - - /** - * - * @param bitOffset first bit to start writing - * @param array array to write into. Bytes are written most-significant byte first. This is the opposite - * of the internal representation, which is exposed by {@link #getBitArray()} - * @param offset position in array to start writing - * @param numBytes how many bytes to write - */ - public void toBytes(int bitOffset, byte[] array, int offset, int numBytes) { - for (int i = 0; i < numBytes; i++) { - int theByte = 0; - for (int j = 0; j < 8; j++) { - if (get(bitOffset)) { - theByte |= 1 << (7 - j); - } - bitOffset++; - } - array[offset + i] = (byte) theByte; - } - } - - /** - * @return underlying array of ints. The first element holds the first 32 bits, and the least - * significant bit is bit 0. - */ - public int[] getBitArray() { - return bits; - } - - /** - * Reverses all bits in the array. - */ - public void reverse() { - int[] newBits = new int[bits.length]; - // reverse all int's first - int len = ((size-1) / 32); - int oldBitsLen = len + 1; - for (int i = 0; i < oldBitsLen; i++) { - long x = (long) bits[i]; - x = ((x >> 1) & 0x55555555L) | ((x & 0x55555555L) << 1); - x = ((x >> 2) & 0x33333333L) | ((x & 0x33333333L) << 2); - x = ((x >> 4) & 0x0f0f0f0fL) | ((x & 0x0f0f0f0fL) << 4); - x = ((x >> 8) & 0x00ff00ffL) | ((x & 0x00ff00ffL) << 8); - x = ((x >> 16) & 0x0000ffffL) | ((x & 0x0000ffffL) << 16); - newBits[len - i] = (int) x; - } - // now correct the int's if the bit size isn't a multiple of 32 - if (size != oldBitsLen * 32) { - int leftOffset = oldBitsLen * 32 - size; - int mask = 1; - for (int i = 0; i < 31 - leftOffset; i++) { - mask = (mask << 1) | 1; - } - int currentInt = (newBits[0] >> leftOffset) & mask; - for (int i = 1; i < oldBitsLen; i++) { - int nextInt = newBits[i]; - currentInt |= nextInt << (32 - leftOffset); - newBits[i - 1] = currentInt; - currentInt = (nextInt >> leftOffset) & mask; - } - newBits[oldBitsLen - 1] = currentInt; - } - bits = newBits; - } - - private static int[] makeArray(int size) { - return new int[(size + 31) / 32]; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BitArray)) { - return false; - } - BitArray other = (BitArray) o; - return size == other.size && Arrays.equals(bits, other.bits); - } - - @Override - public int hashCode() { - return 31 * size + Arrays.hashCode(bits); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(size); - for (int i = 0; i < size; i++) { - if ((i & 0x07) == 0) { - result.append(' '); - } - result.append(get(i) ? 'X' : '.'); - } - return result.toString(); - } - - @Override - public BitArray clone() { - return new BitArray(bits.clone(), size); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/BitMatrix.java b/extern/zxing-core/src/main/java/com/google/zxing/common/BitMatrix.java deleted file mode 100755 index 30e2358cb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/BitMatrix.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import java.util.Arrays; - -/** - *

    Represents a 2D matrix of bits. In function arguments below, and throughout the common - * module, x is the column position, and y is the row position. The ordering is always x, y. - * The origin is at the top-left.

    - * - *

    Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins - * with a new int. This is done intentionally so that we can copy out a row into a BitArray very - * efficiently.

    - * - *

    The ordering of bits is row-major. Within each int, the least significant bits are used first, - * meaning they represent lower x values. This is compatible with BitArray's implementation.

    - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class BitMatrix implements Cloneable { - - private final int width; - private final int height; - private final int rowSize; - private final int[] bits; - - // A helper to construct a square matrix. - public BitMatrix(int dimension) { - this(dimension, dimension); - } - - public BitMatrix(int width, int height) { - if (width < 1 || height < 1) { - throw new IllegalArgumentException("Both dimensions must be greater than 0"); - } - this.width = width; - this.height = height; - this.rowSize = (width + 31) / 32; - bits = new int[rowSize * height]; - } - - private BitMatrix(int width, int height, int rowSize, int[] bits) { - this.width = width; - this.height = height; - this.rowSize = rowSize; - this.bits = bits; - } - - public static BitMatrix parse(String stringRepresentation, String setString, String unsetString) { - if (stringRepresentation == null) { - throw new IllegalArgumentException(); - } - - boolean[] bits = new boolean[stringRepresentation.length()]; - int bitsPos = 0; - int rowStartPos = 0; - int rowLength = -1; - int nRows = 0; - int pos = 0; - while (pos < stringRepresentation.length()) { - if (stringRepresentation.charAt(pos) == '\n' || - stringRepresentation.charAt(pos) == '\r') { - if (bitsPos > rowStartPos) { - if (rowLength == -1) { - rowLength = bitsPos - rowStartPos; - } else if (bitsPos - rowStartPos != rowLength) { - throw new IllegalArgumentException("row lengths do not match"); - } - rowStartPos = bitsPos; - nRows++; - } - pos++; - } else if (stringRepresentation.substring(pos, pos + setString.length()).equals(setString)) { - pos += setString.length(); - bits[bitsPos] = true; - bitsPos++; - } else if (stringRepresentation.substring(pos, pos + unsetString.length()).equals(unsetString)) { - pos += unsetString.length(); - bits[bitsPos] = false; - bitsPos++; - } else { - throw new IllegalArgumentException( - "illegal character encountered: " + stringRepresentation.substring(pos)); - } - } - - // no EOL at end? - if (bitsPos > rowStartPos) { - if(rowLength == -1) { - rowLength = bitsPos - rowStartPos; - } else if (bitsPos - rowStartPos != rowLength) { - throw new IllegalArgumentException("row lengths do not match"); - } - nRows++; - } - - BitMatrix matrix = new BitMatrix(rowLength, nRows); - for (int i = 0; i < bitsPos; i++) { - if (bits[i]) { - matrix.set(i % rowLength, i / rowLength); - } - } - return matrix; - } - - /** - *

    Gets the requested bit, where true means black.

    - * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - * @return value of given bit in matrix - */ - public boolean get(int x, int y) { - int offset = y * rowSize + (x / 32); - return ((bits[offset] >>> (x & 0x1f)) & 1) != 0; - } - - /** - *

    Sets the given bit to true.

    - * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - public void set(int x, int y) { - int offset = y * rowSize + (x / 32); - bits[offset] |= 1 << (x & 0x1f); - } - - public void unset(int x, int y) { - int offset = y * rowSize + (x / 32); - bits[offset] &= ~(1 << (x & 0x1f)); - } - - /** - *

    Flips the given bit.

    - * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - public void flip(int x, int y) { - int offset = y * rowSize + (x / 32); - bits[offset] ^= 1 << (x & 0x1f); - } - - /** - * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding - * mask bit is set. - * - * @param mask XOR mask - */ - public void xor(BitMatrix mask) { - if (width != mask.getWidth() || height != mask.getHeight() - || rowSize != mask.getRowSize()) { - throw new IllegalArgumentException("input matrix dimensions do not match"); - } - BitArray rowArray = new BitArray(width / 32 + 1); - for (int y = 0; y < height; y++) { - int offset = y * rowSize; - int[] row = mask.getRow(y, rowArray).getBitArray(); - for (int x = 0; x < rowSize; x++) { - bits[offset + x] ^= row[x]; - } - } - } - - /** - * Clears all bits (sets to false). - */ - public void clear() { - int max = bits.length; - for (int i = 0; i < max; i++) { - bits[i] = 0; - } - } - - /** - *

    Sets a square region of the bit matrix to true.

    - * - * @param left The horizontal position to begin at (inclusive) - * @param top The vertical position to begin at (inclusive) - * @param width The width of the region - * @param height The height of the region - */ - public void setRegion(int left, int top, int width, int height) { - if (top < 0 || left < 0) { - throw new IllegalArgumentException("Left and top must be nonnegative"); - } - if (height < 1 || width < 1) { - throw new IllegalArgumentException("Height and width must be at least 1"); - } - int right = left + width; - int bottom = top + height; - if (bottom > this.height || right > this.width) { - throw new IllegalArgumentException("The region must fit inside the matrix"); - } - for (int y = top; y < bottom; y++) { - int offset = y * rowSize; - for (int x = left; x < right; x++) { - bits[offset + (x / 32)] |= 1 << (x & 0x1f); - } - } - } - - /** - * A fast method to retrieve one row of data from the matrix as a BitArray. - * - * @param y The row to retrieve - * @param row An optional caller-allocated BitArray, will be allocated if null or too small - * @return The resulting BitArray - this reference should always be used even when passing - * your own row - */ - public BitArray getRow(int y, BitArray row) { - if (row == null || row.getSize() < width) { - row = new BitArray(width); - } else { - row.clear(); - } - int offset = y * rowSize; - for (int x = 0; x < rowSize; x++) { - row.setBulk(x * 32, bits[offset + x]); - } - return row; - } - - /** - * @param y row to set - * @param row {@link BitArray} to copy from - */ - public void setRow(int y, BitArray row) { - System.arraycopy(row.getBitArray(), 0, bits, y * rowSize, rowSize); - } - - /** - * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees - */ - public void rotate180() { - int width = getWidth(); - int height = getHeight(); - BitArray topRow = new BitArray(width); - BitArray bottomRow = new BitArray(width); - for (int i = 0; i < (height+1) / 2; i++) { - topRow = getRow(i, topRow); - bottomRow = getRow(height - 1 - i, bottomRow); - topRow.reverse(); - bottomRow.reverse(); - setRow(i, bottomRow); - setRow(height - 1 - i, topRow); - } - } - - /** - * This is useful in detecting the enclosing rectangle of a 'pure' barcode. - * - * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white - */ - public int[] getEnclosingRectangle() { - int left = width; - int top = height; - int right = -1; - int bottom = -1; - - for (int y = 0; y < height; y++) { - for (int x32 = 0; x32 < rowSize; x32++) { - int theBits = bits[y * rowSize + x32]; - if (theBits != 0) { - if (y < top) { - top = y; - } - if (y > bottom) { - bottom = y; - } - if (x32 * 32 < left) { - int bit = 0; - while ((theBits << (31 - bit)) == 0) { - bit++; - } - if ((x32 * 32 + bit) < left) { - left = x32 * 32 + bit; - } - } - if (x32 * 32 + 31 > right) { - int bit = 31; - while ((theBits >>> bit) == 0) { - bit--; - } - if ((x32 * 32 + bit) > right) { - right = x32 * 32 + bit; - } - } - } - } - } - - int width = right - left; - int height = bottom - top; - - if (width < 0 || height < 0) { - return null; - } - - return new int[] {left, top, width, height}; - } - - /** - * This is useful in detecting a corner of a 'pure' barcode. - * - * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white - */ - public int[] getTopLeftOnBit() { - int bitsOffset = 0; - while (bitsOffset < bits.length && bits[bitsOffset] == 0) { - bitsOffset++; - } - if (bitsOffset == bits.length) { - return null; - } - int y = bitsOffset / rowSize; - int x = (bitsOffset % rowSize) * 32; - - int theBits = bits[bitsOffset]; - int bit = 0; - while ((theBits << (31-bit)) == 0) { - bit++; - } - x += bit; - return new int[] {x, y}; - } - - public int[] getBottomRightOnBit() { - int bitsOffset = bits.length - 1; - while (bitsOffset >= 0 && bits[bitsOffset] == 0) { - bitsOffset--; - } - if (bitsOffset < 0) { - return null; - } - - int y = bitsOffset / rowSize; - int x = (bitsOffset % rowSize) * 32; - - int theBits = bits[bitsOffset]; - int bit = 31; - while ((theBits >>> bit) == 0) { - bit--; - } - x += bit; - - return new int[] {x, y}; - } - - /** - * @return The width of the matrix - */ - public int getWidth() { - return width; - } - - /** - * @return The height of the matrix - */ - public int getHeight() { - return height; - } - - /** - * @return The row size of the matrix - */ - public int getRowSize() { - return rowSize; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BitMatrix)) { - return false; - } - BitMatrix other = (BitMatrix) o; - return width == other.width && height == other.height && rowSize == other.rowSize && - Arrays.equals(bits, other.bits); - } - - @Override - public int hashCode() { - int hash = width; - hash = 31 * hash + width; - hash = 31 * hash + height; - hash = 31 * hash + rowSize; - hash = 31 * hash + Arrays.hashCode(bits); - return hash; - } - - /** - * @return string representation using "X" for set and " " for unset bits - */ - @Override - public String toString() { - return toString("X ", " "); - } - - /** - * @param setString representation of a set bit - * @param unsetString representation of an unset bit - * @return string representation of entire matrix utilizing given strings - */ - public String toString(String setString, String unsetString) { - return toString(setString, unsetString, "\n"); - } - - /** - * @param setString representation of a set bit - * @param unsetString representation of an unset bit - * @param lineSeparator newline character in string representation - * @return string representation of entire matrix utilizing given strings and line separator - * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always - */ - @Deprecated - public String toString(String setString, String unsetString, String lineSeparator) { - StringBuilder result = new StringBuilder(height * (width + 1)); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - result.append(get(x, y) ? setString : unsetString); - } - result.append(lineSeparator); - } - return result.toString(); - } - - @Override - public BitMatrix clone() { - return new BitMatrix(width, height, rowSize, bits.clone()); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/BitSource.java b/extern/zxing-core/src/main/java/com/google/zxing/common/BitSource.java deleted file mode 100755 index 45a3858ef..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/BitSource.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -/** - *

    This provides an easy abstraction to read bits at a time from a sequence of bytes, where the - * number of bits read is not often a multiple of 8.

    - * - *

    This class is thread-safe but not reentrant -- unless the caller modifies the bytes array - * it passed in, in which case all bets are off.

    - * - * @author Sean Owen - */ -public final class BitSource { - - private final byte[] bytes; - private int byteOffset; - private int bitOffset; - - /** - * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. - * Bits are read within a byte from most-significant to least-significant bit. - */ - public BitSource(byte[] bytes) { - this.bytes = bytes; - } - - /** - * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. - */ - public int getBitOffset() { - return bitOffset; - } - - /** - * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. - */ - public int getByteOffset() { - return byteOffset; - } - - /** - * @param numBits number of bits to read - * @return int representing the bits read. The bits will appear as the least-significant - * bits of the int - * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available - */ - public int readBits(int numBits) { - if (numBits < 1 || numBits > 32 || numBits > available()) { - throw new IllegalArgumentException(String.valueOf(numBits)); - } - - int result = 0; - - // First, read remainder from current byte - if (bitOffset > 0) { - int bitsLeft = 8 - bitOffset; - int toRead = numBits < bitsLeft ? numBits : bitsLeft; - int bitsToNotRead = bitsLeft - toRead; - int mask = (0xFF >> (8 - toRead)) << bitsToNotRead; - result = (bytes[byteOffset] & mask) >> bitsToNotRead; - numBits -= toRead; - bitOffset += toRead; - if (bitOffset == 8) { - bitOffset = 0; - byteOffset++; - } - } - - // Next read whole bytes - if (numBits > 0) { - while (numBits >= 8) { - result = (result << 8) | (bytes[byteOffset] & 0xFF); - byteOffset++; - numBits -= 8; - } - - // Finally read a partial byte - if (numBits > 0) { - int bitsToNotRead = 8 - numBits; - int mask = (0xFF >> bitsToNotRead) << bitsToNotRead; - result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead); - bitOffset += numBits; - } - } - - return result; - } - - /** - * @return number of bits that can be read successfully - */ - public int available() { - return 8 * (bytes.length - byteOffset) - bitOffset; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/CharacterSetECI.java b/extern/zxing-core/src/main/java/com/google/zxing/common/CharacterSetECI.java deleted file mode 100644 index 7c3853ca8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/CharacterSetECI.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.FormatException; - -import java.util.HashMap; -import java.util.Map; - -/** - * Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1 - * of ISO 18004. - * - * @author Sean Owen - */ -public enum CharacterSetECI { - - // Enum name is a Java encoding valid for java.lang and java.io - Cp437(new int[]{0,2}), - ISO8859_1(new int[]{1,3}, "ISO-8859-1"), - ISO8859_2(4, "ISO-8859-2"), - ISO8859_3(5, "ISO-8859-3"), - ISO8859_4(6, "ISO-8859-4"), - ISO8859_5(7, "ISO-8859-5"), - ISO8859_6(8, "ISO-8859-6"), - ISO8859_7(9, "ISO-8859-7"), - ISO8859_8(10, "ISO-8859-8"), - ISO8859_9(11, "ISO-8859-9"), - ISO8859_10(12, "ISO-8859-10"), - ISO8859_11(13, "ISO-8859-11"), - ISO8859_13(15, "ISO-8859-13"), - ISO8859_14(16, "ISO-8859-14"), - ISO8859_15(17, "ISO-8859-15"), - ISO8859_16(18, "ISO-8859-16"), - SJIS(20, "Shift_JIS"), - Cp1250(21, "windows-1250"), - Cp1251(22, "windows-1251"), - Cp1252(23, "windows-1252"), - Cp1256(24, "windows-1256"), - UnicodeBigUnmarked(25, "UTF-16BE", "UnicodeBig"), - UTF8(26, "UTF-8"), - ASCII(new int[] {27, 170}, "US-ASCII"), - Big5(28), - GB18030(29, "GB2312", "EUC_CN", "GBK"), - EUC_KR(30, "EUC-KR"); - - private static final Map VALUE_TO_ECI = new HashMap<>(); - private static final Map NAME_TO_ECI = new HashMap<>(); - static { - for (CharacterSetECI eci : values()) { - for (int value : eci.values) { - VALUE_TO_ECI.put(value, eci); - } - NAME_TO_ECI.put(eci.name(), eci); - for (String name : eci.otherEncodingNames) { - NAME_TO_ECI.put(name, eci); - } - } - } - - private final int[] values; - private final String[] otherEncodingNames; - - CharacterSetECI(int value) { - this(new int[] {value}); - } - - CharacterSetECI(int value, String... otherEncodingNames) { - this.values = new int[] {value}; - this.otherEncodingNames = otherEncodingNames; - } - - CharacterSetECI(int[] values, String... otherEncodingNames) { - this.values = values; - this.otherEncodingNames = otherEncodingNames; - } - - public int getValue() { - return values[0]; - } - - /** - * @param value character set ECI value - * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but - * unsupported - * @throws FormatException if ECI value is invalid - */ - public static CharacterSetECI getCharacterSetECIByValue(int value) throws FormatException { - if (value < 0 || value >= 900) { - throw FormatException.getFormatInstance(); - } - return VALUE_TO_ECI.get(value); - } - - /** - * @param name character set ECI encoding name - * @return CharacterSetECI representing ECI for character encoding, or null if it is legal - * but unsupported - */ - public static CharacterSetECI getCharacterSetECIByName(String name) { - return NAME_TO_ECI.get(name); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/DecoderResult.java b/extern/zxing-core/src/main/java/com/google/zxing/common/DecoderResult.java deleted file mode 100644 index bfeacedc8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/DecoderResult.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import java.util.List; - -/** - *

    Encapsulates the result of decoding a matrix of bits. This typically - * applies to 2D barcode formats. For now it contains the raw bytes obtained, - * as well as a String interpretation of those bytes, if applicable.

    - * - * @author Sean Owen - */ -public final class DecoderResult { - - private final byte[] rawBytes; - private final String text; - private final List byteSegments; - private final String ecLevel; - private Integer errorsCorrected; - private Integer erasures; - private Object other; - private final int structuredAppendParity; - private final int structuredAppendSequenceNumber; - - public DecoderResult(byte[] rawBytes, - String text, - List byteSegments, - String ecLevel) { - this(rawBytes, text, byteSegments, ecLevel, -1, -1); - } - - public DecoderResult(byte[] rawBytes, - String text, - List byteSegments, - String ecLevel, - int saSequence, - int saParity) { - this.rawBytes = rawBytes; - this.text = text; - this.byteSegments = byteSegments; - this.ecLevel = ecLevel; - this.structuredAppendParity = saParity; - this.structuredAppendSequenceNumber = saSequence; - } - - public byte[] getRawBytes() { - return rawBytes; - } - - public String getText() { - return text; - } - - public List getByteSegments() { - return byteSegments; - } - - public String getECLevel() { - return ecLevel; - } - - public Integer getErrorsCorrected() { - return errorsCorrected; - } - - public void setErrorsCorrected(Integer errorsCorrected) { - this.errorsCorrected = errorsCorrected; - } - - public Integer getErasures() { - return erasures; - } - - public void setErasures(Integer erasures) { - this.erasures = erasures; - } - - public Object getOther() { - return other; - } - - public void setOther(Object other) { - this.other = other; - } - - public boolean hasStructuredAppend() { - return structuredAppendParity >= 0 && structuredAppendSequenceNumber >= 0; - } - - public int getStructuredAppendParity() { - return structuredAppendParity; - } - - public int getStructuredAppendSequenceNumber() { - return structuredAppendSequenceNumber; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/DefaultGridSampler.java b/extern/zxing-core/src/main/java/com/google/zxing/common/DefaultGridSampler.java deleted file mode 100644 index 0ef0fbee1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/DefaultGridSampler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.NotFoundException; - -/** - * @author Sean Owen - */ -public final class DefaultGridSampler extends GridSampler { - - @Override - public BitMatrix sampleGrid(BitMatrix image, - int dimensionX, - int dimensionY, - float p1ToX, float p1ToY, - float p2ToX, float p2ToY, - float p3ToX, float p3ToY, - float p4ToX, float p4ToY, - float p1FromX, float p1FromY, - float p2FromX, float p2FromY, - float p3FromX, float p3FromY, - float p4FromX, float p4FromY) throws NotFoundException { - - PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral( - p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, - p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY); - - return sampleGrid(image, dimensionX, dimensionY, transform); - } - - @Override - public BitMatrix sampleGrid(BitMatrix image, - int dimensionX, - int dimensionY, - PerspectiveTransform transform) throws NotFoundException { - if (dimensionX <= 0 || dimensionY <= 0) { - throw NotFoundException.getNotFoundInstance(); - } - BitMatrix bits = new BitMatrix(dimensionX, dimensionY); - float[] points = new float[2 * dimensionX]; - for (int y = 0; y < dimensionY; y++) { - int max = points.length; - float iValue = (float) y + 0.5f; - for (int x = 0; x < max; x += 2) { - points[x] = (float) (x / 2) + 0.5f; - points[x + 1] = iValue; - } - transform.transformPoints(points); - // Quick check to see if points transformed to something inside the image; - // sufficient to check the endpoints - checkAndNudgePoints(image, points); - try { - for (int x = 0; x < max; x += 2) { - if (image.get((int) points[x], (int) points[x + 1])) { - // Black(-ish) pixel - bits.set(x / 2, y); - } - } - } catch (ArrayIndexOutOfBoundsException aioobe) { - // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting - // transform gets "twisted" such that it maps a straight line of points to a set of points - // whose endpoints are in bounds, but others are not. There is probably some mathematical - // way to detect this about the transformation that I don't know yet. - // This results in an ugly runtime exception despite our clever checks above -- can't have - // that. We could check each point's coordinates but that feels duplicative. We settle for - // catching and wrapping ArrayIndexOutOfBoundsException. - throw NotFoundException.getNotFoundInstance(); - } - } - return bits; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/DetectorResult.java b/extern/zxing-core/src/main/java/com/google/zxing/common/DetectorResult.java deleted file mode 100644 index 0f3cf15e7..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/DetectorResult.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.ResultPoint; - -/** - *

    Encapsulates the result of detecting a barcode in an image. This includes the raw - * matrix of black/white pixels corresponding to the barcode, and possibly points of interest - * in the image, like the location of finder patterns or corners of the barcode in the image.

    - * - * @author Sean Owen - */ -public class DetectorResult { - - private final BitMatrix bits; - private final ResultPoint[] points; - - public DetectorResult(BitMatrix bits, ResultPoint[] points) { - this.bits = bits; - this.points = points; - } - - public final BitMatrix getBits() { - return bits; - } - - public final ResultPoint[] getPoints() { - return points; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java b/extern/zxing-core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java deleted file mode 100644 index b4c0edbd8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.Binarizer; -import com.google.zxing.LuminanceSource; -import com.google.zxing.NotFoundException; - -/** - * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable - * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding - * algorithm. However, because it picks a global black point, it cannot handle difficult shadows - * and gradients. - * - * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - */ -public class GlobalHistogramBinarizer extends Binarizer { - - private static final int LUMINANCE_BITS = 5; - private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; - private static final int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; - private static final byte[] EMPTY = new byte[0]; - - private byte[] luminances; - private final int[] buckets; - - public GlobalHistogramBinarizer(LuminanceSource source) { - super(source); - luminances = EMPTY; - buckets = new int[LUMINANCE_BUCKETS]; - } - - // Applies simple sharpening to the row data to improve performance of the 1D Readers. - @Override - public BitArray getBlackRow(int y, BitArray row) throws NotFoundException { - LuminanceSource source = getLuminanceSource(); - int width = source.getWidth(); - if (row == null || row.getSize() < width) { - row = new BitArray(width); - } else { - row.clear(); - } - - initArrays(width); - byte[] localLuminances = source.getRow(y, luminances); - int[] localBuckets = buckets; - for (int x = 0; x < width; x++) { - int pixel = localLuminances[x] & 0xff; - localBuckets[pixel >> LUMINANCE_SHIFT]++; - } - int blackPoint = estimateBlackPoint(localBuckets); - - int left = localLuminances[0] & 0xff; - int center = localLuminances[1] & 0xff; - for (int x = 1; x < width - 1; x++) { - int right = localLuminances[x + 1] & 0xff; - // A simple -1 4 -1 box filter with a weight of 2. - int luminance = ((center * 4) - left - right) / 2; - if (luminance < blackPoint) { - row.set(x); - } - left = center; - center = right; - } - return row; - } - - // Does not sharpen the data, as this call is intended to only be used by 2D Readers. - @Override - public BitMatrix getBlackMatrix() throws NotFoundException { - LuminanceSource source = getLuminanceSource(); - int width = source.getWidth(); - int height = source.getHeight(); - BitMatrix matrix = new BitMatrix(width, height); - - // Quickly calculates the histogram by sampling four rows from the image. This proved to be - // more robust on the blackbox tests than sampling a diagonal as we used to do. - initArrays(width); - int[] localBuckets = buckets; - for (int y = 1; y < 5; y++) { - int row = height * y / 5; - byte[] localLuminances = source.getRow(row, luminances); - int right = (width * 4) / 5; - for (int x = width / 5; x < right; x++) { - int pixel = localLuminances[x] & 0xff; - localBuckets[pixel >> LUMINANCE_SHIFT]++; - } - } - int blackPoint = estimateBlackPoint(localBuckets); - - // We delay reading the entire image luminance until the black point estimation succeeds. - // Although we end up reading four rows twice, it is consistent with our motto of - // "fail quickly" which is necessary for continuous scanning. - byte[] localLuminances = source.getMatrix(); - for (int y = 0; y < height; y++) { - int offset = y * width; - for (int x = 0; x< width; x++) { - int pixel = localLuminances[offset + x] & 0xff; - if (pixel < blackPoint) { - matrix.set(x, y); - } - } - } - - return matrix; - } - - @Override - public Binarizer createBinarizer(LuminanceSource source) { - return new GlobalHistogramBinarizer(source); - } - - private void initArrays(int luminanceSize) { - if (luminances.length < luminanceSize) { - luminances = new byte[luminanceSize]; - } - for (int x = 0; x < LUMINANCE_BUCKETS; x++) { - buckets[x] = 0; - } - } - - private static int estimateBlackPoint(int[] buckets) throws NotFoundException { - // Find the tallest peak in the histogram. - int numBuckets = buckets.length; - int maxBucketCount = 0; - int firstPeak = 0; - int firstPeakSize = 0; - for (int x = 0; x < numBuckets; x++) { - if (buckets[x] > firstPeakSize) { - firstPeak = x; - firstPeakSize = buckets[x]; - } - if (buckets[x] > maxBucketCount) { - maxBucketCount = buckets[x]; - } - } - - // Find the second-tallest peak which is somewhat far from the tallest peak. - int secondPeak = 0; - int secondPeakScore = 0; - for (int x = 0; x < numBuckets; x++) { - int distanceToBiggest = x - firstPeak; - // Encourage more distant second peaks by multiplying by square of distance. - int score = buckets[x] * distanceToBiggest * distanceToBiggest; - if (score > secondPeakScore) { - secondPeak = x; - secondPeakScore = score; - } - } - - // Make sure firstPeak corresponds to the black peak. - if (firstPeak > secondPeak) { - int temp = firstPeak; - firstPeak = secondPeak; - secondPeak = temp; - } - - // If there is too little contrast in the image to pick a meaningful black point, throw rather - // than waste time trying to decode the image, and risk false positives. - if (secondPeak - firstPeak <= numBuckets / 16) { - throw NotFoundException.getNotFoundInstance(); - } - - // Find a valley between them that is low and closer to the white peak. - int bestValley = secondPeak - 1; - int bestValleyScore = -1; - for (int x = secondPeak - 1; x > firstPeak; x--) { - int fromFirst = x - firstPeak; - int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]); - if (score > bestValleyScore) { - bestValley = x; - bestValleyScore = score; - } - } - - return bestValley << LUMINANCE_SHIFT; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/GridSampler.java b/extern/zxing-core/src/main/java/com/google/zxing/common/GridSampler.java deleted file mode 100644 index 849588f4e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/GridSampler.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.NotFoundException; - -/** - * Implementations of this class can, given locations of finder patterns for a QR code in an - * image, sample the right points in the image to reconstruct the QR code, accounting for - * perspective distortion. It is abstracted since it is relatively expensive and should be allowed - * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced - * Imaging library, but which may not be available in other environments such as J2ME, and vice - * versa. - * - * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)} - * with an instance of a class which implements this interface. - * - * @author Sean Owen - */ -public abstract class GridSampler { - - private static GridSampler gridSampler = new DefaultGridSampler(); - - /** - * Sets the implementation of GridSampler used by the library. One global - * instance is stored, which may sound problematic. But, the implementation provided - * ought to be appropriate for the entire platform, and all uses of this library - * in the whole lifetime of the JVM. For instance, an Android activity can swap in - * an implementation that takes advantage of native platform libraries. - * - * @param newGridSampler The platform-specific object to install. - */ - public static void setGridSampler(GridSampler newGridSampler) { - gridSampler = newGridSampler; - } - - /** - * @return the current implementation of GridSampler - */ - public static GridSampler getInstance() { - return gridSampler; - } - - /** - * Samples an image for a rectangular matrix of bits of the given dimension. The sampling - * transformation is determined by the coordinates of 4 points, in the original and transformed - * image space. - * - * @param image image to sample - * @param dimensionX width of {@link BitMatrix} to sample from image - * @param dimensionY height of {@link BitMatrix} to sample from image - * @param p1ToX point 1 preimage X - * @param p1ToY point 1 preimage Y - * @param p2ToX point 2 preimage X - * @param p2ToY point 2 preimage Y - * @param p3ToX point 3 preimage X - * @param p3ToY point 3 preimage Y - * @param p4ToX point 4 preimage X - * @param p4ToY point 4 preimage Y - * @param p1FromX point 1 image X - * @param p1FromY point 1 image Y - * @param p2FromX point 2 image X - * @param p2FromY point 2 image Y - * @param p3FromX point 3 image X - * @param p3FromY point 3 image Y - * @param p4FromX point 4 image X - * @param p4FromY point 4 image Y - * @return {@link BitMatrix} representing a grid of points sampled from the image within a region - * defined by the "from" parameters - * @throws NotFoundException if image can't be sampled, for example, if the transformation defined - * by the given points is invalid or results in sampling outside the image boundaries - */ - public abstract BitMatrix sampleGrid(BitMatrix image, - int dimensionX, - int dimensionY, - float p1ToX, float p1ToY, - float p2ToX, float p2ToY, - float p3ToX, float p3ToY, - float p4ToX, float p4ToY, - float p1FromX, float p1FromY, - float p2FromX, float p2FromY, - float p3FromX, float p3FromY, - float p4FromX, float p4FromY) throws NotFoundException; - - public abstract BitMatrix sampleGrid(BitMatrix image, - int dimensionX, - int dimensionY, - PerspectiveTransform transform) throws NotFoundException; - - /** - *

    Checks a set of points that have been transformed to sample points on an image against - * the image's dimensions to see if the point are even within the image.

    - * - *

    This method will actually "nudge" the endpoints back onto the image if they are found to be - * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder - * patterns in an image where the QR Code runs all the way to the image border.

    - * - *

    For efficiency, the method will check points from either end of the line until one is found - * to be within the image. Because the set of points are assumed to be linear, this is valid.

    - * - * @param image image into which the points should map - * @param points actual points in x1,y1,...,xn,yn form - * @throws NotFoundException if an endpoint is lies outside the image boundaries - */ - protected static void checkAndNudgePoints(BitMatrix image, - float[] points) throws NotFoundException { - int width = image.getWidth(); - int height = image.getHeight(); - // Check and nudge points from start until we see some that are OK: - boolean nudged = true; - for (int offset = 0; offset < points.length && nudged; offset += 2) { - int x = (int) points[offset]; - int y = (int) points[offset + 1]; - if (x < -1 || x > width || y < -1 || y > height) { - throw NotFoundException.getNotFoundInstance(); - } - nudged = false; - if (x == -1) { - points[offset] = 0.0f; - nudged = true; - } else if (x == width) { - points[offset] = width - 1; - nudged = true; - } - if (y == -1) { - points[offset + 1] = 0.0f; - nudged = true; - } else if (y == height) { - points[offset + 1] = height - 1; - nudged = true; - } - } - // Check and nudge points from end: - nudged = true; - for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { - int x = (int) points[offset]; - int y = (int) points[offset + 1]; - if (x < -1 || x > width || y < -1 || y > height) { - throw NotFoundException.getNotFoundInstance(); - } - nudged = false; - if (x == -1) { - points[offset] = 0.0f; - nudged = true; - } else if (x == width) { - points[offset] = width - 1; - nudged = true; - } - if (y == -1) { - points[offset + 1] = 0.0f; - nudged = true; - } else if (y == height) { - points[offset + 1] = height - 1; - nudged = true; - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/HybridBinarizer.java b/extern/zxing-core/src/main/java/com/google/zxing/common/HybridBinarizer.java deleted file mode 100644 index de2934da4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/HybridBinarizer.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import com.google.zxing.Binarizer; -import com.google.zxing.LuminanceSource; -import com.google.zxing.NotFoundException; - -/** - * This class implements a local thresholding algorithm, which while slower than the - * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for - * high frequency images of barcodes with black data on white backgrounds. For this application, - * it does a much better job than a global blackpoint with severe shadows and gradients. - * However it tends to produce artifacts on lower frequency images and is therefore not - * a good general purpose binarizer for uses outside ZXing. - * - * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers, - * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already - * inherently local, and only fails for horizontal gradients. We can revisit that problem later, - * but for now it was not a win to use local blocks for 1D. - * - * This Binarizer is the default for the unit tests and the recommended class for library users. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class HybridBinarizer extends GlobalHistogramBinarizer { - - // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels. - // So this is the smallest dimension in each axis we can accept. - private static final int BLOCK_SIZE_POWER = 3; - private static final int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER; // ...0100...00 - private static final int BLOCK_SIZE_MASK = BLOCK_SIZE - 1; // ...0011...11 - private static final int MINIMUM_DIMENSION = BLOCK_SIZE * 5; - private static final int MIN_DYNAMIC_RANGE = 24; - - private BitMatrix matrix; - - public HybridBinarizer(LuminanceSource source) { - super(source); - } - - /** - * Calculates the final BitMatrix once for all requests. This could be called once from the - * constructor instead, but there are some advantages to doing it lazily, such as making - * profiling easier, and not doing heavy lifting when callers don't expect it. - */ - @Override - public BitMatrix getBlackMatrix() throws NotFoundException { - if (matrix != null) { - return matrix; - } - LuminanceSource source = getLuminanceSource(); - int width = source.getWidth(); - int height = source.getHeight(); - if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) { - byte[] luminances = source.getMatrix(); - int subWidth = width >> BLOCK_SIZE_POWER; - if ((width & BLOCK_SIZE_MASK) != 0) { - subWidth++; - } - int subHeight = height >> BLOCK_SIZE_POWER; - if ((height & BLOCK_SIZE_MASK) != 0) { - subHeight++; - } - int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height); - - BitMatrix newMatrix = new BitMatrix(width, height); - calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix); - matrix = newMatrix; - } else { - // If the image is too small, fall back to the global histogram approach. - matrix = super.getBlackMatrix(); - } - return matrix; - } - - @Override - public Binarizer createBinarizer(LuminanceSource source) { - return new HybridBinarizer(source); - } - - /** - * For each block in the image, calculate the average black point using a 5x5 grid - * of the blocks around it. Also handles the corner cases (fractional blocks are computed based - * on the last pixels in the row/column which are also used in the previous block). - */ - private static void calculateThresholdForBlock(byte[] luminances, - int subWidth, - int subHeight, - int width, - int height, - int[][] blackPoints, - BitMatrix matrix) { - for (int y = 0; y < subHeight; y++) { - int yoffset = y << BLOCK_SIZE_POWER; - int maxYOffset = height - BLOCK_SIZE; - if (yoffset > maxYOffset) { - yoffset = maxYOffset; - } - for (int x = 0; x < subWidth; x++) { - int xoffset = x << BLOCK_SIZE_POWER; - int maxXOffset = width - BLOCK_SIZE; - if (xoffset > maxXOffset) { - xoffset = maxXOffset; - } - int left = cap(x, 2, subWidth - 3); - int top = cap(y, 2, subHeight - 3); - int sum = 0; - for (int z = -2; z <= 2; z++) { - int[] blackRow = blackPoints[top + z]; - sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2]; - } - int average = sum / 25; - thresholdBlock(luminances, xoffset, yoffset, average, width, matrix); - } - } - } - - private static int cap(int value, int min, int max) { - return value < min ? min : value > max ? max : value; - } - - /** - * Applies a single threshold to a block of pixels. - */ - private static void thresholdBlock(byte[] luminances, - int xoffset, - int yoffset, - int threshold, - int stride, - BitMatrix matrix) { - for (int y = 0, offset = yoffset * stride + xoffset; y < BLOCK_SIZE; y++, offset += stride) { - for (int x = 0; x < BLOCK_SIZE; x++) { - // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. - if ((luminances[offset + x] & 0xFF) <= threshold) { - matrix.set(xoffset + x, yoffset + y); - } - } - } - } - - /** - * Calculates a single black point for each block of pixels and saves it away. - * See the following thread for a discussion of this algorithm: - * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 - */ - private static int[][] calculateBlackPoints(byte[] luminances, - int subWidth, - int subHeight, - int width, - int height) { - int[][] blackPoints = new int[subHeight][subWidth]; - for (int y = 0; y < subHeight; y++) { - int yoffset = y << BLOCK_SIZE_POWER; - int maxYOffset = height - BLOCK_SIZE; - if (yoffset > maxYOffset) { - yoffset = maxYOffset; - } - for (int x = 0; x < subWidth; x++) { - int xoffset = x << BLOCK_SIZE_POWER; - int maxXOffset = width - BLOCK_SIZE; - if (xoffset > maxXOffset) { - xoffset = maxXOffset; - } - int sum = 0; - int min = 0xFF; - int max = 0; - for (int yy = 0, offset = yoffset * width + xoffset; yy < BLOCK_SIZE; yy++, offset += width) { - for (int xx = 0; xx < BLOCK_SIZE; xx++) { - int pixel = luminances[offset + xx] & 0xFF; - sum += pixel; - // still looking for good contrast - if (pixel < min) { - min = pixel; - } - if (pixel > max) { - max = pixel; - } - } - // short-circuit min/max tests once dynamic range is met - if (max - min > MIN_DYNAMIC_RANGE) { - // finish the rest of the rows quickly - for (yy++, offset += width; yy < BLOCK_SIZE; yy++, offset += width) { - for (int xx = 0; xx < BLOCK_SIZE; xx++) { - sum += luminances[offset + xx] & 0xFF; - } - } - } - } - - // The default estimate is the average of the values in the block. - int average = sum >> (BLOCK_SIZE_POWER * 2); - if (max - min <= MIN_DYNAMIC_RANGE) { - // If variation within the block is low, assume this is a block with only light or only - // dark pixels. In that case we do not want to use the average, as it would divide this - // low contrast area into black and white pixels, essentially creating data out of noise. - // - // The default assumption is that the block is light/background. Since no estimate for - // the level of dark pixels exists locally, use half the min for the block. - average = min / 2; - - if (y > 0 && x > 0) { - // Correct the "white background" assumption for blocks that have neighbors by comparing - // the pixels in this block to the previously calculated black points. This is based on - // the fact that dark barcode symbology is always surrounded by some amount of light - // background for which reasonable black point estimates were made. The bp estimated at - // the boundaries is used for the interior. - - // The (min < bp) is arbitrary but works better than other heuristics that were tried. - int averageNeighborBlackPoint = - (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4; - if (min < averageNeighborBlackPoint) { - average = averageNeighborBlackPoint; - } - } - } - blackPoints[y][x] = average; - } - } - return blackPoints; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/PerspectiveTransform.java b/extern/zxing-core/src/main/java/com/google/zxing/common/PerspectiveTransform.java deleted file mode 100644 index 8ddfa7f24..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/PerspectiveTransform.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -/** - *

    This class implements a perspective transform in two dimensions. Given four source and four - * destination points, it will compute the transformation implied between them. The code is based - * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.

    - * - * @author Sean Owen - */ -public final class PerspectiveTransform { - - private final float a11; - private final float a12; - private final float a13; - private final float a21; - private final float a22; - private final float a23; - private final float a31; - private final float a32; - private final float a33; - - private PerspectiveTransform(float a11, float a21, float a31, - float a12, float a22, float a32, - float a13, float a23, float a33) { - this.a11 = a11; - this.a12 = a12; - this.a13 = a13; - this.a21 = a21; - this.a22 = a22; - this.a23 = a23; - this.a31 = a31; - this.a32 = a32; - this.a33 = a33; - } - - public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0, - float x1, float y1, - float x2, float y2, - float x3, float y3, - float x0p, float y0p, - float x1p, float y1p, - float x2p, float y2p, - float x3p, float y3p) { - - PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); - PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); - return sToQ.times(qToS); - } - - public void transformPoints(float[] points) { - int max = points.length; - float a11 = this.a11; - float a12 = this.a12; - float a13 = this.a13; - float a21 = this.a21; - float a22 = this.a22; - float a23 = this.a23; - float a31 = this.a31; - float a32 = this.a32; - float a33 = this.a33; - for (int i = 0; i < max; i += 2) { - float x = points[i]; - float y = points[i + 1]; - float denominator = a13 * x + a23 * y + a33; - points[i] = (a11 * x + a21 * y + a31) / denominator; - points[i + 1] = (a12 * x + a22 * y + a32) / denominator; - } - } - - public void transformPoints(float[] xValues, float[] yValues) { - int n = xValues.length; - for (int i = 0; i < n; i ++) { - float x = xValues[i]; - float y = yValues[i]; - float denominator = a13 * x + a23 * y + a33; - xValues[i] = (a11 * x + a21 * y + a31) / denominator; - yValues[i] = (a12 * x + a22 * y + a32) / denominator; - } - } - - public static PerspectiveTransform squareToQuadrilateral(float x0, float y0, - float x1, float y1, - float x2, float y2, - float x3, float y3) { - float dx3 = x0 - x1 + x2 - x3; - float dy3 = y0 - y1 + y2 - y3; - if (dx3 == 0.0f && dy3 == 0.0f) { - // Affine - return new PerspectiveTransform(x1 - x0, x2 - x1, x0, - y1 - y0, y2 - y1, y0, - 0.0f, 0.0f, 1.0f); - } else { - float dx1 = x1 - x2; - float dx2 = x3 - x2; - float dy1 = y1 - y2; - float dy2 = y3 - y2; - float denominator = dx1 * dy2 - dx2 * dy1; - float a13 = (dx3 * dy2 - dx2 * dy3) / denominator; - float a23 = (dx1 * dy3 - dx3 * dy1) / denominator; - return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, - y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, - a13, a23, 1.0f); - } - } - - public static PerspectiveTransform quadrilateralToSquare(float x0, float y0, - float x1, float y1, - float x2, float y2, - float x3, float y3) { - // Here, the adjoint serves as the inverse: - return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint(); - } - - PerspectiveTransform buildAdjoint() { - // Adjoint is the transpose of the cofactor matrix: - return new PerspectiveTransform(a22 * a33 - a23 * a32, - a23 * a31 - a21 * a33, - a21 * a32 - a22 * a31, - a13 * a32 - a12 * a33, - a11 * a33 - a13 * a31, - a12 * a31 - a11 * a32, - a12 * a23 - a13 * a22, - a13 * a21 - a11 * a23, - a11 * a22 - a12 * a21); - } - - PerspectiveTransform times(PerspectiveTransform other) { - return new PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13, - a11 * other.a21 + a21 * other.a22 + a31 * other.a23, - a11 * other.a31 + a21 * other.a32 + a31 * other.a33, - a12 * other.a11 + a22 * other.a12 + a32 * other.a13, - a12 * other.a21 + a22 * other.a22 + a32 * other.a23, - a12 * other.a31 + a22 * other.a32 + a32 * other.a33, - a13 * other.a11 + a23 * other.a12 + a33 * other.a13, - a13 * other.a21 + a23 * other.a22 + a33 * other.a23, - a13 * other.a31 + a23 * other.a32 + a33 * other.a33); - - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/StringUtils.java b/extern/zxing-core/src/main/java/com/google/zxing/common/StringUtils.java deleted file mode 100644 index 9ea1d822e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/StringUtils.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -import java.nio.charset.Charset; -import java.util.Map; - -import com.google.zxing.DecodeHintType; - -/** - * Common string-related functions. - * - * @author Sean Owen - * @author Alex Dupre - */ -public final class StringUtils { - - private static final String PLATFORM_DEFAULT_ENCODING = Charset.defaultCharset().name(); - public static final String SHIFT_JIS = "SJIS"; - public static final String GB2312 = "GB2312"; - private static final String EUC_JP = "EUC_JP"; - private static final String UTF8 = "UTF8"; - private static final String ISO88591 = "ISO8859_1"; - private static final boolean ASSUME_SHIFT_JIS = - SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) || - EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING); - - private StringUtils() {} - - /** - * @param bytes bytes encoding a string, whose encoding should be guessed - * @param hints decode hints if applicable - * @return name of guessed encoding; at the moment will only guess one of: - * {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform - * default encoding if none of these can possibly be correct - */ - public static String guessEncoding(byte[] bytes, Map hints) { - if (hints != null) { - String characterSet = (String) hints.get(DecodeHintType.CHARACTER_SET); - if (characterSet != null) { - return characterSet; - } - } - // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS, - // which should be by far the most common encodings. - int length = bytes.length; - boolean canBeISO88591 = true; - boolean canBeShiftJIS = true; - boolean canBeUTF8 = true; - int utf8BytesLeft = 0; - //int utf8LowChars = 0; - int utf2BytesChars = 0; - int utf3BytesChars = 0; - int utf4BytesChars = 0; - int sjisBytesLeft = 0; - //int sjisLowChars = 0; - int sjisKatakanaChars = 0; - //int sjisDoubleBytesChars = 0; - int sjisCurKatakanaWordLength = 0; - int sjisCurDoubleBytesWordLength = 0; - int sjisMaxKatakanaWordLength = 0; - int sjisMaxDoubleBytesWordLength = 0; - //int isoLowChars = 0; - //int isoHighChars = 0; - int isoHighOther = 0; - - boolean utf8bom = bytes.length > 3 && - bytes[0] == (byte) 0xEF && - bytes[1] == (byte) 0xBB && - bytes[2] == (byte) 0xBF; - - for (int i = 0; - i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); - i++) { - - int value = bytes[i] & 0xFF; - - // UTF-8 stuff - if (canBeUTF8) { - if (utf8BytesLeft > 0) { - if ((value & 0x80) == 0) { - canBeUTF8 = false; - } else { - utf8BytesLeft--; - } - } else if ((value & 0x80) != 0) { - if ((value & 0x40) == 0) { - canBeUTF8 = false; - } else { - utf8BytesLeft++; - if ((value & 0x20) == 0) { - utf2BytesChars++; - } else { - utf8BytesLeft++; - if ((value & 0x10) == 0) { - utf3BytesChars++; - } else { - utf8BytesLeft++; - if ((value & 0x08) == 0) { - utf4BytesChars++; - } else { - canBeUTF8 = false; - } - } - } - } - } //else { - //utf8LowChars++; - //} - } - - // ISO-8859-1 stuff - if (canBeISO88591) { - if (value > 0x7F && value < 0xA0) { - canBeISO88591 = false; - } else if (value > 0x9F) { - if (value < 0xC0 || value == 0xD7 || value == 0xF7) { - isoHighOther++; - } //else { - //isoHighChars++; - //} - } //else { - //isoLowChars++; - //} - } - - // Shift_JIS stuff - if (canBeShiftJIS) { - if (sjisBytesLeft > 0) { - if (value < 0x40 || value == 0x7F || value > 0xFC) { - canBeShiftJIS = false; - } else { - sjisBytesLeft--; - } - } else if (value == 0x80 || value == 0xA0 || value > 0xEF) { - canBeShiftJIS = false; - } else if (value > 0xA0 && value < 0xE0) { - sjisKatakanaChars++; - sjisCurDoubleBytesWordLength = 0; - sjisCurKatakanaWordLength++; - if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) { - sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength; - } - } else if (value > 0x7F) { - sjisBytesLeft++; - //sjisDoubleBytesChars++; - sjisCurKatakanaWordLength = 0; - sjisCurDoubleBytesWordLength++; - if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) { - sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength; - } - } else { - //sjisLowChars++; - sjisCurKatakanaWordLength = 0; - sjisCurDoubleBytesWordLength = 0; - } - } - } - - if (canBeUTF8 && utf8BytesLeft > 0) { - canBeUTF8 = false; - } - if (canBeShiftJIS && sjisBytesLeft > 0) { - canBeShiftJIS = false; - } - - // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done - if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) { - return UTF8; - } - // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done - if (canBeShiftJIS && (ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) { - return SHIFT_JIS; - } - // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is: - // - If we saw - // - only two consecutive katakana chars in the whole text, or - // - at least 10% of bytes that could be "upper" not-alphanumeric Latin1, - // - then we conclude Shift_JIS, else ISO-8859-1 - if (canBeISO88591 && canBeShiftJIS) { - return (sjisMaxKatakanaWordLength == 2 && sjisKatakanaChars == 2) || isoHighOther * 10 >= length - ? SHIFT_JIS : ISO88591; - } - - // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding - if (canBeISO88591) { - return ISO88591; - } - if (canBeShiftJIS) { - return SHIFT_JIS; - } - if (canBeUTF8) { - return UTF8; - } - // Otherwise, we take a wild guess with platform encoding - return PLATFORM_DEFAULT_ENCODING; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MathUtils.java b/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MathUtils.java deleted file mode 100644 index 82aa03943..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MathUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.detector; - -public final class MathUtils { - - private MathUtils() { - } - - /** - * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its - * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut - * differ slightly from {@link Math#round(float)} in that half rounds down for negative - * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference. - * - * @param d real value to round - * @return nearest {@code int} - */ - public static int round(float d) { - return (int) (d + (d < 0.0f ? -0.5f : 0.5f)); - } - - public static float distance(float aX, float aY, float bX, float bY) { - float xDiff = aX - bX; - float yDiff = aY - bY; - return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff); - } - - public static float distance(int aX, int aY, int bX, int bY) { - int xDiff = aX - bX; - int yDiff = aY - bY; - return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java b/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java deleted file mode 100644 index 1ce8452ee..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.detector; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; - -/** - *

    A somewhat generic detector that looks for a barcode-like rectangular region within an image. - * It looks within a mostly white region of an image for a region of black and white, but mostly - * black. It returns the four corners of the region, as best it can determine.

    - * - * @author Sean Owen - */ -public final class MonochromeRectangleDetector { - - private static final int MAX_MODULES = 32; - - private final BitMatrix image; - - public MonochromeRectangleDetector(BitMatrix image) { - this.image = image; - } - - /** - *

    Detects a rectangular region of black and white -- mostly black -- with a region of mostly - * white, in an image.

    - * - * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and - * last points are opposed on the diagonal, as are the second and third. The first point will be - * the topmost point and the last, the bottommost. The second point will be leftmost and the - * third, the rightmost - * @throws NotFoundException if no Data Matrix Code can be found - */ - public ResultPoint[] detect() throws NotFoundException { - int height = image.getHeight(); - int width = image.getWidth(); - int halfHeight = height / 2; - int halfWidth = width / 2; - int deltaY = Math.max(1, height / (MAX_MODULES * 8)); - int deltaX = Math.max(1, width / (MAX_MODULES * 8)); - - int top = 0; - int bottom = height; - int left = 0; - int right = width; - ResultPoint pointA = findCornerFromCenter(halfWidth, 0, left, right, - halfHeight, -deltaY, top, bottom, halfWidth / 2); - top = (int) pointA.getY() - 1; - ResultPoint pointB = findCornerFromCenter(halfWidth, -deltaX, left, right, - halfHeight, 0, top, bottom, halfHeight / 2); - left = (int) pointB.getX() - 1; - ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right, - halfHeight, 0, top, bottom, halfHeight / 2); - right = (int) pointC.getX() + 1; - ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right, - halfHeight, deltaY, top, bottom, halfWidth / 2); - bottom = (int) pointD.getY() + 1; - - // Go try to find point A again with better information -- might have been off at first. - pointA = findCornerFromCenter(halfWidth, 0, left, right, - halfHeight, -deltaY, top, bottom, halfWidth / 4); - - return new ResultPoint[] { pointA, pointB, pointC, pointD }; - } - - /** - * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center - * point which should be within the barcode. - * - * @param centerX center's x component (horizontal) - * @param deltaX same as deltaY but change in x per step instead - * @param left minimum value of x - * @param right maximum value of x - * @param centerY center's y component (vertical) - * @param deltaY change in y per step. If scanning up this is negative; down, positive; - * left or right, 0 - * @param top minimum value of y to search through (meaningless when di == 0) - * @param bottom maximum value of y - * @param maxWhiteRun maximum run of white pixels that can still be considered to be within - * the barcode - * @return a {@link com.google.zxing.ResultPoint} encapsulating the corner that was found - * @throws NotFoundException if such a point cannot be found - */ - private ResultPoint findCornerFromCenter(int centerX, - int deltaX, - int left, - int right, - int centerY, - int deltaY, - int top, - int bottom, - int maxWhiteRun) throws NotFoundException { - int[] lastRange = null; - for (int y = centerY, x = centerX; - y < bottom && y >= top && x < right && x >= left; - y += deltaY, x += deltaX) { - int[] range; - if (deltaX == 0) { - // horizontal slices, up and down - range = blackWhiteRange(y, maxWhiteRun, left, right, true); - } else { - // vertical slices, left and right - range = blackWhiteRange(x, maxWhiteRun, top, bottom, false); - } - if (range == null) { - if (lastRange == null) { - throw NotFoundException.getNotFoundInstance(); - } - // lastRange was found - if (deltaX == 0) { - int lastY = y - deltaY; - if (lastRange[0] < centerX) { - if (lastRange[1] > centerX) { - // straddle, choose one or the other based on direction - return new ResultPoint(deltaY > 0 ? lastRange[0] : lastRange[1], lastY); - } - return new ResultPoint(lastRange[0], lastY); - } else { - return new ResultPoint(lastRange[1], lastY); - } - } else { - int lastX = x - deltaX; - if (lastRange[0] < centerY) { - if (lastRange[1] > centerY) { - return new ResultPoint(lastX, deltaX < 0 ? lastRange[0] : lastRange[1]); - } - return new ResultPoint(lastX, lastRange[0]); - } else { - return new ResultPoint(lastX, lastRange[1]); - } - } - } - lastRange = range; - } - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Computes the start and end of a region of pixels, either horizontally or vertically, that could - * be part of a Data Matrix barcode. - * - * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location) - * where we are scanning. If scanning vertically it's the column, the fixed horizontal location - * @param maxWhiteRun largest run of white pixels that can still be considered part of the - * barcode region - * @param minDim minimum pixel location, horizontally or vertically, to consider - * @param maxDim maximum pixel location, horizontally or vertically, to consider - * @param horizontal if true, we're scanning left-right, instead of up-down - * @return int[] with start and end of found range, or null if no such range is found - * (e.g. only white was found) - */ - private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, boolean horizontal) { - - int center = (minDim + maxDim) / 2; - - // Scan left/up first - int start = center; - while (start >= minDim) { - if (horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)) { - start--; - } else { - int whiteRunStart = start; - do { - start--; - } while (start >= minDim && !(horizontal ? image.get(start, fixedDimension) : - image.get(fixedDimension, start))); - int whiteRunSize = whiteRunStart - start; - if (start < minDim || whiteRunSize > maxWhiteRun) { - start = whiteRunStart; - break; - } - } - } - start++; - - // Then try right/down - int end = center; - while (end < maxDim) { - if (horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)) { - end++; - } else { - int whiteRunStart = end; - do { - end++; - } while (end < maxDim && !(horizontal ? image.get(end, fixedDimension) : - image.get(fixedDimension, end))); - int whiteRunSize = end - whiteRunStart; - if (end >= maxDim || whiteRunSize > maxWhiteRun) { - end = whiteRunStart; - break; - } - } - } - end--; - - return end > start ? new int[]{start, end} : null; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java b/extern/zxing-core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java deleted file mode 100644 index 9e0cce0fc..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.detector; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; - -/** - *

    - * Detects a candidate barcode-like rectangular region within an image. It - * starts around the center of the image, increases the size of the candidate - * region until it finds a white rectangular region. By keeping track of the - * last black points it encountered, it determines the corners of the barcode. - *

    - * - * @author David Olivier - */ -public final class WhiteRectangleDetector { - - private static final int INIT_SIZE = 10; - private static final int CORR = 1; - - private final BitMatrix image; - private final int height; - private final int width; - private final int leftInit; - private final int rightInit; - private final int downInit; - private final int upInit; - - public WhiteRectangleDetector(BitMatrix image) throws NotFoundException { - this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2); - } - - /** - * @param image barcode image to find a rectangle in - * @param initSize initial size of search area around center - * @param x x position of search center - * @param y y position of search center - * @throws NotFoundException if image is too small to accommodate {@code initSize} - */ - public WhiteRectangleDetector(BitMatrix image, int initSize, int x, int y) throws NotFoundException { - this.image = image; - height = image.getHeight(); - width = image.getWidth(); - int halfsize = initSize / 2; - leftInit = x - halfsize; - rightInit = x + halfsize; - upInit = y - halfsize; - downInit = y + halfsize; - if (upInit < 0 || leftInit < 0 || downInit >= height || rightInit >= width) { - throw NotFoundException.getNotFoundInstance(); - } - } - - /** - *

    - * Detects a candidate barcode-like rectangular region within an image. It - * starts around the center of the image, increases the size of the candidate - * region until it finds a white rectangular region. - *

    - * - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - * @throws NotFoundException if no Data Matrix Code can be found - */ - public ResultPoint[] detect() throws NotFoundException { - - int left = leftInit; - int right = rightInit; - int up = upInit; - int down = downInit; - boolean sizeExceeded = false; - boolean aBlackPointFoundOnBorder = true; - boolean atLeastOneBlackPointFoundOnBorder = false; - - boolean atLeastOneBlackPointFoundOnRight = false; - boolean atLeastOneBlackPointFoundOnBottom = false; - boolean atLeastOneBlackPointFoundOnLeft = false; - boolean atLeastOneBlackPointFoundOnTop = false; - - while (aBlackPointFoundOnBorder) { - - aBlackPointFoundOnBorder = false; - - // ..... - // . | - // ..... - boolean rightBorderNotWhite = true; - while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) { - rightBorderNotWhite = containsBlackPoint(up, down, right, false); - if (rightBorderNotWhite) { - right++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnRight = true; - } else if (!atLeastOneBlackPointFoundOnRight) { - right++; - } - } - - if (right >= width) { - sizeExceeded = true; - break; - } - - // ..... - // . . - // .___. - boolean bottomBorderNotWhite = true; - while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) { - bottomBorderNotWhite = containsBlackPoint(left, right, down, true); - if (bottomBorderNotWhite) { - down++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnBottom = true; - } else if (!atLeastOneBlackPointFoundOnBottom) { - down++; - } - } - - if (down >= height) { - sizeExceeded = true; - break; - } - - // ..... - // | . - // ..... - boolean leftBorderNotWhite = true; - while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { - leftBorderNotWhite = containsBlackPoint(up, down, left, false); - if (leftBorderNotWhite) { - left--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnLeft = true; - } else if (!atLeastOneBlackPointFoundOnLeft) { - left--; - } - } - - if (left < 0) { - sizeExceeded = true; - break; - } - - // .___. - // . . - // ..... - boolean topBorderNotWhite = true; - while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { - topBorderNotWhite = containsBlackPoint(left, right, up, true); - if (topBorderNotWhite) { - up--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnTop = true; - } else if (!atLeastOneBlackPointFoundOnTop) { - up--; - } - } - - if (up < 0) { - sizeExceeded = true; - break; - } - - if (aBlackPointFoundOnBorder) { - atLeastOneBlackPointFoundOnBorder = true; - } - - } - - if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { - - int maxSize = right - left; - - ResultPoint z = null; - for (int i = 1; i < maxSize; i++) { - z = getBlackPointOnSegment(left, down - i, left + i, down); - if (z != null) { - break; - } - } - - if (z == null) { - throw NotFoundException.getNotFoundInstance(); - } - - ResultPoint t = null; - //go down right - for (int i = 1; i < maxSize; i++) { - t = getBlackPointOnSegment(left, up + i, left + i, up); - if (t != null) { - break; - } - } - - if (t == null) { - throw NotFoundException.getNotFoundInstance(); - } - - ResultPoint x = null; - //go down left - for (int i = 1; i < maxSize; i++) { - x = getBlackPointOnSegment(right, up + i, right - i, up); - if (x != null) { - break; - } - } - - if (x == null) { - throw NotFoundException.getNotFoundInstance(); - } - - ResultPoint y = null; - //go up left - for (int i = 1; i < maxSize; i++) { - y = getBlackPointOnSegment(right, down - i, right - i, down); - if (y != null) { - break; - } - } - - if (y == null) { - throw NotFoundException.getNotFoundInstance(); - } - - return centerEdges(y, z, x, t); - - } else { - throw NotFoundException.getNotFoundInstance(); - } - } - - private ResultPoint getBlackPointOnSegment(float aX, float aY, float bX, float bY) { - int dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY)); - float xStep = (bX - aX) / dist; - float yStep = (bY - aY) / dist; - - for (int i = 0; i < dist; i++) { - int x = MathUtils.round(aX + i * xStep); - int y = MathUtils.round(aY + i * yStep); - if (image.get(x, y)) { - return new ResultPoint(x, y); - } - } - return null; - } - - /** - * recenters the points of a constant distance towards the center - * - * @param y bottom most point - * @param z left most point - * @param x right most point - * @param t top most point - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - */ - private ResultPoint[] centerEdges(ResultPoint y, ResultPoint z, - ResultPoint x, ResultPoint t) { - - // - // t t - // z x - // x OR z - // y y - // - - float yi = y.getX(); - float yj = y.getY(); - float zi = z.getX(); - float zj = z.getY(); - float xi = x.getX(); - float xj = x.getY(); - float ti = t.getX(); - float tj = t.getY(); - - if (yi < width / 2.0f) { - return new ResultPoint[]{ - new ResultPoint(ti - CORR, tj + CORR), - new ResultPoint(zi + CORR, zj + CORR), - new ResultPoint(xi - CORR, xj - CORR), - new ResultPoint(yi + CORR, yj - CORR)}; - } else { - return new ResultPoint[]{ - new ResultPoint(ti + CORR, tj + CORR), - new ResultPoint(zi + CORR, zj - CORR), - new ResultPoint(xi - CORR, xj + CORR), - new ResultPoint(yi - CORR, yj - CORR)}; - } - } - - /** - * Determines whether a segment contains a black point - * - * @param a min value of the scanned coordinate - * @param b max value of the scanned coordinate - * @param fixed value of fixed coordinate - * @param horizontal set to true if scan must be horizontal, false if vertical - * @return true if a black point has been found, else false. - */ - private boolean containsBlackPoint(int a, int b, int fixed, boolean horizontal) { - - if (horizontal) { - for (int x = a; x <= b; x++) { - if (image.get(x, fixed)) { - return true; - } - } - } else { - for (int y = a; y <= b; y++) { - if (image.get(fixed, y)) { - return true; - } - } - } - - return false; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java b/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java deleted file mode 100644 index 9ede5d80a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.reedsolomon; - -/** - *

    This class contains utility methods for performing mathematical operations over - * the Galois Fields. Operations use a given primitive polynomial in calculations.

    - * - *

    Throughout this package, elements of the GF are represented as an {@code int} - * for convenience and speed (but at the cost of memory). - *

    - * - * @author Sean Owen - * @author David Olivier - */ -public final class GenericGF { - - public static final GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 - public static final GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1 - public static final GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1 - public static final GenericGF AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1 - public static final GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 - public static final GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 - public static final GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256; - public static final GenericGF MAXICODE_FIELD_64 = AZTEC_DATA_6; - - private final int[] expTable; - private final int[] logTable; - private final GenericGFPoly zero; - private final GenericGFPoly one; - private final int size; - private final int primitive; - private final int generatorBase; - - /** - * Create a representation of GF(size) using the given primitive polynomial. - * - * @param primitive irreducible polynomial whose coefficients are represented by - * the bits of an int, where the least-significant bit represents the constant - * coefficient - * @param size the size of the field - * @param b the factor b in the generator polynomial can be 0- or 1-based - * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))). - * In most cases it should be 1, but for QR code it is 0. - */ - public GenericGF(int primitive, int size, int b) { - this.primitive = primitive; - this.size = size; - this.generatorBase = b; - - expTable = new int[size]; - logTable = new int[size]; - int x = 1; - for (int i = 0; i < size; i++) { - expTable[i] = x; - x *= 2; // we're assuming the generator alpha is 2 - if (x >= size) { - x ^= primitive; - x &= size-1; - } - } - for (int i = 0; i < size-1; i++) { - logTable[expTable[i]] = i; - } - // logTable[0] == 0 but this should never be used - zero = new GenericGFPoly(this, new int[]{0}); - one = new GenericGFPoly(this, new int[]{1}); - } - - GenericGFPoly getZero() { - return zero; - } - - GenericGFPoly getOne() { - return one; - } - - /** - * @return the monomial representing coefficient * x^degree - */ - GenericGFPoly buildMonomial(int degree, int coefficient) { - if (degree < 0) { - throw new IllegalArgumentException(); - } - if (coefficient == 0) { - return zero; - } - int[] coefficients = new int[degree + 1]; - coefficients[0] = coefficient; - return new GenericGFPoly(this, coefficients); - } - - /** - * Implements both addition and subtraction -- they are the same in GF(size). - * - * @return sum/difference of a and b - */ - static int addOrSubtract(int a, int b) { - return a ^ b; - } - - /** - * @return 2 to the power of a in GF(size) - */ - int exp(int a) { - return expTable[a]; - } - - /** - * @return base 2 log of a in GF(size) - */ - int log(int a) { - if (a == 0) { - throw new IllegalArgumentException(); - } - return logTable[a]; - } - - /** - * @return multiplicative inverse of a - */ - int inverse(int a) { - if (a == 0) { - throw new ArithmeticException(); - } - return expTable[size - logTable[a] - 1]; - } - - /** - * @return product of a and b in GF(size) - */ - int multiply(int a, int b) { - if (a == 0 || b == 0) { - return 0; - } - return expTable[(logTable[a] + logTable[b]) % (size - 1)]; - } - - public int getSize() { - return size; - } - - public int getGeneratorBase() { - return generatorBase; - } - - @Override - public String toString() { - return "GF(0x" + Integer.toHexString(primitive) + ',' + size + ')'; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java b/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java deleted file mode 100644 index 8887e0ee1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.reedsolomon; - -/** - *

    Represents a polynomial whose coefficients are elements of a GF. - * Instances of this class are immutable.

    - * - *

    Much credit is due to William Rucklidge since portions of this code are an indirect - * port of his C++ Reed-Solomon implementation.

    - * - * @author Sean Owen - */ -final class GenericGFPoly { - - private final GenericGF field; - private final int[] coefficients; - - /** - * @param field the {@link GenericGF} instance representing the field to use - * to perform computations - * @param coefficients coefficients as ints representing elements of GF(size), arranged - * from most significant (highest-power term) coefficient to least significant - * @throws IllegalArgumentException if argument is null or empty, - * or if leading coefficient is 0 and this is not a - * constant polynomial (that is, it is not the monomial "0") - */ - GenericGFPoly(GenericGF field, int[] coefficients) { - if (coefficients.length == 0) { - throw new IllegalArgumentException(); - } - this.field = field; - int coefficientsLength = coefficients.length; - if (coefficientsLength > 1 && coefficients[0] == 0) { - // Leading term must be non-zero for anything except the constant polynomial "0" - int firstNonZero = 1; - while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) { - firstNonZero++; - } - if (firstNonZero == coefficientsLength) { - this.coefficients = new int[]{0}; - } else { - this.coefficients = new int[coefficientsLength - firstNonZero]; - System.arraycopy(coefficients, - firstNonZero, - this.coefficients, - 0, - this.coefficients.length); - } - } else { - this.coefficients = coefficients; - } - } - - int[] getCoefficients() { - return coefficients; - } - - /** - * @return degree of this polynomial - */ - int getDegree() { - return coefficients.length - 1; - } - - /** - * @return true iff this polynomial is the monomial "0" - */ - boolean isZero() { - return coefficients[0] == 0; - } - - /** - * @return coefficient of x^degree term in this polynomial - */ - int getCoefficient(int degree) { - return coefficients[coefficients.length - 1 - degree]; - } - - /** - * @return evaluation of this polynomial at a given point - */ - int evaluateAt(int a) { - if (a == 0) { - // Just return the x^0 coefficient - return getCoefficient(0); - } - int size = coefficients.length; - if (a == 1) { - // Just the sum of the coefficients - int result = 0; - for (int coefficient : coefficients) { - result = GenericGF.addOrSubtract(result, coefficient); - } - return result; - } - int result = coefficients[0]; - for (int i = 1; i < size; i++) { - result = GenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); - } - return result; - } - - GenericGFPoly addOrSubtract(GenericGFPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (isZero()) { - return other; - } - if (other.isZero()) { - return this; - } - - int[] smallerCoefficients = this.coefficients; - int[] largerCoefficients = other.coefficients; - if (smallerCoefficients.length > largerCoefficients.length) { - int[] temp = smallerCoefficients; - smallerCoefficients = largerCoefficients; - largerCoefficients = temp; - } - int[] sumDiff = new int[largerCoefficients.length]; - int lengthDiff = largerCoefficients.length - smallerCoefficients.length; - // Copy high-order terms only found in higher-degree polynomial's coefficients - System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - - for (int i = lengthDiff; i < largerCoefficients.length; i++) { - sumDiff[i] = GenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); - } - - return new GenericGFPoly(field, sumDiff); - } - - GenericGFPoly multiply(GenericGFPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (isZero() || other.isZero()) { - return field.getZero(); - } - int[] aCoefficients = this.coefficients; - int aLength = aCoefficients.length; - int[] bCoefficients = other.coefficients; - int bLength = bCoefficients.length; - int[] product = new int[aLength + bLength - 1]; - for (int i = 0; i < aLength; i++) { - int aCoeff = aCoefficients[i]; - for (int j = 0; j < bLength; j++) { - product[i + j] = GenericGF.addOrSubtract(product[i + j], - field.multiply(aCoeff, bCoefficients[j])); - } - } - return new GenericGFPoly(field, product); - } - - GenericGFPoly multiply(int scalar) { - if (scalar == 0) { - return field.getZero(); - } - if (scalar == 1) { - return this; - } - int size = coefficients.length; - int[] product = new int[size]; - for (int i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], scalar); - } - return new GenericGFPoly(field, product); - } - - GenericGFPoly multiplyByMonomial(int degree, int coefficient) { - if (degree < 0) { - throw new IllegalArgumentException(); - } - if (coefficient == 0) { - return field.getZero(); - } - int size = coefficients.length; - int[] product = new int[size + degree]; - for (int i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], coefficient); - } - return new GenericGFPoly(field, product); - } - - GenericGFPoly[] divide(GenericGFPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (other.isZero()) { - throw new IllegalArgumentException("Divide by 0"); - } - - GenericGFPoly quotient = field.getZero(); - GenericGFPoly remainder = this; - - int denominatorLeadingTerm = other.getCoefficient(other.getDegree()); - int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); - - while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) { - int degreeDifference = remainder.getDegree() - other.getDegree(); - int scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm); - GenericGFPoly term = other.multiplyByMonomial(degreeDifference, scale); - GenericGFPoly iterationQuotient = field.buildMonomial(degreeDifference, scale); - quotient = quotient.addOrSubtract(iterationQuotient); - remainder = remainder.addOrSubtract(term); - } - - return new GenericGFPoly[] { quotient, remainder }; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(8 * getDegree()); - for (int degree = getDegree(); degree >= 0; degree--) { - int coefficient = getCoefficient(degree); - if (coefficient != 0) { - if (coefficient < 0) { - result.append(" - "); - coefficient = -coefficient; - } else { - if (result.length() > 0) { - result.append(" + "); - } - } - if (degree == 0 || coefficient != 1) { - int alphaPower = field.log(coefficient); - if (alphaPower == 0) { - result.append('1'); - } else if (alphaPower == 1) { - result.append('a'); - } else { - result.append("a^"); - result.append(alphaPower); - } - } - if (degree != 0) { - if (degree == 1) { - result.append('x'); - } else { - result.append("x^"); - result.append(degree); - } - } - } - } - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java deleted file mode 100644 index 19127e0c6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.reedsolomon; - -/** - *

    Implements Reed-Solomon decoding, as the name implies.

    - * - *

    The algorithm will not be explained here, but the following references were helpful - * in creating this implementation:

    - * - * - * - *

    Much credit is due to William Rucklidge since portions of this code are an indirect - * port of his C++ Reed-Solomon implementation.

    - * - * @author Sean Owen - * @author William Rucklidge - * @author sanfordsquires - */ -public final class ReedSolomonDecoder { - - private final GenericGF field; - - public ReedSolomonDecoder(GenericGF field) { - this.field = field; - } - - /** - *

    Decodes given set of received codewords, which include both data and error-correction - * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, - * in the input.

    - * - * @param received data and error-correction codewords - * @param twoS number of error-correction codewords available - * @throws ReedSolomonException if decoding fails for any reason - */ - public void decode(int[] received, int twoS) throws ReedSolomonException { - GenericGFPoly poly = new GenericGFPoly(field, received); - int[] syndromeCoefficients = new int[twoS]; - boolean noError = true; - for (int i = 0; i < twoS; i++) { - int eval = poly.evaluateAt(field.exp(i + field.getGeneratorBase())); - syndromeCoefficients[syndromeCoefficients.length - 1 - i] = eval; - if (eval != 0) { - noError = false; - } - } - if (noError) { - return; - } - GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients); - GenericGFPoly[] sigmaOmega = - runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS); - GenericGFPoly sigma = sigmaOmega[0]; - GenericGFPoly omega = sigmaOmega[1]; - int[] errorLocations = findErrorLocations(sigma); - int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations); - for (int i = 0; i < errorLocations.length; i++) { - int position = received.length - 1 - field.log(errorLocations[i]); - if (position < 0) { - throw new ReedSolomonException("Bad error location"); - } - received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]); - } - } - - private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R) - throws ReedSolomonException { - // Assume a's degree is >= b's - if (a.getDegree() < b.getDegree()) { - GenericGFPoly temp = a; - a = b; - b = temp; - } - - GenericGFPoly rLast = a; - GenericGFPoly r = b; - GenericGFPoly tLast = field.getZero(); - GenericGFPoly t = field.getOne(); - - // Run Euclidean algorithm until r's degree is less than R/2 - while (r.getDegree() >= R / 2) { - GenericGFPoly rLastLast = rLast; - GenericGFPoly tLastLast = tLast; - rLast = r; - tLast = t; - - // Divide rLastLast by rLast, with quotient in q and remainder in r - if (rLast.isZero()) { - // Oops, Euclidean algorithm already terminated? - throw new ReedSolomonException("r_{i-1} was zero"); - } - r = rLastLast; - GenericGFPoly q = field.getZero(); - int denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree()); - int dltInverse = field.inverse(denominatorLeadingTerm); - while (r.getDegree() >= rLast.getDegree() && !r.isZero()) { - int degreeDiff = r.getDegree() - rLast.getDegree(); - int scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse); - q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); - r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); - } - - t = q.multiply(tLast).addOrSubtract(tLastLast); - - if (r.getDegree() >= rLast.getDegree()) { - throw new IllegalStateException("Division algorithm failed to reduce polynomial?"); - } - } - - int sigmaTildeAtZero = t.getCoefficient(0); - if (sigmaTildeAtZero == 0) { - throw new ReedSolomonException("sigmaTilde(0) was zero"); - } - - int inverse = field.inverse(sigmaTildeAtZero); - GenericGFPoly sigma = t.multiply(inverse); - GenericGFPoly omega = r.multiply(inverse); - return new GenericGFPoly[]{sigma, omega}; - } - - private int[] findErrorLocations(GenericGFPoly errorLocator) throws ReedSolomonException { - // This is a direct application of Chien's search - int numErrors = errorLocator.getDegree(); - if (numErrors == 1) { // shortcut - return new int[] { errorLocator.getCoefficient(1) }; - } - int[] result = new int[numErrors]; - int e = 0; - for (int i = 1; i < field.getSize() && e < numErrors; i++) { - if (errorLocator.evaluateAt(i) == 0) { - result[e] = field.inverse(i); - e++; - } - } - if (e != numErrors) { - throw new ReedSolomonException("Error locator degree does not match number of roots"); - } - return result; - } - - private int[] findErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations) { - // This is directly applying Forney's Formula - int s = errorLocations.length; - int[] result = new int[s]; - for (int i = 0; i < s; i++) { - int xiInverse = field.inverse(errorLocations[i]); - int denominator = 1; - for (int j = 0; j < s; j++) { - if (i != j) { - //denominator = field.multiply(denominator, - // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); - // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. - // Below is a funny-looking workaround from Steven Parkes - int term = field.multiply(errorLocations[j], xiInverse); - int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1; - denominator = field.multiply(denominator, termPlus1); - } - } - result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), - field.inverse(denominator)); - if (field.getGeneratorBase() != 0) { - result[i] = field.multiply(result[i], xiInverse); - } - } - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java deleted file mode 100644 index ff813cb1f..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.reedsolomon; - -import java.util.ArrayList; -import java.util.List; - -/** - *

    Implements Reed-Solomon enbcoding, as the name implies.

    - * - * @author Sean Owen - * @author William Rucklidge - */ -public final class ReedSolomonEncoder { - - private final GenericGF field; - private final List cachedGenerators; - - public ReedSolomonEncoder(GenericGF field) { - this.field = field; - this.cachedGenerators = new ArrayList<>(); - cachedGenerators.add(new GenericGFPoly(field, new int[]{1})); - } - - private GenericGFPoly buildGenerator(int degree) { - if (degree >= cachedGenerators.size()) { - GenericGFPoly lastGenerator = cachedGenerators.get(cachedGenerators.size() - 1); - for (int d = cachedGenerators.size(); d <= degree; d++) { - GenericGFPoly nextGenerator = lastGenerator.multiply( - new GenericGFPoly(field, new int[] { 1, field.exp(d - 1 + field.getGeneratorBase()) })); - cachedGenerators.add(nextGenerator); - lastGenerator = nextGenerator; - } - } - return cachedGenerators.get(degree); - } - - public void encode(int[] toEncode, int ecBytes) { - if (ecBytes == 0) { - throw new IllegalArgumentException("No error correction bytes"); - } - int dataBytes = toEncode.length - ecBytes; - if (dataBytes <= 0) { - throw new IllegalArgumentException("No data bytes provided"); - } - GenericGFPoly generator = buildGenerator(ecBytes); - int[] infoCoefficients = new int[dataBytes]; - System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes); - GenericGFPoly info = new GenericGFPoly(field, infoCoefficients); - info = info.multiplyByMonomial(ecBytes, 1); - GenericGFPoly remainder = info.divide(generator)[1]; - int[] coefficients = remainder.getCoefficients(); - int numZeroCoefficients = ecBytes - coefficients.length; - for (int i = 0; i < numZeroCoefficients; i++) { - toEncode[dataBytes + i] = 0; - } - System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java b/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java deleted file mode 100644 index d5b45a612..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common.reedsolomon; - -/** - *

    Thrown when an exception occurs during Reed-Solomon decoding, such as when - * there are too many errors to correct.

    - * - * @author Sean Owen - */ -public final class ReedSolomonException extends Exception { - - public ReedSolomonException(String message) { - super(message); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixReader.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixReader.java deleted file mode 100644 index e02d766a1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixReader.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.datamatrix.decoder.Decoder; -import com.google.zxing.datamatrix.detector.Detector; - -import java.util.List; -import java.util.Map; - -/** - * This implementation can detect and decode Data Matrix codes in an image. - * - * @author bbrown@google.com (Brian Brown) - */ -public final class DataMatrixReader implements Reader { - - private static final ResultPoint[] NO_POINTS = new ResultPoint[0]; - - private final Decoder decoder = new Decoder(); - - /** - * Locates and decodes a Data Matrix code in an image. - * - * @return a String representing the content encoded by the Data Matrix code - * @throws NotFoundException if a Data Matrix code cannot be found - * @throws FormatException if a Data Matrix code cannot be decoded - * @throws ChecksumException if error correction fails - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException { - return decode(image, null); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, ChecksumException, FormatException { - DecoderResult decoderResult; - ResultPoint[] points; - if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { - BitMatrix bits = extractPureBits(image.getBlackMatrix()); - decoderResult = decoder.decode(bits); - points = NO_POINTS; - } else { - DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(); - decoderResult = decoder.decode(detectorResult.getBits()); - points = detectorResult.getPoints(); - } - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, - BarcodeFormat.DATA_MATRIX); - List byteSegments = decoderResult.getByteSegments(); - if (byteSegments != null) { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - String ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - return result; - } - - @Override - public void reset() { - // do nothing - } - - /** - * This method detects a code in a "pure" image -- that is, pure monochrome image - * which contains only an unrotated, unskewed, image of a code, with some white border - * around it. This is a specialized method that works exceptionally fast in this special - * case. - * - * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix) - */ - private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException { - - int[] leftTopBlack = image.getTopLeftOnBit(); - int[] rightBottomBlack = image.getBottomRightOnBit(); - if (leftTopBlack == null || rightBottomBlack == null) { - throw NotFoundException.getNotFoundInstance(); - } - - int moduleSize = moduleSize(leftTopBlack, image); - - int top = leftTopBlack[1]; - int bottom = rightBottomBlack[1]; - int left = leftTopBlack[0]; - int right = rightBottomBlack[0]; - - int matrixWidth = (right - left + 1) / moduleSize; - int matrixHeight = (bottom - top + 1) / moduleSize; - if (matrixWidth <= 0 || matrixHeight <= 0) { - throw NotFoundException.getNotFoundInstance(); - } - - // Push in the "border" by half the module width so that we start - // sampling in the middle of the module. Just in case the image is a - // little off, this will help recover. - int nudge = moduleSize / 2; - top += nudge; - left += nudge; - - // Now just read off the bits - BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight); - for (int y = 0; y < matrixHeight; y++) { - int iOffset = top + y * moduleSize; - for (int x = 0; x < matrixWidth; x++) { - if (image.get(left + x * moduleSize, iOffset)) { - bits.set(x, y); - } - } - } - return bits; - } - - private static int moduleSize(int[] leftTopBlack, BitMatrix image) throws NotFoundException { - int width = image.getWidth(); - int x = leftTopBlack[0]; - int y = leftTopBlack[1]; - while (x < width && image.get(x, y)) { - x++; - } - if (x == width) { - throw NotFoundException.getNotFoundInstance(); - } - - int moduleSize = x - leftTopBlack[0]; - if (moduleSize == 0) { - throw NotFoundException.getNotFoundInstance(); - } - return moduleSize; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixWriter.java deleted file mode 100644 index 32bf3f67a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/DataMatrixWriter.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.datamatrix.encoder.DefaultPlacement; -import com.google.zxing.Dimension; -import com.google.zxing.datamatrix.encoder.ErrorCorrection; -import com.google.zxing.datamatrix.encoder.HighLevelEncoder; -import com.google.zxing.datamatrix.encoder.SymbolInfo; -import com.google.zxing.datamatrix.encoder.SymbolShapeHint; -import com.google.zxing.qrcode.encoder.ByteMatrix; - -import java.util.Map; - -/** - * This object renders a Data Matrix code as a BitMatrix 2D array of greyscale values. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Guillaume Le Biller Added to zxing lib. - */ -public final class DataMatrixWriter implements Writer { - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) { - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map hints) { - - if (contents.isEmpty()) { - throw new IllegalArgumentException("Found empty contents"); - } - - if (format != BarcodeFormat.DATA_MATRIX) { - throw new IllegalArgumentException("Can only encode DATA_MATRIX, but got " + format); - } - - if (width < 0 || height < 0) { - throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' + height); - } - - // Try to get force shape & min / max size - SymbolShapeHint shape = SymbolShapeHint.FORCE_NONE; - Dimension minSize = null; - Dimension maxSize = null; - if (hints != null) { - SymbolShapeHint requestedShape = (SymbolShapeHint) hints.get(EncodeHintType.DATA_MATRIX_SHAPE); - if (requestedShape != null) { - shape = requestedShape; - } - @SuppressWarnings("deprecation") - Dimension requestedMinSize = (Dimension) hints.get(EncodeHintType.MIN_SIZE); - if (requestedMinSize != null) { - minSize = requestedMinSize; - } - @SuppressWarnings("deprecation") - Dimension requestedMaxSize = (Dimension) hints.get(EncodeHintType.MAX_SIZE); - if (requestedMaxSize != null) { - maxSize = requestedMaxSize; - } - } - - - //1. step: Data encodation - String encoded = HighLevelEncoder.encodeHighLevel(contents, shape, minSize, maxSize); - - SymbolInfo symbolInfo = SymbolInfo.lookup(encoded.length(), shape, minSize, maxSize, true); - - //2. step: ECC generation - String codewords = ErrorCorrection.encodeECC200(encoded, symbolInfo); - - //3. step: Module placement in Matrix - DefaultPlacement placement = - new DefaultPlacement(codewords, symbolInfo.getSymbolDataWidth(), symbolInfo.getSymbolDataHeight()); - placement.place(); - - //4. step: low-level encoding - return encodeLowLevel(placement, symbolInfo); - } - - /** - * Encode the given symbol info to a bit matrix. - * - * @param placement The DataMatrix placement. - * @param symbolInfo The symbol info to encode. - * @return The bit matrix generated. - */ - private static BitMatrix encodeLowLevel(DefaultPlacement placement, SymbolInfo symbolInfo) { - int symbolWidth = symbolInfo.getSymbolDataWidth(); - int symbolHeight = symbolInfo.getSymbolDataHeight(); - - ByteMatrix matrix = new ByteMatrix(symbolInfo.getSymbolWidth(), symbolInfo.getSymbolHeight()); - - int matrixY = 0; - - for (int y = 0; y < symbolHeight; y++) { - // Fill the top edge with alternate 0 / 1 - int matrixX; - if ((y % symbolInfo.matrixHeight) == 0) { - matrixX = 0; - for (int x = 0; x < symbolInfo.getSymbolWidth(); x++) { - matrix.set(matrixX, matrixY, (x % 2) == 0); - matrixX++; - } - matrixY++; - } - matrixX = 0; - for (int x = 0; x < symbolWidth; x++) { - // Fill the right edge with full 1 - if ((x % symbolInfo.matrixWidth) == 0) { - matrix.set(matrixX, matrixY, true); - matrixX++; - } - matrix.set(matrixX, matrixY, placement.getBit(x, y)); - matrixX++; - // Fill the right edge with alternate 0 / 1 - if ((x % symbolInfo.matrixWidth) == symbolInfo.matrixWidth - 1) { - matrix.set(matrixX, matrixY, (y % 2) == 0); - matrixX++; - } - } - matrixY++; - // Fill the bottom edge with full 1 - if ((y % symbolInfo.matrixHeight) == symbolInfo.matrixHeight - 1) { - matrixX = 0; - for (int x = 0; x < symbolInfo.getSymbolWidth(); x++) { - matrix.set(matrixX, matrixY, true); - matrixX++; - } - matrixY++; - } - } - - return convertByteMatrixToBitMatrix(matrix); - } - - /** - * Convert the ByteMatrix to BitMatrix. - * - * @param matrix The input matrix. - * @return The output matrix. - */ - private static BitMatrix convertByteMatrixToBitMatrix(ByteMatrix matrix) { - int matrixWidgth = matrix.getWidth(); - int matrixHeight = matrix.getHeight(); - - BitMatrix output = new BitMatrix(matrixWidgth, matrixHeight); - output.clear(); - for (int i = 0; i < matrixWidgth; i++) { - for (int j = 0; j < matrixHeight; j++) { - // Zero is white in the bytematrix - if (matrix.get(i, j) == 1) { - output.set(i, j); - } - } - } - - return output; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/BitMatrixParser.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/BitMatrixParser.java deleted file mode 100644 index f04f21937..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/BitMatrixParser.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; - -/** - * @author bbrown@google.com (Brian Brown) - */ -final class BitMatrixParser { - - private final BitMatrix mappingBitMatrix; - private final BitMatrix readMappingMatrix; - private final Version version; - - /** - * @param bitMatrix {@link BitMatrix} to parse - * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2 - */ - BitMatrixParser(BitMatrix bitMatrix) throws FormatException { - int dimension = bitMatrix.getHeight(); - if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0) { - throw FormatException.getFormatInstance(); - } - - version = readVersion(bitMatrix); - this.mappingBitMatrix = extractDataRegion(bitMatrix); - this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getWidth(), this.mappingBitMatrix.getHeight()); - } - - Version getVersion() { - return version; - } - - /** - *

    Creates the version object based on the dimension of the original bit matrix from - * the datamatrix code.

    - * - *

    See ISO 16022:2006 Table 7 - ECC 200 symbol attributes

    - * - * @param bitMatrix Original {@link BitMatrix} including alignment patterns - * @return {@link Version} encapsulating the Data Matrix Code's "version" - * @throws FormatException if the dimensions of the mapping matrix are not valid - * Data Matrix dimensions. - */ - private static Version readVersion(BitMatrix bitMatrix) throws FormatException { - int numRows = bitMatrix.getHeight(); - int numColumns = bitMatrix.getWidth(); - return Version.getVersionForDimensions(numRows, numColumns); - } - - /** - *

    Reads the bits in the {@link BitMatrix} representing the mapping matrix (No alignment patterns) - * in the correct order in order to reconstitute the codewords bytes contained within the - * Data Matrix Code.

    - * - * @return bytes encoded within the Data Matrix Code - * @throws FormatException if the exact number of bytes expected is not read - */ - byte[] readCodewords() throws FormatException { - - byte[] result = new byte[version.getTotalCodewords()]; - int resultOffset = 0; - - int row = 4; - int column = 0; - - int numRows = mappingBitMatrix.getHeight(); - int numColumns = mappingBitMatrix.getWidth(); - - boolean corner1Read = false; - boolean corner2Read = false; - boolean corner3Read = false; - boolean corner4Read = false; - - // Read all of the codewords - do { - // Check the four corner cases - if ((row == numRows) && (column == 0) && !corner1Read) { - result[resultOffset++] = (byte) readCorner1(numRows, numColumns); - row -= 2; - column +=2; - corner1Read = true; - } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read) { - result[resultOffset++] = (byte) readCorner2(numRows, numColumns); - row -= 2; - column +=2; - corner2Read = true; - } else if ((row == numRows+4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read) { - result[resultOffset++] = (byte) readCorner3(numRows, numColumns); - row -= 2; - column +=2; - corner3Read = true; - } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read) { - result[resultOffset++] = (byte) readCorner4(numRows, numColumns); - row -= 2; - column +=2; - corner4Read = true; - } else { - // Sweep upward diagonally to the right - do { - if ((row < numRows) && (column >= 0) && !readMappingMatrix.get(column, row)) { - result[resultOffset++] = (byte) readUtah(row, column, numRows, numColumns); - } - row -= 2; - column +=2; - } while ((row >= 0) && (column < numColumns)); - row += 1; - column +=3; - - // Sweep downward diagonally to the left - do { - if ((row >= 0) && (column < numColumns) && !readMappingMatrix.get(column, row)) { - result[resultOffset++] = (byte) readUtah(row, column, numRows, numColumns); - } - row += 2; - column -=2; - } while ((row < numRows) && (column >= 0)); - row += 3; - column +=1; - } - } while ((row < numRows) || (column < numColumns)); - - if (resultOffset != version.getTotalCodewords()) { - throw FormatException.getFormatInstance(); - } - return result; - } - - /** - *

    Reads a bit of the mapping matrix accounting for boundary wrapping.

    - * - * @param row Row to read in the mapping matrix - * @param column Column to read in the mapping matrix - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return value of the given bit in the mapping matrix - */ - boolean readModule(int row, int column, int numRows, int numColumns) { - // Adjust the row and column indices based on boundary wrapping - if (row < 0) { - row += numRows; - column += 4 - ((numRows + 4) & 0x07); - } - if (column < 0) { - column += numColumns; - row += 4 - ((numColumns + 4) & 0x07); - } - readMappingMatrix.set(column, row); - return mappingBitMatrix.get(column, row); - } - - /** - *

    Reads the 8 bits of the standard Utah-shaped pattern.

    - * - *

    See ISO 16022:2006, 5.8.1 Figure 6

    - * - * @param row Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern - * @param column Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return byte from the utah shape - */ - int readUtah(int row, int column, int numRows, int numColumns) { - int currentByte = 0; - if (readModule(row - 2, column - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 2, column - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column, numRows, numColumns)) { - currentByte |= 1; - } - return currentByte; - } - - /** - *

    Reads the 8 bits of the special corner condition 1.

    - * - *

    See ISO 16022:2006, Figure F.3

    - * - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return byte from the Corner condition 1 - */ - int readCorner1(int numRows, int numColumns) { - int currentByte = 0; - if (readModule(numRows - 1, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(2, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(3, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - return currentByte; - } - - /** - *

    Reads the 8 bits of the special corner condition 2.

    - * - *

    See ISO 16022:2006, Figure F.4

    - * - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return byte from the Corner condition 2 - */ - int readCorner2(int numRows, int numColumns) { - int currentByte = 0; - if (readModule(numRows - 3, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 2, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 4, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 3, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - return currentByte; - } - - /** - *

    Reads the 8 bits of the special corner condition 3.

    - * - *

    See ISO 16022:2006, Figure F.5

    - * - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return byte from the Corner condition 3 - */ - int readCorner3(int numRows, int numColumns) { - int currentByte = 0; - if (readModule(numRows - 1, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 3, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 3, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - return currentByte; - } - - /** - *

    Reads the 8 bits of the special corner condition 4.

    - * - *

    See ISO 16022:2006, Figure F.6

    - * - * @param numRows Number of rows in the mapping matrix - * @param numColumns Number of columns in the mapping matrix - * @return byte from the Corner condition 4 - */ - int readCorner4(int numRows, int numColumns) { - int currentByte = 0; - if (readModule(numRows - 3, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 2, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 0, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(2, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(3, numColumns - 1, numRows, numColumns)) { - currentByte |= 1; - } - return currentByte; - } - - /** - *

    Extracts the data region from a {@link BitMatrix} that contains - * alignment patterns.

    - * - * @param bitMatrix Original {@link BitMatrix} with alignment patterns - * @return BitMatrix that has the alignment patterns removed - */ - BitMatrix extractDataRegion(BitMatrix bitMatrix) { - int symbolSizeRows = version.getSymbolSizeRows(); - int symbolSizeColumns = version.getSymbolSizeColumns(); - - if (bitMatrix.getHeight() != symbolSizeRows) { - throw new IllegalArgumentException("Dimension of bitMarix must match the version size"); - } - - int dataRegionSizeRows = version.getDataRegionSizeRows(); - int dataRegionSizeColumns = version.getDataRegionSizeColumns(); - - int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows; - int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns; - - int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows; - int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns; - - BitMatrix bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow); - for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) { - int dataRegionRowOffset = dataRegionRow * dataRegionSizeRows; - for (int dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) { - int dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns; - for (int i = 0; i < dataRegionSizeRows; ++i) { - int readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i; - int writeRowOffset = dataRegionRowOffset + i; - for (int j = 0; j < dataRegionSizeColumns; ++j) { - int readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j; - if (bitMatrix.get(readColumnOffset, readRowOffset)) { - int writeColumnOffset = dataRegionColumnOffset + j; - bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset); - } - } - } - } - } - return bitMatrixWithoutAlignment; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DataBlock.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DataBlock.java deleted file mode 100644 index 35edd42f5..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DataBlock.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.decoder; - -/** - *

    Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into - * multiple blocks, each of which is a unit of data and error-correction codewords. Each - * is represented by an instance of this class.

    - * - * @author bbrown@google.com (Brian Brown) - */ -final class DataBlock { - - private final int numDataCodewords; - private final byte[] codewords; - - private DataBlock(int numDataCodewords, byte[] codewords) { - this.numDataCodewords = numDataCodewords; - this.codewords = codewords; - } - - /** - *

    When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them. - * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This - * method will separate the data into original blocks.

    - * - * @param rawCodewords bytes as read directly from the Data Matrix Code - * @param version version of the Data Matrix Code - * @return DataBlocks containing original bytes, "de-interleaved" from representation in the - * Data Matrix Code - */ - static DataBlock[] getDataBlocks(byte[] rawCodewords, - Version version) { - // Figure out the number and size of data blocks used by this version - Version.ECBlocks ecBlocks = version.getECBlocks(); - - // First count the total number of data blocks - int totalBlocks = 0; - Version.ECB[] ecBlockArray = ecBlocks.getECBlocks(); - for (Version.ECB ecBlock : ecBlockArray) { - totalBlocks += ecBlock.getCount(); - } - - // Now establish DataBlocks of the appropriate size and number of data codewords - DataBlock[] result = new DataBlock[totalBlocks]; - int numResultBlocks = 0; - for (Version.ECB ecBlock : ecBlockArray) { - for (int i = 0; i < ecBlock.getCount(); i++) { - int numDataCodewords = ecBlock.getDataCodewords(); - int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords; - result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]); - } - } - - // All blocks have the same amount of data, except that the last n - // (where n may be 0) have 1 less byte. Figure out where these start. - // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144 - int longerBlocksTotalCodewords = result[0].codewords.length; - //int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1; - - int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords(); - int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1; - // The last elements of result may be 1 element shorter for 144 matrix - // first fill out as many elements as all of them have minus 1 - int rawCodewordsOffset = 0; - for (int i = 0; i < shorterBlocksNumDataCodewords; i++) { - for (int j = 0; j < numResultBlocks; j++) { - result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; - } - } - - // Fill out the last data block in the longer ones - boolean specialVersion = version.getVersionNumber() == 24; - int numLongerBlocks = specialVersion ? 8 : numResultBlocks; - for (int j = 0; j < numLongerBlocks; j++) { - result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++]; - } - - // Now add in error correction blocks - int max = result[0].codewords.length; - for (int i = longerBlocksNumDataCodewords; i < max; i++) { - for (int j = 0; j < numResultBlocks; j++) { - int jOffset = specialVersion ? (j + 8) % numResultBlocks : j; - int iOffset = specialVersion && jOffset > 7 ? i - 1 : i; - result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; - } - } - - if (rawCodewordsOffset != rawCodewords.length) { - throw new IllegalArgumentException(); - } - - return result; - } - - int getNumDataCodewords() { - return numDataCodewords; - } - - byte[] getCodewords() { - return codewords; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java deleted file mode 100644 index 16f2ecb7d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.common.BitSource; -import com.google.zxing.common.DecoderResult; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - *

    Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes - * in one Data Matrix Code. This class decodes the bits back into text.

    - * - *

    See ISO 16022:2006, 5.2.1 - 5.2.9.2

    - * - * @author bbrown@google.com (Brian Brown) - * @author Sean Owen - */ -final class DecodedBitStreamParser { - - private enum Mode { - PAD_ENCODE, // Not really a mode - ASCII_ENCODE, - C40_ENCODE, - TEXT_ENCODE, - ANSIX12_ENCODE, - EDIFACT_ENCODE, - BASE256_ENCODE - } - - /** - * See ISO 16022:2006, Annex C Table C.1 - * The C40 Basic Character Set (*'s used for placeholders for the shift values) - */ - private static final char[] C40_BASIC_SET_CHARS = { - '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' - }; - - private static final char[] C40_SHIFT2_SET_CHARS = { - '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', - '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_' - }; - - /** - * See ISO 16022:2006, Annex C Table C.2 - * The Text Basic Character Set (*'s used for placeholders for the shift values) - */ - private static final char[] TEXT_BASIC_SET_CHARS = { - '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' - }; - - // Shift 2 for Text is the same encoding as C40 - private static final char[] TEXT_SHIFT2_SET_CHARS = C40_SHIFT2_SET_CHARS; - - private static final char[] TEXT_SHIFT3_SET_CHARS = { - '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (char) 127 - }; - - private DecodedBitStreamParser() { - } - - static DecoderResult decode(byte[] bytes) throws FormatException { - BitSource bits = new BitSource(bytes); - StringBuilder result = new StringBuilder(100); - StringBuilder resultTrailer = new StringBuilder(0); - List byteSegments = new ArrayList<>(1); - Mode mode = Mode.ASCII_ENCODE; - do { - if (mode == Mode.ASCII_ENCODE) { - mode = decodeAsciiSegment(bits, result, resultTrailer); - } else { - switch (mode) { - case C40_ENCODE: - decodeC40Segment(bits, result); - break; - case TEXT_ENCODE: - decodeTextSegment(bits, result); - break; - case ANSIX12_ENCODE: - decodeAnsiX12Segment(bits, result); - break; - case EDIFACT_ENCODE: - decodeEdifactSegment(bits, result); - break; - case BASE256_ENCODE: - decodeBase256Segment(bits, result, byteSegments); - break; - default: - throw FormatException.getFormatInstance(); - } - mode = Mode.ASCII_ENCODE; - } - } while (mode != Mode.PAD_ENCODE && bits.available() > 0); - if (resultTrailer.length() > 0) { - result.append(resultTrailer); - } - return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, null); - } - - /** - * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2 - */ - private static Mode decodeAsciiSegment(BitSource bits, - StringBuilder result, - StringBuilder resultTrailer) throws FormatException { - boolean upperShift = false; - do { - int oneByte = bits.readBits(8); - if (oneByte == 0) { - throw FormatException.getFormatInstance(); - } else if (oneByte <= 128) { // ASCII data (ASCII value + 1) - if (upperShift) { - oneByte += 128; - //upperShift = false; - } - result.append((char) (oneByte - 1)); - return Mode.ASCII_ENCODE; - } else if (oneByte == 129) { // Pad - return Mode.PAD_ENCODE; - } else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130) - int value = oneByte - 130; - if (value < 10) { // pad with '0' for single digit values - result.append('0'); - } - result.append(value); - } else if (oneByte == 230) { // Latch to C40 encodation - return Mode.C40_ENCODE; - } else if (oneByte == 231) { // Latch to Base 256 encodation - return Mode.BASE256_ENCODE; - } else if (oneByte == 232) { - // FNC1 - result.append((char) 29); // translate as ASCII 29 - } else if (oneByte == 233 || oneByte == 234) { - // Structured Append, Reader Programming - // Ignore these symbols for now - //throw ReaderException.getInstance(); - } else if (oneByte == 235) { // Upper Shift (shift to Extended ASCII) - upperShift = true; - } else if (oneByte == 236) { // 05 Macro - result.append("[)>\u001E05\u001D"); - resultTrailer.insert(0, "\u001E\u0004"); - } else if (oneByte == 237) { // 06 Macro - result.append("[)>\u001E06\u001D"); - resultTrailer.insert(0, "\u001E\u0004"); - } else if (oneByte == 238) { // Latch to ANSI X12 encodation - return Mode.ANSIX12_ENCODE; - } else if (oneByte == 239) { // Latch to Text encodation - return Mode.TEXT_ENCODE; - } else if (oneByte == 240) { // Latch to EDIFACT encodation - return Mode.EDIFACT_ENCODE; - } else if (oneByte == 241) { // ECI Character - // TODO(bbrown): I think we need to support ECI - //throw ReaderException.getInstance(); - // Ignore this symbol for now - } else if (oneByte >= 242) { // Not to be used in ASCII encodation - // ... but work around encoders that end with 254, latch back to ASCII - if (oneByte != 254 || bits.available() != 0) { - throw FormatException.getFormatInstance(); - } - } - } while (bits.available() > 0); - return Mode.ASCII_ENCODE; - } - - /** - * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1 - */ - private static void decodeC40Segment(BitSource bits, StringBuilder result) throws FormatException { - // Three C40 values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time - boolean upperShift = false; - - int[] cValues = new int[3]; - int shift = 0; - - do { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) { - return; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) { // Unlatch codeword - return; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) { - int cValue = cValues[i]; - switch (shift) { - case 0: - if (cValue < 3) { - shift = cValue + 1; - } else if (cValue < C40_BASIC_SET_CHARS.length) { - char c40char = C40_BASIC_SET_CHARS[cValue]; - if (upperShift) { - result.append((char) (c40char + 128)); - upperShift = false; - } else { - result.append(c40char); - } - } else { - throw FormatException.getFormatInstance(); - } - break; - case 1: - if (upperShift) { - result.append((char) (cValue + 128)); - upperShift = false; - } else { - result.append((char) cValue); - } - shift = 0; - break; - case 2: - if (cValue < C40_SHIFT2_SET_CHARS.length) { - char c40char = C40_SHIFT2_SET_CHARS[cValue]; - if (upperShift) { - result.append((char) (c40char + 128)); - upperShift = false; - } else { - result.append(c40char); - } - } else if (cValue == 27) { // FNC1 - result.append((char) 29); // translate as ASCII 29 - } else if (cValue == 30) { // Upper Shift - upperShift = true; - } else { - throw FormatException.getFormatInstance(); - } - shift = 0; - break; - case 3: - if (upperShift) { - result.append((char) (cValue + 224)); - upperShift = false; - } else { - result.append((char) (cValue + 96)); - } - shift = 0; - break; - default: - throw FormatException.getFormatInstance(); - } - } - } while (bits.available() > 0); - } - - /** - * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2 - */ - private static void decodeTextSegment(BitSource bits, StringBuilder result) throws FormatException { - // Three Text values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time - boolean upperShift = false; - - int[] cValues = new int[3]; - int shift = 0; - do { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) { - return; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) { // Unlatch codeword - return; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) { - int cValue = cValues[i]; - switch (shift) { - case 0: - if (cValue < 3) { - shift = cValue + 1; - } else if (cValue < TEXT_BASIC_SET_CHARS.length) { - char textChar = TEXT_BASIC_SET_CHARS[cValue]; - if (upperShift) { - result.append((char) (textChar + 128)); - upperShift = false; - } else { - result.append(textChar); - } - } else { - throw FormatException.getFormatInstance(); - } - break; - case 1: - if (upperShift) { - result.append((char) (cValue + 128)); - upperShift = false; - } else { - result.append((char) cValue); - } - shift = 0; - break; - case 2: - // Shift 2 for Text is the same encoding as C40 - if (cValue < TEXT_SHIFT2_SET_CHARS.length) { - char textChar = TEXT_SHIFT2_SET_CHARS[cValue]; - if (upperShift) { - result.append((char) (textChar + 128)); - upperShift = false; - } else { - result.append(textChar); - } - } else if (cValue == 27) { // FNC1 - result.append((char) 29); // translate as ASCII 29 - } else if (cValue == 30) { // Upper Shift - upperShift = true; - } else { - throw FormatException.getFormatInstance(); - } - shift = 0; - break; - case 3: - if (cValue < TEXT_SHIFT3_SET_CHARS.length) { - char textChar = TEXT_SHIFT3_SET_CHARS[cValue]; - if (upperShift) { - result.append((char) (textChar + 128)); - upperShift = false; - } else { - result.append(textChar); - } - shift = 0; - } else { - throw FormatException.getFormatInstance(); - } - break; - default: - throw FormatException.getFormatInstance(); - } - } - } while (bits.available() > 0); - } - - /** - * See ISO 16022:2006, 5.2.7 - */ - private static void decodeAnsiX12Segment(BitSource bits, - StringBuilder result) throws FormatException { - // Three ANSI X12 values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - - int[] cValues = new int[3]; - do { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) { - return; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) { // Unlatch codeword - return; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) { - int cValue = cValues[i]; - if (cValue == 0) { // X12 segment terminator - result.append('\r'); - } else if (cValue == 1) { // X12 segment separator * - result.append('*'); - } else if (cValue == 2) { // X12 sub-element separator > - result.append('>'); - } else if (cValue == 3) { // space - result.append(' '); - } else if (cValue < 14) { // 0 - 9 - result.append((char) (cValue + 44)); - } else if (cValue < 40) { // A - Z - result.append((char) (cValue + 51)); - } else { - throw FormatException.getFormatInstance(); - } - } - } while (bits.available() > 0); - } - - private static void parseTwoBytes(int firstByte, int secondByte, int[] result) { - int fullBitValue = (firstByte << 8) + secondByte - 1; - int temp = fullBitValue / 1600; - result[0] = temp; - fullBitValue -= temp * 1600; - temp = fullBitValue / 40; - result[1] = temp; - result[2] = fullBitValue - temp * 40; - } - - /** - * See ISO 16022:2006, 5.2.8 and Annex C Table C.3 - */ - private static void decodeEdifactSegment(BitSource bits, StringBuilder result) { - do { - // If there is only two or less bytes left then it will be encoded as ASCII - if (bits.available() <= 16) { - return; - } - - for (int i = 0; i < 4; i++) { - int edifactValue = bits.readBits(6); - - // Check for the unlatch character - if (edifactValue == 0x1F) { // 011111 - // Read rest of byte, which should be 0, and stop - int bitsLeft = 8 - bits.getBitOffset(); - if (bitsLeft != 8) { - bits.readBits(bitsLeft); - } - return; - } - - if ((edifactValue & 0x20) == 0) { // no 1 in the leading (6th) bit - edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value - } - result.append((char) edifactValue); - } - } while (bits.available() > 0); - } - - /** - * See ISO 16022:2006, 5.2.9 and Annex B, B.2 - */ - private static void decodeBase256Segment(BitSource bits, - StringBuilder result, - Collection byteSegments) - throws FormatException { - // Figure out how long the Base 256 Segment is. - int codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed - int d1 = unrandomize255State(bits.readBits(8), codewordPosition++); - int count; - if (d1 == 0) { // Read the remainder of the symbol - count = bits.available() / 8; - } else if (d1 < 250) { - count = d1; - } else { - count = 250 * (d1 - 249) + unrandomize255State(bits.readBits(8), codewordPosition++); - } - - // We're seeing NegativeArraySizeException errors from users. - if (count < 0) { - throw FormatException.getFormatInstance(); - } - - byte[] bytes = new byte[count]; - for (int i = 0; i < count; i++) { - // Have seen this particular error in the wild, such as at - // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2 - if (bits.available() < 8) { - throw FormatException.getFormatInstance(); - } - bytes[i] = (byte) unrandomize255State(bits.readBits(8), codewordPosition++); - } - byteSegments.add(bytes); - try { - result.append(new String(bytes, "ISO8859_1")); - } catch (UnsupportedEncodingException uee) { - throw new IllegalStateException("Platform does not support required encoding: " + uee); - } - } - - /** - * See ISO 16022:2006, Annex B, B.2 - */ - private static int unrandomize255State(int randomizedBase256Codeword, - int base256CodewordPosition) { - int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1; - int tempVariable = randomizedBase256Codeword - pseudoRandomNumber; - return tempVariable >= 0 ? tempVariable : tempVariable + 256; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Decoder.java deleted file mode 100644 index 7a1ad6b93..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Decoder.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.decoder; - -import com.google.zxing.ChecksumException; -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonDecoder; -import com.google.zxing.common.reedsolomon.ReedSolomonException; - -/** - *

    The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting - * the Data Matrix Code from an image.

    - * - * @author bbrown@google.com (Brian Brown) - */ -public final class Decoder { - - private final ReedSolomonDecoder rsDecoder; - - public Decoder() { - rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256); - } - - /** - *

    Convenience method that can decode a Data Matrix Code represented as a 2D array of booleans. - * "true" is taken to mean a black module.

    - * - * @param image booleans representing white/black Data Matrix Code modules - * @return text and bytes encoded within the Data Matrix Code - * @throws FormatException if the Data Matrix Code cannot be decoded - * @throws ChecksumException if error correction fails - */ - public DecoderResult decode(boolean[][] image) throws FormatException, ChecksumException { - int dimension = image.length; - BitMatrix bits = new BitMatrix(dimension); - for (int i = 0; i < dimension; i++) { - for (int j = 0; j < dimension; j++) { - if (image[i][j]) { - bits.set(j, i); - } - } - } - return decode(bits); - } - - /** - *

    Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or "true" is taken - * to mean a black module.

    - * - * @param bits booleans representing white/black Data Matrix Code modules - * @return text and bytes encoded within the Data Matrix Code - * @throws FormatException if the Data Matrix Code cannot be decoded - * @throws ChecksumException if error correction fails - */ - public DecoderResult decode(BitMatrix bits) throws FormatException, ChecksumException { - - // Construct a parser and read version, error-correction level - BitMatrixParser parser = new BitMatrixParser(bits); - Version version = parser.getVersion(); - - // Read codewords - byte[] codewords = parser.readCodewords(); - // Separate into data blocks - DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version); - - int dataBlocksCount = dataBlocks.length; - - // Count total number of data bytes - int totalBytes = 0; - for (DataBlock db : dataBlocks) { - totalBytes += db.getNumDataCodewords(); - } - byte[] resultBytes = new byte[totalBytes]; - - // Error-correct and copy data blocks together into a stream of bytes - for (int j = 0; j < dataBlocksCount; j++) { - DataBlock dataBlock = dataBlocks[j]; - byte[] codewordBytes = dataBlock.getCodewords(); - int numDataCodewords = dataBlock.getNumDataCodewords(); - correctErrors(codewordBytes, numDataCodewords); - for (int i = 0; i < numDataCodewords; i++) { - // De-interlace data blocks. - resultBytes[i * dataBlocksCount + j] = codewordBytes[i]; - } - } - - // Decode the contents of that stream of bytes - return DecodedBitStreamParser.decode(resultBytes); - } - - /** - *

    Given data and error-correction codewords received, possibly corrupted by errors, attempts to - * correct the errors in-place using Reed-Solomon error correction.

    - * - * @param codewordBytes data and error correction codewords - * @param numDataCodewords number of codewords that are data bytes - * @throws ChecksumException if error correction fails - */ - private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException { - int numCodewords = codewordBytes.length; - // First read into an array of ints - int[] codewordsInts = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++) { - codewordsInts[i] = codewordBytes[i] & 0xFF; - } - int numECCodewords = codewordBytes.length - numDataCodewords; - try { - rsDecoder.decode(codewordsInts, numECCodewords); - } catch (ReedSolomonException ignored) { - throw ChecksumException.getChecksumInstance(); - } - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < numDataCodewords; i++) { - codewordBytes[i] = (byte) codewordsInts[i]; - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Version.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Version.java deleted file mode 100644 index fff9e1798..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/decoder/Version.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.decoder; - -import com.google.zxing.FormatException; - -/** - * The Version object encapsulates attributes about a particular - * size Data Matrix Code. - * - * @author bbrown@google.com (Brian Brown) - */ -public final class Version { - - private static final Version[] VERSIONS = buildVersions(); - - private final int versionNumber; - private final int symbolSizeRows; - private final int symbolSizeColumns; - private final int dataRegionSizeRows; - private final int dataRegionSizeColumns; - private final ECBlocks ecBlocks; - private final int totalCodewords; - - private Version(int versionNumber, - int symbolSizeRows, - int symbolSizeColumns, - int dataRegionSizeRows, - int dataRegionSizeColumns, - ECBlocks ecBlocks) { - this.versionNumber = versionNumber; - this.symbolSizeRows = symbolSizeRows; - this.symbolSizeColumns = symbolSizeColumns; - this.dataRegionSizeRows = dataRegionSizeRows; - this.dataRegionSizeColumns = dataRegionSizeColumns; - this.ecBlocks = ecBlocks; - - // Calculate the total number of codewords - int total = 0; - int ecCodewords = ecBlocks.getECCodewords(); - ECB[] ecbArray = ecBlocks.getECBlocks(); - for (ECB ecBlock : ecbArray) { - total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); - } - this.totalCodewords = total; - } - - public int getVersionNumber() { - return versionNumber; - } - - public int getSymbolSizeRows() { - return symbolSizeRows; - } - - public int getSymbolSizeColumns() { - return symbolSizeColumns; - } - - public int getDataRegionSizeRows() { - return dataRegionSizeRows; - } - - public int getDataRegionSizeColumns() { - return dataRegionSizeColumns; - } - - public int getTotalCodewords() { - return totalCodewords; - } - - ECBlocks getECBlocks() { - return ecBlocks; - } - - /** - *

    Deduces version information from Data Matrix dimensions.

    - * - * @param numRows Number of rows in modules - * @param numColumns Number of columns in modules - * @return Version for a Data Matrix Code of those dimensions - * @throws FormatException if dimensions do correspond to a valid Data Matrix size - */ - public static Version getVersionForDimensions(int numRows, int numColumns) throws FormatException { - if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) { - throw FormatException.getFormatInstance(); - } - - for (Version version : VERSIONS) { - if (version.symbolSizeRows == numRows && version.symbolSizeColumns == numColumns) { - return version; - } - } - - throw FormatException.getFormatInstance(); - } - - /** - *

    Encapsulates a set of error-correction blocks in one symbol version. Most versions will - * use blocks of differing sizes within one version, so, this encapsulates the parameters for - * each set of blocks. It also holds the number of error-correction codewords per block since it - * will be the same across all blocks within one version.

    - */ - static final class ECBlocks { - private final int ecCodewords; - private final ECB[] ecBlocks; - - private ECBlocks(int ecCodewords, ECB ecBlocks) { - this.ecCodewords = ecCodewords; - this.ecBlocks = new ECB[] { ecBlocks }; - } - - private ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2) { - this.ecCodewords = ecCodewords; - this.ecBlocks = new ECB[] { ecBlocks1, ecBlocks2 }; - } - - int getECCodewords() { - return ecCodewords; - } - - ECB[] getECBlocks() { - return ecBlocks; - } - } - - /** - *

    Encapsualtes the parameters for one error-correction block in one symbol version. - * This includes the number of data codewords, and the number of times a block with these - * parameters is used consecutively in the Data Matrix code version's format.

    - */ - static final class ECB { - private final int count; - private final int dataCodewords; - - private ECB(int count, int dataCodewords) { - this.count = count; - this.dataCodewords = dataCodewords; - } - - int getCount() { - return count; - } - - int getDataCodewords() { - return dataCodewords; - } - } - - @Override - public String toString() { - return String.valueOf(versionNumber); - } - - /** - * See ISO 16022:2006 5.5.1 Table 7 - */ - private static Version[] buildVersions() { - return new Version[]{ - new Version(1, 10, 10, 8, 8, - new ECBlocks(5, new ECB(1, 3))), - new Version(2, 12, 12, 10, 10, - new ECBlocks(7, new ECB(1, 5))), - new Version(3, 14, 14, 12, 12, - new ECBlocks(10, new ECB(1, 8))), - new Version(4, 16, 16, 14, 14, - new ECBlocks(12, new ECB(1, 12))), - new Version(5, 18, 18, 16, 16, - new ECBlocks(14, new ECB(1, 18))), - new Version(6, 20, 20, 18, 18, - new ECBlocks(18, new ECB(1, 22))), - new Version(7, 22, 22, 20, 20, - new ECBlocks(20, new ECB(1, 30))), - new Version(8, 24, 24, 22, 22, - new ECBlocks(24, new ECB(1, 36))), - new Version(9, 26, 26, 24, 24, - new ECBlocks(28, new ECB(1, 44))), - new Version(10, 32, 32, 14, 14, - new ECBlocks(36, new ECB(1, 62))), - new Version(11, 36, 36, 16, 16, - new ECBlocks(42, new ECB(1, 86))), - new Version(12, 40, 40, 18, 18, - new ECBlocks(48, new ECB(1, 114))), - new Version(13, 44, 44, 20, 20, - new ECBlocks(56, new ECB(1, 144))), - new Version(14, 48, 48, 22, 22, - new ECBlocks(68, new ECB(1, 174))), - new Version(15, 52, 52, 24, 24, - new ECBlocks(42, new ECB(2, 102))), - new Version(16, 64, 64, 14, 14, - new ECBlocks(56, new ECB(2, 140))), - new Version(17, 72, 72, 16, 16, - new ECBlocks(36, new ECB(4, 92))), - new Version(18, 80, 80, 18, 18, - new ECBlocks(48, new ECB(4, 114))), - new Version(19, 88, 88, 20, 20, - new ECBlocks(56, new ECB(4, 144))), - new Version(20, 96, 96, 22, 22, - new ECBlocks(68, new ECB(4, 174))), - new Version(21, 104, 104, 24, 24, - new ECBlocks(56, new ECB(6, 136))), - new Version(22, 120, 120, 18, 18, - new ECBlocks(68, new ECB(6, 175))), - new Version(23, 132, 132, 20, 20, - new ECBlocks(62, new ECB(8, 163))), - new Version(24, 144, 144, 22, 22, - new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))), - new Version(25, 8, 18, 6, 16, - new ECBlocks(7, new ECB(1, 5))), - new Version(26, 8, 32, 6, 14, - new ECBlocks(11, new ECB(1, 10))), - new Version(27, 12, 26, 10, 24, - new ECBlocks(14, new ECB(1, 16))), - new Version(28, 12, 36, 10, 16, - new ECBlocks(18, new ECB(1, 22))), - new Version(29, 16, 36, 14, 16, - new ECBlocks(24, new ECB(1, 32))), - new Version(30, 16, 48, 14, 22, - new ECBlocks(28, new ECB(1, 49))) - }; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/detector/Detector.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/detector/Detector.java deleted file mode 100644 index 4e3de8168..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/detector/Detector.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.detector; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.common.GridSampler; -import com.google.zxing.common.detector.MathUtils; -import com.google.zxing.common.detector.WhiteRectangleDetector; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - *

    Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code - * is rotated or skewed, or partially obscured.

    - * - * @author Sean Owen - */ -public final class Detector { - - private final BitMatrix image; - private final WhiteRectangleDetector rectangleDetector; - - public Detector(BitMatrix image) throws NotFoundException { - this.image = image; - rectangleDetector = new WhiteRectangleDetector(image); - } - - /** - *

    Detects a Data Matrix Code in an image.

    - * - * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code - * @throws NotFoundException if no Data Matrix Code can be found - */ - public DetectorResult detect() throws NotFoundException { - - ResultPoint[] cornerPoints = rectangleDetector.detect(); - ResultPoint pointA = cornerPoints[0]; - ResultPoint pointB = cornerPoints[1]; - ResultPoint pointC = cornerPoints[2]; - ResultPoint pointD = cornerPoints[3]; - - // Point A and D are across the diagonal from one another, - // as are B and C. Figure out which are the solid black lines - // by counting transitions - List transitions = new ArrayList<>(4); - transitions.add(transitionsBetween(pointA, pointB)); - transitions.add(transitionsBetween(pointA, pointC)); - transitions.add(transitionsBetween(pointB, pointD)); - transitions.add(transitionsBetween(pointC, pointD)); - Collections.sort(transitions, new ResultPointsAndTransitionsComparator()); - - // Sort by number of transitions. First two will be the two solid sides; last two - // will be the two alternating black/white sides - ResultPointsAndTransitions lSideOne = transitions.get(0); - ResultPointsAndTransitions lSideTwo = transitions.get(1); - - // Figure out which point is their intersection by tallying up the number of times we see the - // endpoints in the four endpoints. One will show up twice. - Map pointCount = new HashMap<>(); - increment(pointCount, lSideOne.getFrom()); - increment(pointCount, lSideOne.getTo()); - increment(pointCount, lSideTwo.getFrom()); - increment(pointCount, lSideTwo.getTo()); - - ResultPoint maybeTopLeft = null; - ResultPoint bottomLeft = null; - ResultPoint maybeBottomRight = null; - for (Map.Entry entry : pointCount.entrySet()) { - ResultPoint point = entry.getKey(); - Integer value = entry.getValue(); - if (value == 2) { - bottomLeft = point; // this is definitely the bottom left, then -- end of two L sides - } else { - // Otherwise it's either top left or bottom right -- just assign the two arbitrarily now - if (maybeTopLeft == null) { - maybeTopLeft = point; - } else { - maybeBottomRight = point; - } - } - } - - if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null) { - throw NotFoundException.getNotFoundInstance(); - } - - // Bottom left is correct but top left and bottom right might be switched - ResultPoint[] corners = { maybeTopLeft, bottomLeft, maybeBottomRight }; - // Use the dot product trick to sort them out - ResultPoint.orderBestPatterns(corners); - - // Now we know which is which: - ResultPoint bottomRight = corners[0]; - bottomLeft = corners[1]; - ResultPoint topLeft = corners[2]; - - // Which point didn't we find in relation to the "L" sides? that's the top right corner - ResultPoint topRight; - if (!pointCount.containsKey(pointA)) { - topRight = pointA; - } else if (!pointCount.containsKey(pointB)) { - topRight = pointB; - } else if (!pointCount.containsKey(pointC)) { - topRight = pointC; - } else { - topRight = pointD; - } - - // Next determine the dimension by tracing along the top or right side and counting black/white - // transitions. Since we start inside a black module, we should see a number of transitions - // equal to 1 less than the code dimension. Well, actually 2 less, because we are going to - // end on a black module: - - // The top right point is actually the corner of a module, which is one of the two black modules - // adjacent to the white module at the top right. Tracing to that corner from either the top left - // or bottom right should work here. - - int dimensionTop = transitionsBetween(topLeft, topRight).getTransitions(); - int dimensionRight = transitionsBetween(bottomRight, topRight).getTransitions(); - - if ((dimensionTop & 0x01) == 1) { - // it can't be odd, so, round... up? - dimensionTop++; - } - dimensionTop += 2; - - if ((dimensionRight & 0x01) == 1) { - // it can't be odd, so, round... up? - dimensionRight++; - } - dimensionRight += 2; - - BitMatrix bits; - ResultPoint correctedTopRight; - - // Rectanguar symbols are 6x16, 6x28, 10x24, 10x32, 14x32, or 14x44. If one dimension is more - // than twice the other, it's certainly rectangular, but to cut a bit more slack we accept it as - // rectangular if the bigger side is at least 7/4 times the other: - if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) { - // The matrix is rectangular - - correctedTopRight = - correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight); - if (correctedTopRight == null){ - correctedTopRight = topRight; - } - - dimensionTop = transitionsBetween(topLeft, correctedTopRight).getTransitions(); - dimensionRight = transitionsBetween(bottomRight, correctedTopRight).getTransitions(); - - if ((dimensionTop & 0x01) == 1) { - // it can't be odd, so, round... up? - dimensionTop++; - } - - if ((dimensionRight & 0x01) == 1) { - // it can't be odd, so, round... up? - dimensionRight++; - } - - bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight); - - } else { - // The matrix is square - - int dimension = Math.min(dimensionRight, dimensionTop); - // correct top right point to match the white module - correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension); - if (correctedTopRight == null){ - correctedTopRight = topRight; - } - - // Redetermine the dimension using the corrected top right point - int dimensionCorrected = Math.max(transitionsBetween(topLeft, correctedTopRight).getTransitions(), - transitionsBetween(bottomRight, correctedTopRight).getTransitions()); - dimensionCorrected++; - if ((dimensionCorrected & 0x01) == 1) { - dimensionCorrected++; - } - - bits = sampleGrid(image, - topLeft, - bottomLeft, - bottomRight, - correctedTopRight, - dimensionCorrected, - dimensionCorrected); - } - - return new DetectorResult(bits, new ResultPoint[]{topLeft, bottomLeft, bottomRight, correctedTopRight}); - } - - /** - * Calculates the position of the white top right module using the output of the rectangle detector - * for a rectangular matrix - */ - private ResultPoint correctTopRightRectangular(ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topLeft, - ResultPoint topRight, - int dimensionTop, - int dimensionRight) { - - float corr = distance(bottomLeft, bottomRight) / (float)dimensionTop; - int norm = distance(topLeft, topRight); - float cos = (topRight.getX() - topLeft.getX()) / norm; - float sin = (topRight.getY() - topLeft.getY()) / norm; - - ResultPoint c1 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin); - - corr = distance(bottomLeft, topLeft) / (float)dimensionRight; - norm = distance(bottomRight, topRight); - cos = (topRight.getX() - bottomRight.getX()) / norm; - sin = (topRight.getY() - bottomRight.getY()) / norm; - - ResultPoint c2 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin); - - if (!isValid(c1)) { - if (isValid(c2)) { - return c2; - } - return null; - } - if (!isValid(c2)){ - return c1; - } - - int l1 = Math.abs(dimensionTop - transitionsBetween(topLeft, c1).getTransitions()) + - Math.abs(dimensionRight - transitionsBetween(bottomRight, c1).getTransitions()); - int l2 = Math.abs(dimensionTop - transitionsBetween(topLeft, c2).getTransitions()) + - Math.abs(dimensionRight - transitionsBetween(bottomRight, c2).getTransitions()); - - if (l1 <= l2){ - return c1; - } - - return c2; - } - - /** - * Calculates the position of the white top right module using the output of the rectangle detector - * for a square matrix - */ - private ResultPoint correctTopRight(ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topLeft, - ResultPoint topRight, - int dimension) { - - float corr = distance(bottomLeft, bottomRight) / (float) dimension; - int norm = distance(topLeft, topRight); - float cos = (topRight.getX() - topLeft.getX()) / norm; - float sin = (topRight.getY() - topLeft.getY()) / norm; - - ResultPoint c1 = new ResultPoint(topRight.getX() + corr * cos, topRight.getY() + corr * sin); - - corr = distance(bottomLeft, topLeft) / (float) dimension; - norm = distance(bottomRight, topRight); - cos = (topRight.getX() - bottomRight.getX()) / norm; - sin = (topRight.getY() - bottomRight.getY()) / norm; - - ResultPoint c2 = new ResultPoint(topRight.getX() + corr * cos, topRight.getY() + corr * sin); - - if (!isValid(c1)) { - if (isValid(c2)) { - return c2; - } - return null; - } - if (!isValid(c2)) { - return c1; - } - - int l1 = Math.abs(transitionsBetween(topLeft, c1).getTransitions() - - transitionsBetween(bottomRight, c1).getTransitions()); - int l2 = Math.abs(transitionsBetween(topLeft, c2).getTransitions() - - transitionsBetween(bottomRight, c2).getTransitions()); - - return l1 <= l2 ? c1 : c2; - } - - private boolean isValid(ResultPoint p) { - return p.getX() >= 0 && p.getX() < image.getWidth() && p.getY() > 0 && p.getY() < image.getHeight(); - } - - private static int distance(ResultPoint a, ResultPoint b) { - return MathUtils.round(ResultPoint.distance(a, b)); - } - - /** - * Increments the Integer associated with a key by one. - */ - private static void increment(Map table, ResultPoint key) { - Integer value = table.get(key); - table.put(key, value == null ? 1 : value + 1); - } - - private static BitMatrix sampleGrid(BitMatrix image, - ResultPoint topLeft, - ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topRight, - int dimensionX, - int dimensionY) throws NotFoundException { - - GridSampler sampler = GridSampler.getInstance(); - - return sampler.sampleGrid(image, - dimensionX, - dimensionY, - 0.5f, - 0.5f, - dimensionX - 0.5f, - 0.5f, - dimensionX - 0.5f, - dimensionY - 0.5f, - 0.5f, - dimensionY - 0.5f, - topLeft.getX(), - topLeft.getY(), - topRight.getX(), - topRight.getY(), - bottomRight.getX(), - bottomRight.getY(), - bottomLeft.getX(), - bottomLeft.getY()); - } - - /** - * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm. - */ - private ResultPointsAndTransitions transitionsBetween(ResultPoint from, ResultPoint to) { - // See QR Code Detector, sizeOfBlackWhiteBlackRun() - int fromX = (int) from.getX(); - int fromY = (int) from.getY(); - int toX = (int) to.getX(); - int toY = (int) to.getY(); - boolean steep = Math.abs(toY - fromY) > Math.abs(toX - fromX); - if (steep) { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } - - int dx = Math.abs(toX - fromX); - int dy = Math.abs(toY - fromY); - int error = -dx / 2; - int ystep = fromY < toY ? 1 : -1; - int xstep = fromX < toX ? 1 : -1; - int transitions = 0; - boolean inBlack = image.get(steep ? fromY : fromX, steep ? fromX : fromY); - for (int x = fromX, y = fromY; x != toX; x += xstep) { - boolean isBlack = image.get(steep ? y : x, steep ? x : y); - if (isBlack != inBlack) { - transitions++; - inBlack = isBlack; - } - error += dy; - if (error > 0) { - if (y == toY) { - break; - } - y += ystep; - error -= dx; - } - } - return new ResultPointsAndTransitions(from, to, transitions); - } - - /** - * Simply encapsulates two points and a number of transitions between them. - */ - private static final class ResultPointsAndTransitions { - - private final ResultPoint from; - private final ResultPoint to; - private final int transitions; - - private ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions) { - this.from = from; - this.to = to; - this.transitions = transitions; - } - - ResultPoint getFrom() { - return from; - } - - ResultPoint getTo() { - return to; - } - - public int getTransitions() { - return transitions; - } - - @Override - public String toString() { - return from + "/" + to + '/' + transitions; - } - } - - /** - * Orders ResultPointsAndTransitions by number of transitions, ascending. - */ - private static final class ResultPointsAndTransitionsComparator - implements Comparator, Serializable { - @Override - public int compare(ResultPointsAndTransitions o1, ResultPointsAndTransitions o2) { - return o1.getTransitions() - o2.getTransitions(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ASCIIEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ASCIIEncoder.java deleted file mode 100644 index b9cb72bd2..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ASCIIEncoder.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class ASCIIEncoder implements Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.ASCII_ENCODATION; - } - - @Override - public void encode(EncoderContext context) { - //step B - int n = HighLevelEncoder.determineConsecutiveDigitCount(context.getMessage(), context.pos); - if (n >= 2) { - context.writeCodeword(encodeASCIIDigits(context.getMessage().charAt(context.pos), - context.getMessage().charAt(context.pos + 1))); - context.pos += 2; - } else { - char c = context.getCurrentChar(); - int newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - switch (newMode) { - case HighLevelEncoder.BASE256_ENCODATION: - context.writeCodeword(HighLevelEncoder.LATCH_TO_BASE256); - context.signalEncoderChange(HighLevelEncoder.BASE256_ENCODATION); - return; - case HighLevelEncoder.C40_ENCODATION: - context.writeCodeword(HighLevelEncoder.LATCH_TO_C40); - context.signalEncoderChange(HighLevelEncoder.C40_ENCODATION); - return; - case HighLevelEncoder.X12_ENCODATION: - context.writeCodeword(HighLevelEncoder.LATCH_TO_ANSIX12); - context.signalEncoderChange(HighLevelEncoder.X12_ENCODATION); - break; - case HighLevelEncoder.TEXT_ENCODATION: - context.writeCodeword(HighLevelEncoder.LATCH_TO_TEXT); - context.signalEncoderChange(HighLevelEncoder.TEXT_ENCODATION); - break; - case HighLevelEncoder.EDIFACT_ENCODATION: - context.writeCodeword(HighLevelEncoder.LATCH_TO_EDIFACT); - context.signalEncoderChange(HighLevelEncoder.EDIFACT_ENCODATION); - break; - default: - throw new IllegalStateException("Illegal mode: " + newMode); - } - } else if (HighLevelEncoder.isExtendedASCII(c)) { - context.writeCodeword(HighLevelEncoder.UPPER_SHIFT); - context.writeCodeword((char) (c - 128 + 1)); - context.pos++; - } else { - context.writeCodeword((char) (c + 1)); - context.pos++; - } - - } - } - - private static char encodeASCIIDigits(char digit1, char digit2) { - if (HighLevelEncoder.isDigit(digit1) && HighLevelEncoder.isDigit(digit2)) { - int num = (digit1 - 48) * 10 + (digit2 - 48); - return (char) (num + 130); - } - throw new IllegalArgumentException("not digits: " + digit1 + digit2); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Base256Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Base256Encoder.java deleted file mode 100644 index b66e48551..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Base256Encoder.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class Base256Encoder implements Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.BASE256_ENCODATION; - } - - @Override - public void encode(EncoderContext context) { - StringBuilder buffer = new StringBuilder(); - buffer.append('\0'); //Initialize length field - while (context.hasMoreCharacters()) { - char c = context.getCurrentChar(); - buffer.append(c); - - context.pos++; - - int newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - int dataCount = buffer.length() - 1; - int lengthFieldSize = 1; - int currentSize = context.getCodewordCount() + dataCount + lengthFieldSize; - context.updateSymbolInfo(currentSize); - boolean mustPad = (context.getSymbolInfo().getDataCapacity() - currentSize) > 0; - if (context.hasMoreCharacters() || mustPad) { - if (dataCount <= 249) { - buffer.setCharAt(0, (char) dataCount); - } else if (dataCount > 249 && dataCount <= 1555) { - buffer.setCharAt(0, (char) ((dataCount / 250) + 249)); - buffer.insert(1, (char) (dataCount % 250)); - } else { - throw new IllegalStateException( - "Message length not in valid ranges: " + dataCount); - } - } - for (int i = 0, c = buffer.length(); i < c; i++) { - context.writeCodeword(randomize255State( - buffer.charAt(i), context.getCodewordCount() + 1)); - } - } - - private static char randomize255State(char ch, int codewordPosition) { - int pseudoRandom = ((149 * codewordPosition) % 255) + 1; - int tempVariable = ch + pseudoRandom; - if (tempVariable <= 255) { - return (char) tempVariable; - } else { - return (char) (tempVariable - 256); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/C40Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/C40Encoder.java deleted file mode 100644 index acd02f6c8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/C40Encoder.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -class C40Encoder implements Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.C40_ENCODATION; - } - - @Override - public void encode(EncoderContext context) { - //step C - StringBuilder buffer = new StringBuilder(); - while (context.hasMoreCharacters()) { - char c = context.getCurrentChar(); - context.pos++; - - int lastCharSize = encodeChar(c, buffer); - - int unwritten = (buffer.length() / 3) * 2; - - int curCodewordCount = context.getCodewordCount() + unwritten; - context.updateSymbolInfo(curCodewordCount); - int available = context.getSymbolInfo().getDataCapacity() - curCodewordCount; - - if (!context.hasMoreCharacters()) { - //Avoid having a single C40 value in the last triplet - StringBuilder removed = new StringBuilder(); - if ((buffer.length() % 3) == 2) { - if (available < 2 || available > 2) { - lastCharSize = backtrackOneCharacter(context, buffer, removed, - lastCharSize); - } - } - while ((buffer.length() % 3) == 1 - && ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) { - lastCharSize = backtrackOneCharacter(context, buffer, removed, lastCharSize); - } - break; - } - - int count = buffer.length(); - if ((count % 3) == 0) { - int newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer); - } - - private int backtrackOneCharacter(EncoderContext context, - StringBuilder buffer, StringBuilder removed, int lastCharSize) { - int count = buffer.length(); - buffer.delete(count - lastCharSize, count); - context.pos--; - char c = context.getCurrentChar(); - lastCharSize = encodeChar(c, removed); - context.resetSymbolInfo(); //Deal with possible reduction in symbol size - return lastCharSize; - } - - static void writeNextTriplet(EncoderContext context, StringBuilder buffer) { - context.writeCodewords(encodeToCodewords(buffer, 0)); - buffer.delete(0, 3); - } - - /** - * Handle "end of data" situations - * - * @param context the encoder context - * @param buffer the buffer with the remaining encoded characters - */ - void handleEOD(EncoderContext context, StringBuilder buffer) { - int unwritten = (buffer.length() / 3) * 2; - int rest = buffer.length() % 3; - - int curCodewordCount = context.getCodewordCount() + unwritten; - context.updateSymbolInfo(curCodewordCount); - int available = context.getSymbolInfo().getDataCapacity() - curCodewordCount; - - if (rest == 2) { - buffer.append('\0'); //Shift 1 - while (buffer.length() >= 3) { - writeNextTriplet(context, buffer); - } - if (context.hasMoreCharacters()) { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - } else if (available == 1 && rest == 1) { - while (buffer.length() >= 3) { - writeNextTriplet(context, buffer); - } - if (context.hasMoreCharacters()) { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - // else no unlatch - context.pos--; - } else if (rest == 0) { - while (buffer.length() >= 3) { - writeNextTriplet(context, buffer); - } - if (available > 0 || context.hasMoreCharacters()) { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - } else { - throw new IllegalStateException("Unexpected case. Please report!"); - } - context.signalEncoderChange(HighLevelEncoder.ASCII_ENCODATION); - } - - int encodeChar(char c, StringBuilder sb) { - if (c == ' ') { - sb.append('\3'); - return 1; - } else if (c >= '0' && c <= '9') { - sb.append((char) (c - 48 + 4)); - return 1; - } else if (c >= 'A' && c <= 'Z') { - sb.append((char) (c - 65 + 14)); - return 1; - } else if (c >= '\0' && c <= '\u001f') { - sb.append('\0'); //Shift 1 Set - sb.append(c); - return 2; - } else if (c >= '!' && c <= '/') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 33)); - return 2; - } else if (c >= ':' && c <= '@') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 58 + 15)); - return 2; - } else if (c >= '[' && c <= '_') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 91 + 22)); - return 2; - } else if (c >= '\u0060' && c <= '\u007f') { - sb.append('\2'); //Shift 3 Set - sb.append((char) (c - 96)); - return 2; - } else if (c >= '\u0080') { - sb.append("\1\u001e"); //Shift 2, Upper Shift - int len = 2; - len += encodeChar((char) (c - 128), sb); - return len; - } else { - throw new IllegalArgumentException("Illegal character: " + c); - } - } - - private static String encodeToCodewords(CharSequence sb, int startPos) { - char c1 = sb.charAt(startPos); - char c2 = sb.charAt(startPos + 1); - char c3 = sb.charAt(startPos + 2); - int v = (1600 * c1) + (40 * c2) + c3 + 1; - char cw1 = (char) (v / 256); - char cw2 = (char) (v % 256); - return new String(new char[] {cw1, cw2}); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DataMatrixSymbolInfo144.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DataMatrixSymbolInfo144.java deleted file mode 100644 index 31463539a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DataMatrixSymbolInfo144.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class DataMatrixSymbolInfo144 extends SymbolInfo { - - DataMatrixSymbolInfo144() { - super(false, 1558, 620, 22, 22, 36, -1, 62); - } - - @Override - public int getInterleavedBlockCount() { - return 10; - } - - @Override - public int getDataLengthForInterleavedBlock(int index) { - return (index <= 8) ? 156 : 155; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DefaultPlacement.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DefaultPlacement.java deleted file mode 100644 index 5efb5a580..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/DefaultPlacement.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -import java.util.Arrays; - -/** - * Symbol Character Placement Program. Adapted from Annex M.1 in ISO/IEC 16022:2000(E). - */ -public class DefaultPlacement { - - private final CharSequence codewords; - private final int numrows; - private final int numcols; - private final byte[] bits; - - /** - * Main constructor - * - * @param codewords the codewords to place - * @param numcols the number of columns - * @param numrows the number of rows - */ - public DefaultPlacement(CharSequence codewords, int numcols, int numrows) { - this.codewords = codewords; - this.numcols = numcols; - this.numrows = numrows; - this.bits = new byte[numcols * numrows]; - Arrays.fill(this.bits, (byte) -1); //Initialize with "not set" value - } - - final int getNumrows() { - return numrows; - } - - final int getNumcols() { - return numcols; - } - - final byte[] getBits() { - return bits; - } - - public final boolean getBit(int col, int row) { - return bits[row * numcols + col] == 1; - } - - final void setBit(int col, int row, boolean bit) { - bits[row * numcols + col] = bit ? (byte) 1 : (byte) 0; - } - - final boolean hasBit(int col, int row) { - return bits[row * numcols + col] >= 0; - } - - public final void place() { - int pos = 0; - int row = 4; - int col = 0; - - do { - /* repeatedly first check for one of the special corner cases, then... */ - if ((row == numrows) && (col == 0)) { - corner1(pos++); - } - if ((row == numrows - 2) && (col == 0) && ((numcols % 4) != 0)) { - corner2(pos++); - } - if ((row == numrows - 2) && (col == 0) && (numcols % 8 == 4)) { - corner3(pos++); - } - if ((row == numrows + 4) && (col == 2) && ((numcols % 8) == 0)) { - corner4(pos++); - } - /* sweep upward diagonally, inserting successive characters... */ - do { - if ((row < numrows) && (col >= 0) && !hasBit(col, row)) { - utah(row, col, pos++); - } - row -= 2; - col += 2; - } while (row >= 0 && (col < numcols)); - row++; - col += 3; - - /* and then sweep downward diagonally, inserting successive characters, ... */ - do { - if ((row >= 0) && (col < numcols) && !hasBit(col, row)) { - utah(row, col, pos++); - } - row += 2; - col -= 2; - } while ((row < numrows) && (col >= 0)); - row += 3; - col++; - - /* ...until the entire array is scanned */ - } while ((row < numrows) || (col < numcols)); - - /* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */ - if (!hasBit(numcols - 1, numrows - 1)) { - setBit(numcols - 1, numrows - 1, true); - setBit(numcols - 2, numrows - 2, true); - } - } - - private void module(int row, int col, int pos, int bit) { - if (row < 0) { - row += numrows; - col += 4 - ((numrows + 4) % 8); - } - if (col < 0) { - col += numcols; - row += 4 - ((numcols + 4) % 8); - } - // Note the conversion: - int v = codewords.charAt(pos); - v &= 1 << (8 - bit); - setBit(col, row, v != 0); - } - - /** - * Places the 8 bits of a utah-shaped symbol character in ECC200. - * - * @param row the row - * @param col the column - * @param pos character position - */ - private void utah(int row, int col, int pos) { - module(row - 2, col - 2, pos, 1); - module(row - 2, col - 1, pos, 2); - module(row - 1, col - 2, pos, 3); - module(row - 1, col - 1, pos, 4); - module(row - 1, col, pos, 5); - module(row, col - 2, pos, 6); - module(row, col - 1, pos, 7); - module(row, col, pos, 8); - } - - private void corner1(int pos) { - module(numrows - 1, 0, pos, 1); - module(numrows - 1, 1, pos, 2); - module(numrows - 1, 2, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 1, pos, 6); - module(2, numcols - 1, pos, 7); - module(3, numcols - 1, pos, 8); - } - - private void corner2(int pos) { - module(numrows - 3, 0, pos, 1); - module(numrows - 2, 0, pos, 2); - module(numrows - 1, 0, pos, 3); - module(0, numcols - 4, pos, 4); - module(0, numcols - 3, pos, 5); - module(0, numcols - 2, pos, 6); - module(0, numcols - 1, pos, 7); - module(1, numcols - 1, pos, 8); - } - - private void corner3(int pos) { - module(numrows - 3, 0, pos, 1); - module(numrows - 2, 0, pos, 2); - module(numrows - 1, 0, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 1, pos, 6); - module(2, numcols - 1, pos, 7); - module(3, numcols - 1, pos, 8); - } - - private void corner4(int pos) { - module(numrows - 1, 0, pos, 1); - module(numrows - 1, numcols - 1, pos, 2); - module(0, numcols - 3, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 3, pos, 6); - module(1, numcols - 2, pos, 7); - module(1, numcols - 1, pos, 8); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EdifactEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EdifactEncoder.java deleted file mode 100644 index dbb3f130e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EdifactEncoder.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class EdifactEncoder implements Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.EDIFACT_ENCODATION; - } - - @Override - public void encode(EncoderContext context) { - //step F - StringBuilder buffer = new StringBuilder(); - while (context.hasMoreCharacters()) { - char c = context.getCurrentChar(); - encodeChar(c, buffer); - context.pos++; - - int count = buffer.length(); - if (count >= 4) { - context.writeCodewords(encodeToCodewords(buffer, 0)); - buffer.delete(0, 4); - - int newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(HighLevelEncoder.ASCII_ENCODATION); - break; - } - } - } - buffer.append((char) 31); //Unlatch - handleEOD(context, buffer); - } - - /** - * Handle "end of data" situations - * - * @param context the encoder context - * @param buffer the buffer with the remaining encoded characters - */ - private static void handleEOD(EncoderContext context, CharSequence buffer) { - try { - int count = buffer.length(); - if (count == 0) { - return; //Already finished - } - if (count == 1) { - //Only an unlatch at the end - context.updateSymbolInfo(); - int available = context.getSymbolInfo().getDataCapacity() - context.getCodewordCount(); - int remaining = context.getRemainingCharacters(); - if (remaining == 0 && available <= 2) { - return; //No unlatch - } - } - - if (count > 4) { - throw new IllegalStateException("Count must not exceed 4"); - } - int restChars = count - 1; - String encoded = encodeToCodewords(buffer, 0); - boolean endOfSymbolReached = !context.hasMoreCharacters(); - boolean restInAscii = endOfSymbolReached && restChars <= 2; - - if (restChars <= 2) { - context.updateSymbolInfo(context.getCodewordCount() + restChars); - int available = context.getSymbolInfo().getDataCapacity() - context.getCodewordCount(); - if (available >= 3) { - restInAscii = false; - context.updateSymbolInfo(context.getCodewordCount() + encoded.length()); - //available = context.symbolInfo.dataCapacity - context.getCodewordCount(); - } - } - - if (restInAscii) { - context.resetSymbolInfo(); - context.pos -= restChars; - } else { - context.writeCodewords(encoded); - } - } finally { - context.signalEncoderChange(HighLevelEncoder.ASCII_ENCODATION); - } - } - - private static void encodeChar(char c, StringBuilder sb) { - if (c >= ' ' && c <= '?') { - sb.append(c); - } else if (c >= '@' && c <= '^') { - sb.append((char) (c - 64)); - } else { - HighLevelEncoder.illegalCharacter(c); - } - } - - private static String encodeToCodewords(CharSequence sb, int startPos) { - int len = sb.length() - startPos; - if (len == 0) { - throw new IllegalStateException("StringBuilder must not be empty"); - } - char c1 = sb.charAt(startPos); - char c2 = len >= 2 ? sb.charAt(startPos + 1) : 0; - char c3 = len >= 3 ? sb.charAt(startPos + 2) : 0; - char c4 = len >= 4 ? sb.charAt(startPos + 3) : 0; - - int v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4; - char cw1 = (char) ((v >> 16) & 255); - char cw2 = (char) ((v >> 8) & 255); - char cw3 = (char) (v & 255); - StringBuilder res = new StringBuilder(3); - res.append(cw1); - if (len >= 2) { - res.append(cw2); - } - if (len >= 3) { - res.append(cw3); - } - return res.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Encoder.java deleted file mode 100644 index 7a91e1e41..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/Encoder.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -interface Encoder { - - int getEncodingMode(); - - void encode(EncoderContext context); - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EncoderContext.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EncoderContext.java deleted file mode 100644 index ba92278a3..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/EncoderContext.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -import com.google.zxing.Dimension; - -import java.nio.charset.Charset; - -final class EncoderContext { - - private final String msg; - private SymbolShapeHint shape; - private Dimension minSize; - private Dimension maxSize; - private final StringBuilder codewords; - int pos; - private int newEncoding; - private SymbolInfo symbolInfo; - private int skipAtEnd; - - EncoderContext(String msg) { - //From this point on Strings are not Unicode anymore! - byte[] msgBinary = msg.getBytes(Charset.forName("ISO-8859-1")); - StringBuilder sb = new StringBuilder(msgBinary.length); - for (int i = 0, c = msgBinary.length; i < c; i++) { - char ch = (char) (msgBinary[i] & 0xff); - if (ch == '?' && msg.charAt(i) != '?') { - throw new IllegalArgumentException("Message contains characters outside ISO-8859-1 encoding."); - } - sb.append(ch); - } - this.msg = sb.toString(); //Not Unicode here! - shape = SymbolShapeHint.FORCE_NONE; - this.codewords = new StringBuilder(msg.length()); - newEncoding = -1; - } - - public void setSymbolShape(SymbolShapeHint shape) { - this.shape = shape; - } - - public void setSizeConstraints(Dimension minSize, Dimension maxSize) { - this.minSize = minSize; - this.maxSize = maxSize; - } - - public String getMessage() { - return this.msg; - } - - public void setSkipAtEnd(int count) { - this.skipAtEnd = count; - } - - public char getCurrentChar() { - return msg.charAt(pos); - } - - public char getCurrent() { - return msg.charAt(pos); - } - - public StringBuilder getCodewords() { - return codewords; - } - - public void writeCodewords(String codewords) { - this.codewords.append(codewords); - } - - public void writeCodeword(char codeword) { - this.codewords.append(codeword); - } - - public int getCodewordCount() { - return this.codewords.length(); - } - - public int getNewEncoding() { - return newEncoding; - } - - public void signalEncoderChange(int encoding) { - this.newEncoding = encoding; - } - - public void resetEncoderSignal() { - this.newEncoding = -1; - } - - public boolean hasMoreCharacters() { - return pos < getTotalMessageCharCount(); - } - - private int getTotalMessageCharCount() { - return msg.length() - skipAtEnd; - } - - public int getRemainingCharacters() { - return getTotalMessageCharCount() - pos; - } - - public SymbolInfo getSymbolInfo() { - return symbolInfo; - } - - public void updateSymbolInfo() { - updateSymbolInfo(getCodewordCount()); - } - - public void updateSymbolInfo(int len) { - if (this.symbolInfo == null || len > this.symbolInfo.getDataCapacity()) { - this.symbolInfo = SymbolInfo.lookup(len, shape, minSize, maxSize, true); - } - } - - public void resetSymbolInfo() { - this.symbolInfo = null; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ErrorCorrection.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ErrorCorrection.java deleted file mode 100644 index d38933498..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/ErrorCorrection.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -/** - * Error Correction Code for ECC200. - */ -public final class ErrorCorrection { - - /** - * Lookup table which factors to use for which number of error correction codewords. - * See FACTORS. - */ - private static final int[] FACTOR_SETS - = {5, 7, 10, 11, 12, 14, 18, 20, 24, 28, 36, 42, 48, 56, 62, 68}; - - /** - * Precomputed polynomial factors for ECC 200. - */ - private static final int[][] FACTORS = { - {228, 48, 15, 111, 62}, - {23, 68, 144, 134, 240, 92, 254}, - {28, 24, 185, 166, 223, 248, 116, 255, 110, 61}, - {175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120}, - {41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242}, - {156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185}, - {83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48, 90, 188}, - {15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186, 172}, - {52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, - 254, 124, 12, 181, 184, 96, 50, 193}, - {211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121, - 17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255}, - {245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182, - 229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25, - 225, 98, 81, 112}, - {77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8, - 175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, - 248, 202, 69, 50, 150, 177, 226, 5, 9, 5}, - {245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, - 191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138, - 186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19}, - {175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235, - 150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232, - 144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, - 155, 43, 203, 107, 233, 53, 143, 46}, - {242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, - 185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71, - 161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31, - 176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204}, - {220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127, - 213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236, - 66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239, - 181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153, 132, 63, - 96, 103, 82, 186}}; - - private static final int MODULO_VALUE = 0x12D; - - private static final int[] LOG; - private static final int[] ALOG; - - static { - //Create log and antilog table - LOG = new int[256]; - ALOG = new int[255]; - - int p = 1; - for (int i = 0; i < 255; i++) { - ALOG[i] = p; - LOG[p] = i; - p *= 2; - if (p >= 256) { - p ^= MODULO_VALUE; - } - } - } - - private ErrorCorrection() { - } - - /** - * Creates the ECC200 error correction for an encoded message. - * - * @param codewords the codewords - * @param symbolInfo information about the symbol to be encoded - * @return the codewords with interleaved error correction. - */ - public static String encodeECC200(String codewords, SymbolInfo symbolInfo) { - if (codewords.length() != symbolInfo.getDataCapacity()) { - throw new IllegalArgumentException( - "The number of codewords does not match the selected symbol"); - } - StringBuilder sb = new StringBuilder(symbolInfo.getDataCapacity() + symbolInfo.getErrorCodewords()); - sb.append(codewords); - int blockCount = symbolInfo.getInterleavedBlockCount(); - if (blockCount == 1) { - String ecc = createECCBlock(codewords, symbolInfo.getErrorCodewords()); - sb.append(ecc); - } else { - sb.setLength(sb.capacity()); - int[] dataSizes = new int[blockCount]; - int[] errorSizes = new int[blockCount]; - int[] startPos = new int[blockCount]; - for (int i = 0; i < blockCount; i++) { - dataSizes[i] = symbolInfo.getDataLengthForInterleavedBlock(i + 1); - errorSizes[i] = symbolInfo.getErrorLengthForInterleavedBlock(i + 1); - startPos[i] = 0; - if (i > 0) { - startPos[i] = startPos[i - 1] + dataSizes[i]; - } - } - for (int block = 0; block < blockCount; block++) { - StringBuilder temp = new StringBuilder(dataSizes[block]); - for (int d = block; d < symbolInfo.getDataCapacity(); d += blockCount) { - temp.append(codewords.charAt(d)); - } - String ecc = createECCBlock(temp.toString(), errorSizes[block]); - int pos = 0; - for (int e = block; e < errorSizes[block] * blockCount; e += blockCount) { - sb.setCharAt(symbolInfo.getDataCapacity() + e, ecc.charAt(pos++)); - } - } - } - return sb.toString(); - - } - - private static String createECCBlock(CharSequence codewords, int numECWords) { - return createECCBlock(codewords, 0, codewords.length(), numECWords); - } - - private static String createECCBlock(CharSequence codewords, int start, int len, int numECWords) { - int table = -1; - for (int i = 0; i < FACTOR_SETS.length; i++) { - if (FACTOR_SETS[i] == numECWords) { - table = i; - break; - } - } - if (table < 0) { - throw new IllegalArgumentException( - "Illegal number of error correction codewords specified: " + numECWords); - } - int[] poly = FACTORS[table]; - char[] ecc = new char[numECWords]; - for (int i = 0; i < numECWords; i++) { - ecc[i] = 0; - } - for (int i = start; i < start + len; i++) { - int m = ecc[numECWords - 1] ^ codewords.charAt(i); - for (int k = numECWords - 1; k > 0; k--) { - if (m != 0 && poly[k] != 0) { - ecc[k] = (char) (ecc[k - 1] ^ ALOG[(LOG[m] + LOG[poly[k]]) % 255]); - } else { - ecc[k] = ecc[k - 1]; - } - } - if (m != 0 && poly[0] != 0) { - ecc[0] = (char) ALOG[(LOG[m] + LOG[poly[0]]) % 255]; - } else { - ecc[0] = 0; - } - } - char[] eccReversed = new char[numECWords]; - for (int i = 0; i < numECWords; i++) { - eccReversed[i] = ecc[numECWords - i - 1]; - } - return String.valueOf(eccReversed); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/HighLevelEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/HighLevelEncoder.java deleted file mode 100644 index caec10970..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/HighLevelEncoder.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -import com.google.zxing.Dimension; - -import java.util.Arrays; - -/** - * DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in - * annex S. - */ -public final class HighLevelEncoder { - - /** - * Padding character - */ - private static final char PAD = 129; - /** - * mode latch to C40 encodation mode - */ - static final char LATCH_TO_C40 = 230; - /** - * mode latch to Base 256 encodation mode - */ - static final char LATCH_TO_BASE256 = 231; - /** - * FNC1 Codeword - */ - //private static final char FNC1 = 232; - /** - * Structured Append Codeword - */ - //private static final char STRUCTURED_APPEND = 233; - /** - * Reader Programming - */ - //private static final char READER_PROGRAMMING = 234; - /** - * Upper Shift - */ - static final char UPPER_SHIFT = 235; - /** - * 05 Macro - */ - private static final char MACRO_05 = 236; - /** - * 06 Macro - */ - private static final char MACRO_06 = 237; - /** - * mode latch to ANSI X.12 encodation mode - */ - static final char LATCH_TO_ANSIX12 = 238; - /** - * mode latch to Text encodation mode - */ - static final char LATCH_TO_TEXT = 239; - /** - * mode latch to EDIFACT encodation mode - */ - static final char LATCH_TO_EDIFACT = 240; - /** - * ECI character (Extended Channel Interpretation) - */ - //private static final char ECI = 241; - - /** - * Unlatch from C40 encodation - */ - static final char C40_UNLATCH = 254; - /** - * Unlatch from X12 encodation - */ - static final char X12_UNLATCH = 254; - - /** - * 05 Macro header - */ - private static final String MACRO_05_HEADER = "[)>\u001E05\u001D"; - /** - * 06 Macro header - */ - private static final String MACRO_06_HEADER = "[)>\u001E06\u001D"; - /** - * Macro trailer - */ - private static final String MACRO_TRAILER = "\u001E\u0004"; - - static final int ASCII_ENCODATION = 0; - static final int C40_ENCODATION = 1; - static final int TEXT_ENCODATION = 2; - static final int X12_ENCODATION = 3; - static final int EDIFACT_ENCODATION = 4; - static final int BASE256_ENCODATION = 5; - - private HighLevelEncoder() { - } - - /* - * Converts the message to a byte array using the default encoding (cp437) as defined by the - * specification - * - * @param msg the message - * @return the byte array of the message - */ - - /* - public static byte[] getBytesForMessage(String msg) { - return msg.getBytes(Charset.forName("cp437")); //See 4.4.3 and annex B of ISO/IEC 15438:2001(E) - } - */ - - private static char randomize253State(char ch, int codewordPosition) { - int pseudoRandom = ((149 * codewordPosition) % 253) + 1; - int tempVariable = ch + pseudoRandom; - return tempVariable <= 254 ? (char) tempVariable : (char) (tempVariable - 254); - } - - /** - * Performs message encoding of a DataMatrix message using the algorithm described in annex P - * of ISO/IEC 16022:2000(E). - * - * @param msg the message - * @return the encoded message (the char values range from 0 to 255) - */ - public static String encodeHighLevel(String msg) { - return encodeHighLevel(msg, SymbolShapeHint.FORCE_NONE, null, null); - } - - /** - * Performs message encoding of a DataMatrix message using the algorithm described in annex P - * of ISO/IEC 16022:2000(E). - * - * @param msg the message - * @param shape requested shape. May be {@code SymbolShapeHint.FORCE_NONE}, - * {@code SymbolShapeHint.FORCE_SQUARE} or {@code SymbolShapeHint.FORCE_RECTANGLE}. - * @param minSize the minimum symbol size constraint or null for no constraint - * @param maxSize the maximum symbol size constraint or null for no constraint - * @return the encoded message (the char values range from 0 to 255) - */ - public static String encodeHighLevel(String msg, - SymbolShapeHint shape, - Dimension minSize, - Dimension maxSize) { - //the codewords 0..255 are encoded as Unicode characters - Encoder[] encoders = { - new ASCIIEncoder(), new C40Encoder(), new TextEncoder(), - new X12Encoder(), new EdifactEncoder(), new Base256Encoder() - }; - - EncoderContext context = new EncoderContext(msg); - context.setSymbolShape(shape); - context.setSizeConstraints(minSize, maxSize); - - if (msg.startsWith(MACRO_05_HEADER) && msg.endsWith(MACRO_TRAILER)) { - context.writeCodeword(MACRO_05); - context.setSkipAtEnd(2); - context.pos += MACRO_05_HEADER.length(); - } else if (msg.startsWith(MACRO_06_HEADER) && msg.endsWith(MACRO_TRAILER)) { - context.writeCodeword(MACRO_06); - context.setSkipAtEnd(2); - context.pos += MACRO_06_HEADER.length(); - } - - int encodingMode = ASCII_ENCODATION; //Default mode - while (context.hasMoreCharacters()) { - encoders[encodingMode].encode(context); - if (context.getNewEncoding() >= 0) { - encodingMode = context.getNewEncoding(); - context.resetEncoderSignal(); - } - } - int len = context.getCodewordCount(); - context.updateSymbolInfo(); - int capacity = context.getSymbolInfo().getDataCapacity(); - if (len < capacity) { - if (encodingMode != ASCII_ENCODATION && encodingMode != BASE256_ENCODATION) { - context.writeCodeword('\u00fe'); //Unlatch (254) - } - } - //Padding - StringBuilder codewords = context.getCodewords(); - if (codewords.length() < capacity) { - codewords.append(PAD); - } - while (codewords.length() < capacity) { - codewords.append(randomize253State(PAD, codewords.length() + 1)); - } - - return context.getCodewords().toString(); - } - - static int lookAheadTest(CharSequence msg, int startpos, int currentMode) { - if (startpos >= msg.length()) { - return currentMode; - } - float[] charCounts; - //step J - if (currentMode == ASCII_ENCODATION) { - charCounts = new float[]{0, 1, 1, 1, 1, 1.25f}; - } else { - charCounts = new float[]{1, 2, 2, 2, 2, 2.25f}; - charCounts[currentMode] = 0; - } - - int charsProcessed = 0; - while (true) { - //step K - if ((startpos + charsProcessed) == msg.length()) { - int min = Integer.MAX_VALUE; - byte[] mins = new byte[6]; - int[] intCharCounts = new int[6]; - min = findMinimums(charCounts, intCharCounts, min, mins); - int minCount = getMinimumCount(mins); - - if (intCharCounts[ASCII_ENCODATION] == min) { - return ASCII_ENCODATION; - } - if (minCount == 1 && mins[BASE256_ENCODATION] > 0) { - return BASE256_ENCODATION; - } - if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { - return EDIFACT_ENCODATION; - } - if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { - return TEXT_ENCODATION; - } - if (minCount == 1 && mins[X12_ENCODATION] > 0) { - return X12_ENCODATION; - } - return C40_ENCODATION; - } - - char c = msg.charAt(startpos + charsProcessed); - charsProcessed++; - - //step L - if (isDigit(c)) { - charCounts[ASCII_ENCODATION] += 0.5; - } else if (isExtendedASCII(c)) { - charCounts[ASCII_ENCODATION] = (int) Math.ceil(charCounts[ASCII_ENCODATION]); - charCounts[ASCII_ENCODATION] += 2; - } else { - charCounts[ASCII_ENCODATION] = (int) Math.ceil(charCounts[ASCII_ENCODATION]); - charCounts[ASCII_ENCODATION]++; - } - - //step M - if (isNativeC40(c)) { - charCounts[C40_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[C40_ENCODATION] += 8.0f / 3.0f; - } else { - charCounts[C40_ENCODATION] += 4.0f / 3.0f; - } - - //step N - if (isNativeText(c)) { - charCounts[TEXT_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[TEXT_ENCODATION] += 8.0f / 3.0f; - } else { - charCounts[TEXT_ENCODATION] += 4.0f / 3.0f; - } - - //step O - if (isNativeX12(c)) { - charCounts[X12_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[X12_ENCODATION] += 13.0f / 3.0f; - } else { - charCounts[X12_ENCODATION] += 10.0f / 3.0f; - } - - //step P - if (isNativeEDIFACT(c)) { - charCounts[EDIFACT_ENCODATION] += 3.0f / 4.0f; - } else if (isExtendedASCII(c)) { - charCounts[EDIFACT_ENCODATION] += 17.0f / 4.0f; - } else { - charCounts[EDIFACT_ENCODATION] += 13.0f / 4.0f; - } - - // step Q - if (isSpecialB256(c)) { - charCounts[BASE256_ENCODATION] += 4; - } else { - charCounts[BASE256_ENCODATION]++; - } - - //step R - if (charsProcessed >= 4) { - int[] intCharCounts = new int[6]; - byte[] mins = new byte[6]; - findMinimums(charCounts, intCharCounts, Integer.MAX_VALUE, mins); - int minCount = getMinimumCount(mins); - - if (intCharCounts[ASCII_ENCODATION] < intCharCounts[BASE256_ENCODATION] - && intCharCounts[ASCII_ENCODATION] < intCharCounts[C40_ENCODATION] - && intCharCounts[ASCII_ENCODATION] < intCharCounts[TEXT_ENCODATION] - && intCharCounts[ASCII_ENCODATION] < intCharCounts[X12_ENCODATION] - && intCharCounts[ASCII_ENCODATION] < intCharCounts[EDIFACT_ENCODATION]) { - return ASCII_ENCODATION; - } - if (intCharCounts[BASE256_ENCODATION] < intCharCounts[ASCII_ENCODATION] - || (mins[C40_ENCODATION] + mins[TEXT_ENCODATION] + mins[X12_ENCODATION] + mins[EDIFACT_ENCODATION]) == 0) { - return BASE256_ENCODATION; - } - if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { - return EDIFACT_ENCODATION; - } - if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { - return TEXT_ENCODATION; - } - if (minCount == 1 && mins[X12_ENCODATION] > 0) { - return X12_ENCODATION; - } - if (intCharCounts[C40_ENCODATION] + 1 < intCharCounts[ASCII_ENCODATION] - && intCharCounts[C40_ENCODATION] + 1 < intCharCounts[BASE256_ENCODATION] - && intCharCounts[C40_ENCODATION] + 1 < intCharCounts[EDIFACT_ENCODATION] - && intCharCounts[C40_ENCODATION] + 1 < intCharCounts[TEXT_ENCODATION]) { - if (intCharCounts[C40_ENCODATION] < intCharCounts[X12_ENCODATION]) { - return C40_ENCODATION; - } - if (intCharCounts[C40_ENCODATION] == intCharCounts[X12_ENCODATION]) { - int p = startpos + charsProcessed + 1; - while (p < msg.length()) { - char tc = msg.charAt(p); - if (isX12TermSep(tc)) { - return X12_ENCODATION; - } - if (!isNativeX12(tc)) { - break; - } - p++; - } - return C40_ENCODATION; - } - } - } - } - } - - private static int findMinimums(float[] charCounts, int[] intCharCounts, int min, byte[] mins) { - Arrays.fill(mins, (byte) 0); - for (int i = 0; i < 6; i++) { - intCharCounts[i] = (int) Math.ceil(charCounts[i]); - int current = intCharCounts[i]; - if (min > current) { - min = current; - Arrays.fill(mins, (byte) 0); - } - if (min == current) { - mins[i]++; - - } - } - return min; - } - - private static int getMinimumCount(byte[] mins) { - int minCount = 0; - for (int i = 0; i < 6; i++) { - minCount += mins[i]; - } - return minCount; - } - - static boolean isDigit(char ch) { - return ch >= '0' && ch <= '9'; - } - - static boolean isExtendedASCII(char ch) { - return ch >= 128 && ch <= 255; - } - - private static boolean isNativeC40(char ch) { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); - } - - private static boolean isNativeText(char ch) { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z'); - } - - private static boolean isNativeX12(char ch) { - return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); - } - - private static boolean isX12TermSep(char ch) { - return (ch == '\r') //CR - || (ch == '*') - || (ch == '>'); - } - - private static boolean isNativeEDIFACT(char ch) { - return ch >= ' ' && ch <= '^'; - } - - private static boolean isSpecialB256(char ch) { - return false; //TODO NOT IMPLEMENTED YET!!! - } - - /** - * Determines the number of consecutive characters that are encodable using numeric compaction. - * - * @param msg the message - * @param startpos the start position within the message - * @return the requested character count - */ - public static int determineConsecutiveDigitCount(CharSequence msg, int startpos) { - int count = 0; - int len = msg.length(); - int idx = startpos; - if (idx < len) { - char ch = msg.charAt(idx); - while (isDigit(ch) && idx < len) { - count++; - idx++; - if (idx < len) { - ch = msg.charAt(idx); - } - } - } - return count; - } - - static void illegalCharacter(char c) { - String hex = Integer.toHexString(c); - hex = "0000".substring(0, 4 - hex.length()) + hex; - throw new IllegalArgumentException("Illegal character: " + c + " (0x" + hex + ')'); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolInfo.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolInfo.java deleted file mode 100644 index 2cb956cfa..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolInfo.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -import com.google.zxing.Dimension; - -/** - * Symbol info table for DataMatrix. - * - * @version $Id$ - */ -public class SymbolInfo { - - static final SymbolInfo[] PROD_SYMBOLS = { - new SymbolInfo(false, 3, 5, 8, 8, 1), - new SymbolInfo(false, 5, 7, 10, 10, 1), - /*rect*/new SymbolInfo(true, 5, 7, 16, 6, 1), - new SymbolInfo(false, 8, 10, 12, 12, 1), - /*rect*/new SymbolInfo(true, 10, 11, 14, 6, 2), - new SymbolInfo(false, 12, 12, 14, 14, 1), - /*rect*/new SymbolInfo(true, 16, 14, 24, 10, 1), - - new SymbolInfo(false, 18, 14, 16, 16, 1), - new SymbolInfo(false, 22, 18, 18, 18, 1), - /*rect*/new SymbolInfo(true, 22, 18, 16, 10, 2), - new SymbolInfo(false, 30, 20, 20, 20, 1), - /*rect*/new SymbolInfo(true, 32, 24, 16, 14, 2), - new SymbolInfo(false, 36, 24, 22, 22, 1), - new SymbolInfo(false, 44, 28, 24, 24, 1), - /*rect*/new SymbolInfo(true, 49, 28, 22, 14, 2), - - new SymbolInfo(false, 62, 36, 14, 14, 4), - new SymbolInfo(false, 86, 42, 16, 16, 4), - new SymbolInfo(false, 114, 48, 18, 18, 4), - new SymbolInfo(false, 144, 56, 20, 20, 4), - new SymbolInfo(false, 174, 68, 22, 22, 4), - - new SymbolInfo(false, 204, 84, 24, 24, 4, 102, 42), - new SymbolInfo(false, 280, 112, 14, 14, 16, 140, 56), - new SymbolInfo(false, 368, 144, 16, 16, 16, 92, 36), - new SymbolInfo(false, 456, 192, 18, 18, 16, 114, 48), - new SymbolInfo(false, 576, 224, 20, 20, 16, 144, 56), - new SymbolInfo(false, 696, 272, 22, 22, 16, 174, 68), - new SymbolInfo(false, 816, 336, 24, 24, 16, 136, 56), - new SymbolInfo(false, 1050, 408, 18, 18, 36, 175, 68), - new SymbolInfo(false, 1304, 496, 20, 20, 36, 163, 62), - new DataMatrixSymbolInfo144(), - }; - - private static SymbolInfo[] symbols = PROD_SYMBOLS; - - /** - * Overrides the symbol info set used by this class. Used for testing purposes. - * - * @param override the symbol info set to use - */ - public static void overrideSymbolSet(SymbolInfo[] override) { - symbols = override; - } - - private final boolean rectangular; - private final int dataCapacity; - private final int errorCodewords; - public final int matrixWidth; - public final int matrixHeight; - private final int dataRegions; - private final int rsBlockData; - private final int rsBlockError; - - public SymbolInfo(boolean rectangular, int dataCapacity, int errorCodewords, - int matrixWidth, int matrixHeight, int dataRegions) { - this(rectangular, dataCapacity, errorCodewords, matrixWidth, matrixHeight, dataRegions, - dataCapacity, errorCodewords); - } - - SymbolInfo(boolean rectangular, int dataCapacity, int errorCodewords, - int matrixWidth, int matrixHeight, int dataRegions, - int rsBlockData, int rsBlockError) { - this.rectangular = rectangular; - this.dataCapacity = dataCapacity; - this.errorCodewords = errorCodewords; - this.matrixWidth = matrixWidth; - this.matrixHeight = matrixHeight; - this.dataRegions = dataRegions; - this.rsBlockData = rsBlockData; - this.rsBlockError = rsBlockError; - } - - public static SymbolInfo lookup(int dataCodewords) { - return lookup(dataCodewords, SymbolShapeHint.FORCE_NONE, true); - } - - public static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape) { - return lookup(dataCodewords, shape, true); - } - - public static SymbolInfo lookup(int dataCodewords, boolean allowRectangular, boolean fail) { - SymbolShapeHint shape = allowRectangular - ? SymbolShapeHint.FORCE_NONE : SymbolShapeHint.FORCE_SQUARE; - return lookup(dataCodewords, shape, fail); - } - - private static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape, boolean fail) { - return lookup(dataCodewords, shape, null, null, fail); - } - - public static SymbolInfo lookup(int dataCodewords, - SymbolShapeHint shape, - Dimension minSize, - Dimension maxSize, - boolean fail) { - for (SymbolInfo symbol : symbols) { - if (shape == SymbolShapeHint.FORCE_SQUARE && symbol.rectangular) { - continue; - } - if (shape == SymbolShapeHint.FORCE_RECTANGLE && !symbol.rectangular) { - continue; - } - if (minSize != null - && (symbol.getSymbolWidth() < minSize.getWidth() - || symbol.getSymbolHeight() < minSize.getHeight())) { - continue; - } - if (maxSize != null - && (symbol.getSymbolWidth() > maxSize.getWidth() - || symbol.getSymbolHeight() > maxSize.getHeight())) { - continue; - } - if (dataCodewords <= symbol.dataCapacity) { - return symbol; - } - } - if (fail) { - throw new IllegalArgumentException( - "Can't find a symbol arrangement that matches the message. Data codewords: " - + dataCodewords); - } - return null; - } - - final int getHorizontalDataRegions() { - switch (dataRegions) { - case 1: - return 1; - case 2: - return 2; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - throw new IllegalStateException("Cannot handle this number of data regions"); - } - } - - final int getVerticalDataRegions() { - switch (dataRegions) { - case 1: - return 1; - case 2: - return 1; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - throw new IllegalStateException("Cannot handle this number of data regions"); - } - } - - public final int getSymbolDataWidth() { - return getHorizontalDataRegions() * matrixWidth; - } - - public final int getSymbolDataHeight() { - return getVerticalDataRegions() * matrixHeight; - } - - public final int getSymbolWidth() { - return getSymbolDataWidth() + (getHorizontalDataRegions() * 2); - } - - public final int getSymbolHeight() { - return getSymbolDataHeight() + (getVerticalDataRegions() * 2); - } - - public int getCodewordCount() { - return dataCapacity + errorCodewords; - } - - public int getInterleavedBlockCount() { - return dataCapacity / rsBlockData; - } - - public final int getDataCapacity() { - return dataCapacity; - } - - public final int getErrorCodewords() { - return errorCodewords; - } - - public int getDataLengthForInterleavedBlock(int index) { - return rsBlockData; - } - - public final int getErrorLengthForInterleavedBlock(int index) { - return rsBlockError; - } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(rectangular ? "Rectangular Symbol:" : "Square Symbol:"); - sb.append(" data region ").append(matrixWidth).append('x').append(matrixHeight); - sb.append(", symbol size ").append(getSymbolWidth()).append('x').append(getSymbolHeight()); - sb.append(", symbol data size ").append(getSymbolDataWidth()).append('x').append(getSymbolDataHeight()); - sb.append(", codewords ").append(dataCapacity).append('+').append(errorCodewords); - return sb.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolShapeHint.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolShapeHint.java deleted file mode 100644 index 58739b8b9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/SymbolShapeHint.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -/** - * Enumeration for DataMatrix symbol shape hint. It can be used to force square or rectangular - * symbols. - */ -public enum SymbolShapeHint { - - FORCE_NONE, - FORCE_SQUARE, - FORCE_RECTANGLE, - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/TextEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/TextEncoder.java deleted file mode 100644 index 19af016b7..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/TextEncoder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class TextEncoder extends C40Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.TEXT_ENCODATION; - } - - @Override - int encodeChar(char c, StringBuilder sb) { - if (c == ' ') { - sb.append('\3'); - return 1; - } - if (c >= '0' && c <= '9') { - sb.append((char) (c - 48 + 4)); - return 1; - } - if (c >= 'a' && c <= 'z') { - sb.append((char) (c - 97 + 14)); - return 1; - } - if (c >= '\0' && c <= '\u001f') { - sb.append('\0'); //Shift 1 Set - sb.append(c); - return 2; - } - if (c >= '!' && c <= '/') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 33)); - return 2; - } - if (c >= ':' && c <= '@') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 58 + 15)); - return 2; - } - if (c >= '[' && c <= '_') { - sb.append('\1'); //Shift 2 Set - sb.append((char) (c - 91 + 22)); - return 2; - } - if (c == '\u0060') { - sb.append('\2'); //Shift 3 Set - sb.append((char) (c - 96)); - return 2; - } - if (c >= 'A' && c <= 'Z') { - sb.append('\2'); //Shift 3 Set - sb.append((char) (c - 65 + 1)); - return 2; - } - if (c >= '{' && c <= '\u007f') { - sb.append('\2'); //Shift 3 Set - sb.append((char) (c - 123 + 27)); - return 2; - } - if (c >= '\u0080') { - sb.append("\1\u001e"); //Shift 2, Upper Shift - int len = 2; - len += encodeChar((char) (c - 128), sb); - return len; - } - HighLevelEncoder.illegalCharacter(c); - return -1; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/X12Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/X12Encoder.java deleted file mode 100644 index 0184bec49..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/datamatrix/encoder/X12Encoder.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.datamatrix.encoder; - -final class X12Encoder extends C40Encoder { - - @Override - public int getEncodingMode() { - return HighLevelEncoder.X12_ENCODATION; - } - - @Override - public void encode(EncoderContext context) { - //step C - StringBuilder buffer = new StringBuilder(); - while (context.hasMoreCharacters()) { - char c = context.getCurrentChar(); - context.pos++; - - encodeChar(c, buffer); - - int count = buffer.length(); - if ((count % 3) == 0) { - writeNextTriplet(context, buffer); - - int newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer); - } - - @Override - int encodeChar(char c, StringBuilder sb) { - if (c == '\r') { - sb.append('\0'); - } else if (c == '*') { - sb.append('\1'); - } else if (c == '>') { - sb.append('\2'); - } else if (c == ' ') { - sb.append('\3'); - } else if (c >= '0' && c <= '9') { - sb.append((char) (c - 48 + 4)); - } else if (c >= 'A' && c <= 'Z') { - sb.append((char) (c - 65 + 14)); - } else { - HighLevelEncoder.illegalCharacter(c); - } - return 1; - } - - @Override - void handleEOD(EncoderContext context, StringBuilder buffer) { - context.updateSymbolInfo(); - int available = context.getSymbolInfo().getDataCapacity() - context.getCodewordCount(); - int count = buffer.length(); - context.pos -= count; - if (context.getRemainingCharacters() > 1 || available > 1 || - context.getRemainingCharacters() != available) { - context.writeCodeword(HighLevelEncoder.X12_UNLATCH); - } - if (context.getNewEncoding() < 0) { - context.signalEncoderChange(HighLevelEncoder.ASCII_ENCODATION); - } - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/MaxiCodeReader.java b/extern/zxing-core/src/main/java/com/google/zxing/maxicode/MaxiCodeReader.java deleted file mode 100644 index 6eb3b959e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/MaxiCodeReader.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.maxicode; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.maxicode.decoder.Decoder; - -import java.util.Map; - -/** - * This implementation can detect and decode a MaxiCode in an image. - */ -public final class MaxiCodeReader implements Reader { - - private static final ResultPoint[] NO_POINTS = new ResultPoint[0]; - private static final int MATRIX_WIDTH = 30; - private static final int MATRIX_HEIGHT = 33; - - private final Decoder decoder = new Decoder(); - - /* - Decoder getDecoder() { - return decoder; - } - */ - - /** - * Locates and decodes a MaxiCode in an image. - * - * @return a String representing the content encoded by the MaxiCode - * @throws NotFoundException if a MaxiCode cannot be found - * @throws FormatException if a MaxiCode cannot be decoded - * @throws ChecksumException if error correction fails - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException { - return decode(image, null); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, ChecksumException, FormatException { - DecoderResult decoderResult; - if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { - BitMatrix bits = extractPureBits(image.getBlackMatrix()); - decoderResult = decoder.decode(bits, hints); - } else { - throw NotFoundException.getNotFoundInstance(); - } - - ResultPoint[] points = NO_POINTS; - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.MAXICODE); - - String ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - return result; - } - - @Override - public void reset() { - // do nothing - } - - /** - * This method detects a code in a "pure" image -- that is, pure monochrome image - * which contains only an unrotated, unskewed, image of a code, with some white border - * around it. This is a specialized method that works exceptionally fast in this special - * case. - * - * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix) - * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix) - */ - private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException { - - int[] enclosingRectangle = image.getEnclosingRectangle(); - if (enclosingRectangle == null) { - throw NotFoundException.getNotFoundInstance(); - } - - int left = enclosingRectangle[0]; - int top = enclosingRectangle[1]; - int width = enclosingRectangle[2]; - int height = enclosingRectangle[3]; - - // Now just read off the bits - BitMatrix bits = new BitMatrix(MATRIX_WIDTH, MATRIX_HEIGHT); - for (int y = 0; y < MATRIX_HEIGHT; y++) { - int iy = top + (y * height + height / 2) / MATRIX_HEIGHT; - for (int x = 0; x < MATRIX_WIDTH; x++) { - int ix = left + (x * width + width / 2 + (y & 0x01) * width / 2) / MATRIX_WIDTH; - if (image.get(ix, iy)) { - bits.set(x, y); - } - } - } - return bits; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/BitMatrixParser.java b/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/BitMatrixParser.java deleted file mode 100644 index be18a7e2a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/BitMatrixParser.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.maxicode.decoder; - -import com.google.zxing.common.BitMatrix; - -/** - * @author mike32767 - * @author Manuel Kasten - */ -final class BitMatrixParser { - - private static final int[][] BITNR = { - {121,120,127,126,133,132,139,138,145,144,151,150,157,156,163,162,169,168,175,174,181,180,187,186,193,192,199,198, -2, -2}, - {123,122,129,128,135,134,141,140,147,146,153,152,159,158,165,164,171,170,177,176,183,182,189,188,195,194,201,200,816, -3}, - {125,124,131,130,137,136,143,142,149,148,155,154,161,160,167,166,173,172,179,178,185,184,191,190,197,196,203,202,818,817}, - {283,282,277,276,271,270,265,264,259,258,253,252,247,246,241,240,235,234,229,228,223,222,217,216,211,210,205,204,819, -3}, - {285,284,279,278,273,272,267,266,261,260,255,254,249,248,243,242,237,236,231,230,225,224,219,218,213,212,207,206,821,820}, - {287,286,281,280,275,274,269,268,263,262,257,256,251,250,245,244,239,238,233,232,227,226,221,220,215,214,209,208,822, -3}, - {289,288,295,294,301,300,307,306,313,312,319,318,325,324,331,330,337,336,343,342,349,348,355,354,361,360,367,366,824,823}, - {291,290,297,296,303,302,309,308,315,314,321,320,327,326,333,332,339,338,345,344,351,350,357,356,363,362,369,368,825, -3}, - {293,292,299,298,305,304,311,310,317,316,323,322,329,328,335,334,341,340,347,346,353,352,359,358,365,364,371,370,827,826}, - {409,408,403,402,397,396,391,390, 79, 78, -2, -2, 13, 12, 37, 36, 2, -1, 44, 43,109,108,385,384,379,378,373,372,828, -3}, - {411,410,405,404,399,398,393,392, 81, 80, 40, -2, 15, 14, 39, 38, 3, -1, -1, 45,111,110,387,386,381,380,375,374,830,829}, - {413,412,407,406,401,400,395,394, 83, 82, 41, -3, -3, -3, -3, -3, 5, 4, 47, 46,113,112,389,388,383,382,377,376,831, -3}, - {415,414,421,420,427,426,103,102, 55, 54, 16, -3, -3, -3, -3, -3, -3, -3, 20, 19, 85, 84,433,432,439,438,445,444,833,832}, - {417,416,423,422,429,428,105,104, 57, 56, -3, -3, -3, -3, -3, -3, -3, -3, 22, 21, 87, 86,435,434,441,440,447,446,834, -3}, - {419,418,425,424,431,430,107,106, 59, 58, -3, -3, -3, -3, -3, -3, -3, -3, -3, 23, 89, 88,437,436,443,442,449,448,836,835}, - {481,480,475,474,469,468, 48, -2, 30, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 0, 53, 52,463,462,457,456,451,450,837, -3}, - {483,482,477,476,471,470, 49, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -1,465,464,459,458,453,452,839,838}, - {485,484,479,478,473,472, 51, 50, 31, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 1, -2, 42,467,466,461,460,455,454,840, -3}, - {487,486,493,492,499,498, 97, 96, 61, 60, -3, -3, -3, -3, -3, -3, -3, -3, -3, 26, 91, 90,505,504,511,510,517,516,842,841}, - {489,488,495,494,501,500, 99, 98, 63, 62, -3, -3, -3, -3, -3, -3, -3, -3, 28, 27, 93, 92,507,506,513,512,519,518,843, -3}, - {491,490,497,496,503,502,101,100, 65, 64, 17, -3, -3, -3, -3, -3, -3, -3, 18, 29, 95, 94,509,508,515,514,521,520,845,844}, - {559,558,553,552,547,546,541,540, 73, 72, 32, -3, -3, -3, -3, -3, -3, 10, 67, 66,115,114,535,534,529,528,523,522,846, -3}, - {561,560,555,554,549,548,543,542, 75, 74, -2, -1, 7, 6, 35, 34, 11, -2, 69, 68,117,116,537,536,531,530,525,524,848,847}, - {563,562,557,556,551,550,545,544, 77, 76, -2, 33, 9, 8, 25, 24, -1, -2, 71, 70,119,118,539,538,533,532,527,526,849, -3}, - {565,564,571,570,577,576,583,582,589,588,595,594,601,600,607,606,613,612,619,618,625,624,631,630,637,636,643,642,851,850}, - {567,566,573,572,579,578,585,584,591,590,597,596,603,602,609,608,615,614,621,620,627,626,633,632,639,638,645,644,852, -3}, - {569,568,575,574,581,580,587,586,593,592,599,598,605,604,611,610,617,616,623,622,629,628,635,634,641,640,647,646,854,853}, - {727,726,721,720,715,714,709,708,703,702,697,696,691,690,685,684,679,678,673,672,667,666,661,660,655,654,649,648,855, -3}, - {729,728,723,722,717,716,711,710,705,704,699,698,693,692,687,686,681,680,675,674,669,668,663,662,657,656,651,650,857,856}, - {731,730,725,724,719,718,713,712,707,706,701,700,695,694,689,688,683,682,677,676,671,670,665,664,659,658,653,652,858, -3}, - {733,732,739,738,745,744,751,750,757,756,763,762,769,768,775,774,781,780,787,786,793,792,799,798,805,804,811,810,860,859}, - {735,734,741,740,747,746,753,752,759,758,765,764,771,770,777,776,783,782,789,788,795,794,801,800,807,806,813,812,861, -3}, - {737,736,743,742,749,748,755,754,761,760,767,766,773,772,779,778,785,784,791,790,797,796,803,802,809,808,815,814,863,862} - }; - - private final BitMatrix bitMatrix; - - /** - * @param bitMatrix {@link BitMatrix} to parse - */ - BitMatrixParser(BitMatrix bitMatrix) { - this.bitMatrix = bitMatrix; - } - - byte[] readCodewords() { - byte[] result = new byte[144]; - int height = bitMatrix.getHeight(); - int width = bitMatrix.getWidth(); - for (int y = 0; y < height; y++) { - int[] bitnrRow = BITNR[y]; - for (int x = 0; x < width; x++) { - int bit = bitnrRow[x]; - if (bit >= 0 && bitMatrix.get(x, y)) { - result[bit / 6] |= (byte) (1 << (5 - (bit % 6))); - } - } - } - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/DecodedBitStreamParser.java b/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/DecodedBitStreamParser.java deleted file mode 100644 index 4744d4db2..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/DecodedBitStreamParser.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.maxicode.decoder; - -import com.google.zxing.common.DecoderResult; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - *

    MaxiCodes can encode text or structured information as bits in one of several modes, - * with multiple character sets in one code. This class decodes the bits back into text.

    - * - * @author mike32767 - * @author Manuel Kasten - */ -final class DecodedBitStreamParser { - - private static final char SHIFTA = '\uFFF0'; - private static final char SHIFTB = '\uFFF1'; - private static final char SHIFTC = '\uFFF2'; - private static final char SHIFTD = '\uFFF3'; - private static final char SHIFTE = '\uFFF4'; - private static final char TWOSHIFTA = '\uFFF5'; - private static final char THREESHIFTA = '\uFFF6'; - private static final char LATCHA = '\uFFF7'; - private static final char LATCHB = '\uFFF8'; - private static final char LOCK = '\uFFF9'; - private static final char ECI = '\uFFFA'; - private static final char NS = '\uFFFB'; - private static final char PAD = '\uFFFC'; - private static final char FS = '\u001C'; - private static final char GS = '\u001D'; - private static final char RS = '\u001E'; - private static final NumberFormat NINE_DIGITS = new DecimalFormat("000000000"); - private static final NumberFormat THREE_DIGITS = new DecimalFormat("000"); - - private static final String[] SETS = { - "\nABCDEFGHIJKLMNOPQRSTUVWXYZ"+ECI+FS+GS+RS+NS+' '+PAD+"\"#$%&'()*+,-./0123456789:"+SHIFTB+SHIFTC+SHIFTD+SHIFTE+LATCHB, - "`abcdefghijklmnopqrstuvwxyz"+ECI+FS+GS+RS+NS+'{'+PAD+"}~\u007F;<=>?[\\]^_ ,./:@!|"+PAD+TWOSHIFTA+THREESHIFTA+PAD+SHIFTA+SHIFTC+SHIFTD+SHIFTE+LATCHA, - "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA"+ECI+FS+GS+RS+"\u00DB\u00DC\u00DD\u00DE\u00DF\u00AA\u00AC\u00B1\u00B2\u00B3\u00B5\u00B9\u00BA\u00BC\u00BD\u00BE\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089"+LATCHA+' '+LOCK+SHIFTD+SHIFTE+LATCHB, - "\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA"+ECI+FS+GS+RS+NS+"\u00FB\u00FC\u00FD\u00FE\u00FF\u00A1\u00A8\u00AB\u00AF\u00B0\u00B4\u00B7\u00B8\u00BB\u00BF\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094"+LATCHA+' '+SHIFTC+LOCK+SHIFTE+LATCHB, - "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\n\u000B\u000C\r\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A"+ECI+PAD+PAD+'\u001B'+NS+FS+GS+RS+"\u001F\u009F\u00A0\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A9\u00AD\u00AE\u00B6\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E"+LATCHA+' '+SHIFTC+SHIFTD+LOCK+LATCHB, - "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\n\u000B\u000C\r\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\u0020\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F" - }; - - private DecodedBitStreamParser() { - } - - static DecoderResult decode(byte[] bytes, int mode) { - StringBuilder result = new StringBuilder(144); - switch (mode) { - case 2: - case 3: - String postcode; - if (mode == 2) { - int pc = getPostCode2(bytes); - NumberFormat df = new DecimalFormat("0000000000".substring(0, getPostCode2Length(bytes))); - postcode = df.format(pc); - } else { - postcode = getPostCode3(bytes); - } - String country = THREE_DIGITS.format(getCountry(bytes)); - String service = THREE_DIGITS.format(getServiceClass(bytes)); - result.append(getMessage(bytes, 10, 84)); - if (result.toString().startsWith("[)>"+RS+"01"+GS)) { - result.insert(9, postcode + GS + country + GS + service + GS); - } else { - result.insert(0, postcode + GS + country + GS + service + GS); - } - break; - case 4: - result.append(getMessage(bytes, 1, 93)); - break; - case 5: - result.append(getMessage(bytes, 1, 77)); - break; - } - return new DecoderResult(bytes, result.toString(), null, String.valueOf(mode)); - } - - private static int getBit(int bit, byte[] bytes) { - bit--; - return (bytes[bit / 6] & (1 << (5 - (bit % 6)))) == 0 ? 0 : 1; - } - - private static int getInt(byte[] bytes, byte[] x) { - if (x.length == 0) { - throw new IllegalArgumentException(); - } - int val = 0; - for (int i = 0; i < x.length; i++) { - val += getBit(x[i], bytes) << (x.length - i - 1); - } - return val; - } - - private static int getCountry(byte[] bytes) { - return getInt(bytes, new byte[] {53, 54, 43, 44, 45, 46, 47, 48, 37, 38}); - } - - private static int getServiceClass(byte[] bytes) { - return getInt(bytes, new byte[] {55, 56, 57, 58, 59, 60, 49, 50, 51, 52}); - } - - private static int getPostCode2Length(byte[] bytes) { - return getInt(bytes, new byte[] {39, 40, 41, 42, 31, 32}); - } - - private static int getPostCode2(byte[] bytes) { - return getInt(bytes, new byte[] {33, 34, 35, 36, 25, 26, 27, 28, 29, 30, 19, - 20, 21, 22, 23, 24, 13, 14, 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, 2}); - } - - private static String getPostCode3(byte[] bytes) { - return String.valueOf( - new char[] { - SETS[0].charAt(getInt(bytes, new byte[] {39, 40, 41, 42, 31, 32})), - SETS[0].charAt(getInt(bytes, new byte[] {33, 34, 35, 36, 25, 26})), - SETS[0].charAt(getInt(bytes, new byte[] {27, 28, 29, 30, 19, 20})), - SETS[0].charAt(getInt(bytes, new byte[] {21, 22, 23, 24, 13, 14})), - SETS[0].charAt(getInt(bytes, new byte[] {15, 16, 17, 18, 7, 8})), - SETS[0].charAt(getInt(bytes, new byte[] { 9, 10, 11, 12, 1, 2})), - } - ); - } - - private static String getMessage(byte[] bytes, int start, int len) { - StringBuilder sb = new StringBuilder(); - int shift = -1; - int set = 0; - int lastset = 0; - for (int i = start; i < start + len; i++) { - char c = SETS[set].charAt(bytes[i]); - switch (c) { - case LATCHA: - set = 0; - shift = -1; - break; - case LATCHB: - set = 1; - shift = -1; - break; - case SHIFTA: - case SHIFTB: - case SHIFTC: - case SHIFTD: - case SHIFTE: - lastset = set; - set = c - SHIFTA; - shift = 1; - break; - case TWOSHIFTA: - lastset = set; - set = 0; - shift = 2; - break; - case THREESHIFTA: - lastset = set; - set = 0; - shift = 3; - break; - case NS: - int nsval = (bytes[++i] << 24) + (bytes[++i] << 18) + (bytes[++i] << 12) + (bytes[++i] << 6) + bytes[++i]; - sb.append(NINE_DIGITS.format(nsval)); - break; - case LOCK: - shift = -1; - break; - default: - sb.append(c); - } - if (shift-- == 0) { - set = lastset; - } - } - while (sb.length() > 0 && sb.charAt(sb.length() - 1) == PAD) { - sb.setLength(sb.length() - 1); - } - return sb.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/Decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/Decoder.java deleted file mode 100644 index f7836f4e2..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/maxicode/decoder/Decoder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.maxicode.decoder; - -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonDecoder; -import com.google.zxing.common.reedsolomon.ReedSolomonException; - -import java.util.Map; - -/** - *

    The main class which implements MaxiCode decoding -- as opposed to locating and extracting - * the MaxiCode from an image.

    - * - * @author Manuel Kasten - */ -public final class Decoder { - - private static final int ALL = 0; - private static final int EVEN = 1; - private static final int ODD = 2; - - private final ReedSolomonDecoder rsDecoder; - - public Decoder() { - rsDecoder = new ReedSolomonDecoder(GenericGF.MAXICODE_FIELD_64); - } - - public DecoderResult decode(BitMatrix bits) throws ChecksumException, FormatException { - return decode(bits, null); - } - - public DecoderResult decode(BitMatrix bits, - Map hints) throws FormatException, ChecksumException { - BitMatrixParser parser = new BitMatrixParser(bits); - byte[] codewords = parser.readCodewords(); - - correctErrors(codewords, 0, 10, 10, ALL); - int mode = codewords[0] & 0x0F; - byte[] datawords; - switch (mode) { - case 2: - case 3: - case 4: - correctErrors(codewords, 20, 84, 40, EVEN); - correctErrors(codewords, 20, 84, 40, ODD); - datawords = new byte[94]; - break; - case 5: - correctErrors(codewords, 20, 68, 56, EVEN); - correctErrors(codewords, 20, 68, 56, ODD); - datawords = new byte[78]; - break; - default: - throw FormatException.getFormatInstance(); - } - - System.arraycopy(codewords, 0, datawords, 0, 10); - System.arraycopy(codewords, 20, datawords, 10, datawords.length - 10); - - return DecodedBitStreamParser.decode(datawords, mode); - } - - private void correctErrors(byte[] codewordBytes, - int start, - int dataCodewords, - int ecCodewords, - int mode) throws ChecksumException { - int codewords = dataCodewords + ecCodewords; - - // in EVEN or ODD mode only half the codewords - int divisor = mode == ALL ? 1 : 2; - - // First read into an array of ints - int[] codewordsInts = new int[codewords / divisor]; - for (int i = 0; i < codewords; i++) { - if ((mode == ALL) || (i % 2 == (mode - 1))) { - codewordsInts[i / divisor] = codewordBytes[i + start] & 0xFF; - } - } - try { - rsDecoder.decode(codewordsInts, ecCodewords / divisor); - } catch (ReedSolomonException ignored) { - throw ChecksumException.getChecksumInstance(); - } - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < dataCodewords; i++) { - if ((mode == ALL) || (i % 2 == (mode - 1))) { - codewordBytes[i + start] = (byte) codewordsInts[i / divisor]; - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/ByQuadrantReader.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/ByQuadrantReader.java deleted file mode 100644 index 06e4b1a28..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/ByQuadrantReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; - -import java.util.Map; - -/** - * This class attempts to decode a barcode from an image, not by scanning the whole image, - * but by scanning subsets of the image. This is important when there may be multiple barcodes in - * an image, and detecting a barcode may find parts of multiple barcode and fail to decode - * (e.g. QR Codes). Instead this scans the four quadrants of the image -- and also the center - * 'quadrant' to cover the case where a barcode is found in the center. - * - * @see GenericMultipleBarcodeReader - */ -public final class ByQuadrantReader implements Reader { - - private final Reader delegate; - - public ByQuadrantReader(Reader delegate) { - this.delegate = delegate; - } - - @Override - public Result decode(BinaryBitmap image) - throws NotFoundException, ChecksumException, FormatException { - return decode(image, null); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, ChecksumException, FormatException { - - int width = image.getWidth(); - int height = image.getHeight(); - int halfWidth = width / 2; - int halfHeight = height / 2; - - try { - // No need to call makeAbsolute as results will be relative to original top left here - return delegate.decode(image.crop(0, 0, halfWidth, halfHeight), hints); - } catch (NotFoundException re) { - // continue - } - - try { - Result result = delegate.decode(image.crop(halfWidth, 0, halfWidth, halfHeight), hints); - makeAbsolute(result.getResultPoints(), halfWidth, 0); - return result; - } catch (NotFoundException re) { - // continue - } - - try { - Result result = delegate.decode(image.crop(0, halfHeight, halfWidth, halfHeight), hints); - makeAbsolute(result.getResultPoints(), 0, halfHeight); - return result; - } catch (NotFoundException re) { - // continue - } - - try { - Result result = delegate.decode(image.crop(halfWidth, halfHeight, halfWidth, halfHeight), hints); - makeAbsolute(result.getResultPoints(), halfWidth, halfHeight); - return result; - } catch (NotFoundException re) { - // continue - } - - int quarterWidth = halfWidth / 2; - int quarterHeight = halfHeight / 2; - BinaryBitmap center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight); - Result result = delegate.decode(center, hints); - makeAbsolute(result.getResultPoints(), quarterWidth, quarterHeight); - return result; - } - - @Override - public void reset() { - delegate.reset(); - } - - private static void makeAbsolute(ResultPoint[] points, int leftOffset, int topOffset) { - if (points != null) { - for (int i = 0; i < points.length; i++) { - ResultPoint relative = points[i]; - points[i] = new ResultPoint(relative.getX() + leftOffset, relative.getY() + topOffset); - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/GenericMultipleBarcodeReader.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/GenericMultipleBarcodeReader.java deleted file mode 100644 index b90dc0e31..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/GenericMultipleBarcodeReader.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - *

    Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image. - * After one barcode is found, the areas left, above, right and below the barcode's - * {@link ResultPoint}s are scanned, recursively.

    - * - *

    A caller may want to also employ {@link ByQuadrantReader} when attempting to find multiple - * 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent - * detecting any one of them.

    - * - *

    That is, instead of passing a {@link Reader} a caller might pass - * {@code new ByQuadrantReader(reader)}.

    - * - * @author Sean Owen - */ -public final class GenericMultipleBarcodeReader implements MultipleBarcodeReader { - - private static final int MIN_DIMENSION_TO_RECUR = 100; - private static final int MAX_DEPTH = 4; - - private final Reader delegate; - - public GenericMultipleBarcodeReader(Reader delegate) { - this.delegate = delegate; - } - - @Override - public Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException { - return decodeMultiple(image, null); - } - - @Override - public Result[] decodeMultiple(BinaryBitmap image, Map hints) - throws NotFoundException { - List results = new ArrayList<>(); - doDecodeMultiple(image, hints, results, 0, 0, 0); - if (results.isEmpty()) { - throw NotFoundException.getNotFoundInstance(); - } - return results.toArray(new Result[results.size()]); - } - - private void doDecodeMultiple(BinaryBitmap image, - Map hints, - List results, - int xOffset, - int yOffset, - int currentDepth) { - if (currentDepth > MAX_DEPTH) { - return; - } - - Result result; - try { - result = delegate.decode(image, hints); - } catch (ReaderException ignored) { - return; - } - boolean alreadyFound = false; - for (Result existingResult : results) { - if (existingResult.getText().equals(result.getText())) { - alreadyFound = true; - break; - } - } - if (!alreadyFound) { - results.add(translateResultPoints(result, xOffset, yOffset)); - } - ResultPoint[] resultPoints = result.getResultPoints(); - if (resultPoints == null || resultPoints.length == 0) { - return; - } - int width = image.getWidth(); - int height = image.getHeight(); - float minX = width; - float minY = height; - float maxX = 0.0f; - float maxY = 0.0f; - for (ResultPoint point : resultPoints) { - if (point == null) { - continue; - } - float x = point.getX(); - float y = point.getY(); - if (x < minX) { - minX = x; - } - if (y < minY) { - minY = y; - } - if (x > maxX) { - maxX = x; - } - if (y > maxY) { - maxY = y; - } - } - - // Decode left of barcode - if (minX > MIN_DIMENSION_TO_RECUR) { - doDecodeMultiple(image.crop(0, 0, (int) minX, height), - hints, results, - xOffset, yOffset, - currentDepth + 1); - } - // Decode above barcode - if (minY > MIN_DIMENSION_TO_RECUR) { - doDecodeMultiple(image.crop(0, 0, width, (int) minY), - hints, results, - xOffset, yOffset, - currentDepth + 1); - } - // Decode right of barcode - if (maxX < width - MIN_DIMENSION_TO_RECUR) { - doDecodeMultiple(image.crop((int) maxX, 0, width - (int) maxX, height), - hints, results, - xOffset + (int) maxX, yOffset, - currentDepth + 1); - } - // Decode below barcode - if (maxY < height - MIN_DIMENSION_TO_RECUR) { - doDecodeMultiple(image.crop(0, (int) maxY, width, height - (int) maxY), - hints, results, - xOffset, yOffset + (int) maxY, - currentDepth + 1); - } - } - - private static Result translateResultPoints(Result result, int xOffset, int yOffset) { - ResultPoint[] oldResultPoints = result.getResultPoints(); - if (oldResultPoints == null) { - return result; - } - ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.length]; - for (int i = 0; i < oldResultPoints.length; i++) { - ResultPoint oldPoint = oldResultPoints[i]; - if (oldPoint != null) { - newResultPoints[i] = new ResultPoint(oldPoint.getX() + xOffset, oldPoint.getY() + yOffset); - } - } - Result newResult = new Result(result.getText(), result.getRawBytes(), newResultPoints, result.getBarcodeFormat()); - newResult.putAllMetadata(result.getResultMetadata()); - return newResult; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/MultipleBarcodeReader.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/MultipleBarcodeReader.java deleted file mode 100644 index a35872799..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/MultipleBarcodeReader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; - -import java.util.Map; - -/** - * Implementation of this interface attempt to read several barcodes from one image. - * - * @see com.google.zxing.Reader - * @author Sean Owen - */ -public interface MultipleBarcodeReader { - - Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException; - - Result[] decodeMultiple(BinaryBitmap image, - Map hints) throws NotFoundException; - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/QRCodeMultiReader.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/QRCodeMultiReader.java deleted file mode 100644 index 7f4a531bc..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/QRCodeMultiReader.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi.qrcode; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.multi.MultipleBarcodeReader; -import com.google.zxing.multi.qrcode.detector.MultiDetector; -import com.google.zxing.qrcode.QRCodeReader; -import com.google.zxing.qrcode.decoder.QRCodeDecoderMetaData; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Collections; -import java.util.Comparator; - -/** - * This implementation can detect and decode multiple QR Codes in an image. - * - * @author Sean Owen - * @author Hannes Erven - */ -public final class QRCodeMultiReader extends QRCodeReader implements MultipleBarcodeReader { - - private static final Result[] EMPTY_RESULT_ARRAY = new Result[0]; - private static final ResultPoint[] NO_POINTS = new ResultPoint[0]; - - @Override - public Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException { - return decodeMultiple(image, null); - } - - @Override - public Result[] decodeMultiple(BinaryBitmap image, Map hints) throws NotFoundException { - List results = new ArrayList<>(); - DetectorResult[] detectorResults = new MultiDetector(image.getBlackMatrix()).detectMulti(hints); - for (DetectorResult detectorResult : detectorResults) { - try { - DecoderResult decoderResult = getDecoder().decode(detectorResult.getBits(), hints); - ResultPoint[] points = detectorResult.getPoints(); - // If the code was mirrored: swap the bottom-left and the top-right points. - if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) { - ((QRCodeDecoderMetaData) decoderResult.getOther()).applyMirroredCorrection(points); - } - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, - BarcodeFormat.QR_CODE); - List byteSegments = decoderResult.getByteSegments(); - if (byteSegments != null) { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - String ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - if (decoderResult.hasStructuredAppend()) { - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, - decoderResult.getStructuredAppendSequenceNumber()); - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, - decoderResult.getStructuredAppendParity()); - } - results.add(result); - } catch (ReaderException re) { - // ignore and continue - } - } - if (results.isEmpty()) { - return EMPTY_RESULT_ARRAY; - } else { - results = processStructuredAppend(results); - return results.toArray(new Result[results.size()]); - } - } - - private static List processStructuredAppend(List results) { - boolean hasSA = false; - - // first, check, if there is at least on SA result in the list - for (Result result : results) { - if (result.getResultMetadata().containsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { - hasSA = true; - break; - } - } - if (!hasSA) { - return results; - } - - // it is, second, split the lists and built a new result list - List newResults = new ArrayList<>(); - List saResults = new ArrayList<>(); - for (Result result : results) { - newResults.add(result); - if (result.getResultMetadata().containsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { - saResults.add(result); - } - } - // sort and concatenate the SA list items - Collections.sort(saResults, new SAComparator()); - StringBuilder concatedText = new StringBuilder(); - int rawBytesLen = 0; - int byteSegmentLength = 0; - for (Result saResult : saResults) { - concatedText.append(saResult.getText()); - rawBytesLen += saResult.getRawBytes().length; - if (saResult.getResultMetadata().containsKey(ResultMetadataType.BYTE_SEGMENTS)) { - @SuppressWarnings("unchecked") - Iterable byteSegments = - (Iterable) saResult.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS); - for (byte[] segment : byteSegments) { - byteSegmentLength += segment.length; - } - } - } - byte[] newRawBytes = new byte[rawBytesLen]; - byte[] newByteSegment = new byte[byteSegmentLength]; - int newRawBytesIndex = 0; - int byteSegmentIndex = 0; - for (Result saResult : saResults) { - System.arraycopy(saResult.getRawBytes(), 0, newRawBytes, newRawBytesIndex, saResult.getRawBytes().length); - newRawBytesIndex += saResult.getRawBytes().length; - if (saResult.getResultMetadata().containsKey(ResultMetadataType.BYTE_SEGMENTS)) { - @SuppressWarnings("unchecked") - Iterable byteSegments = - (Iterable) saResult.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS); - for (byte[] segment : byteSegments) { - System.arraycopy(segment, 0, newByteSegment, byteSegmentIndex, segment.length); - byteSegmentIndex += segment.length; - } - } - } - Result newResult = new Result(concatedText.toString(), newRawBytes, NO_POINTS, BarcodeFormat.QR_CODE); - if (byteSegmentLength > 0) { - Collection byteSegmentList = new ArrayList<>(); - byteSegmentList.add(newByteSegment); - newResult.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegmentList); - } - newResults.add(newResult); - return newResults; - } - - private static final class SAComparator implements Comparator, Serializable { - @Override - public int compare(Result a, Result b) { - int aNumber = (int) (a.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)); - int bNumber = (int) (b.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)); - if (aNumber < bNumber) { - return -1; - } - if (aNumber > bNumber) { - return 1; - } - return 0; - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiDetector.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiDetector.java deleted file mode 100644 index 9b242104b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiDetector.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi.qrcode.detector; - -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.ReaderException; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.qrcode.detector.Detector; -import com.google.zxing.qrcode.detector.FinderPatternInfo; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - *

    Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code - * is rotated or skewed, or partially obscured.

    - * - * @author Sean Owen - * @author Hannes Erven - */ -public final class MultiDetector extends Detector { - - private static final DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0]; - - public MultiDetector(BitMatrix image) { - super(image); - } - - public DetectorResult[] detectMulti(Map hints) throws NotFoundException { - BitMatrix image = getImage(); - ResultPointCallback resultPointCallback = - hints == null ? null : (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image, resultPointCallback); - FinderPatternInfo[] infos = finder.findMulti(hints); - - if (infos.length == 0) { - throw NotFoundException.getNotFoundInstance(); - } - - List result = new ArrayList<>(); - for (FinderPatternInfo info : infos) { - try { - result.add(processFinderPatternInfo(info)); - } catch (ReaderException e) { - // ignore - } - } - if (result.isEmpty()) { - return EMPTY_DETECTOR_RESULTS; - } else { - return result.toArray(new DetectorResult[result.size()]); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java b/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java deleted file mode 100644 index 6ec4bc46a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.multi.qrcode.detector; - -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.detector.FinderPattern; -import com.google.zxing.qrcode.detector.FinderPatternFinder; -import com.google.zxing.qrcode.detector.FinderPatternInfo; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -/** - *

    This class attempts to find finder patterns in a QR Code. Finder patterns are the square - * markers at three corners of a QR Code.

    - * - *

    This class is thread-safe but not reentrant. Each thread must allocate its own object. - * - *

    In contrast to {@link FinderPatternFinder}, this class will return an array of all possible - * QR code locations in the image.

    - * - *

    Use the TRY_HARDER hint to ask for a more thorough detection.

    - * - * @author Sean Owen - * @author Hannes Erven - */ -final class MultiFinderPatternFinder extends FinderPatternFinder { - - private static final FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0]; - - // TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for - // since it limits the number of regions to decode - - // max. legal count of modules per QR code edge (177) - private static final float MAX_MODULE_COUNT_PER_EDGE = 180; - // min. legal count per modules per QR code edge (11) - private static final float MIN_MODULE_COUNT_PER_EDGE = 9; - - /** - * More or less arbitrary cutoff point for determining if two finder patterns might belong - * to the same code if they differ less than DIFF_MODSIZE_CUTOFF_PERCENT percent in their - * estimated modules sizes. - */ - private static final float DIFF_MODSIZE_CUTOFF_PERCENT = 0.05f; - - /** - * More or less arbitrary cutoff point for determining if two finder patterns might belong - * to the same code if they differ less than DIFF_MODSIZE_CUTOFF pixels/module in their - * estimated modules sizes. - */ - private static final float DIFF_MODSIZE_CUTOFF = 0.5f; - - - /** - * A comparator that orders FinderPatterns by their estimated module size. - */ - private static final class ModuleSizeComparator implements Comparator, Serializable { - @Override - public int compare(FinderPattern center1, FinderPattern center2) { - float value = center2.getEstimatedModuleSize() - center1.getEstimatedModuleSize(); - return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; - } - } - - /** - *

    Creates a finder that will search the image for three finder patterns.

    - * - * @param image image to search - */ - MultiFinderPatternFinder(BitMatrix image) { - super(image); - } - - MultiFinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) { - super(image, resultPointCallback); - } - - /** - * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are - * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module - * size differs from the average among those patterns the least - * @throws NotFoundException if 3 such finder patterns do not exist - */ - private FinderPattern[][] selectMutipleBestPatterns() throws NotFoundException { - List possibleCenters = getPossibleCenters(); - int size = possibleCenters.size(); - - if (size < 3) { - // Couldn't find enough finder patterns - throw NotFoundException.getNotFoundInstance(); - } - - /* - * Begin HE modifications to safely detect multiple codes of equal size - */ - if (size == 3) { - return new FinderPattern[][]{ - new FinderPattern[]{ - possibleCenters.get(0), - possibleCenters.get(1), - possibleCenters.get(2) - } - }; - } - - // Sort by estimated module size to speed up the upcoming checks - Collections.sort(possibleCenters, new ModuleSizeComparator()); - - /* - * Now lets start: build a list of tuples of three finder locations that - * - feature similar module sizes - * - are placed in a distance so the estimated module count is within the QR specification - * - have similar distance between upper left/right and left top/bottom finder patterns - * - form a triangle with 90° angle (checked by comparing top right/bottom left distance - * with pythagoras) - * - * Note: we allow each point to be used for more than one code region: this might seem - * counterintuitive at first, but the performance penalty is not that big. At this point, - * we cannot make a good quality decision whether the three finders actually represent - * a QR code, or are just by chance layouted so it looks like there might be a QR code there. - * So, if the layout seems right, lets have the decoder try to decode. - */ - - List results = new ArrayList<>(); // holder for the results - - for (int i1 = 0; i1 < (size - 2); i1++) { - FinderPattern p1 = possibleCenters.get(i1); - if (p1 == null) { - continue; - } - - for (int i2 = i1 + 1; i2 < (size - 1); i2++) { - FinderPattern p2 = possibleCenters.get(i2); - if (p2 == null) { - continue; - } - - // Compare the expected module sizes; if they are really off, skip - float vModSize12 = (p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize()) / - Math.min(p1.getEstimatedModuleSize(), p2.getEstimatedModuleSize()); - float vModSize12A = Math.abs(p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize()); - if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT) { - // break, since elements are ordered by the module size deviation there cannot be - // any more interesting elements for the given p1. - break; - } - - for (int i3 = i2 + 1; i3 < size; i3++) { - FinderPattern p3 = possibleCenters.get(i3); - if (p3 == null) { - continue; - } - - // Compare the expected module sizes; if they are really off, skip - float vModSize23 = (p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize()) / - Math.min(p2.getEstimatedModuleSize(), p3.getEstimatedModuleSize()); - float vModSize23A = Math.abs(p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize()); - if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT) { - // break, since elements are ordered by the module size deviation there cannot be - // any more interesting elements for the given p1. - break; - } - - FinderPattern[] test = {p1, p2, p3}; - ResultPoint.orderBestPatterns(test); - - // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal - FinderPatternInfo info = new FinderPatternInfo(test); - float dA = ResultPoint.distance(info.getTopLeft(), info.getBottomLeft()); - float dC = ResultPoint.distance(info.getTopRight(), info.getBottomLeft()); - float dB = ResultPoint.distance(info.getTopLeft(), info.getTopRight()); - - // Check the sizes - float estimatedModuleCount = (dA + dB) / (p1.getEstimatedModuleSize() * 2.0f); - if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE || - estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE) { - continue; - } - - // Calculate the difference of the edge lengths in percent - float vABBC = Math.abs((dA - dB) / Math.min(dA, dB)); - if (vABBC >= 0.1f) { - continue; - } - - // Calculate the diagonal length by assuming a 90° angle at topleft - float dCpy = (float) Math.sqrt(dA * dA + dB * dB); - // Compare to the real distance in % - float vPyC = Math.abs((dC - dCpy) / Math.min(dC, dCpy)); - - if (vPyC >= 0.1f) { - continue; - } - - // All tests passed! - results.add(test); - } // end iterate p3 - } // end iterate p2 - } // end iterate p1 - - if (!results.isEmpty()) { - return results.toArray(new FinderPattern[results.size()][]); - } - - // Nothing found! - throw NotFoundException.getNotFoundInstance(); - } - - public FinderPatternInfo[] findMulti(Map hints) throws NotFoundException { - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - boolean pureBarcode = hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE); - BitMatrix image = getImage(); - int maxI = image.getHeight(); - int maxJ = image.getWidth(); - // We are looking for black/white/black/white/black modules in - // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far - - // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the - // image, and then account for the center being 3 modules in size. This gives the smallest - // number of pixels the center could be, so skip this often. When trying harder, look for all - // QR versions regardless of how dense they are. - int iSkip = (int) (maxI / (MAX_MODULES * 4.0f) * 3); - if (iSkip < MIN_SKIP || tryHarder) { - iSkip = MIN_SKIP; - } - - int[] stateCount = new int[5]; - for (int i = iSkip - 1; i < maxI; i += iSkip) { - // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - int currentState = 0; - for (int j = 0; j < maxJ; j++) { - if (image.get(j, i)) { - // Black pixel - if ((currentState & 1) == 1) { // Counting white pixels - currentState++; - } - stateCount[currentState]++; - } else { // White pixel - if ((currentState & 1) == 0) { // Counting black pixels - if (currentState == 4) { // A winner? - if (foundPatternCross(stateCount) && handlePossibleCenter(stateCount, i, j, pureBarcode)) { // Yes - // Clear state to start looking again - currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - } else { // No, shift counts back by two - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - } - } else { - stateCount[++currentState]++; - } - } else { // Counting white pixels - stateCount[currentState]++; - } - } - } // for j=... - - if (foundPatternCross(stateCount)) { - handlePossibleCenter(stateCount, i, maxJ, pureBarcode); - } // end if foundPatternCross - } // for i=iSkip-1 ... - FinderPattern[][] patternInfo = selectMutipleBestPatterns(); - List result = new ArrayList<>(); - for (FinderPattern[] pattern : patternInfo) { - ResultPoint.orderBestPatterns(pattern); - result.add(new FinderPatternInfo(pattern)); - } - - if (result.isEmpty()) { - return EMPTY_RESULT_ARRAY; - } else { - return result.toArray(new FinderPatternInfo[result.size()]); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarReader.java deleted file mode 100644 index d5fd956cb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarReader.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.Map; - -/** - *

    Decodes Codabar barcodes.

    - * - * @author Bas Vijfwinkel - * @author David Walker - */ -public final class CodaBarReader extends OneDReader { - - // These values are critical for determining how permissive the decoding - // will be. All stripe sizes must be within the window these define, as - // compared to the average stripe size. - private static final float MAX_ACCEPTABLE = 2.0f; - private static final float PADDING = 1.5f; - - private static final String ALPHABET_STRING = "0123456789-$:/.+ABCD"; - static final char[] ALPHABET = ALPHABET_STRING.toCharArray(); - - /** - * These represent the encodings of characters, as patterns of wide and narrow bars. The 7 least-significant bits of - * each int correspond to the pattern of wide and narrow, with 1s representing "wide" and 0s representing narrow. - */ - static final int[] CHARACTER_ENCODINGS = { - 0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, // 0-9 - 0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E, // -$:/.+ABCD - }; - - // minimal number of characters that should be present (inclusing start and stop characters) - // under normal circumstances this should be set to 3, but can be set higher - // as a last-ditch attempt to reduce false positives. - private static final int MIN_CHARACTER_LENGTH = 3; - - // official start and end patterns - private static final char[] STARTEND_ENCODING = {'A', 'B', 'C', 'D'}; - // some codabar generator allow the codabar string to be closed by every - // character. This will cause lots of false positives! - - // some industries use a checksum standard but this is not part of the original codabar standard - // for more information see : http://www.mecsw.com/specs/codabar.html - - // Keep some instance variables to avoid reallocations - private final StringBuilder decodeRowResult; - private int[] counters; - private int counterLength; - - public CodaBarReader() { - decodeRowResult = new StringBuilder(20); - counters = new int[80]; - counterLength = 0; - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) throws NotFoundException { - - Arrays.fill(counters, 0); - setCounters(row); - int startOffset = findStartPattern(); - int nextStart = startOffset; - - decodeRowResult.setLength(0); - do { - int charOffset = toNarrowWidePattern(nextStart); - if (charOffset == -1) { - throw NotFoundException.getNotFoundInstance(); - } - // Hack: We store the position in the alphabet table into a - // StringBuilder, so that we can access the decoded patterns in - // validatePattern. We'll translate to the actual characters later. - decodeRowResult.append((char)charOffset); - nextStart += 8; - // Stop as soon as we see the end character. - if (decodeRowResult.length() > 1 && - arrayContains(STARTEND_ENCODING, ALPHABET[charOffset])) { - break; - } - } while (nextStart < counterLength); // no fixed end pattern so keep on reading while data is available - - // Look for whitespace after pattern: - int trailingWhitespace = counters[nextStart - 1]; - int lastPatternSize = 0; - for (int i = -8; i < -1; i++) { - lastPatternSize += counters[nextStart + i]; - } - - // We need to see whitespace equal to 50% of the last pattern size, - // otherwise this is probably a false positive. The exception is if we are - // at the end of the row. (I.e. the barcode barely fits.) - if (nextStart < counterLength && trailingWhitespace < lastPatternSize / 2) { - throw NotFoundException.getNotFoundInstance(); - } - - validatePattern(startOffset); - - // Translate character table offsets to actual characters. - for (int i = 0; i < decodeRowResult.length(); i++) { - decodeRowResult.setCharAt(i, ALPHABET[decodeRowResult.charAt(i)]); - } - // Ensure a valid start and end character - char startchar = decodeRowResult.charAt(0); - if (!arrayContains(STARTEND_ENCODING, startchar)) { - throw NotFoundException.getNotFoundInstance(); - } - char endchar = decodeRowResult.charAt(decodeRowResult.length() - 1); - if (!arrayContains(STARTEND_ENCODING, endchar)) { - throw NotFoundException.getNotFoundInstance(); - } - - // remove stop/start characters character and check if a long enough string is contained - if (decodeRowResult.length() <= MIN_CHARACTER_LENGTH) { - // Almost surely a false positive ( start + stop + at least 1 character) - throw NotFoundException.getNotFoundInstance(); - } - - if (hints == null || !hints.containsKey(DecodeHintType.RETURN_CODABAR_START_END)) { - decodeRowResult.deleteCharAt(decodeRowResult.length() - 1); - decodeRowResult.deleteCharAt(0); - } - - int runningCount = 0; - for (int i = 0; i < startOffset; i++) { - runningCount += counters[i]; - } - float left = (float) runningCount; - for (int i = startOffset; i < nextStart - 1; i++) { - runningCount += counters[i]; - } - float right = (float) runningCount; - return new Result( - decodeRowResult.toString(), - null, - new ResultPoint[]{ - new ResultPoint(left, (float) rowNumber), - new ResultPoint(right, (float) rowNumber)}, - BarcodeFormat.CODABAR); - } - - void validatePattern(int start) throws NotFoundException { - // First, sum up the total size of our four categories of stripe sizes; - int[] sizes = {0, 0, 0, 0}; - int[] counts = {0, 0, 0, 0}; - int end = decodeRowResult.length() - 1; - - // We break out of this loop in the middle, in order to handle - // inter-character spaces properly. - int pos = start; - for (int i = 0; true; i++) { - int pattern = CHARACTER_ENCODINGS[decodeRowResult.charAt(i)]; - for (int j = 6; j >= 0; j--) { - // Even j = bars, while odd j = spaces. Categories 2 and 3 are for - // long stripes, while 0 and 1 are for short stripes. - int category = (j & 1) + (pattern & 1) * 2; - sizes[category] += counters[pos + j]; - counts[category]++; - pattern >>= 1; - } - if (i >= end) { - break; - } - // We ignore the inter-character space - it could be of any size. - pos += 8; - } - - // Calculate our allowable size thresholds using fixed-point math. - float[] maxes = new float[4]; - float[] mins = new float[4]; - // Define the threshold of acceptability to be the midpoint between the - // average small stripe and the average large stripe. No stripe lengths - // should be on the "wrong" side of that line. - for (int i = 0; i < 2; i++) { - mins[i] = 0.0f; // Accept arbitrarily small "short" stripes. - mins[i + 2] = ((float) sizes[i] / counts[i] + (float) sizes[i + 2] / counts[i + 2]) / 2.0f; - maxes[i] = mins[i + 2]; - maxes[i + 2] = (sizes[i + 2] * MAX_ACCEPTABLE + PADDING) / counts[i + 2]; - } - - // Now verify that all of the stripes are within the thresholds. - pos = start; - for (int i = 0; true; i++) { - int pattern = CHARACTER_ENCODINGS[decodeRowResult.charAt(i)]; - for (int j = 6; j >= 0; j--) { - // Even j = bars, while odd j = spaces. Categories 2 and 3 are for - // long stripes, while 0 and 1 are for short stripes. - int category = (j & 1) + (pattern & 1) * 2; - int size = counters[pos + j]; - if (size < mins[category] || size > maxes[category]) { - throw NotFoundException.getNotFoundInstance(); - } - pattern >>= 1; - } - if (i >= end) { - break; - } - pos += 8; - } - } - - /** - * Records the size of all runs of white and black pixels, starting with white. - * This is just like recordPattern, except it records all the counters, and - * uses our builtin "counters" member for storage. - * @param row row to count from - */ - private void setCounters(BitArray row) throws NotFoundException { - counterLength = 0; - // Start from the first white bit. - int i = row.getNextUnset(0); - int end = row.getSize(); - if (i >= end) { - throw NotFoundException.getNotFoundInstance(); - } - boolean isWhite = true; - int count = 0; - while (i < end) { - if (row.get(i) ^ isWhite) { // that is, exactly one is true - count++; - } else { - counterAppend(count); - count = 1; - isWhite = !isWhite; - } - i++; - } - counterAppend(count); - } - - private void counterAppend(int e) { - counters[counterLength] = e; - counterLength++; - if (counterLength >= counters.length) { - int[] temp = new int[counterLength * 2]; - System.arraycopy(counters, 0, temp, 0, counterLength); - counters = temp; - } - } - - private int findStartPattern() throws NotFoundException { - for (int i = 1; i < counterLength; i += 2) { - int charOffset = toNarrowWidePattern(i); - if (charOffset != -1 && arrayContains(STARTEND_ENCODING, ALPHABET[charOffset])) { - // Look for whitespace before start pattern, >= 50% of width of start pattern - // We make an exception if the whitespace is the first element. - int patternSize = 0; - for (int j = i; j < i + 7; j++) { - patternSize += counters[j]; - } - if (i == 1 || counters[i-1] >= patternSize / 2) { - return i; - } - } - } - throw NotFoundException.getNotFoundInstance(); - } - - static boolean arrayContains(char[] array, char key) { - if (array != null) { - for (char c : array) { - if (c == key) { - return true; - } - } - } - return false; - } - - // Assumes that counters[position] is a bar. - private int toNarrowWidePattern(int position) { - int end = position + 7; - if (end >= counterLength) { - return -1; - } - - int[] theCounters = counters; - - int maxBar = 0; - int minBar = Integer.MAX_VALUE; - for (int j = position; j < end; j += 2) { - int currentCounter = theCounters[j]; - if (currentCounter < minBar) { - minBar = currentCounter; - } - if (currentCounter > maxBar) { - maxBar = currentCounter; - } - } - int thresholdBar = (minBar + maxBar) / 2; - - int maxSpace = 0; - int minSpace = Integer.MAX_VALUE; - for (int j = position + 1; j < end; j += 2) { - int currentCounter = theCounters[j]; - if (currentCounter < minSpace) { - minSpace = currentCounter; - } - if (currentCounter > maxSpace) { - maxSpace = currentCounter; - } - } - int thresholdSpace = (minSpace + maxSpace) / 2; - - int bitmask = 1 << 7; - int pattern = 0; - for (int i = 0; i < 7; i++) { - int threshold = (i & 1) == 0 ? thresholdBar : thresholdSpace; - bitmask >>= 1; - if (theCounters[position + i] > threshold) { - pattern |= bitmask; - } - } - - for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) { - if (CHARACTER_ENCODINGS[i] == pattern) { - return i; - } - } - return -1; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarWriter.java deleted file mode 100644 index d27a166f1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/CodaBarWriter.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -/** - * This class renders CodaBar as {@code boolean[]}. - * - * @author dsbnatut@gmail.com (Kazuki Nishiura) - */ -public final class CodaBarWriter extends OneDimensionalCodeWriter { - - private static final char[] START_END_CHARS = {'A', 'B', 'C', 'D'}; - private static final char[] ALT_START_END_CHARS = {'T', 'N', '*', 'E'}; - private static final char[] CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED = {'/', ':', '+', '.'}; - private static final char DEFAULT_GUARD = START_END_CHARS[0]; - - @Override - public boolean[] encode(String contents) { - - if (contents.length() < 2) { - // Can't have a start/end guard, so tentatively add default guards - contents = DEFAULT_GUARD + contents + DEFAULT_GUARD; - } else { - // Verify input and calculate decoded length. - char firstChar = Character.toUpperCase(contents.charAt(0)); - char lastChar = Character.toUpperCase(contents.charAt(contents.length() - 1)); - boolean startsNormal = CodaBarReader.arrayContains(START_END_CHARS, firstChar); - boolean endsNormal = CodaBarReader.arrayContains(START_END_CHARS, lastChar); - boolean startsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, firstChar); - boolean endsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, lastChar); - if (startsNormal) { - if (!endsNormal) { - throw new IllegalArgumentException("Invalid start/end guards: " + contents); - } - // else already has valid start/end - } else if (startsAlt) { - if (!endsAlt) { - throw new IllegalArgumentException("Invalid start/end guards: " + contents); - } - // else already has valid start/end - } else { - // Doesn't start with a guard - if (endsNormal || endsAlt) { - throw new IllegalArgumentException("Invalid start/end guards: " + contents); - } - // else doesn't end with guard either, so add a default - contents = DEFAULT_GUARD + contents + DEFAULT_GUARD; - } - } - - // The start character and the end character are decoded to 10 length each. - int resultLength = 20; - for (int i = 1; i < contents.length() - 1; i++) { - if (Character.isDigit(contents.charAt(i)) || contents.charAt(i) == '-' || contents.charAt(i) == '$') { - resultLength += 9; - } else if (CodaBarReader.arrayContains(CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED, contents.charAt(i))) { - resultLength += 10; - } else { - throw new IllegalArgumentException("Cannot encode : '" + contents.charAt(i) + '\''); - } - } - // A blank is placed between each character. - resultLength += contents.length() - 1; - - boolean[] result = new boolean[resultLength]; - int position = 0; - for (int index = 0; index < contents.length(); index++) { - char c = Character.toUpperCase(contents.charAt(index)); - if (index == 0 || index == contents.length() - 1) { - // The start/end chars are not in the CodaBarReader.ALPHABET. - switch (c) { - case 'T': - c = 'A'; - break; - case 'N': - c = 'B'; - break; - case '*': - c = 'C'; - break; - case 'E': - c = 'D'; - break; - } - } - int code = 0; - for (int i = 0; i < CodaBarReader.ALPHABET.length; i++) { - // Found any, because I checked above. - if (c == CodaBarReader.ALPHABET[i]) { - code = CodaBarReader.CHARACTER_ENCODINGS[i]; - break; - } - } - boolean color = true; - int counter = 0; - int bit = 0; - while (bit < 7) { // A character consists of 7 digit. - result[position] = color; - position++; - if (((code >> (6 - bit)) & 1) == 0 || counter == 1) { - color = !color; // Flip the color. - bit++; - counter = 0; - } else { - counter++; - } - } - if (index < contents.length() - 1) { - result[position] = false; - position++; - } - } - return result; - } -} - diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Reader.java deleted file mode 100644 index 5fe6c986c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Reader.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - *

    Decodes Code 128 barcodes.

    - * - * @author Sean Owen - */ -public final class Code128Reader extends OneDReader { - - static final int[][] CODE_PATTERNS = { - {2, 1, 2, 2, 2, 2}, // 0 - {2, 2, 2, 1, 2, 2}, - {2, 2, 2, 2, 2, 1}, - {1, 2, 1, 2, 2, 3}, - {1, 2, 1, 3, 2, 2}, - {1, 3, 1, 2, 2, 2}, // 5 - {1, 2, 2, 2, 1, 3}, - {1, 2, 2, 3, 1, 2}, - {1, 3, 2, 2, 1, 2}, - {2, 2, 1, 2, 1, 3}, - {2, 2, 1, 3, 1, 2}, // 10 - {2, 3, 1, 2, 1, 2}, - {1, 1, 2, 2, 3, 2}, - {1, 2, 2, 1, 3, 2}, - {1, 2, 2, 2, 3, 1}, - {1, 1, 3, 2, 2, 2}, // 15 - {1, 2, 3, 1, 2, 2}, - {1, 2, 3, 2, 2, 1}, - {2, 2, 3, 2, 1, 1}, - {2, 2, 1, 1, 3, 2}, - {2, 2, 1, 2, 3, 1}, // 20 - {2, 1, 3, 2, 1, 2}, - {2, 2, 3, 1, 1, 2}, - {3, 1, 2, 1, 3, 1}, - {3, 1, 1, 2, 2, 2}, - {3, 2, 1, 1, 2, 2}, // 25 - {3, 2, 1, 2, 2, 1}, - {3, 1, 2, 2, 1, 2}, - {3, 2, 2, 1, 1, 2}, - {3, 2, 2, 2, 1, 1}, - {2, 1, 2, 1, 2, 3}, // 30 - {2, 1, 2, 3, 2, 1}, - {2, 3, 2, 1, 2, 1}, - {1, 1, 1, 3, 2, 3}, - {1, 3, 1, 1, 2, 3}, - {1, 3, 1, 3, 2, 1}, // 35 - {1, 1, 2, 3, 1, 3}, - {1, 3, 2, 1, 1, 3}, - {1, 3, 2, 3, 1, 1}, - {2, 1, 1, 3, 1, 3}, - {2, 3, 1, 1, 1, 3}, // 40 - {2, 3, 1, 3, 1, 1}, - {1, 1, 2, 1, 3, 3}, - {1, 1, 2, 3, 3, 1}, - {1, 3, 2, 1, 3, 1}, - {1, 1, 3, 1, 2, 3}, // 45 - {1, 1, 3, 3, 2, 1}, - {1, 3, 3, 1, 2, 1}, - {3, 1, 3, 1, 2, 1}, - {2, 1, 1, 3, 3, 1}, - {2, 3, 1, 1, 3, 1}, // 50 - {2, 1, 3, 1, 1, 3}, - {2, 1, 3, 3, 1, 1}, - {2, 1, 3, 1, 3, 1}, - {3, 1, 1, 1, 2, 3}, - {3, 1, 1, 3, 2, 1}, // 55 - {3, 3, 1, 1, 2, 1}, - {3, 1, 2, 1, 1, 3}, - {3, 1, 2, 3, 1, 1}, - {3, 3, 2, 1, 1, 1}, - {3, 1, 4, 1, 1, 1}, // 60 - {2, 2, 1, 4, 1, 1}, - {4, 3, 1, 1, 1, 1}, - {1, 1, 1, 2, 2, 4}, - {1, 1, 1, 4, 2, 2}, - {1, 2, 1, 1, 2, 4}, // 65 - {1, 2, 1, 4, 2, 1}, - {1, 4, 1, 1, 2, 2}, - {1, 4, 1, 2, 2, 1}, - {1, 1, 2, 2, 1, 4}, - {1, 1, 2, 4, 1, 2}, // 70 - {1, 2, 2, 1, 1, 4}, - {1, 2, 2, 4, 1, 1}, - {1, 4, 2, 1, 1, 2}, - {1, 4, 2, 2, 1, 1}, - {2, 4, 1, 2, 1, 1}, // 75 - {2, 2, 1, 1, 1, 4}, - {4, 1, 3, 1, 1, 1}, - {2, 4, 1, 1, 1, 2}, - {1, 3, 4, 1, 1, 1}, - {1, 1, 1, 2, 4, 2}, // 80 - {1, 2, 1, 1, 4, 2}, - {1, 2, 1, 2, 4, 1}, - {1, 1, 4, 2, 1, 2}, - {1, 2, 4, 1, 1, 2}, - {1, 2, 4, 2, 1, 1}, // 85 - {4, 1, 1, 2, 1, 2}, - {4, 2, 1, 1, 1, 2}, - {4, 2, 1, 2, 1, 1}, - {2, 1, 2, 1, 4, 1}, - {2, 1, 4, 1, 2, 1}, // 90 - {4, 1, 2, 1, 2, 1}, - {1, 1, 1, 1, 4, 3}, - {1, 1, 1, 3, 4, 1}, - {1, 3, 1, 1, 4, 1}, - {1, 1, 4, 1, 1, 3}, // 95 - {1, 1, 4, 3, 1, 1}, - {4, 1, 1, 1, 1, 3}, - {4, 1, 1, 3, 1, 1}, - {1, 1, 3, 1, 4, 1}, - {1, 1, 4, 1, 3, 1}, // 100 - {3, 1, 1, 1, 4, 1}, - {4, 1, 1, 1, 3, 1}, - {2, 1, 1, 4, 1, 2}, - {2, 1, 1, 2, 1, 4}, - {2, 1, 1, 2, 3, 2}, // 105 - {2, 3, 3, 1, 1, 1, 2} - }; - - private static final float MAX_AVG_VARIANCE = 0.25f; - private static final float MAX_INDIVIDUAL_VARIANCE = 0.7f; - - private static final int CODE_SHIFT = 98; - - private static final int CODE_CODE_C = 99; - private static final int CODE_CODE_B = 100; - private static final int CODE_CODE_A = 101; - - private static final int CODE_FNC_1 = 102; - private static final int CODE_FNC_2 = 97; - private static final int CODE_FNC_3 = 96; - private static final int CODE_FNC_4_A = 101; - private static final int CODE_FNC_4_B = 100; - - private static final int CODE_START_A = 103; - private static final int CODE_START_B = 104; - private static final int CODE_START_C = 105; - private static final int CODE_STOP = 106; - - private static int[] findStartPattern(BitArray row) throws NotFoundException { - int width = row.getSize(); - int rowOffset = row.getNextSet(0); - - int counterPosition = 0; - int[] counters = new int[6]; - int patternStart = rowOffset; - boolean isWhite = false; - int patternLength = counters.length; - - for (int i = rowOffset; i < width; i++) { - if (row.get(i) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - float bestVariance = MAX_AVG_VARIANCE; - int bestMatch = -1; - for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { - float variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], - MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) { - bestVariance = variance; - bestMatch = startCode; - } - } - // Look for whitespace before start pattern, >= 50% of width of start pattern - if (bestMatch >= 0 && - row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { - return new int[]{patternStart, i, bestMatch}; - } - patternStart += counters[0] + counters[1]; - System.arraycopy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static int decodeCode(BitArray row, int[] counters, int rowOffset) - throws NotFoundException { - recordPattern(row, rowOffset, counters); - float bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - int bestMatch = -1; - for (int d = 0; d < CODE_PATTERNS.length; d++) { - int[] pattern = CODE_PATTERNS[d]; - float variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) { - bestVariance = variance; - bestMatch = d; - } - } - // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. - if (bestMatch >= 0) { - return bestMatch; - } else { - throw NotFoundException.getNotFoundInstance(); - } - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, FormatException, ChecksumException { - - boolean convertFNC1 = hints != null && hints.containsKey(DecodeHintType.ASSUME_GS1); - - int[] startPatternInfo = findStartPattern(row); - int startCode = startPatternInfo[2]; - - List rawCodes = new ArrayList<>(20); - rawCodes.add((byte) startCode); - - int codeSet; - switch (startCode) { - case CODE_START_A: - codeSet = CODE_CODE_A; - break; - case CODE_START_B: - codeSet = CODE_CODE_B; - break; - case CODE_START_C: - codeSet = CODE_CODE_C; - break; - default: - throw FormatException.getFormatInstance(); - } - - boolean done = false; - boolean isNextShifted = false; - - StringBuilder result = new StringBuilder(20); - - int lastStart = startPatternInfo[0]; - int nextStart = startPatternInfo[1]; - int[] counters = new int[6]; - - int lastCode = 0; - int code = 0; - int checksumTotal = startCode; - int multiplier = 0; - boolean lastCharacterWasPrintable = true; - boolean upperMode = false; - boolean shiftUpperMode = false; - - while (!done) { - - boolean unshift = isNextShifted; - isNextShifted = false; - - // Save off last code - lastCode = code; - - // Decode another code from image - code = decodeCode(row, counters, nextStart); - - rawCodes.add((byte) code); - - // Remember whether the last code was printable or not (excluding CODE_STOP) - if (code != CODE_STOP) { - lastCharacterWasPrintable = true; - } - - // Add to checksum computation (if not CODE_STOP of course) - if (code != CODE_STOP) { - multiplier++; - checksumTotal += multiplier * code; - } - - // Advance to where the next code will to start - lastStart = nextStart; - for (int counter : counters) { - nextStart += counter; - } - - // Take care of illegal start codes - switch (code) { - case CODE_START_A: - case CODE_START_B: - case CODE_START_C: - throw FormatException.getFormatInstance(); - } - - switch (codeSet) { - - case CODE_CODE_A: - if (code < 64) { - if (shiftUpperMode == upperMode) { - result.append((char) (' ' + code)); - } else { - result.append((char) (' ' + code + 128)); - } - shiftUpperMode = false; - } else if (code < 96) { - if (shiftUpperMode == upperMode) { - result.append((char) (code - 64)); - } else { - result.append((char) (code + 64)); - } - shiftUpperMode = false; - } else { - // Don't let CODE_STOP, which always appears, affect whether whether we think the last - // code was printable or not. - if (code != CODE_STOP) { - lastCharacterWasPrintable = false; - } - switch (code) { - case CODE_FNC_1: - if (convertFNC1) { - if (result.length() == 0){ - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.append("]C1"); - } else { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.append((char) 29); - } - } - break; - case CODE_FNC_2: - case CODE_FNC_3: - // do nothing? - break; - case CODE_FNC_4_A: - if (!upperMode && shiftUpperMode) { - upperMode = true; - shiftUpperMode = false; - } else if (upperMode && shiftUpperMode) { - upperMode = false; - shiftUpperMode = false; - } else { - shiftUpperMode = true; - } - break; - case CODE_SHIFT: - isNextShifted = true; - codeSet = CODE_CODE_B; - break; - case CODE_CODE_B: - codeSet = CODE_CODE_B; - break; - case CODE_CODE_C: - codeSet = CODE_CODE_C; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - case CODE_CODE_B: - if (code < 96) { - if (shiftUpperMode == upperMode) { - result.append((char) (' ' + code)); - } else { - result.append((char) (' ' + code + 128)); - } - shiftUpperMode = false; - } else { - if (code != CODE_STOP) { - lastCharacterWasPrintable = false; - } - switch (code) { - case CODE_FNC_1: - if (convertFNC1) { - if (result.length() == 0){ - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.append("]C1"); - } else { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.append((char) 29); - } - } - break; - case CODE_FNC_2: - case CODE_FNC_3: - // do nothing? - break; - case CODE_FNC_4_B: - if (!upperMode && shiftUpperMode) { - upperMode = true; - shiftUpperMode = false; - } else if (upperMode && shiftUpperMode) { - upperMode = false; - shiftUpperMode = false; - } else { - shiftUpperMode = true; - } - break; - case CODE_SHIFT: - isNextShifted = true; - codeSet = CODE_CODE_A; - break; - case CODE_CODE_A: - codeSet = CODE_CODE_A; - break; - case CODE_CODE_C: - codeSet = CODE_CODE_C; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - case CODE_CODE_C: - if (code < 100) { - if (code < 10) { - result.append('0'); - } - result.append(code); - } else { - if (code != CODE_STOP) { - lastCharacterWasPrintable = false; - } - switch (code) { - case CODE_FNC_1: - if (convertFNC1) { - if (result.length() == 0){ - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.append("]C1"); - } else { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.append((char) 29); - } - } - break; - case CODE_CODE_A: - codeSet = CODE_CODE_A; - break; - case CODE_CODE_B: - codeSet = CODE_CODE_B; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - } - - // Unshift back to another code set if we were shifted - if (unshift) { - codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A; - } - - } - - int lastPatternSize = nextStart - lastStart; - - // Check for ample whitespace following pattern, but, to do this we first need to remember that - // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left - // to read off. Would be slightly better to properly read. Here we just skip it: - nextStart = row.getNextUnset(nextStart); - if (!row.isRange(nextStart, - Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2), - false)) { - throw NotFoundException.getNotFoundInstance(); - } - - // Pull out from sum the value of the penultimate check code - checksumTotal -= multiplier * lastCode; - // lastCode is the checksum then: - if (checksumTotal % 103 != lastCode) { - throw ChecksumException.getChecksumInstance(); - } - - // Need to pull out the check digits from string - int resultLength = result.length(); - if (resultLength == 0) { - // false positive - throw NotFoundException.getNotFoundInstance(); - } - - // Only bother if the result had at least one character, and if the checksum digit happened to - // be a printable character. If it was just interpreted as a control code, nothing to remove. - if (resultLength > 0 && lastCharacterWasPrintable) { - if (codeSet == CODE_CODE_C) { - result.delete(resultLength - 2, resultLength); - } else { - result.delete(resultLength - 1, resultLength); - } - } - - float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f; - float right = lastStart + lastPatternSize / 2.0f; - - int rawCodesSize = rawCodes.size(); - byte[] rawBytes = new byte[rawCodesSize]; - for (int i = 0; i < rawCodesSize; i++) { - rawBytes[i] = rawCodes.get(i); - } - - return new Result( - result.toString(), - rawBytes, - new ResultPoint[]{ - new ResultPoint(left, (float) rowNumber), - new ResultPoint(right, (float) rowNumber)}, - BarcodeFormat.CODE_128); - - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Writer.java deleted file mode 100644 index ad149e4d0..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code128Writer.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - * This object renders a CODE128 code as a {@link BitMatrix}. - * - * @author erik.barbara@gmail.com (Erik Barbara) - */ -public final class Code128Writer extends OneDimensionalCodeWriter { - - private static final int CODE_START_B = 104; - private static final int CODE_START_C = 105; - private static final int CODE_CODE_B = 100; - private static final int CODE_CODE_C = 99; - private static final int CODE_STOP = 106; - - // Dummy characters used to specify control characters in input - private static final char ESCAPE_FNC_1 = '\u00f1'; - private static final char ESCAPE_FNC_2 = '\u00f2'; - private static final char ESCAPE_FNC_3 = '\u00f3'; - private static final char ESCAPE_FNC_4 = '\u00f4'; - - private static final int CODE_FNC_1 = 102; // Code A, Code B, Code C - private static final int CODE_FNC_2 = 97; // Code A, Code B - private static final int CODE_FNC_3 = 96; // Code A, Code B - private static final int CODE_FNC_4_B = 100; // Code B - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.CODE_128) { - throw new IllegalArgumentException("Can only encode CODE_128, but got " + format); - } - return super.encode(contents, format, width, height, hints); - } - - @Override - public boolean[] encode(String contents) { - int length = contents.length(); - // Check length - if (length < 1 || length > 80) { - throw new IllegalArgumentException( - "Contents length should be between 1 and 80 characters, but got " + length); - } - // Check content - for (int i = 0; i < length; i++) { - char c = contents.charAt(i); - if (c < ' ' || c > '~') { - switch (c) { - case ESCAPE_FNC_1: - case ESCAPE_FNC_2: - case ESCAPE_FNC_3: - case ESCAPE_FNC_4: - break; - default: - throw new IllegalArgumentException("Bad character in input: " + c); - } - } - } - - Collection patterns = new ArrayList<>(); // temporary storage for patterns - int checkSum = 0; - int checkWeight = 1; - int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C) - int position = 0; // position in contents - - while (position < length) { - //Select code to use - int requiredDigitCount = codeSet == CODE_CODE_C ? 2 : 4; - int newCodeSet; - if (isDigits(contents, position, requiredDigitCount)) { - newCodeSet = CODE_CODE_C; - } else { - newCodeSet = CODE_CODE_B; - } - - //Get the pattern index - int patternIndex; - if (newCodeSet == codeSet) { - // Encode the current character - // First handle escapes - switch (contents.charAt(position)) { - case ESCAPE_FNC_1: - patternIndex = CODE_FNC_1; - break; - case ESCAPE_FNC_2: - patternIndex = CODE_FNC_2; - break; - case ESCAPE_FNC_3: - patternIndex = CODE_FNC_3; - break; - case ESCAPE_FNC_4: - patternIndex = CODE_FNC_4_B; // FIXME if this ever outputs Code A - break; - default: - // Then handle normal characters otherwise - if (codeSet == CODE_CODE_B) { - patternIndex = contents.charAt(position) - ' '; - } else { // CODE_CODE_C - patternIndex = Integer.parseInt(contents.substring(position, position + 2)); - position++; // Also incremented below - } - } - position++; - } else { - // Should we change the current code? - // Do we have a code set? - if (codeSet == 0) { - // No, we don't have a code set - if (newCodeSet == CODE_CODE_B) { - patternIndex = CODE_START_B; - } else { - // CODE_CODE_C - patternIndex = CODE_START_C; - } - } else { - // Yes, we have a code set - patternIndex = newCodeSet; - } - codeSet = newCodeSet; - } - - // Get the pattern - patterns.add(Code128Reader.CODE_PATTERNS[patternIndex]); - - // Compute checksum - checkSum += patternIndex * checkWeight; - if (position != 0) { - checkWeight++; - } - } - - // Compute and append checksum - checkSum %= 103; - patterns.add(Code128Reader.CODE_PATTERNS[checkSum]); - - // Append stop code - patterns.add(Code128Reader.CODE_PATTERNS[CODE_STOP]); - - // Compute code width - int codeWidth = 0; - for (int[] pattern : patterns) { - for (int width : pattern) { - codeWidth += width; - } - } - - // Compute result - boolean[] result = new boolean[codeWidth]; - int pos = 0; - for (int[] pattern : patterns) { - pos += appendPattern(result, pos, pattern, true); - } - - return result; - } - - private static boolean isDigits(CharSequence value, int start, int length) { - int end = start + length; - int last = value.length(); - for (int i = start; i < end && i < last; i++) { - char c = value.charAt(i); - if (c < '0' || c > '9') { - if (c != ESCAPE_FNC_1) { - return false; - } - end++; // ignore FNC_1 - } - } - return end <= last; // end > last if we've run out of string - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Reader.java deleted file mode 100644 index 76eee5717..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Reader.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.Map; - -/** - *

    Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.

    - * - * @author Sean Owen - * @see Code93Reader - */ -public final class Code39Reader extends OneDReader { - - static final String ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; - private static final char[] ALPHABET = ALPHABET_STRING.toCharArray(); - - /** - * These represent the encodings of characters, as patterns of wide and narrow bars. - * The 9 least-significant bits of each int correspond to the pattern of wide and narrow, - * with 1s representing "wide" and 0s representing narrow. - */ - static final int[] CHARACTER_ENCODINGS = { - 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 - 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J - 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T - 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-* - 0x0A8, 0x0A2, 0x08A, 0x02A // $-% - }; - - private static final int ASTERISK_ENCODING = CHARACTER_ENCODINGS[39]; - - private final boolean usingCheckDigit; - private final boolean extendedMode; - private final StringBuilder decodeRowResult; - private final int[] counters; - - /** - * Creates a reader that assumes all encoded data is data, and does not treat the final - * character as a check digit. It will not decoded "extended Code 39" sequences. - */ - public Code39Reader() { - this(false); - } - - /** - * Creates a reader that can be configured to check the last character as a check digit. - * It will not decoded "extended Code 39" sequences. - * - * @param usingCheckDigit if true, treat the last data character as a check digit, not - * data, and verify that the checksum passes. - */ - public Code39Reader(boolean usingCheckDigit) { - this(usingCheckDigit, false); - } - - /** - * Creates a reader that can be configured to check the last character as a check digit, - * or optionally attempt to decode "extended Code 39" sequences that are used to encode - * the full ASCII character set. - * - * @param usingCheckDigit if true, treat the last data character as a check digit, not - * data, and verify that the checksum passes. - * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the - * text. - */ - public Code39Reader(boolean usingCheckDigit, boolean extendedMode) { - this.usingCheckDigit = usingCheckDigit; - this.extendedMode = extendedMode; - decodeRowResult = new StringBuilder(20); - counters = new int[9]; - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, ChecksumException, FormatException { - - int[] theCounters = counters; - Arrays.fill(theCounters, 0); - StringBuilder result = decodeRowResult; - result.setLength(0); - - int[] start = findAsteriskPattern(row, theCounters); - // Read off white space - int nextStart = row.getNextSet(start[1]); - int end = row.getSize(); - - char decodedChar; - int lastStart; - do { - recordPattern(row, nextStart, theCounters); - int pattern = toNarrowWidePattern(theCounters); - if (pattern < 0) { - throw NotFoundException.getNotFoundInstance(); - } - decodedChar = patternToChar(pattern); - result.append(decodedChar); - lastStart = nextStart; - for (int counter : theCounters) { - nextStart += counter; - } - // Read off white space - nextStart = row.getNextSet(nextStart); - } while (decodedChar != '*'); - result.setLength(result.length() - 1); // remove asterisk - - // Look for whitespace after pattern: - int lastPatternSize = 0; - for (int counter : theCounters) { - lastPatternSize += counter; - } - int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; - // If 50% of last pattern size, following last pattern, is not whitespace, fail - // (but if it's whitespace to the very end of the image, that's OK) - if (nextStart != end && (whiteSpaceAfterEnd * 2) < lastPatternSize) { - throw NotFoundException.getNotFoundInstance(); - } - - if (usingCheckDigit) { - int max = result.length() - 1; - int total = 0; - for (int i = 0; i < max; i++) { - total += ALPHABET_STRING.indexOf(decodeRowResult.charAt(i)); - } - if (result.charAt(max) != ALPHABET[total % 43]) { - throw ChecksumException.getChecksumInstance(); - } - result.setLength(max); - } - - if (result.length() == 0) { - // false positive - throw NotFoundException.getNotFoundInstance(); - } - - String resultString; - if (extendedMode) { - resultString = decodeExtended(result); - } else { - resultString = result.toString(); - } - - float left = (float) (start[1] + start[0]) / 2.0f; - float right = lastStart + lastPatternSize / 2.0f; - return new Result( - resultString, - null, - new ResultPoint[]{ - new ResultPoint(left, (float) rowNumber), - new ResultPoint(right, (float) rowNumber)}, - BarcodeFormat.CODE_39); - - } - - private static int[] findAsteriskPattern(BitArray row, int[] counters) throws NotFoundException { - int width = row.getSize(); - int rowOffset = row.getNextSet(0); - - int counterPosition = 0; - int patternStart = rowOffset; - boolean isWhite = false; - int patternLength = counters.length; - - for (int i = rowOffset; i < width; i++) { - if (row.get(i) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - // Look for whitespace before start pattern, >= 50% of width of start pattern - if (toNarrowWidePattern(counters) == ASTERISK_ENCODING && - row.isRange(Math.max(0, patternStart - ((i - patternStart) / 2)), patternStart, false)) { - return new int[]{patternStart, i}; - } - patternStart += counters[0] + counters[1]; - System.arraycopy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions - // per image when using some of our blackbox images. - private static int toNarrowWidePattern(int[] counters) { - int numCounters = counters.length; - int maxNarrowCounter = 0; - int wideCounters; - do { - int minCounter = Integer.MAX_VALUE; - for (int counter : counters) { - if (counter < minCounter && counter > maxNarrowCounter) { - minCounter = counter; - } - } - maxNarrowCounter = minCounter; - wideCounters = 0; - int totalWideCountersWidth = 0; - int pattern = 0; - for (int i = 0; i < numCounters; i++) { - int counter = counters[i]; - if (counter > maxNarrowCounter) { - pattern |= 1 << (numCounters - 1 - i); - wideCounters++; - totalWideCountersWidth += counter; - } - } - if (wideCounters == 3) { - // Found 3 wide counters, but are they close enough in width? - // We can perform a cheap, conservative check to see if any individual - // counter is more than 1.5 times the average: - for (int i = 0; i < numCounters && wideCounters > 0; i++) { - int counter = counters[i]; - if (counter > maxNarrowCounter) { - wideCounters--; - // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average - if ((counter * 2) >= totalWideCountersWidth) { - return -1; - } - } - } - return pattern; - } - } while (wideCounters > 3); - return -1; - } - - private static char patternToChar(int pattern) throws NotFoundException { - for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) { - if (CHARACTER_ENCODINGS[i] == pattern) { - return ALPHABET[i]; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static String decodeExtended(CharSequence encoded) throws FormatException { - int length = encoded.length(); - StringBuilder decoded = new StringBuilder(length); - for (int i = 0; i < length; i++) { - char c = encoded.charAt(i); - if (c == '+' || c == '$' || c == '%' || c == '/') { - char next = encoded.charAt(i + 1); - char decodedChar = '\0'; - switch (c) { - case '+': - // +A to +Z map to a to z - if (next >= 'A' && next <= 'Z') { - decodedChar = (char) (next + 32); - } else { - throw FormatException.getFormatInstance(); - } - break; - case '$': - // $A to $Z map to control codes SH to SB - if (next >= 'A' && next <= 'Z') { - decodedChar = (char) (next - 64); - } else { - throw FormatException.getFormatInstance(); - } - break; - case '%': - // %A to %E map to control codes ESC to US - if (next >= 'A' && next <= 'E') { - decodedChar = (char) (next - 38); - } else if (next >= 'F' && next <= 'W') { - decodedChar = (char) (next - 11); - } else { - throw FormatException.getFormatInstance(); - } - break; - case '/': - // /A to /O map to ! to , and /Z maps to : - if (next >= 'A' && next <= 'O') { - decodedChar = (char) (next - 32); - } else if (next == 'Z') { - decodedChar = ':'; - } else { - throw FormatException.getFormatInstance(); - } - break; - } - decoded.append(decodedChar); - // bump up i again since we read two characters - i++; - } else { - decoded.append(c); - } - } - return decoded.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Writer.java deleted file mode 100644 index 8a498a0ab..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code39Writer.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * This object renders a CODE39 code as a {@link BitMatrix}. - * - * @author erik.barbara@gmail.com (Erik Barbara) - */ -public final class Code39Writer extends OneDimensionalCodeWriter { - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.CODE_39) { - throw new IllegalArgumentException("Can only encode CODE_39, but got " + format); - } - return super.encode(contents, format, width, height, hints); - } - - @Override - public boolean[] encode(String contents) { - int length = contents.length(); - if (length > 80) { - throw new IllegalArgumentException( - "Requested contents should be less than 80 digits long, but got " + length); - } - - int[] widths = new int[9]; - int codeWidth = 24 + 1 + length; - for (int i = 0; i < length; i++) { - int indexInString = Code39Reader.ALPHABET_STRING.indexOf(contents.charAt(i)); - if (indexInString < 0) { - throw new IllegalArgumentException("Bad contents: " + contents); - } - toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths); - for (int width : widths) { - codeWidth += width; - } - } - boolean[] result = new boolean[codeWidth]; - toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths); - int pos = appendPattern(result, 0, widths, true); - int[] narrowWhite = {1}; - pos += appendPattern(result, pos, narrowWhite, false); - //append next character to byte matrix - for (int i = 0; i < length; i++) { - int indexInString = Code39Reader.ALPHABET_STRING.indexOf(contents.charAt(i)); - toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths); - pos += appendPattern(result, pos, widths, true); - pos += appendPattern(result, pos, narrowWhite, false); - } - toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths); - appendPattern(result, pos, widths, true); - return result; - } - - private static void toIntArray(int a, int[] toReturn) { - for (int i = 0; i < 9; i++) { - int temp = a & (1 << (8 - i)); - toReturn[i] = temp == 0 ? 1 : 2; - } - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code93Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/Code93Reader.java deleted file mode 100644 index 0db67ea70..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/Code93Reader.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.Map; - -/** - *

    Decodes Code 93 barcodes.

    - * - * @author Sean Owen - * @see Code39Reader - */ -public final class Code93Reader extends OneDReader { - - // Note that 'abcd' are dummy characters in place of control characters. - private static final String ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd*"; - private static final char[] ALPHABET = ALPHABET_STRING.toCharArray(); - - /** - * These represent the encodings of characters, as patterns of wide and narrow bars. - * The 9 least-significant bits of each int correspond to the pattern of wide and narrow. - */ - private static final int[] CHARACTER_ENCODINGS = { - 0x114, 0x148, 0x144, 0x142, 0x128, 0x124, 0x122, 0x150, 0x112, 0x10A, // 0-9 - 0x1A8, 0x1A4, 0x1A2, 0x194, 0x192, 0x18A, 0x168, 0x164, 0x162, 0x134, // A-J - 0x11A, 0x158, 0x14C, 0x146, 0x12C, 0x116, 0x1B4, 0x1B2, 0x1AC, 0x1A6, // K-T - 0x196, 0x19A, 0x16C, 0x166, 0x136, 0x13A, // U-Z - 0x12E, 0x1D4, 0x1D2, 0x1CA, 0x16E, 0x176, 0x1AE, // - - % - 0x126, 0x1DA, 0x1D6, 0x132, 0x15E, // Control chars? $-* - }; - private static final int ASTERISK_ENCODING = CHARACTER_ENCODINGS[47]; - - private final StringBuilder decodeRowResult; - private final int[] counters; - - public Code93Reader() { - decodeRowResult = new StringBuilder(20); - counters = new int[6]; - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, ChecksumException, FormatException { - - int[] start = findAsteriskPattern(row); - // Read off white space - int nextStart = row.getNextSet(start[1]); - int end = row.getSize(); - - int[] theCounters = counters; - Arrays.fill(theCounters, 0); - StringBuilder result = decodeRowResult; - result.setLength(0); - - char decodedChar; - int lastStart; - do { - recordPattern(row, nextStart, theCounters); - int pattern = toPattern(theCounters); - if (pattern < 0) { - throw NotFoundException.getNotFoundInstance(); - } - decodedChar = patternToChar(pattern); - result.append(decodedChar); - lastStart = nextStart; - for (int counter : theCounters) { - nextStart += counter; - } - // Read off white space - nextStart = row.getNextSet(nextStart); - } while (decodedChar != '*'); - result.deleteCharAt(result.length() - 1); // remove asterisk - - int lastPatternSize = 0; - for (int counter : theCounters) { - lastPatternSize += counter; - } - - // Should be at least one more black module - if (nextStart == end || !row.get(nextStart)) { - throw NotFoundException.getNotFoundInstance(); - } - - if (result.length() < 2) { - // false positive -- need at least 2 checksum digits - throw NotFoundException.getNotFoundInstance(); - } - - checkChecksums(result); - // Remove checksum digits - result.setLength(result.length() - 2); - - String resultString = decodeExtended(result); - - float left = (float) (start[1] + start[0]) / 2.0f; - float right = lastStart + lastPatternSize / 2.0f; - return new Result( - resultString, - null, - new ResultPoint[]{ - new ResultPoint(left, (float) rowNumber), - new ResultPoint(right, (float) rowNumber)}, - BarcodeFormat.CODE_93); - - } - - private int[] findAsteriskPattern(BitArray row) throws NotFoundException { - int width = row.getSize(); - int rowOffset = row.getNextSet(0); - - Arrays.fill(counters, 0); - int[] theCounters = counters; - int patternStart = rowOffset; - boolean isWhite = false; - int patternLength = theCounters.length; - - int counterPosition = 0; - for (int i = rowOffset; i < width; i++) { - if (row.get(i) ^ isWhite) { - theCounters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - if (toPattern(theCounters) == ASTERISK_ENCODING) { - return new int[]{patternStart, i}; - } - patternStart += theCounters[0] + theCounters[1]; - System.arraycopy(theCounters, 2, theCounters, 0, patternLength - 2); - theCounters[patternLength - 2] = 0; - theCounters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - theCounters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static int toPattern(int[] counters) { - int max = counters.length; - int sum = 0; - for (int counter : counters) { - sum += counter; - } - int pattern = 0; - for (int i = 0; i < max; i++) { - int scaled = Math.round(counters[i] * 9.0f / sum); - if (scaled < 1 || scaled > 4) { - return -1; - } - if ((i & 0x01) == 0) { - for (int j = 0; j < scaled; j++) { - pattern = (pattern << 1) | 0x01; - } - } else { - pattern <<= scaled; - } - } - return pattern; - } - - private static char patternToChar(int pattern) throws NotFoundException { - for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) { - if (CHARACTER_ENCODINGS[i] == pattern) { - return ALPHABET[i]; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static String decodeExtended(CharSequence encoded) throws FormatException { - int length = encoded.length(); - StringBuilder decoded = new StringBuilder(length); - for (int i = 0; i < length; i++) { - char c = encoded.charAt(i); - if (c >= 'a' && c <= 'd') { - if (i >= length - 1) { - throw FormatException.getFormatInstance(); - } - char next = encoded.charAt(i + 1); - char decodedChar = '\0'; - switch (c) { - case 'd': - // +A to +Z map to a to z - if (next >= 'A' && next <= 'Z') { - decodedChar = (char) (next + 32); - } else { - throw FormatException.getFormatInstance(); - } - break; - case 'a': - // $A to $Z map to control codes SH to SB - if (next >= 'A' && next <= 'Z') { - decodedChar = (char) (next - 64); - } else { - throw FormatException.getFormatInstance(); - } - break; - case 'b': - if (next >= 'A' && next <= 'E') { - // %A to %E map to control codes ESC to USep - decodedChar = (char) (next - 38); - } else if (next >= 'F' && next <= 'J') { - // %F to %J map to ; < = > ? - decodedChar = (char) (next - 11); - } else if (next >= 'K' && next <= 'O') { - // %K to %O map to [ \ ] ^ _ - decodedChar = (char) (next + 16); - } else if (next >= 'P' && next <= 'S') { - // %P to %S map to { | } ~ - decodedChar = (char) (next + 43); - } else if (next >= 'T' && next <= 'Z') { - // %T to %Z all map to DEL (127) - decodedChar = 127; - } else { - throw FormatException.getFormatInstance(); - } - break; - case 'c': - // /A to /O map to ! to , and /Z maps to : - if (next >= 'A' && next <= 'O') { - decodedChar = (char) (next - 32); - } else if (next == 'Z') { - decodedChar = ':'; - } else { - throw FormatException.getFormatInstance(); - } - break; - } - decoded.append(decodedChar); - // bump up i again since we read two characters - i++; - } else { - decoded.append(c); - } - } - return decoded.toString(); - } - - private static void checkChecksums(CharSequence result) throws ChecksumException { - int length = result.length(); - checkOneChecksum(result, length - 2, 20); - checkOneChecksum(result, length - 1, 15); - } - - private static void checkOneChecksum(CharSequence result, int checkPosition, int weightMax) - throws ChecksumException { - int weight = 1; - int total = 0; - for (int i = checkPosition - 1; i >= 0; i--) { - total += weight * ALPHABET_STRING.indexOf(result.charAt(i)); - if (++weight > weightMax) { - weight = 1; - } - } - if (result.charAt(checkPosition) != ALPHABET[total % 47]) { - throw ChecksumException.getChecksumInstance(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Reader.java deleted file mode 100644 index c537eac51..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Reader.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - *

    Implements decoding of the EAN-13 format.

    - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - * @author alasdair@google.com (Alasdair Mackintosh) - */ -public final class EAN13Reader extends UPCEANReader { - - // For an EAN-13 barcode, the first digit is represented by the parities used - // to encode the next six digits, according to the table below. For example, - // if the barcode is 5 123456 789012 then the value of the first digit is - // signified by using odd for '1', even for '2', even for '3', odd for '4', - // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13 - // - // Parity of next 6 digits - // Digit 0 1 2 3 4 5 - // 0 Odd Odd Odd Odd Odd Odd - // 1 Odd Odd Even Odd Even Even - // 2 Odd Odd Even Even Odd Even - // 3 Odd Odd Even Even Even Odd - // 4 Odd Even Odd Odd Even Even - // 5 Odd Even Even Odd Odd Even - // 6 Odd Even Even Even Odd Odd - // 7 Odd Even Odd Even Odd Even - // 8 Odd Even Odd Even Even Odd - // 9 Odd Even Even Odd Even Odd - // - // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence - // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0. - // - // The encoding is represented by the following array, which is a bit pattern - // using Odd = 0 and Even = 1. For example, 5 is represented by: - // - // Odd Even Even Odd Odd Even - // in binary: - // 0 1 1 0 0 1 == 0x19 - // - static final int[] FIRST_DIGIT_ENCODINGS = { - 0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A - }; - - private final int[] decodeMiddleCounters; - - public EAN13Reader() { - decodeMiddleCounters = new int[4]; - } - - @Override - protected int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder resultString) throws NotFoundException { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.getSize(); - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 6 && rowOffset < end; x++) { - int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS); - resultString.append((char) ('0' + bestMatch % 10)); - for (int counter : counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - lgPatternFound |= 1 << (5 - x); - } - } - - determineFirstDigit(resultString, lgPatternFound); - - int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); - rowOffset = middleRange[1]; - - for (int x = 0; x < 6 && rowOffset < end; x++) { - int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); - resultString.append((char) ('0' + bestMatch)); - for (int counter : counters) { - rowOffset += counter; - } - } - - return rowOffset; - } - - @Override - BarcodeFormat getBarcodeFormat() { - return BarcodeFormat.EAN_13; - } - - /** - * Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded - * digits in a barcode, determines the implicitly encoded first digit and adds it to the - * result string. - * - * @param resultString string to insert decoded first digit into - * @param lgPatternFound int whose bits indicates the pattern of odd/even L/G patterns used to - * encode digits - * @throws NotFoundException if first digit cannot be determined - */ - private static void determineFirstDigit(StringBuilder resultString, int lgPatternFound) - throws NotFoundException { - for (int d = 0; d < 10; d++) { - if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { - resultString.insert(0, (char) ('0' + d)); - return; - } - } - throw NotFoundException.getNotFoundInstance(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Writer.java deleted file mode 100644 index f3e947d69..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN13Writer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * This object renders an EAN13 code as a {@link BitMatrix}. - * - * @author aripollak@gmail.com (Ari Pollak) - */ -public final class EAN13Writer extends UPCEANWriter { - - private static final int CODE_WIDTH = 3 + // start guard - (7 * 6) + // left bars - 5 + // middle guard - (7 * 6) + // right bars - 3; // end guard - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.EAN_13) { - throw new IllegalArgumentException("Can only encode EAN_13, but got " + format); - } - - return super.encode(contents, format, width, height, hints); - } - - @Override - public boolean[] encode(String contents) { - if (contents.length() != 13) { - throw new IllegalArgumentException( - "Requested contents should be 13 digits long, but got " + contents.length()); - } - try { - if (!UPCEANReader.checkStandardUPCEANChecksum(contents)) { - throw new IllegalArgumentException("Contents do not pass checksum"); - } - } catch (FormatException ignored) { - throw new IllegalArgumentException("Illegal contents"); - } - - int firstDigit = Integer.parseInt(contents.substring(0, 1)); - int parities = EAN13Reader.FIRST_DIGIT_ENCODINGS[firstDigit]; - boolean[] result = new boolean[CODE_WIDTH]; - int pos = 0; - - pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - // See {@link #EAN13Reader} for a description of how the first digit & left bars are encoded - for (int i = 1; i <= 6; i++) { - int digit = Integer.parseInt(contents.substring(i, i + 1)); - if ((parities >> (6 - i) & 1) == 1) { - digit += 10; - } - pos += appendPattern(result, pos, UPCEANReader.L_AND_G_PATTERNS[digit], false); - } - - pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false); - - for (int i = 7; i <= 12; i++) { - int digit = Integer.parseInt(contents.substring(i, i + 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true); - } - appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Reader.java deleted file mode 100644 index 8d0b7e21e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Reader.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - *

    Implements decoding of the EAN-8 format.

    - * - * @author Sean Owen - */ -public final class EAN8Reader extends UPCEANReader { - - private final int[] decodeMiddleCounters; - - public EAN8Reader() { - decodeMiddleCounters = new int[4]; - } - - @Override - protected int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder result) throws NotFoundException { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.getSize(); - int rowOffset = startRange[1]; - - for (int x = 0; x < 4 && rowOffset < end; x++) { - int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); - result.append((char) ('0' + bestMatch)); - for (int counter : counters) { - rowOffset += counter; - } - } - - int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); - rowOffset = middleRange[1]; - - for (int x = 0; x < 4 && rowOffset < end; x++) { - int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); - result.append((char) ('0' + bestMatch)); - for (int counter : counters) { - rowOffset += counter; - } - } - - return rowOffset; - } - - @Override - BarcodeFormat getBarcodeFormat() { - return BarcodeFormat.EAN_8; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Writer.java deleted file mode 100644 index efd807d97..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/EAN8Writer.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * This object renders an EAN8 code as a {@link BitMatrix}. - * - * @author aripollak@gmail.com (Ari Pollak) - */ -public final class EAN8Writer extends UPCEANWriter { - - private static final int CODE_WIDTH = 3 + // start guard - (7 * 4) + // left bars - 5 + // middle guard - (7 * 4) + // right bars - 3; // end guard - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.EAN_8) { - throw new IllegalArgumentException("Can only encode EAN_8, but got " - + format); - } - - return super.encode(contents, format, width, height, hints); - } - - /** - * @return a byte array of horizontal pixels (false = white, true = black) - */ - @Override - public boolean[] encode(String contents) { - if (contents.length() != 8) { - throw new IllegalArgumentException( - "Requested contents should be 8 digits long, but got " + contents.length()); - } - - boolean[] result = new boolean[CODE_WIDTH]; - int pos = 0; - - pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - for (int i = 0; i <= 3; i++) { - int digit = Integer.parseInt(contents.substring(i, i + 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], false); - } - - pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false); - - for (int i = 4; i <= 7; i++) { - int digit = Integer.parseInt(contents.substring(i, i + 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true); - } - appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/EANManufacturerOrgSupport.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/EANManufacturerOrgSupport.java deleted file mode 100644 index e5b439264..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/EANManufacturerOrgSupport.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import java.util.ArrayList; -import java.util.List; - -/** - * Records EAN prefix to GS1 Member Organization, where the member organization - * correlates strongly with a country. This is an imperfect means of identifying - * a country of origin by EAN-13 barcode value. See - * - * http://en.wikipedia.org/wiki/List_of_GS1_country_codes. - * - * @author Sean Owen - */ -final class EANManufacturerOrgSupport { - - private final List ranges = new ArrayList<>(); - private final List countryIdentifiers = new ArrayList<>(); - - String lookupCountryIdentifier(String productCode) { - initIfNeeded(); - int prefix = Integer.parseInt(productCode.substring(0, 3)); - int max = ranges.size(); - for (int i = 0; i < max; i++) { - int[] range = ranges.get(i); - int start = range[0]; - if (prefix < start) { - return null; - } - int end = range.length == 1 ? start : range[1]; - if (prefix <= end) { - return countryIdentifiers.get(i); - } - } - return null; - } - - private void add(int[] range, String id) { - ranges.add(range); - countryIdentifiers.add(id); - } - - private synchronized void initIfNeeded() { - if (!ranges.isEmpty()) { - return; - } - add(new int[] {0,19}, "US/CA"); - add(new int[] {30,39}, "US"); - add(new int[] {60,139}, "US/CA"); - add(new int[] {300,379}, "FR"); - add(new int[] {380}, "BG"); - add(new int[] {383}, "SI"); - add(new int[] {385}, "HR"); - add(new int[] {387}, "BA"); - add(new int[] {400,440}, "DE"); - add(new int[] {450,459}, "JP"); - add(new int[] {460,469}, "RU"); - add(new int[] {471}, "TW"); - add(new int[] {474}, "EE"); - add(new int[] {475}, "LV"); - add(new int[] {476}, "AZ"); - add(new int[] {477}, "LT"); - add(new int[] {478}, "UZ"); - add(new int[] {479}, "LK"); - add(new int[] {480}, "PH"); - add(new int[] {481}, "BY"); - add(new int[] {482}, "UA"); - add(new int[] {484}, "MD"); - add(new int[] {485}, "AM"); - add(new int[] {486}, "GE"); - add(new int[] {487}, "KZ"); - add(new int[] {489}, "HK"); - add(new int[] {490,499}, "JP"); - add(new int[] {500,509}, "GB"); - add(new int[] {520}, "GR"); - add(new int[] {528}, "LB"); - add(new int[] {529}, "CY"); - add(new int[] {531}, "MK"); - add(new int[] {535}, "MT"); - add(new int[] {539}, "IE"); - add(new int[] {540,549}, "BE/LU"); - add(new int[] {560}, "PT"); - add(new int[] {569}, "IS"); - add(new int[] {570,579}, "DK"); - add(new int[] {590}, "PL"); - add(new int[] {594}, "RO"); - add(new int[] {599}, "HU"); - add(new int[] {600,601}, "ZA"); - add(new int[] {603}, "GH"); - add(new int[] {608}, "BH"); - add(new int[] {609}, "MU"); - add(new int[] {611}, "MA"); - add(new int[] {613}, "DZ"); - add(new int[] {616}, "KE"); - add(new int[] {618}, "CI"); - add(new int[] {619}, "TN"); - add(new int[] {621}, "SY"); - add(new int[] {622}, "EG"); - add(new int[] {624}, "LY"); - add(new int[] {625}, "JO"); - add(new int[] {626}, "IR"); - add(new int[] {627}, "KW"); - add(new int[] {628}, "SA"); - add(new int[] {629}, "AE"); - add(new int[] {640,649}, "FI"); - add(new int[] {690,695}, "CN"); - add(new int[] {700,709}, "NO"); - add(new int[] {729}, "IL"); - add(new int[] {730,739}, "SE"); - add(new int[] {740}, "GT"); - add(new int[] {741}, "SV"); - add(new int[] {742}, "HN"); - add(new int[] {743}, "NI"); - add(new int[] {744}, "CR"); - add(new int[] {745}, "PA"); - add(new int[] {746}, "DO"); - add(new int[] {750}, "MX"); - add(new int[] {754,755}, "CA"); - add(new int[] {759}, "VE"); - add(new int[] {760,769}, "CH"); - add(new int[] {770}, "CO"); - add(new int[] {773}, "UY"); - add(new int[] {775}, "PE"); - add(new int[] {777}, "BO"); - add(new int[] {779}, "AR"); - add(new int[] {780}, "CL"); - add(new int[] {784}, "PY"); - add(new int[] {785}, "PE"); - add(new int[] {786}, "EC"); - add(new int[] {789,790}, "BR"); - add(new int[] {800,839}, "IT"); - add(new int[] {840,849}, "ES"); - add(new int[] {850}, "CU"); - add(new int[] {858}, "SK"); - add(new int[] {859}, "CZ"); - add(new int[] {860}, "YU"); - add(new int[] {865}, "MN"); - add(new int[] {867}, "KP"); - add(new int[] {868,869}, "TR"); - add(new int[] {870,879}, "NL"); - add(new int[] {880}, "KR"); - add(new int[] {885}, "TH"); - add(new int[] {888}, "SG"); - add(new int[] {890}, "IN"); - add(new int[] {893}, "VN"); - add(new int[] {896}, "PK"); - add(new int[] {899}, "ID"); - add(new int[] {900,919}, "AT"); - add(new int[] {930,939}, "AU"); - add(new int[] {940,949}, "AZ"); - add(new int[] {955}, "MY"); - add(new int[] {958}, "MO"); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFReader.java deleted file mode 100644 index d9e586412..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFReader.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.Map; - -/** - *

    Implements decoding of the ITF format, or Interleaved Two of Five.

    - * - *

    This Reader will scan ITF barcodes of certain lengths only. - * At the moment it reads length 6, 8, 10, 12, 14, 16, 18, 20, 24, and 44 as these have appeared "in the wild". Not all - * lengths are scanned, especially shorter ones, to avoid false positives. This in turn is due to a lack of - * required checksum function.

    - * - *

    The checksum is optional and is not applied by this Reader. The consumer of the decoded - * value will have to apply a checksum if required.

    - * - *

    http://en.wikipedia.org/wiki/Interleaved_2_of_5 - * is a great reference for Interleaved 2 of 5 information.

    - * - * @author kevin.osullivan@sita.aero, SITA Lab. - */ -public final class ITFReader extends OneDReader { - - private static final float MAX_AVG_VARIANCE = 0.38f; - private static final float MAX_INDIVIDUAL_VARIANCE = 0.78f; - - private static final int W = 3; // Pixel width of a wide line - private static final int N = 1; // Pixed width of a narrow line - - /** Valid ITF lengths. Anything longer than the largest value is also allowed. */ - private static final int[] DEFAULT_ALLOWED_LENGTHS = { 6, 8, 10, 12, 14 }; - - // Stores the actual narrow line width of the image being decoded. - private int narrowLineWidth = -1; - - /** - * Start/end guard pattern. - * - * Note: The end pattern is reversed because the row is reversed before - * searching for the END_PATTERN - */ - private static final int[] START_PATTERN = {N, N, N, N}; - private static final int[] END_PATTERN_REVERSED = {N, N, W}; - - /** - * Patterns of Wide / Narrow lines to indicate each digit - */ - static final int[][] PATTERNS = { - {N, N, W, W, N}, // 0 - {W, N, N, N, W}, // 1 - {N, W, N, N, W}, // 2 - {W, W, N, N, N}, // 3 - {N, N, W, N, W}, // 4 - {W, N, W, N, N}, // 5 - {N, W, W, N, N}, // 6 - {N, N, N, W, W}, // 7 - {W, N, N, W, N}, // 8 - {N, W, N, W, N} // 9 - }; - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws FormatException, NotFoundException { - - // Find out where the Middle section (payload) starts & ends - int[] startRange = decodeStart(row); - int[] endRange = decodeEnd(row); - - StringBuilder result = new StringBuilder(20); - decodeMiddle(row, startRange[1], endRange[0], result); - String resultString = result.toString(); - - int[] allowedLengths = null; - if (hints != null) { - allowedLengths = (int[]) hints.get(DecodeHintType.ALLOWED_LENGTHS); - - } - if (allowedLengths == null) { - allowedLengths = DEFAULT_ALLOWED_LENGTHS; - } - - // To avoid false positives with 2D barcodes (and other patterns), make - // an assumption that the decoded string must be a 'standard' length if it's short - int length = resultString.length(); - boolean lengthOK = false; - int maxAllowedLength = 0; - for (int allowedLength : allowedLengths) { - if (length == allowedLength) { - lengthOK = true; - break; - } - if (allowedLength > maxAllowedLength) { - maxAllowedLength = allowedLength; - } - } - if (!lengthOK && length > maxAllowedLength) { - lengthOK = true; - } - if (!lengthOK) { - throw FormatException.getFormatInstance(); - } - - return new Result( - resultString, - null, // no natural byte representation for these barcodes - new ResultPoint[] { new ResultPoint(startRange[1], (float) rowNumber), - new ResultPoint(endRange[0], (float) rowNumber)}, - BarcodeFormat.ITF); - } - - /** - * @param row row of black/white values to search - * @param payloadStart offset of start pattern - * @param resultString {@link StringBuilder} to append decoded chars to - * @throws NotFoundException if decoding could not complete successfully - */ - private static void decodeMiddle(BitArray row, - int payloadStart, - int payloadEnd, - StringBuilder resultString) throws NotFoundException { - - // Digits are interleaved in pairs - 5 black lines for one digit, and the - // 5 - // interleaved white lines for the second digit. - // Therefore, need to scan 10 lines and then - // split these into two arrays - int[] counterDigitPair = new int[10]; - int[] counterBlack = new int[5]; - int[] counterWhite = new int[5]; - - while (payloadStart < payloadEnd) { - - // Get 10 runs of black/white. - recordPattern(row, payloadStart, counterDigitPair); - // Split them into each array - for (int k = 0; k < 5; k++) { - int twoK = 2 * k; - counterBlack[k] = counterDigitPair[twoK]; - counterWhite[k] = counterDigitPair[twoK + 1]; - } - - int bestMatch = decodeDigit(counterBlack); - resultString.append((char) ('0' + bestMatch)); - bestMatch = decodeDigit(counterWhite); - resultString.append((char) ('0' + bestMatch)); - - for (int counterDigit : counterDigitPair) { - payloadStart += counterDigit; - } - } - } - - /** - * Identify where the start of the middle / payload section starts. - * - * @param row row of black/white values to search - * @return Array, containing index of start of 'start block' and end of - * 'start block' - * @throws NotFoundException - */ - int[] decodeStart(BitArray row) throws NotFoundException { - int endStart = skipWhiteSpace(row); - int[] startPattern = findGuardPattern(row, endStart, START_PATTERN); - - // Determine the width of a narrow line in pixels. We can do this by - // getting the width of the start pattern and dividing by 4 because its - // made up of 4 narrow lines. - this.narrowLineWidth = (startPattern[1] - startPattern[0]) / 4; - - validateQuietZone(row, startPattern[0]); - - return startPattern; - } - - /** - * The start & end patterns must be pre/post fixed by a quiet zone. This - * zone must be at least 10 times the width of a narrow line. Scan back until - * we either get to the start of the barcode or match the necessary number of - * quiet zone pixels. - * - * Note: Its assumed the row is reversed when using this method to find - * quiet zone after the end pattern. - * - * ref: http://www.barcode-1.net/i25code.html - * - * @param row bit array representing the scanned barcode. - * @param startPattern index into row of the start or end pattern. - * @throws NotFoundException if the quiet zone cannot be found, a ReaderException is thrown. - */ - private void validateQuietZone(BitArray row, int startPattern) throws NotFoundException { - - int quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone - - // if there are not so many pixel at all let's try as many as possible - quietCount = quietCount < startPattern ? quietCount : startPattern; - - for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) { - if (row.get(i)) { - break; - } - quietCount--; - } - if (quietCount != 0) { - // Unable to find the necessary number of quiet zone pixels. - throw NotFoundException.getNotFoundInstance(); - } - } - - /** - * Skip all whitespace until we get to the first black line. - * - * @param row row of black/white values to search - * @return index of the first black line. - * @throws NotFoundException Throws exception if no black lines are found in the row - */ - private static int skipWhiteSpace(BitArray row) throws NotFoundException { - int width = row.getSize(); - int endStart = row.getNextSet(0); - if (endStart == width) { - throw NotFoundException.getNotFoundInstance(); - } - - return endStart; - } - - /** - * Identify where the end of the middle / payload section ends. - * - * @param row row of black/white values to search - * @return Array, containing index of start of 'end block' and end of 'end - * block' - * @throws NotFoundException - */ - int[] decodeEnd(BitArray row) throws NotFoundException { - - // For convenience, reverse the row and then - // search from 'the start' for the end block - row.reverse(); - try { - int endStart = skipWhiteSpace(row); - int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED); - - // The start & end patterns must be pre/post fixed by a quiet zone. This - // zone must be at least 10 times the width of a narrow line. - // ref: http://www.barcode-1.net/i25code.html - validateQuietZone(row, endPattern[0]); - - // Now recalculate the indices of where the 'endblock' starts & stops to - // accommodate - // the reversed nature of the search - int temp = endPattern[0]; - endPattern[0] = row.getSize() - endPattern[1]; - endPattern[1] = row.getSize() - temp; - - return endPattern; - } finally { - // Put the row back the right way. - row.reverse(); - } - } - - /** - * @param row row of black/white values to search - * @param rowOffset position to start search - * @param pattern pattern of counts of number of black and white pixels that are - * being searched for as a pattern - * @return start/end horizontal offset of guard pattern, as an array of two - * ints - * @throws NotFoundException if pattern is not found - */ - private static int[] findGuardPattern(BitArray row, - int rowOffset, - int[] pattern) throws NotFoundException { - int patternLength = pattern.length; - int[] counters = new int[patternLength]; - int width = row.getSize(); - boolean isWhite = false; - - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) { - if (row.get(x) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { - return new int[]{patternStart, x}; - } - patternStart += counters[0] + counters[1]; - System.arraycopy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Attempts to decode a sequence of ITF black/white lines into single - * digit. - * - * @param counters the counts of runs of observed black/white/black/... values - * @return The decoded digit - * @throws NotFoundException if digit cannot be decoded - */ - private static int decodeDigit(int[] counters) throws NotFoundException { - float bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - int bestMatch = -1; - int max = PATTERNS.length; - for (int i = 0; i < max; i++) { - int[] pattern = PATTERNS[i]; - float variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) { - bestVariance = variance; - bestMatch = i; - } - } - if (bestMatch >= 0) { - return bestMatch; - } else { - throw NotFoundException.getNotFoundInstance(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFWriter.java deleted file mode 100644 index 3ce020775..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/ITFWriter.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * This object renders a ITF code as a {@link BitMatrix}. - * - * @author erik.barbara@gmail.com (Erik Barbara) - */ -public final class ITFWriter extends OneDimensionalCodeWriter { - - private static final int[] START_PATTERN = {1, 1, 1, 1}; - private static final int[] END_PATTERN = {3, 1, 1}; - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.ITF) { - throw new IllegalArgumentException("Can only encode ITF, but got " + format); - } - - return super.encode(contents, format, width, height, hints); - } - - @Override - public boolean[] encode(String contents) { - int length = contents.length(); - if (length % 2 != 0) { - throw new IllegalArgumentException("The lenght of the input should be even"); - } - if (length > 80) { - throw new IllegalArgumentException( - "Requested contents should be less than 80 digits long, but got " + length); - } - boolean[] result = new boolean[9 + 9 * length]; - int pos = appendPattern(result, 0, START_PATTERN, true); - for (int i = 0; i < length; i += 2) { - int one = Character.digit(contents.charAt(i), 10); - int two = Character.digit(contents.charAt(i+1), 10); - int[] encoding = new int[18]; - for (int j = 0; j < 5; j++) { - encoding[2 * j] = ITFReader.PATTERNS[one][j]; - encoding[2 * j + 1] = ITFReader.PATTERNS[two][j]; - } - pos += appendPattern(result, pos, encoding, true); - } - appendPattern(result, pos, END_PATTERN, true); - - return result; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatOneDReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatOneDReader.java deleted file mode 100644 index 031bd1128..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatOneDReader.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.common.BitArray; -import com.google.zxing.oned.rss.RSS14Reader; -import com.google.zxing.oned.rss.expanded.RSSExpandedReader; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - */ -public final class MultiFormatOneDReader extends OneDReader { - - private final OneDReader[] readers; - - public MultiFormatOneDReader(Map hints) { - @SuppressWarnings("unchecked") - Collection possibleFormats = hints == null ? null : - (Collection) hints.get(DecodeHintType.POSSIBLE_FORMATS); - boolean useCode39CheckDigit = hints != null && - hints.get(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT) != null; - Collection readers = new ArrayList<>(); - if (possibleFormats != null) { - if (possibleFormats.contains(BarcodeFormat.EAN_13) || - possibleFormats.contains(BarcodeFormat.UPC_A) || - possibleFormats.contains(BarcodeFormat.EAN_8) || - possibleFormats.contains(BarcodeFormat.UPC_E)) { - readers.add(new MultiFormatUPCEANReader(hints)); - } - if (possibleFormats.contains(BarcodeFormat.CODE_39)) { - readers.add(new Code39Reader(useCode39CheckDigit)); - } - if (possibleFormats.contains(BarcodeFormat.CODE_93)) { - readers.add(new Code93Reader()); - } - if (possibleFormats.contains(BarcodeFormat.CODE_128)) { - readers.add(new Code128Reader()); - } - if (possibleFormats.contains(BarcodeFormat.ITF)) { - readers.add(new ITFReader()); - } - if (possibleFormats.contains(BarcodeFormat.CODABAR)) { - readers.add(new CodaBarReader()); - } - if (possibleFormats.contains(BarcodeFormat.RSS_14)) { - readers.add(new RSS14Reader()); - } - if (possibleFormats.contains(BarcodeFormat.RSS_EXPANDED)){ - readers.add(new RSSExpandedReader()); - } - } - if (readers.isEmpty()) { - readers.add(new MultiFormatUPCEANReader(hints)); - readers.add(new Code39Reader()); - readers.add(new CodaBarReader()); - readers.add(new Code93Reader()); - readers.add(new Code128Reader()); - readers.add(new ITFReader()); - readers.add(new RSS14Reader()); - readers.add(new RSSExpandedReader()); - } - this.readers = readers.toArray(new OneDReader[readers.size()]); - } - - @Override - public Result decodeRow(int rowNumber, - BitArray row, - Map hints) throws NotFoundException { - for (OneDReader reader : readers) { - try { - return reader.decodeRow(rowNumber, row, hints); - } catch (ReaderException re) { - // continue - } - } - - throw NotFoundException.getNotFoundInstance(); - } - - @Override - public void reset() { - for (Reader reader : readers) { - reader.reset(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatUPCEANReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatUPCEANReader.java deleted file mode 100644 index 9449f155c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/MultiFormatUPCEANReader.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.common.BitArray; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - *

    A reader that can read all available UPC/EAN formats. If a caller wants to try to - * read all such formats, it is most efficient to use this implementation rather than invoke - * individual readers.

    - * - * @author Sean Owen - */ -public final class MultiFormatUPCEANReader extends OneDReader { - - private final UPCEANReader[] readers; - - public MultiFormatUPCEANReader(Map hints) { - @SuppressWarnings("unchecked") - Collection possibleFormats = hints == null ? null : - (Collection) hints.get(DecodeHintType.POSSIBLE_FORMATS); - Collection readers = new ArrayList<>(); - if (possibleFormats != null) { - if (possibleFormats.contains(BarcodeFormat.EAN_13)) { - readers.add(new EAN13Reader()); - } else if (possibleFormats.contains(BarcodeFormat.UPC_A)) { - readers.add(new UPCAReader()); - } - if (possibleFormats.contains(BarcodeFormat.EAN_8)) { - readers.add(new EAN8Reader()); - } - if (possibleFormats.contains(BarcodeFormat.UPC_E)) { - readers.add(new UPCEReader()); - } - } - if (readers.isEmpty()) { - readers.add(new EAN13Reader()); - // UPC-A is covered by EAN-13 - readers.add(new EAN8Reader()); - readers.add(new UPCEReader()); - } - this.readers = readers.toArray(new UPCEANReader[readers.size()]); - } - - @Override - public Result decodeRow(int rowNumber, - BitArray row, - Map hints) throws NotFoundException { - // Compute this location once and reuse it on multiple implementations - int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row); - for (UPCEANReader reader : readers) { - Result result; - try { - result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); - } catch (ReaderException ignored) { - continue; - } - // Special case: a 12-digit code encoded in UPC-A is identical to a "0" - // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, - // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". - // Individually these are correct and their readers will both read such a code - // and correctly call it EAN-13, or UPC-A, respectively. - // - // In this case, if we've been looking for both types, we'd like to call it - // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read - // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A - // result if appropriate. - // - // But, don't return UPC-A if UPC-A was not a requested format! - boolean ean13MayBeUPCA = - result.getBarcodeFormat() == BarcodeFormat.EAN_13 && - result.getText().charAt(0) == '0'; - @SuppressWarnings("unchecked") - Collection possibleFormats = - hints == null ? null : (Collection) hints.get(DecodeHintType.POSSIBLE_FORMATS); - boolean canReturnUPCA = possibleFormats == null || possibleFormats.contains(BarcodeFormat.UPC_A); - - if (ean13MayBeUPCA && canReturnUPCA) { - // Transfer the metdata across - Result resultUPCA = new Result(result.getText().substring(1), - result.getRawBytes(), - result.getResultPoints(), - BarcodeFormat.UPC_A); - resultUPCA.putAllMetadata(result.getResultMetadata()); - return resultUPCA; - } - return result; - } - - throw NotFoundException.getNotFoundInstance(); - } - - @Override - public void reset() { - for (Reader reader : readers) { - reader.reset(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDReader.java deleted file mode 100644 index 1c7a95fd1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDReader.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.Map; - -/** - * Encapsulates functionality and implementation that is common to all families - * of one-dimensional barcodes. - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - */ -public abstract class OneDReader implements Reader { - - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, FormatException { - return decode(image, null); - } - - // Note that we don't try rotation without the try harder flag, even if rotation was supported. - @Override - public Result decode(BinaryBitmap image, - Map hints) throws NotFoundException, FormatException { - try { - return doDecode(image, hints); - } catch (NotFoundException nfe) { - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - if (tryHarder && image.isRotateSupported()) { - BinaryBitmap rotatedImage = image.rotateCounterClockwise(); - Result result = doDecode(rotatedImage, hints); - // Record that we found it rotated 90 degrees CCW / 270 degrees CW - Map metadata = result.getResultMetadata(); - int orientation = 270; - if (metadata != null && metadata.containsKey(ResultMetadataType.ORIENTATION)) { - // But if we found it reversed in doDecode(), add in that result here: - orientation = (orientation + - (Integer) metadata.get(ResultMetadataType.ORIENTATION)) % 360; - } - result.putMetadata(ResultMetadataType.ORIENTATION, orientation); - // Update result points - ResultPoint[] points = result.getResultPoints(); - if (points != null) { - int height = rotatedImage.getHeight(); - for (int i = 0; i < points.length; i++) { - points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX()); - } - } - return result; - } else { - throw nfe; - } - } - } - - @Override - public void reset() { - // do nothing - } - - /** - * We're going to examine rows from the middle outward, searching alternately above and below the - * middle, and farther out each time. rowStep is the number of rows between each successive - * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then - * middle + rowStep, then middle - (2 * rowStep), etc. - * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily - * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the - * image if "trying harder". - * - * @param image The image to decode - * @param hints Any hints that were requested - * @return The contents of the decoded barcode - * @throws NotFoundException Any spontaneous errors which occur - */ - private Result doDecode(BinaryBitmap image, - Map hints) throws NotFoundException { - int width = image.getWidth(); - int height = image.getHeight(); - BitArray row = new BitArray(width); - - int middle = height >> 1; - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - int rowStep = Math.max(1, height >> (tryHarder ? 8 : 5)); - int maxLines; - if (tryHarder) { - maxLines = height; // Look at the whole image, not just the center - } else { - maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image - } - - for (int x = 0; x < maxLines; x++) { - - // Scanning from the middle out. Determine which row we're looking at next: - int rowStepsAboveOrBelow = (x + 1) / 2; - boolean isAbove = (x & 0x01) == 0; // i.e. is x even? - int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); - if (rowNumber < 0 || rowNumber >= height) { - // Oops, if we run off the top or bottom, stop - break; - } - - // Estimate black point for this row and load it: - try { - row = image.getBlackRow(rowNumber, row); - } catch (NotFoundException ignored) { - continue; - } - - // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to - // handle decoding upside down barcodes. - for (int attempt = 0; attempt < 2; attempt++) { - if (attempt == 1) { // trying again? - row.reverse(); // reverse the row and continue - // This means we will only ever draw result points *once* in the life of this method - // since we want to avoid drawing the wrong points after flipping the row, and, - // don't want to clutter with noise from every single row scan -- just the scans - // that start on the center line. - if (hints != null && hints.containsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) { - Map newHints = new EnumMap<>(DecodeHintType.class); - newHints.putAll(hints); - newHints.remove(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - hints = newHints; - } - } - try { - // Look for a barcode - Result result = decodeRow(rowNumber, row, hints); - // We found our barcode - if (attempt == 1) { - // But it was upside down, so note that - result.putMetadata(ResultMetadataType.ORIENTATION, 180); - // And remember to flip the result points horizontally. - ResultPoint[] points = result.getResultPoints(); - if (points != null) { - points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY()); - points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY()); - } - } - return result; - } catch (ReaderException re) { - // continue -- just couldn't decode this row - } - } - } - - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Records the size of successive runs of white and black pixels in a row, starting at a given point. - * The values are recorded in the given array, and the number of runs recorded is equal to the size - * of the array. If the row starts on a white pixel at the given start point, then the first count - * recorded is the run of white pixels starting from that point; likewise it is the count of a run - * of black pixels if the row begin on a black pixels at that point. - * - * @param row row to count from - * @param start offset into row to start at - * @param counters array into which to record counts - * @throws NotFoundException if counters cannot be filled entirely from row before running out - * of pixels - */ - protected static void recordPattern(BitArray row, - int start, - int[] counters) throws NotFoundException { - int numCounters = counters.length; - Arrays.fill(counters, 0, numCounters, 0); - int end = row.getSize(); - if (start >= end) { - throw NotFoundException.getNotFoundInstance(); - } - boolean isWhite = !row.get(start); - int counterPosition = 0; - int i = start; - while (i < end) { - if (row.get(i) ^ isWhite) { // that is, exactly one is true - counters[counterPosition]++; - } else { - counterPosition++; - if (counterPosition == numCounters) { - break; - } else { - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - i++; - } - // If we read fully the last section of pixels and filled up our counters -- or filled - // the last counter but ran off the side of the image, OK. Otherwise, a problem. - if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) { - throw NotFoundException.getNotFoundInstance(); - } - } - - protected static void recordPatternInReverse(BitArray row, int start, int[] counters) - throws NotFoundException { - // This could be more efficient I guess - int numTransitionsLeft = counters.length; - boolean last = row.get(start); - while (start > 0 && numTransitionsLeft >= 0) { - if (row.get(--start) != last) { - numTransitionsLeft--; - last = !last; - } - } - if (numTransitionsLeft >= 0) { - throw NotFoundException.getNotFoundInstance(); - } - recordPattern(row, start + 1, counters); - } - - /** - * Determines how closely a set of observed counts of runs of black/white values matches a given - * target pattern. This is reported as the ratio of the total variance from the expected pattern - * proportions across all pattern elements, to the length of the pattern. - * - * @param counters observed counters - * @param pattern expected pattern - * @param maxIndividualVariance The most any counter can differ before we give up - * @return ratio of total variance between counters and pattern compared to total pattern size - */ - protected static float patternMatchVariance(int[] counters, - int[] pattern, - float maxIndividualVariance) { - int numCounters = counters.length; - int total = 0; - int patternLength = 0; - for (int i = 0; i < numCounters; i++) { - total += counters[i]; - patternLength += pattern[i]; - } - if (total < patternLength) { - // If we don't even have one pixel per unit of bar width, assume this is too small - // to reliably match, so fail: - return Float.POSITIVE_INFINITY; - } - - float unitBarWidth = (float) total / patternLength; - maxIndividualVariance *= unitBarWidth; - - float totalVariance = 0.0f; - for (int x = 0; x < numCounters; x++) { - int counter = counters[x]; - float scaledPattern = pattern[x] * unitBarWidth; - float variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; - if (variance > maxIndividualVariance) { - return Float.POSITIVE_INFINITY; - } - totalVariance += variance; - } - return totalVariance / total; - } - - /** - *

    Attempts to decode a one-dimensional barcode format given a single row of - * an image.

    - * - * @param rowNumber row number from top of the row - * @param row the black/white pixel data of the row - * @param hints decode hints - * @return {@link Result} containing encoded string and start/end of barcode - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - public abstract Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, ChecksumException, FormatException; - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDimensionalCodeWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDimensionalCodeWriter.java deleted file mode 100644 index c2dad999e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/OneDimensionalCodeWriter.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - *

    Encapsulates functionality and implementation that is common to one-dimensional barcodes.

    - * - * @author dsbnatut@gmail.com (Kazuki Nishiura) - */ -public abstract class OneDimensionalCodeWriter implements Writer { - - @Override - public final BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - throws WriterException { - return encode(contents, format, width, height, null); - } - - /** - * Encode the contents following specified format. - * {@code width} and {@code height} are required size. This method may return bigger size - * {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - * {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - * or {@code height}, {@code IllegalArgumentException} is thrown. - */ - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (contents.isEmpty()) { - throw new IllegalArgumentException("Found empty contents"); - } - - if (width < 0 || height < 0) { - throw new IllegalArgumentException("Negative size is not allowed. Input: " - + width + 'x' + height); - } - - int sidesMargin = getDefaultMargin(); - if (hints != null) { - Integer sidesMarginInt = (Integer) hints.get(EncodeHintType.MARGIN); - if (sidesMarginInt != null) { - sidesMargin = sidesMarginInt; - } - } - - boolean[] code = encode(contents); - return renderResult(code, width, height, sidesMargin); - } - - /** - * @return a byte array of horizontal pixels (0 = white, 1 = black) - */ - private static BitMatrix renderResult(boolean[] code, int width, int height, int sidesMargin) { - int inputWidth = code.length; - // Add quiet zone on both sides. - int fullWidth = inputWidth + sidesMargin; - int outputWidth = Math.max(width, fullWidth); - int outputHeight = Math.max(1, height); - - int multiple = outputWidth / fullWidth; - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - - BitMatrix output = new BitMatrix(outputWidth, outputHeight); - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { - if (code[inputX]) { - output.setRegion(outputX, 0, multiple, outputHeight); - } - } - return output; - } - - - /** - * @param target encode black/white pattern into this array - * @param pos position to start encoding at in {@code target} - * @param pattern lengths of black/white runs to encode - * @param startColor starting color - false for white, true for black - * @return the number of elements added to target. - */ - protected static int appendPattern(boolean[] target, int pos, int[] pattern, boolean startColor) { - boolean color = startColor; - int numAdded = 0; - for (int len : pattern) { - for (int j = 0; j < len; j++) { - target[pos++] = color; - } - numAdded += len; - color = !color; // flip color after each segment - } - return numAdded; - } - - public int getDefaultMargin() { - // CodaBar spec requires a side margin to be more than ten times wider than narrow space. - // This seems like a decent idea for a default for all formats. - return 10; - } - - /** - * Encode the contents to boolean array expression of one-dimensional barcode. - * Start code and end code should be included in result, and side margins should not be included. - * - * @param contents barcode contents to encode - * @return a {@code boolean[]} of horizontal pixels (false = white, true = black) - */ - public abstract boolean[] encode(String contents); -} - diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAReader.java deleted file mode 100644 index 62f69cce3..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAReader.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.common.BitArray; - -import java.util.Map; - -/** - *

    Implements decoding of the UPC-A format.

    - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - */ -public final class UPCAReader extends UPCEANReader { - - private final UPCEANReader ean13Reader = new EAN13Reader(); - - @Override - public Result decodeRow(int rowNumber, - BitArray row, - int[] startGuardRange, - Map hints) - throws NotFoundException, FormatException, ChecksumException { - return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints)); - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, FormatException, ChecksumException { - return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints)); - } - - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, FormatException { - return maybeReturnResult(ean13Reader.decode(image)); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, FormatException { - return maybeReturnResult(ean13Reader.decode(image, hints)); - } - - @Override - BarcodeFormat getBarcodeFormat() { - return BarcodeFormat.UPC_A; - } - - @Override - protected int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) - throws NotFoundException { - return ean13Reader.decodeMiddle(row, startRange, resultString); - } - - private static Result maybeReturnResult(Result result) throws FormatException { - String text = result.getText(); - if (text.charAt(0) == '0') { - return new Result(text.substring(1), null, result.getResultPoints(), BarcodeFormat.UPC_A); - } else { - throw FormatException.getFormatInstance(); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAWriter.java deleted file mode 100644 index 64f777de4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCAWriter.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; - -import java.util.Map; - -/** - * This object renders a UPC-A code as a {@link BitMatrix}. - * - * @author qwandor@google.com (Andrew Walbran) - */ -public final class UPCAWriter implements Writer { - - private final EAN13Writer subWriter = new EAN13Writer(); - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - throws WriterException { - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.UPC_A) { - throw new IllegalArgumentException("Can only encode UPC-A, but got " + format); - } - return subWriter.encode(preencode(contents), BarcodeFormat.EAN_13, width, height, hints); - } - - /** - * Transform a UPC-A code into the equivalent EAN-13 code, and add a check digit if it is not - * already present. - */ - private static String preencode(String contents) { - int length = contents.length(); - if (length == 11) { - // No check digit present, calculate it and add it - int sum = 0; - for (int i = 0; i < 11; ++i) { - sum += (contents.charAt(i) - '0') * (i % 2 == 0 ? 3 : 1); - } - contents += (1000 - sum) % 10; - } else if (length != 12) { - throw new IllegalArgumentException( - "Requested contents should be 11 or 12 digits long, but got " + contents.length()); - } - return '0' + contents; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension2Support.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension2Support.java deleted file mode 100644 index 03cd35d4d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension2Support.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.EnumMap; -import java.util.Map; - -/** - * @see UPCEANExtension5Support - */ -final class UPCEANExtension2Support { - - private final int[] decodeMiddleCounters = new int[4]; - private final StringBuilder decodeRowStringBuffer = new StringBuilder(); - - Result decodeRow(int rowNumber, BitArray row, int[] extensionStartRange) throws NotFoundException { - - StringBuilder result = decodeRowStringBuffer; - result.setLength(0); - int end = decodeMiddle(row, extensionStartRange, result); - - String resultString = result.toString(); - Map extensionData = parseExtensionString(resultString); - - Result extensionResult = - new Result(resultString, - null, - new ResultPoint[] { - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0f, (float) rowNumber), - new ResultPoint((float) end, (float) rowNumber), - }, - BarcodeFormat.UPC_EAN_EXTENSION); - if (extensionData != null) { - extensionResult.putAllMetadata(extensionData); - } - return extensionResult; - } - - int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) throws NotFoundException { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.getSize(); - int rowOffset = startRange[1]; - - int checkParity = 0; - - for (int x = 0; x < 2 && rowOffset < end; x++) { - int bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS); - resultString.append((char) ('0' + bestMatch % 10)); - for (int counter : counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - checkParity |= 1 << (1 - x); - } - if (x != 1) { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } - - if (resultString.length() != 2) { - throw NotFoundException.getNotFoundInstance(); - } - - if (Integer.parseInt(resultString.toString()) % 4 != checkParity) { - throw NotFoundException.getNotFoundInstance(); - } - - return rowOffset; - } - - /** - * @param raw raw content of extension - * @return formatted interpretation of raw content as a {@link Map} mapping - * one {@link ResultMetadataType} to appropriate value, or {@code null} if not known - */ - private static Map parseExtensionString(String raw) { - if (raw.length() != 2) { - return null; - } - Map result = new EnumMap<>(ResultMetadataType.class); - result.put(ResultMetadataType.ISSUE_NUMBER, Integer.valueOf(raw)); - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension5Support.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension5Support.java deleted file mode 100644 index ecd421e0d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtension5Support.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; - -import java.util.EnumMap; -import java.util.Map; - -/** - * @see UPCEANExtension2Support - */ -final class UPCEANExtension5Support { - - private static final int[] CHECK_DIGIT_ENCODINGS = { - 0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05 - }; - - private final int[] decodeMiddleCounters = new int[4]; - private final StringBuilder decodeRowStringBuffer = new StringBuilder(); - - Result decodeRow(int rowNumber, BitArray row, int[] extensionStartRange) throws NotFoundException { - - StringBuilder result = decodeRowStringBuffer; - result.setLength(0); - int end = decodeMiddle(row, extensionStartRange, result); - - String resultString = result.toString(); - Map extensionData = parseExtensionString(resultString); - - Result extensionResult = - new Result(resultString, - null, - new ResultPoint[] { - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0f, (float) rowNumber), - new ResultPoint((float) end, (float) rowNumber), - }, - BarcodeFormat.UPC_EAN_EXTENSION); - if (extensionData != null) { - extensionResult.putAllMetadata(extensionData); - } - return extensionResult; - } - - int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) throws NotFoundException { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.getSize(); - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 5 && rowOffset < end; x++) { - int bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS); - resultString.append((char) ('0' + bestMatch % 10)); - for (int counter : counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - lgPatternFound |= 1 << (4 - x); - } - if (x != 4) { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } - - if (resultString.length() != 5) { - throw NotFoundException.getNotFoundInstance(); - } - - int checkDigit = determineCheckDigit(lgPatternFound); - if (extensionChecksum(resultString.toString()) != checkDigit) { - throw NotFoundException.getNotFoundInstance(); - } - - return rowOffset; - } - - private static int extensionChecksum(CharSequence s) { - int length = s.length(); - int sum = 0; - for (int i = length - 2; i >= 0; i -= 2) { - sum += (int) s.charAt(i) - (int) '0'; - } - sum *= 3; - for (int i = length - 1; i >= 0; i -= 2) { - sum += (int) s.charAt(i) - (int) '0'; - } - sum *= 3; - return sum % 10; - } - - private static int determineCheckDigit(int lgPatternFound) - throws NotFoundException { - for (int d = 0; d < 10; d++) { - if (lgPatternFound == CHECK_DIGIT_ENCODINGS[d]) { - return d; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - /** - * @param raw raw content of extension - * @return formatted interpretation of raw content as a {@link Map} mapping - * one {@link ResultMetadataType} to appropriate value, or {@code null} if not known - */ - private static Map parseExtensionString(String raw) { - if (raw.length() != 5) { - return null; - } - Object value = parseExtension5String(raw); - if (value == null) { - return null; - } - Map result = new EnumMap<>(ResultMetadataType.class); - result.put(ResultMetadataType.SUGGESTED_PRICE, value); - return result; - } - - private static String parseExtension5String(String raw) { - String currency; - switch (raw.charAt(0)) { - case '0': - currency = "£"; - break; - case '5': - currency = "$"; - break; - case '9': - // Reference: http://www.jollytech.com - if ("90000".equals(raw)) { - // No suggested retail price - return null; - } - if ("99991".equals(raw)) { - // Complementary - return "0.00"; - } - if ("99990".equals(raw)) { - return "Used"; - } - // Otherwise... unknown currency? - currency = ""; - break; - default: - currency = ""; - break; - } - int rawAmount = Integer.parseInt(raw.substring(1)); - String unitsString = String.valueOf(rawAmount / 100); - int hundredths = rawAmount % 100; - String hundredthsString = hundredths < 10 ? "0" + hundredths : String.valueOf(hundredths); - return currency + unitsString + '.' + hundredthsString; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtensionSupport.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtensionSupport.java deleted file mode 100644 index b36a58141..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANExtensionSupport.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.common.BitArray; - -final class UPCEANExtensionSupport { - - private static final int[] EXTENSION_START_PATTERN = {1,1,2}; - - private final UPCEANExtension2Support twoSupport = new UPCEANExtension2Support(); - private final UPCEANExtension5Support fiveSupport = new UPCEANExtension5Support(); - - Result decodeRow(int rowNumber, BitArray row, int rowOffset) throws NotFoundException { - int[] extensionStartRange = UPCEANReader.findGuardPattern(row, rowOffset, false, EXTENSION_START_PATTERN); - try { - return fiveSupport.decodeRow(rowNumber, row, extensionStartRange); - } catch (ReaderException ignored) { - return twoSupport.decodeRow(rowNumber, row, extensionStartRange); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANReader.java deleted file mode 100644 index 677ec9172..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANReader.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitArray; - -import java.util.Arrays; -import java.util.Map; - -/** - *

    Encapsulates functionality and implementation that is common to UPC and EAN families - * of one-dimensional barcodes.

    - * - * @author dswitkin@google.com (Daniel Switkin) - * @author Sean Owen - * @author alasdair@google.com (Alasdair Mackintosh) - */ -public abstract class UPCEANReader extends OneDReader { - - // These two values are critical for determining how permissive the decoding will be. - // We've arrived at these values through a lot of trial and error. Setting them any higher - // lets false positives creep in quickly. - private static final float MAX_AVG_VARIANCE = 0.48f; - private static final float MAX_INDIVIDUAL_VARIANCE = 0.7f; - - /** - * Start/end guard pattern. - */ - static final int[] START_END_PATTERN = {1, 1, 1,}; - - /** - * Pattern marking the middle of a UPC/EAN pattern, separating the two halves. - */ - static final int[] MIDDLE_PATTERN = {1, 1, 1, 1, 1}; - - /** - * "Odd", or "L" patterns used to encode UPC/EAN digits. - */ - static final int[][] L_PATTERNS = { - {3, 2, 1, 1}, // 0 - {2, 2, 2, 1}, // 1 - {2, 1, 2, 2}, // 2 - {1, 4, 1, 1}, // 3 - {1, 1, 3, 2}, // 4 - {1, 2, 3, 1}, // 5 - {1, 1, 1, 4}, // 6 - {1, 3, 1, 2}, // 7 - {1, 2, 1, 3}, // 8 - {3, 1, 1, 2} // 9 - }; - - /** - * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. - */ - static final int[][] L_AND_G_PATTERNS; - - static { - L_AND_G_PATTERNS = new int[20][]; - System.arraycopy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10); - for (int i = 10; i < 20; i++) { - int[] widths = L_PATTERNS[i - 10]; - int[] reversedWidths = new int[widths.length]; - for (int j = 0; j < widths.length; j++) { - reversedWidths[j] = widths[widths.length - j - 1]; - } - L_AND_G_PATTERNS[i] = reversedWidths; - } - } - - private final StringBuilder decodeRowStringBuffer; - private final UPCEANExtensionSupport extensionReader; - private final EANManufacturerOrgSupport eanManSupport; - - protected UPCEANReader() { - decodeRowStringBuffer = new StringBuilder(20); - extensionReader = new UPCEANExtensionSupport(); - eanManSupport = new EANManufacturerOrgSupport(); - } - - static int[] findStartGuardPattern(BitArray row) throws NotFoundException { - boolean foundStart = false; - int[] startRange = null; - int nextStart = 0; - int[] counters = new int[START_END_PATTERN.length]; - while (!foundStart) { - Arrays.fill(counters, 0, START_END_PATTERN.length, 0); - startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, counters); - int start = startRange[0]; - nextStart = startRange[1]; - // Make sure there is a quiet zone at least as big as the start pattern before the barcode. - // If this check would run off the left edge of the image, do not accept this barcode, - // as it is very likely to be a false positive. - int quietStart = start - (nextStart - start); - if (quietStart >= 0) { - foundStart = row.isRange(quietStart, start, false); - } - } - return startRange; - } - - @Override - public Result decodeRow(int rowNumber, BitArray row, Map hints) - throws NotFoundException, ChecksumException, FormatException { - return decodeRow(rowNumber, row, findStartGuardPattern(row), hints); - } - - /** - *

    Like {@link #decodeRow(int, BitArray, java.util.Map)}, but - * allows caller to inform method about where the UPC/EAN start pattern is - * found. This allows this to be computed once and reused across many implementations.

    - * - * @param rowNumber row index into the image - * @param row encoding of the row of the barcode image - * @param startGuardRange start/end column where the opening start pattern was found - * @param hints optional hints that influence decoding - * @return {@link Result} encapsulating the result of decoding a barcode in the row - * @throws NotFoundException if no potential barcode is found - * @throws ChecksumException if a potential barcode is found but does not pass its checksum - * @throws FormatException if a potential barcode is found but format is invalid - */ - public Result decodeRow(int rowNumber, - BitArray row, - int[] startGuardRange, - Map hints) - throws NotFoundException, ChecksumException, FormatException { - - ResultPointCallback resultPointCallback = hints == null ? null : - (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - - if (resultPointCallback != null) { - resultPointCallback.foundPossibleResultPoint(new ResultPoint( - (startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber - )); - } - - StringBuilder result = decodeRowStringBuffer; - result.setLength(0); - int endStart = decodeMiddle(row, startGuardRange, result); - - if (resultPointCallback != null) { - resultPointCallback.foundPossibleResultPoint(new ResultPoint( - endStart, rowNumber - )); - } - - int[] endRange = decodeEnd(row, endStart); - - if (resultPointCallback != null) { - resultPointCallback.foundPossibleResultPoint(new ResultPoint( - (endRange[0] + endRange[1]) / 2.0f, rowNumber - )); - } - - - // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The - // spec might want more whitespace, but in practice this is the maximum we can count on. - int end = endRange[1]; - int quietEnd = end + (end - endRange[0]); - if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) { - throw NotFoundException.getNotFoundInstance(); - } - - String resultString = result.toString(); - // UPC/EAN should never be less than 8 chars anyway - if (resultString.length() < 8) { - throw FormatException.getFormatInstance(); - } - if (!checkChecksum(resultString)) { - throw ChecksumException.getChecksumInstance(); - } - - float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; - float right = (float) (endRange[1] + endRange[0]) / 2.0f; - BarcodeFormat format = getBarcodeFormat(); - Result decodeResult = new Result(resultString, - null, // no natural byte representation for these barcodes - new ResultPoint[]{ - new ResultPoint(left, (float) rowNumber), - new ResultPoint(right, (float) rowNumber)}, - format); - - int extensionLength = 0; - - try { - Result extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]); - decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.getText()); - decodeResult.putAllMetadata(extensionResult.getResultMetadata()); - decodeResult.addResultPoints(extensionResult.getResultPoints()); - extensionLength = extensionResult.getText().length(); - } catch (ReaderException re) { - // continue - } - - int[] allowedExtensions = - hints == null ? null : (int[]) hints.get(DecodeHintType.ALLOWED_EAN_EXTENSIONS); - if (allowedExtensions != null) { - boolean valid = false; - for (int length : allowedExtensions) { - if (extensionLength == length) { - valid = true; - break; - } - } - if (!valid) { - throw NotFoundException.getNotFoundInstance(); - } - } - - if (format == BarcodeFormat.EAN_13 || format == BarcodeFormat.UPC_A) { - String countryID = eanManSupport.lookupCountryIdentifier(resultString); - if (countryID != null) { - decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); - } - } - - return decodeResult; - } - - /** - * @param s string of digits to check - * @return {@link #checkStandardUPCEANChecksum(CharSequence)} - * @throws FormatException if the string does not contain only digits - */ - boolean checkChecksum(String s) throws FormatException { - return checkStandardUPCEANChecksum(s); - } - - /** - * Computes the UPC/EAN checksum on a string of digits, and reports - * whether the checksum is correct or not. - * - * @param s string of digits to check - * @return true iff string of digits passes the UPC/EAN checksum algorithm - * @throws FormatException if the string does not contain only digits - */ - static boolean checkStandardUPCEANChecksum(CharSequence s) throws FormatException { - int length = s.length(); - if (length == 0) { - return false; - } - - int sum = 0; - for (int i = length - 2; i >= 0; i -= 2) { - int digit = (int) s.charAt(i) - (int) '0'; - if (digit < 0 || digit > 9) { - throw FormatException.getFormatInstance(); - } - sum += digit; - } - sum *= 3; - for (int i = length - 1; i >= 0; i -= 2) { - int digit = (int) s.charAt(i) - (int) '0'; - if (digit < 0 || digit > 9) { - throw FormatException.getFormatInstance(); - } - sum += digit; - } - return sum % 10 == 0; - } - - int[] decodeEnd(BitArray row, int endStart) throws NotFoundException { - return findGuardPattern(row, endStart, false, START_END_PATTERN); - } - - static int[] findGuardPattern(BitArray row, - int rowOffset, - boolean whiteFirst, - int[] pattern) throws NotFoundException { - return findGuardPattern(row, rowOffset, whiteFirst, pattern, new int[pattern.length]); - } - - /** - * @param row row of black/white values to search - * @param rowOffset position to start search - * @param whiteFirst if true, indicates that the pattern specifies white/black/white/... - * pixel counts, otherwise, it is interpreted as black/white/black/... - * @param pattern pattern of counts of number of black and white pixels that are being - * searched for as a pattern - * @param counters array of counters, as long as pattern, to re-use - * @return start/end horizontal offset of guard pattern, as an array of two ints - * @throws NotFoundException if pattern is not found - */ - private static int[] findGuardPattern(BitArray row, - int rowOffset, - boolean whiteFirst, - int[] pattern, - int[] counters) throws NotFoundException { - int patternLength = pattern.length; - int width = row.getSize(); - boolean isWhite = whiteFirst; - rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset); - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) { - if (row.get(x) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { - return new int[]{patternStart, x}; - } - patternStart += counters[0] + counters[1]; - System.arraycopy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Attempts to decode a single UPC/EAN-encoded digit. - * - * @param row row of black/white values to decode - * @param counters the counts of runs of observed black/white/black/... values - * @param rowOffset horizontal offset to start decoding from - * @param patterns the set of patterns to use to decode -- sometimes different encodings - * for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should - * be used - * @return horizontal offset of first pixel beyond the decoded digit - * @throws NotFoundException if digit cannot be decoded - */ - static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns) - throws NotFoundException { - recordPattern(row, rowOffset, counters); - float bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - int bestMatch = -1; - int max = patterns.length; - for (int i = 0; i < max; i++) { - int[] pattern = patterns[i]; - float variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) { - bestVariance = variance; - bestMatch = i; - } - } - if (bestMatch >= 0) { - return bestMatch; - } else { - throw NotFoundException.getNotFoundInstance(); - } - } - - /** - * Get the format of this decoder. - * - * @return The 1D format. - */ - abstract BarcodeFormat getBarcodeFormat(); - - /** - * Subclasses override this to decode the portion of a barcode between the start - * and end guard patterns. - * - * @param row row of black/white values to search - * @param startRange start/end offset of start guard pattern - * @param resultString {@link StringBuilder} to append decoded chars to - * @return horizontal offset of first pixel after the "middle" that was decoded - * @throws NotFoundException if decoding could not complete successfully - */ - protected abstract int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder resultString) throws NotFoundException; - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANWriter.java deleted file mode 100644 index a39937dbb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEANWriter.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -/** - *

    Encapsulates functionality and implementation that is common to UPC and EAN families - * of one-dimensional barcodes.

    - * - * @author aripollak@gmail.com (Ari Pollak) - * @author dsbnatut@gmail.com (Kazuki Nishiura) - */ -public abstract class UPCEANWriter extends OneDimensionalCodeWriter { - - @Override - public int getDefaultMargin() { - // Use a different default more appropriate for UPC/EAN - return UPCEANReader.START_END_PATTERN.length; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEReader.java deleted file mode 100644 index ba86eb279..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/UPCEReader.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - *

    Implements decoding of the UPC-E format.

    - *

    This is a great reference for - * UPC-E information.

    - * - * @author Sean Owen - */ -public final class UPCEReader extends UPCEANReader { - - /** - * The pattern that marks the middle, and end, of a UPC-E pattern. - * There is no "second half" to a UPC-E barcode. - */ - private static final int[] MIDDLE_END_PATTERN = {1, 1, 1, 1, 1, 1}; - - /** - * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of - * even-odd parity encodings of digits that imply both the number system (0 or 1) - * used, and the check digit. - */ - private static final int[][] NUMSYS_AND_CHECK_DIGIT_PATTERNS = { - {0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25}, - {0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A} - }; - - private final int[] decodeMiddleCounters; - - public UPCEReader() { - decodeMiddleCounters = new int[4]; - } - - @Override - protected int decodeMiddle(BitArray row, int[] startRange, StringBuilder result) - throws NotFoundException { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.getSize(); - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 6 && rowOffset < end; x++) { - int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS); - result.append((char) ('0' + bestMatch % 10)); - for (int counter : counters) { - rowOffset += counter; - } - if (bestMatch >= 10) { - lgPatternFound |= 1 << (5 - x); - } - } - - determineNumSysAndCheckDigit(result, lgPatternFound); - - return rowOffset; - } - - @Override - protected int[] decodeEnd(BitArray row, int endStart) throws NotFoundException { - return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN); - } - - @Override - protected boolean checkChecksum(String s) throws FormatException { - return super.checkChecksum(convertUPCEtoUPCA(s)); - } - - private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound) - throws NotFoundException { - - for (int numSys = 0; numSys <= 1; numSys++) { - for (int d = 0; d < 10; d++) { - if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { - resultString.insert(0, (char) ('0' + numSys)); - resultString.append((char) ('0' + d)); - return; - } - } - } - throw NotFoundException.getNotFoundInstance(); - } - - @Override - BarcodeFormat getBarcodeFormat() { - return BarcodeFormat.UPC_E; - } - - /** - * Expands a UPC-E value back into its full, equivalent UPC-A code value. - * - * @param upce UPC-E code as string of digits - * @return equivalent UPC-A code as string of digits - */ - public static String convertUPCEtoUPCA(String upce) { - char[] upceChars = new char[6]; - upce.getChars(1, 7, upceChars, 0); - StringBuilder result = new StringBuilder(12); - result.append(upce.charAt(0)); - char lastChar = upceChars[5]; - switch (lastChar) { - case '0': - case '1': - case '2': - result.append(upceChars, 0, 2); - result.append(lastChar); - result.append("0000"); - result.append(upceChars, 2, 3); - break; - case '3': - result.append(upceChars, 0, 3); - result.append("00000"); - result.append(upceChars, 3, 2); - break; - case '4': - result.append(upceChars, 0, 4); - result.append("00000"); - result.append(upceChars[4]); - break; - default: - result.append(upceChars, 0, 5); - result.append("0000"); - result.append(lastChar); - break; - } - result.append(upce.charAt(7)); - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/AbstractRSSReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/AbstractRSSReader.java deleted file mode 100644 index e86b394de..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/AbstractRSSReader.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -import com.google.zxing.NotFoundException; -import com.google.zxing.oned.OneDReader; - -public abstract class AbstractRSSReader extends OneDReader { - - private static final float MAX_AVG_VARIANCE = 0.2f; - private static final float MAX_INDIVIDUAL_VARIANCE = 0.45f; - - private static final float MIN_FINDER_PATTERN_RATIO = 9.5f / 12.0f; - private static final float MAX_FINDER_PATTERN_RATIO = 12.5f / 14.0f; - - private final int[] decodeFinderCounters; - private final int[] dataCharacterCounters; - private final float[] oddRoundingErrors; - private final float[] evenRoundingErrors; - private final int[] oddCounts; - private final int[] evenCounts; - - protected AbstractRSSReader(){ - decodeFinderCounters = new int[4]; - dataCharacterCounters = new int[8]; - oddRoundingErrors = new float[4]; - evenRoundingErrors = new float[4]; - oddCounts = new int[dataCharacterCounters.length / 2]; - evenCounts = new int[dataCharacterCounters.length / 2]; - } - - protected final int[] getDecodeFinderCounters() { - return decodeFinderCounters; - } - - protected final int[] getDataCharacterCounters() { - return dataCharacterCounters; - } - - protected final float[] getOddRoundingErrors() { - return oddRoundingErrors; - } - - protected final float[] getEvenRoundingErrors() { - return evenRoundingErrors; - } - - protected final int[] getOddCounts() { - return oddCounts; - } - - protected final int[] getEvenCounts() { - return evenCounts; - } - - protected static int parseFinderValue(int[] counters, - int[][] finderPatterns) throws NotFoundException { - for (int value = 0; value < finderPatterns.length; value++) { - if (patternMatchVariance(counters, finderPatterns[value], MAX_INDIVIDUAL_VARIANCE) < - MAX_AVG_VARIANCE) { - return value; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - protected static int count(int[] array) { - int count = 0; - for (int a : array) { - count += a; - } - return count; - } - - protected static void increment(int[] array, float[] errors) { - int index = 0; - float biggestError = errors[0]; - for (int i = 1; i < array.length; i++) { - if (errors[i] > biggestError) { - biggestError = errors[i]; - index = i; - } - } - array[index]++; - } - - protected static void decrement(int[] array, float[] errors) { - int index = 0; - float biggestError = errors[0]; - for (int i = 1; i < array.length; i++) { - if (errors[i] < biggestError) { - biggestError = errors[i]; - index = i; - } - } - array[index]--; - } - - protected static boolean isFinderPattern(int[] counters) { - int firstTwoSum = counters[0] + counters[1]; - int sum = firstTwoSum + counters[2] + counters[3]; - float ratio = (float) firstTwoSum / (float) sum; - if (ratio >= MIN_FINDER_PATTERN_RATIO && ratio <= MAX_FINDER_PATTERN_RATIO) { - // passes ratio test in spec, but see if the counts are unreasonable - int minCounter = Integer.MAX_VALUE; - int maxCounter = Integer.MIN_VALUE; - for (int counter : counters) { - if (counter > maxCounter) { - maxCounter = counter; - } - if (counter < minCounter) { - minCounter = counter; - } - } - return maxCounter < 10 * minCounter; - } - return false; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/DataCharacter.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/DataCharacter.java deleted file mode 100644 index 167930000..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/DataCharacter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -public class DataCharacter { - - private final int value; - private final int checksumPortion; - - public DataCharacter(int value, int checksumPortion) { - this.value = value; - this.checksumPortion = checksumPortion; - } - - public final int getValue() { - return value; - } - - public final int getChecksumPortion() { - return checksumPortion; - } - - @Override - public final String toString() { - return value + "(" + checksumPortion + ')'; - } - - @Override - public final boolean equals(Object o) { - if(!(o instanceof DataCharacter)) { - return false; - } - DataCharacter that = (DataCharacter) o; - return value == that.value && checksumPortion == that.checksumPortion; - } - - @Override - public final int hashCode() { - return value ^ checksumPortion; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/FinderPattern.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/FinderPattern.java deleted file mode 100644 index 492aec977..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/FinderPattern.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -import com.google.zxing.ResultPoint; - -public final class FinderPattern { - - private final int value; - private final int[] startEnd; - private final ResultPoint[] resultPoints; - - public FinderPattern(int value, int[] startEnd, int start, int end, int rowNumber) { - this.value = value; - this.startEnd = startEnd; - this.resultPoints = new ResultPoint[] { - new ResultPoint((float) start, (float) rowNumber), - new ResultPoint((float) end, (float) rowNumber), - }; - } - - public int getValue() { - return value; - } - - public int[] getStartEnd() { - return startEnd; - } - - public ResultPoint[] getResultPoints() { - return resultPoints; - } - - @Override - public boolean equals(Object o) { - if(!(o instanceof FinderPattern)) { - return false; - } - FinderPattern that = (FinderPattern) o; - return value == that.value; - } - - @Override - public int hashCode() { - return value; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/Pair.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/Pair.java deleted file mode 100644 index e2371d29e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/Pair.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -final class Pair extends DataCharacter { - - private final FinderPattern finderPattern; - private int count; - - Pair(int value, int checksumPortion, FinderPattern finderPattern) { - super(value, checksumPortion); - this.finderPattern = finderPattern; - } - - FinderPattern getFinderPattern() { - return finderPattern; - } - - int getCount() { - return count; - } - - void incrementCount() { - count++; - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSS14Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSS14Reader.java deleted file mode 100644 index 604a2aa7a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSS14Reader.java +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitArray; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * Decodes RSS-14, including truncated and stacked variants. See ISO/IEC 24724:2006. - */ -public final class RSS14Reader extends AbstractRSSReader { - - private static final int[] OUTSIDE_EVEN_TOTAL_SUBSET = {1,10,34,70,126}; - private static final int[] INSIDE_ODD_TOTAL_SUBSET = {4,20,48,81}; - private static final int[] OUTSIDE_GSUM = {0,161,961,2015,2715}; - private static final int[] INSIDE_GSUM = {0,336,1036,1516}; - private static final int[] OUTSIDE_ODD_WIDEST = {8,6,4,3,1}; - private static final int[] INSIDE_ODD_WIDEST = {2,4,6,8}; - - private static final int[][] FINDER_PATTERNS = { - {3,8,2,1}, - {3,5,5,1}, - {3,3,7,1}, - {3,1,9,1}, - {2,7,4,1}, - {2,5,6,1}, - {2,3,8,1}, - {1,5,7,1}, - {1,3,9,1}, - }; - - private final List possibleLeftPairs; - private final List possibleRightPairs; - - public RSS14Reader() { - possibleLeftPairs = new ArrayList<>(); - possibleRightPairs = new ArrayList<>(); - } - - @Override - public Result decodeRow(int rowNumber, - BitArray row, - Map hints) throws NotFoundException { - Pair leftPair = decodePair(row, false, rowNumber, hints); - addOrTally(possibleLeftPairs, leftPair); - row.reverse(); - Pair rightPair = decodePair(row, true, rowNumber, hints); - addOrTally(possibleRightPairs, rightPair); - row.reverse(); - int lefSize = possibleLeftPairs.size(); - for (int i = 0; i < lefSize; i++) { - Pair left = possibleLeftPairs.get(i); - if (left.getCount() > 1) { - int rightSize = possibleRightPairs.size(); - for (int j = 0; j < rightSize; j++) { - Pair right = possibleRightPairs.get(j); - if (right.getCount() > 1) { - if (checkChecksum(left, right)) { - return constructResult(left, right); - } - } - } - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static void addOrTally(Collection possiblePairs, Pair pair) { - if (pair == null) { - return; - } - boolean found = false; - for (Pair other : possiblePairs) { - if (other.getValue() == pair.getValue()) { - other.incrementCount(); - found = true; - break; - } - } - if (!found) { - possiblePairs.add(pair); - } - } - - @Override - public void reset() { - possibleLeftPairs.clear(); - possibleRightPairs.clear(); - } - - private static Result constructResult(Pair leftPair, Pair rightPair) { - long symbolValue = 4537077L * leftPair.getValue() + rightPair.getValue(); - String text = String.valueOf(symbolValue); - - StringBuilder buffer = new StringBuilder(14); - for (int i = 13 - text.length(); i > 0; i--) { - buffer.append('0'); - } - buffer.append(text); - - int checkDigit = 0; - for (int i = 0; i < 13; i++) { - int digit = buffer.charAt(i) - '0'; - checkDigit += (i & 0x01) == 0 ? 3 * digit : digit; - } - checkDigit = 10 - (checkDigit % 10); - if (checkDigit == 10) { - checkDigit = 0; - } - buffer.append(checkDigit); - - ResultPoint[] leftPoints = leftPair.getFinderPattern().getResultPoints(); - ResultPoint[] rightPoints = rightPair.getFinderPattern().getResultPoints(); - return new Result( - String.valueOf(buffer.toString()), - null, - new ResultPoint[] { leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1], }, - BarcodeFormat.RSS_14); - } - - private static boolean checkChecksum(Pair leftPair, Pair rightPair) { - //int leftFPValue = leftPair.getFinderPattern().getValue(); - //int rightFPValue = rightPair.getFinderPattern().getValue(); - //if ((leftFPValue == 0 && rightFPValue == 8) || - // (leftFPValue == 8 && rightFPValue == 0)) { - //} - int checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79; - int targetCheckValue = - 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue(); - if (targetCheckValue > 72) { - targetCheckValue--; - } - if (targetCheckValue > 8) { - targetCheckValue--; - } - return checkValue == targetCheckValue; - } - - private Pair decodePair(BitArray row, boolean right, int rowNumber, Map hints) { - try { - int[] startEnd = findFinderPattern(row, 0, right); - FinderPattern pattern = parseFoundFinderPattern(row, rowNumber, right, startEnd); - - ResultPointCallback resultPointCallback = hints == null ? null : - (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - - if (resultPointCallback != null) { - float center = (startEnd[0] + startEnd[1]) / 2.0f; - if (right) { - // row is actually reversed - center = row.getSize() - 1 - center; - } - resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber)); - } - - DataCharacter outside = decodeDataCharacter(row, pattern, true); - DataCharacter inside = decodeDataCharacter(row, pattern, false); - return new Pair(1597 * outside.getValue() + inside.getValue(), - outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), - pattern); - } catch (NotFoundException ignored) { - return null; - } - } - - private DataCharacter decodeDataCharacter(BitArray row, FinderPattern pattern, boolean outsideChar) - throws NotFoundException { - - int[] counters = getDataCharacterCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - counters[4] = 0; - counters[5] = 0; - counters[6] = 0; - counters[7] = 0; - - if (outsideChar) { - recordPatternInReverse(row, pattern.getStartEnd()[0], counters); - } else { - recordPattern(row, pattern.getStartEnd()[1] + 1, counters); - // reverse it - for (int i = 0, j = counters.length - 1; i < j; i++, j--) { - int temp = counters[i]; - counters[i] = counters[j]; - counters[j] = temp; - } - } - - int numModules = outsideChar ? 16 : 15; - float elementWidth = (float) count(counters) / (float) numModules; - - int[] oddCounts = this.getOddCounts(); - int[] evenCounts = this.getEvenCounts(); - float[] oddRoundingErrors = this.getOddRoundingErrors(); - float[] evenRoundingErrors = this.getEvenRoundingErrors(); - - for (int i = 0; i < counters.length; i++) { - float value = (float) counters[i] / elementWidth; - int count = (int) (value + 0.5f); // Round - if (count < 1) { - count = 1; - } else if (count > 8) { - count = 8; - } - int offset = i / 2; - if ((i & 0x01) == 0) { - oddCounts[offset] = count; - oddRoundingErrors[offset] = value - count; - } else { - evenCounts[offset] = count; - evenRoundingErrors[offset] = value - count; - } - } - - adjustOddEvenCounts(outsideChar, numModules); - - int oddSum = 0; - int oddChecksumPortion = 0; - for (int i = oddCounts.length - 1; i >= 0; i--) { - oddChecksumPortion *= 9; - oddChecksumPortion += oddCounts[i]; - oddSum += oddCounts[i]; - } - int evenChecksumPortion = 0; - int evenSum = 0; - for (int i = evenCounts.length - 1; i >= 0; i--) { - evenChecksumPortion *= 9; - evenChecksumPortion += evenCounts[i]; - evenSum += evenCounts[i]; - } - int checksumPortion = oddChecksumPortion + 3*evenChecksumPortion; - - if (outsideChar) { - if ((oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4) { - throw NotFoundException.getNotFoundInstance(); - } - int group = (12 - oddSum) / 2; - int oddWidest = OUTSIDE_ODD_WIDEST[group]; - int evenWidest = 9 - oddWidest; - int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false); - int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true); - int tEven = OUTSIDE_EVEN_TOTAL_SUBSET[group]; - int gSum = OUTSIDE_GSUM[group]; - return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion); - } else { - if ((evenSum & 0x01) != 0 || evenSum > 10 || evenSum < 4) { - throw NotFoundException.getNotFoundInstance(); - } - int group = (10 - evenSum) / 2; - int oddWidest = INSIDE_ODD_WIDEST[group]; - int evenWidest = 9 - oddWidest; - int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true); - int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false); - int tOdd = INSIDE_ODD_TOTAL_SUBSET[group]; - int gSum = INSIDE_GSUM[group]; - return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion); - } - - } - - private int[] findFinderPattern(BitArray row, int rowOffset, boolean rightFinderPattern) - throws NotFoundException { - - int[] counters = getDecodeFinderCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - - int width = row.getSize(); - boolean isWhite = false; - while (rowOffset < width) { - isWhite = !row.get(rowOffset); - if (rightFinderPattern == isWhite) { - // Will encounter white first when searching for right finder pattern - break; - } - rowOffset++; - } - - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) { - if (row.get(x) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == 3) { - if (isFinderPattern(counters)) { - return new int[]{patternStart, x}; - } - patternStart += counters[0] + counters[1]; - counters[0] = counters[2]; - counters[1] = counters[3]; - counters[2] = 0; - counters[3] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - - } - - private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean right, int[] startEnd) - throws NotFoundException { - // Actually we found elements 2-5 - boolean firstIsBlack = row.get(startEnd[0]); - int firstElementStart = startEnd[0] - 1; - // Locate element 1 - while (firstElementStart >= 0 && firstIsBlack ^ row.get(firstElementStart)) { - firstElementStart--; - } - firstElementStart++; - int firstCounter = startEnd[0] - firstElementStart; - // Make 'counters' hold 1-4 - int[] counters = getDecodeFinderCounters(); - System.arraycopy(counters, 0, counters, 1, counters.length - 1); - counters[0] = firstCounter; - int value = parseFinderValue(counters, FINDER_PATTERNS); - int start = firstElementStart; - int end = startEnd[1]; - if (right) { - // row is actually reversed - start = row.getSize() - 1 - start; - end = row.getSize() - 1 - end; - } - return new FinderPattern(value, new int[] {firstElementStart, startEnd[1]}, start, end, rowNumber); - } - - private void adjustOddEvenCounts(boolean outsideChar, int numModules) throws NotFoundException { - - int oddSum = count(getOddCounts()); - int evenSum = count(getEvenCounts()); - int mismatch = oddSum + evenSum - numModules; - boolean oddParityBad = (oddSum & 0x01) == (outsideChar ? 1 : 0); - boolean evenParityBad = (evenSum & 0x01) == 1; - - boolean incrementOdd = false; - boolean decrementOdd = false; - boolean incrementEven = false; - boolean decrementEven = false; - - if (outsideChar) { - if (oddSum > 12) { - decrementOdd = true; - } else if (oddSum < 4) { - incrementOdd = true; - } - if (evenSum > 12) { - decrementEven = true; - } else if (evenSum < 4) { - incrementEven = true; - } - } else { - if (oddSum > 11) { - decrementOdd = true; - } else if (oddSum < 5) { - incrementOdd = true; - } - if (evenSum > 10) { - decrementEven = true; - } else if (evenSum < 4) { - incrementEven = true; - } - } - - /*if (mismatch == 2) { - if (!(oddParityBad && evenParityBad)) { - throw ReaderException.getInstance(); - } - decrementOdd = true; - decrementEven = true; - } else if (mismatch == -2) { - if (!(oddParityBad && evenParityBad)) { - throw ReaderException.getInstance(); - } - incrementOdd = true; - incrementEven = true; - } else */if (mismatch == 1) { - if (oddParityBad) { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - decrementOdd = true; - } else { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - decrementEven = true; - } - } else if (mismatch == -1) { - if (oddParityBad) { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - incrementOdd = true; - } else { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - incrementEven = true; - } - } else if (mismatch == 0) { - if (oddParityBad) { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - // Both bad - if (oddSum < evenSum) { - incrementOdd = true; - decrementEven = true; - } else { - decrementOdd = true; - incrementEven = true; - } - } else { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - // Nothing to do! - } - } else { - throw NotFoundException.getNotFoundInstance(); - } - - if (incrementOdd) { - if (decrementOdd) { - throw NotFoundException.getNotFoundInstance(); - } - increment(getOddCounts(), getOddRoundingErrors()); - } - if (decrementOdd) { - decrement(getOddCounts(), getOddRoundingErrors()); - } - if (incrementEven) { - if (decrementEven) { - throw NotFoundException.getNotFoundInstance(); - } - increment(getEvenCounts(), getOddRoundingErrors()); - } - if (decrementEven) { - decrement(getEvenCounts(), getEvenRoundingErrors()); - } - - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSSUtils.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSSUtils.java deleted file mode 100644 index fb5a1d020..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/RSSUtils.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss; - -/** Adapted from listings in ISO/IEC 24724 Appendix B and Appendix G. */ -public final class RSSUtils { - - private RSSUtils() {} - - /* - static int[] getRSSwidths(int val, int n, int elements, int maxWidth, boolean noNarrow) { - int[] widths = new int[elements]; - int bar; - int narrowMask = 0; - for (bar = 0; bar < elements - 1; bar++) { - narrowMask |= 1 << bar; - int elmWidth = 1; - int subVal; - while (true) { - subVal = combins(n - elmWidth - 1, elements - bar - 2); - if (noNarrow && (narrowMask == 0) && - (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { - subVal -= combins(n - elmWidth - (elements - bar), elements - bar - 2); - } - if (elements - bar - 1 > 1) { - int lessVal = 0; - for (int mxwElement = n - elmWidth - (elements - bar - 2); - mxwElement > maxWidth; - mxwElement--) { - lessVal += combins(n - elmWidth - mxwElement - 1, elements - bar - 3); - } - subVal -= lessVal * (elements - 1 - bar); - } else if (n - elmWidth > maxWidth) { - subVal--; - } - val -= subVal; - if (val < 0) { - break; - } - elmWidth++; - narrowMask &= ~(1 << bar); - } - val += subVal; - n -= elmWidth; - widths[bar] = elmWidth; - } - widths[bar] = n; - return widths; - } - */ - - public static int getRSSvalue(int[] widths, int maxWidth, boolean noNarrow) { - int elements = widths.length; - int n = 0; - for (int width : widths) { - n += width; - } - int val = 0; - int narrowMask = 0; - for (int bar = 0; bar < elements - 1; bar++) { - int elmWidth; - for (elmWidth = 1, narrowMask |= 1 << bar; - elmWidth < widths[bar]; - elmWidth++, narrowMask &= ~(1 << bar)) { - int subVal = combins(n - elmWidth - 1, elements - bar - 2); - if (noNarrow && (narrowMask == 0) && - (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { - subVal -= combins(n - elmWidth - (elements - bar), - elements - bar - 2); - } - if (elements - bar - 1 > 1) { - int lessVal = 0; - for (int mxwElement = n - elmWidth - (elements - bar - 2); - mxwElement > maxWidth; mxwElement--) { - lessVal += combins(n - elmWidth - mxwElement - 1, - elements - bar - 3); - } - subVal -= lessVal * (elements - 1 - bar); - } else if (n - elmWidth > maxWidth) { - subVal--; - } - val += subVal; - } - n -= elmWidth; - } - return val; - } - - private static int combins(int n, int r) { - int maxDenom; - int minDenom; - if (n - r > r) { - minDenom = r; - maxDenom = n - r; - } else { - minDenom = n - r; - maxDenom = r; - } - int val = 1; - int j = 1; - for (int i = n; i > maxDenom; i--) { - val *= i; - if (j <= minDenom) { - val /= j; - j++; - } - } - while (j <= minDenom) { - val /= j; - j++; - } - return val; - } - - /* - static int[] elements(int[] eDist, int N, int K) { - int[] widths = new int[eDist.length + 2]; - int twoK = 2 * K; - widths[0] = 1; - int i; - int minEven = 10; - int barSum = 1; - for (i = 1; i < twoK - 2; i += 2) { - widths[i] = eDist[i - 1] - widths[i - 1]; - widths[i + 1] = eDist[i] - widths[i]; - barSum += widths[i] + widths[i + 1]; - if (widths[i] < minEven) { - minEven = widths[i]; - } - } - widths[twoK - 1] = N - barSum; - if (widths[twoK - 1] < minEven) { - minEven = widths[twoK - 1]; - } - if (minEven > 1) { - for (i = 0; i < twoK; i += 2) { - widths[i] += minEven - 1; - widths[i + 1] -= minEven - 1; - } - } - return widths; - } - */ - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java deleted file mode 100644 index 0fa4edeec..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.common.BitArray; - -import java.util.List; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class BitArrayBuilder { - - private BitArrayBuilder() { - } - - static BitArray buildBitArray(List pairs) { - int charNumber = (pairs.size() * 2) - 1; - if (pairs.get(pairs.size() - 1).getRightChar() == null) { - charNumber -= 1; - } - - int size = 12 * charNumber; - - BitArray binary = new BitArray(size); - int accPos = 0; - - ExpandedPair firstPair = pairs.get(0); - int firstValue = firstPair.getRightChar().getValue(); - for(int i = 11; i >= 0; --i){ - if ((firstValue & (1 << i)) != 0) { - binary.set(accPos); - } - accPos++; - } - - for(int i = 1; i < pairs.size(); ++i){ - ExpandedPair currentPair = pairs.get(i); - - int leftValue = currentPair.getLeftChar().getValue(); - for(int j = 11; j >= 0; --j){ - if ((leftValue & (1 << j)) != 0) { - binary.set(accPos); - } - accPos++; - } - - if(currentPair.getRightChar() != null){ - int rightValue = currentPair.getRightChar().getValue(); - for(int j = 11; j >= 0; --j){ - if ((rightValue & (1 << j)) != 0) { - binary.set(accPos); - } - accPos++; - } - } - } - return binary; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedPair.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedPair.java deleted file mode 100644 index 8c2a501fa..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedPair.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.oned.rss.DataCharacter; -import com.google.zxing.oned.rss.FinderPattern; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class ExpandedPair { - - private final boolean mayBeLast; - private final DataCharacter leftChar; - private final DataCharacter rightChar; - private final FinderPattern finderPattern; - - ExpandedPair(DataCharacter leftChar, - DataCharacter rightChar, - FinderPattern finderPattern, - boolean mayBeLast) { - this.leftChar = leftChar; - this.rightChar = rightChar; - this.finderPattern = finderPattern; - this.mayBeLast = mayBeLast; - } - - boolean mayBeLast(){ - return this.mayBeLast; - } - - DataCharacter getLeftChar() { - return this.leftChar; - } - - DataCharacter getRightChar() { - return this.rightChar; - } - - FinderPattern getFinderPattern() { - return this.finderPattern; - } - - public boolean mustBeLast() { - return this.rightChar == null; - } - - @Override - public String toString() { - return - "[ " + leftChar + " , " + rightChar + " : " + - (finderPattern == null ? "null" : finderPattern.getValue()) + " ]"; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof ExpandedPair)) { - return false; - } - ExpandedPair that = (ExpandedPair) o; - return - equalsOrNull(leftChar, that.leftChar) && - equalsOrNull(rightChar, that.rightChar) && - equalsOrNull(finderPattern, that.finderPattern); - } - - private static boolean equalsOrNull(Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals(o2); - } - - @Override - public int hashCode() { - return hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern); - } - - private static int hashNotNull(Object o) { - return o == null ? 0 : o.hashCode(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedRow.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedRow.java deleted file mode 100644 index 037328e8f..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/ExpandedRow.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.oned.rss.expanded; - -import java.util.ArrayList; -import java.util.List; - -/** - * One row of an RSS Expanded Stacked symbol, consisting of 1+ expanded pairs. - */ -final class ExpandedRow { - - private final List pairs; - private final int rowNumber; - /** Did this row of the image have to be reversed (mirrored) to recognize the pairs? */ - private final boolean wasReversed; - - ExpandedRow(List pairs, int rowNumber, boolean wasReversed) { - this.pairs = new ArrayList<>(pairs); - this.rowNumber = rowNumber; - this.wasReversed = wasReversed; - } - - List getPairs() { - return this.pairs; - } - - int getRowNumber() { - return this.rowNumber; - } - - boolean isReversed() { - return this.wasReversed; - } - - boolean isEquivalent(List otherPairs) { - return this.pairs.equals(otherPairs); - } - - @Override - public String toString() { - return "{ " + pairs + " }"; - } - - /** - * Two rows are equal if they contain the same pairs in the same order. - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof ExpandedRow)) { - return false; - } - ExpandedRow that = (ExpandedRow) o; - return this.pairs.equals(that.getPairs()) && wasReversed == that.wasReversed; - } - - @Override - public int hashCode() { - return pairs.hashCode() ^ Boolean.valueOf(wasReversed).hashCode(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java deleted file mode 100644 index e52829e87..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java +++ /dev/null @@ -1,783 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitArray; -import com.google.zxing.oned.rss.AbstractRSSReader; -import com.google.zxing.oned.rss.DataCharacter; -import com.google.zxing.oned.rss.FinderPattern; -import com.google.zxing.oned.rss.RSSUtils; -import com.google.zxing.oned.rss.expanded.decoders.AbstractExpandedDecoder; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Collections; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -public final class RSSExpandedReader extends AbstractRSSReader { - - private static final int[] SYMBOL_WIDEST = {7, 5, 4, 3, 1}; - private static final int[] EVEN_TOTAL_SUBSET = {4, 20, 52, 104, 204}; - private static final int[] GSUM = {0, 348, 1388, 2948, 3988}; - - private static final int[][] FINDER_PATTERNS = { - {1,8,4,1}, // A - {3,6,4,1}, // B - {3,4,6,1}, // C - {3,2,8,1}, // D - {2,6,5,1}, // E - {2,2,9,1} // F - }; - - private static final int[][] WEIGHTS = { - { 1, 3, 9, 27, 81, 32, 96, 77}, - { 20, 60, 180, 118, 143, 7, 21, 63}, - {189, 145, 13, 39, 117, 140, 209, 205}, - {193, 157, 49, 147, 19, 57, 171, 91}, - { 62, 186, 136, 197, 169, 85, 44, 132}, - {185, 133, 188, 142, 4, 12, 36, 108}, - {113, 128, 173, 97, 80, 29, 87, 50}, - {150, 28, 84, 41, 123, 158, 52, 156}, - { 46, 138, 203, 187, 139, 206, 196, 166}, - { 76, 17, 51, 153, 37, 111, 122, 155}, - { 43, 129, 176, 106, 107, 110, 119, 146}, - { 16, 48, 144, 10, 30, 90, 59, 177}, - {109, 116, 137, 200, 178, 112, 125, 164}, - { 70, 210, 208, 202, 184, 130, 179, 115}, - {134, 191, 151, 31, 93, 68, 204, 190}, - {148, 22, 66, 198, 172, 94, 71, 2}, - { 6, 18, 54, 162, 64, 192,154, 40}, - {120, 149, 25, 75, 14, 42,126, 167}, - { 79, 26, 78, 23, 69, 207,199, 175}, - {103, 98, 83, 38, 114, 131, 182, 124}, - {161, 61, 183, 127, 170, 88, 53, 159}, - { 55, 165, 73, 8, 24, 72, 5, 15}, - { 45, 135, 194, 160, 58, 174, 100, 89} - }; - - private static final int FINDER_PAT_A = 0; - private static final int FINDER_PAT_B = 1; - private static final int FINDER_PAT_C = 2; - private static final int FINDER_PAT_D = 3; - private static final int FINDER_PAT_E = 4; - private static final int FINDER_PAT_F = 5; - - private static final int[][] FINDER_PATTERN_SEQUENCES = { - { FINDER_PAT_A, FINDER_PAT_A }, - { FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B }, - { FINDER_PAT_A, FINDER_PAT_C, FINDER_PAT_B, FINDER_PAT_D }, - { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_C }, - { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_F }, - { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D }, - { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E }, - { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - }; - - private static final int MAX_PAIRS = 11; - - private final List pairs = new ArrayList<>(MAX_PAIRS); - private final List rows = new ArrayList<>(); - private final int [] startEnd = new int[2]; - private boolean startFromEven; - - @Override - public Result decodeRow(int rowNumber, - BitArray row, - Map hints) throws NotFoundException, FormatException { - // Rows can start with even pattern in case in prev rows there where odd number of patters. - // So lets try twice - this.pairs.clear(); - this.startFromEven = false; - try { - List pairs = decodeRow2pairs(rowNumber, row); - return constructResult(pairs); - } catch (NotFoundException e) { - // OK - } - - this.pairs.clear(); - this.startFromEven = true; - List pairs = decodeRow2pairs(rowNumber, row); - return constructResult(pairs); - } - - @Override - public void reset() { - this.pairs.clear(); - this.rows.clear(); - } - - // Not private for testing - List decodeRow2pairs(int rowNumber, BitArray row) throws NotFoundException { - try { - while (true){ - ExpandedPair nextPair = retrieveNextPair(row, this.pairs, rowNumber); - this.pairs.add(nextPair); - // exit this loop when retrieveNextPair() fails and throws - } - } catch (NotFoundException nfe) { - if (this.pairs.isEmpty()) { - throw nfe; - } - } - - // TODO: verify sequence of finder patterns as in checkPairSequence() - if (checkChecksum()) { - return this.pairs; - } - - boolean tryStackedDecode = !this.rows.isEmpty(); - boolean wasReversed = false; // TODO: deal with reversed rows - storeRow(rowNumber, wasReversed); - if (tryStackedDecode) { - // When the image is 180-rotated, then rows are sorted in wrong direction. - // Try twice with both the directions. - List ps = checkRows(false); - if (ps != null) { - return ps; - } - ps = checkRows(true); - if (ps != null) { - return ps; - } - } - - throw NotFoundException.getNotFoundInstance(); - } - - private List checkRows(boolean reverse) { - // Limit number of rows we are checking - // We use recursive algorithm with pure complexity and don't want it to take forever - // Stacked barcode can have up to 11 rows, so 25 seems reasonable enough - if (this.rows.size() > 25) { - this.rows.clear(); // We will never have a chance to get result, so clear it - return null; - } - - this.pairs.clear(); - if (reverse) { - Collections.reverse(this.rows); - } - - List ps = null; - try { - ps = checkRows(new ArrayList(), 0); - } catch (NotFoundException e) { - // OK - } - - if (reverse) { - Collections.reverse(this.rows); - } - - return ps; - } - - // Try to construct a valid rows sequence - // Recursion is used to implement backtracking - private List checkRows(List collectedRows, int currentRow) throws NotFoundException { - for (int i = currentRow; i < rows.size(); i++) { - ExpandedRow row = rows.get(i); - this.pairs.clear(); - int size = collectedRows.size(); - for (int j = 0; j < size; j++) { - this.pairs.addAll(collectedRows.get(j).getPairs()); - } - this.pairs.addAll(row.getPairs()); - - if (!isValidSequence(this.pairs)) { - continue; - } - - if (checkChecksum()) { - return this.pairs; - } - - List rs = new ArrayList<>(); - rs.addAll(collectedRows); - rs.add(row); - try { - // Recursion: try to add more rows - return checkRows(rs, i + 1); - } catch (NotFoundException e) { - // We failed, try the next candidate - } - } - - throw NotFoundException.getNotFoundInstance(); - } - - // Whether the pairs form a valid find pattern seqience, - // either complete or a prefix - private static boolean isValidSequence(List pairs) { - for (int[] sequence : FINDER_PATTERN_SEQUENCES) { - if (pairs.size() > sequence.length) { - continue; - } - - boolean stop = true; - for (int j = 0; j < pairs.size(); j++) { - if (pairs.get(j).getFinderPattern().getValue() != sequence[j]) { - stop = false; - break; - } - } - - if (stop) { - return true; - } - } - - return false; - } - - private void storeRow(int rowNumber, boolean wasReversed) { - // Discard if duplicate above or below; otherwise insert in order by row number. - int insertPos = 0; - boolean prevIsSame = false; - boolean nextIsSame = false; - while (insertPos < this.rows.size()) { - ExpandedRow erow = this.rows.get(insertPos); - if (erow.getRowNumber() > rowNumber) { - nextIsSame = erow.isEquivalent(this.pairs); - break; - } - prevIsSame = erow.isEquivalent(this.pairs); - insertPos++; - } - if (nextIsSame || prevIsSame) { - return; - } - - // When the row was partially decoded (e.g. 2 pairs found instead of 3), - // it will prevent us from detecting the barcode. - // Try to merge partial rows - - // Check whether the row is part of an allready detected row - if (isPartialRow(this.pairs, this.rows)) { - return; - } - - this.rows.add(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed)); - - removePartialRows(this.pairs, this.rows); - } - - // Remove all the rows that contains only specified pairs - private static void removePartialRows(List pairs, List rows) { - for (Iterator iterator = rows.iterator(); iterator.hasNext();) { - ExpandedRow r = iterator.next(); - if (r.getPairs().size() == pairs.size()) { - continue; - } - boolean allFound = true; - for (ExpandedPair p : r.getPairs()) { - boolean found = false; - for (ExpandedPair pp : pairs) { - if (p.equals(pp)) { - found = true; - break; - } - } - if (!found) { - allFound = false; - break; - } - } - if (allFound) { - // 'pairs' contains all the pairs from the row 'r' - iterator.remove(); - } - } - } - - // Returns true when one of the rows already contains all the pairs - private static boolean isPartialRow(Iterable pairs, Iterable rows) { - for (ExpandedRow r : rows) { - boolean allFound = true; - for (ExpandedPair p : pairs) { - boolean found = false; - for (ExpandedPair pp : r.getPairs()) { - if (p.equals(pp)) { - found = true; - break; - } - } - if (!found) { - allFound = false; - break; - } - } - if (allFound) { - // the row 'r' contain all the pairs from 'pairs' - return true; - } - } - return false; - } - - // Only used for unit testing - List getRows() { - return this.rows; - } - - // Not private for unit testing - static Result constructResult(List pairs) throws NotFoundException, FormatException { - BitArray binary = BitArrayBuilder.buildBitArray(pairs); - - AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary); - String resultingString = decoder.parseInformation(); - - ResultPoint[] firstPoints = pairs.get(0).getFinderPattern().getResultPoints(); - ResultPoint[] lastPoints = pairs.get(pairs.size() - 1).getFinderPattern().getResultPoints(); - - return new Result( - resultingString, - null, - new ResultPoint[]{firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]}, - BarcodeFormat.RSS_EXPANDED - ); - } - - private boolean checkChecksum() { - ExpandedPair firstPair = this.pairs.get(0); - DataCharacter checkCharacter = firstPair.getLeftChar(); - DataCharacter firstCharacter = firstPair.getRightChar(); - - if (firstCharacter == null) { - return false; - } - - int checksum = firstCharacter.getChecksumPortion(); - int s = 2; - - for(int i = 1; i < this.pairs.size(); ++i){ - ExpandedPair currentPair = this.pairs.get(i); - checksum += currentPair.getLeftChar().getChecksumPortion(); - s++; - DataCharacter currentRightChar = currentPair.getRightChar(); - if (currentRightChar != null) { - checksum += currentRightChar.getChecksumPortion(); - s++; - } - } - - checksum %= 211; - - int checkCharacterValue = 211 * (s - 4) + checksum; - - return checkCharacterValue == checkCharacter.getValue(); - } - - private static int getNextSecondBar(BitArray row, int initialPos){ - int currentPos; - if (row.get(initialPos)) { - currentPos = row.getNextUnset(initialPos); - currentPos = row.getNextSet(currentPos); - } else { - currentPos = row.getNextSet(initialPos); - currentPos = row.getNextUnset(currentPos); - } - return currentPos; - } - - // not private for testing - ExpandedPair retrieveNextPair(BitArray row, List previousPairs, int rowNumber) - throws NotFoundException { - boolean isOddPattern = previousPairs.size() % 2 == 0; - if (startFromEven) { - isOddPattern = !isOddPattern; - } - - FinderPattern pattern; - - boolean keepFinding = true; - int forcedOffset = -1; - do{ - this.findNextPair(row, previousPairs, forcedOffset); - pattern = parseFoundFinderPattern(row, rowNumber, isOddPattern); - if (pattern == null){ - forcedOffset = getNextSecondBar(row, this.startEnd[0]); - } else { - keepFinding = false; - } - }while(keepFinding); - - // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not. - // boolean mayBeLast = checkPairSequence(previousPairs, pattern); - - DataCharacter leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true); - - if (!previousPairs.isEmpty() && previousPairs.get(previousPairs.size()-1).mustBeLast()) { - throw NotFoundException.getNotFoundInstance(); - } - - DataCharacter rightChar; - try { - rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false); - } catch(NotFoundException ignored) { - rightChar = null; - } - boolean mayBeLast = true; - return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast); - } - - private void findNextPair(BitArray row, List previousPairs, int forcedOffset) - throws NotFoundException { - int[] counters = this.getDecodeFinderCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - - int width = row.getSize(); - - int rowOffset; - if (forcedOffset >= 0) { - rowOffset = forcedOffset; - } else if (previousPairs.isEmpty()) { - rowOffset = 0; - } else{ - ExpandedPair lastPair = previousPairs.get(previousPairs.size() - 1); - rowOffset = lastPair.getFinderPattern().getStartEnd()[1]; - } - boolean searchingEvenPair = previousPairs.size() % 2 != 0; - if (startFromEven) { - searchingEvenPair = !searchingEvenPair; - } - - boolean isWhite = false; - while (rowOffset < width) { - isWhite = !row.get(rowOffset); - if (!isWhite) { - break; - } - rowOffset++; - } - - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) { - if (row.get(x) ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == 3) { - if (searchingEvenPair) { - reverseCounters(counters); - } - - if (isFinderPattern(counters)){ - this.startEnd[0] = patternStart; - this.startEnd[1] = x; - return; - } - - if (searchingEvenPair) { - reverseCounters(counters); - } - - patternStart += counters[0] + counters[1]; - counters[0] = counters[2]; - counters[1] = counters[3]; - counters[2] = 0; - counters[3] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - throw NotFoundException.getNotFoundInstance(); - } - - private static void reverseCounters(int [] counters){ - int length = counters.length; - for(int i = 0; i < length / 2; ++i){ - int tmp = counters[i]; - counters[i] = counters[length - i - 1]; - counters[length - i - 1] = tmp; - } - } - - private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean oddPattern) { - // Actually we found elements 2-5. - int firstCounter; - int start; - int end; - - if(oddPattern){ - // If pattern number is odd, we need to locate element 1 *before* the current block. - - int firstElementStart = this.startEnd[0] - 1; - // Locate element 1 - while (firstElementStart >= 0 && !row.get(firstElementStart)) { - firstElementStart--; - } - - firstElementStart++; - firstCounter = this.startEnd[0] - firstElementStart; - start = firstElementStart; - end = this.startEnd[1]; - - }else{ - // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block. - - start = this.startEnd[0]; - - end = row.getNextUnset(this.startEnd[1] + 1); - firstCounter = end - this.startEnd[1]; - } - - // Make 'counters' hold 1-4 - int [] counters = this.getDecodeFinderCounters(); - System.arraycopy(counters, 0, counters, 1, counters.length - 1); - - counters[0] = firstCounter; - int value; - try { - value = parseFinderValue(counters, FINDER_PATTERNS); - } catch (NotFoundException ignored) { - return null; - } - return new FinderPattern(value, new int[] {start, end}, start, end, rowNumber); - } - - DataCharacter decodeDataCharacter(BitArray row, - FinderPattern pattern, - boolean isOddPattern, - boolean leftChar) throws NotFoundException { - int[] counters = this.getDataCharacterCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - counters[4] = 0; - counters[5] = 0; - counters[6] = 0; - counters[7] = 0; - - if (leftChar) { - recordPatternInReverse(row, pattern.getStartEnd()[0], counters); - } else { - recordPattern(row, pattern.getStartEnd()[1], counters); - // reverse it - for (int i = 0, j = counters.length - 1; i < j; i++, j--) { - int temp = counters[i]; - counters[i] = counters[j]; - counters[j] = temp; - } - }//counters[] has the pixels of the module - - int numModules = 17; //left and right data characters have all the same length - float elementWidth = (float) count(counters) / (float) numModules; - - // Sanity check: element width for pattern and the character should match - float expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0f; - if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3f) { - throw NotFoundException.getNotFoundInstance(); - } - - int[] oddCounts = this.getOddCounts(); - int[] evenCounts = this.getEvenCounts(); - float[] oddRoundingErrors = this.getOddRoundingErrors(); - float[] evenRoundingErrors = this.getEvenRoundingErrors(); - - for (int i = 0; i < counters.length; i++) { - float value = 1.0f * counters[i] / elementWidth; - int count = (int) (value + 0.5f); // Round - if (count < 1) { - if (value < 0.3f) { - throw NotFoundException.getNotFoundInstance(); - } - count = 1; - } else if (count > 8) { - if (value > 8.7f) { - throw NotFoundException.getNotFoundInstance(); - } - count = 8; - } - int offset = i / 2; - if ((i & 0x01) == 0) { - oddCounts[offset] = count; - oddRoundingErrors[offset] = value - count; - } else { - evenCounts[offset] = count; - evenRoundingErrors[offset] = value - count; - } - } - - adjustOddEvenCounts(numModules); - - int weightRowNumber = 4 * pattern.getValue() + (isOddPattern?0:2) + (leftChar?0:1) - 1; - - int oddSum = 0; - int oddChecksumPortion = 0; - for (int i = oddCounts.length - 1; i >= 0; i--) { - if(isNotA1left(pattern, isOddPattern, leftChar)){ - int weight = WEIGHTS[weightRowNumber][2 * i]; - oddChecksumPortion += oddCounts[i] * weight; - } - oddSum += oddCounts[i]; - } - int evenChecksumPortion = 0; - //int evenSum = 0; - for (int i = evenCounts.length - 1; i >= 0; i--) { - if(isNotA1left(pattern, isOddPattern, leftChar)){ - int weight = WEIGHTS[weightRowNumber][2 * i + 1]; - evenChecksumPortion += evenCounts[i] * weight; - } - //evenSum += evenCounts[i]; - } - int checksumPortion = oddChecksumPortion + evenChecksumPortion; - - if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) { - throw NotFoundException.getNotFoundInstance(); - } - - int group = (13 - oddSum) / 2; - int oddWidest = SYMBOL_WIDEST[group]; - int evenWidest = 9 - oddWidest; - int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true); - int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false); - int tEven = EVEN_TOTAL_SUBSET[group]; - int gSum = GSUM[group]; - int value = vOdd * tEven + vEven + gSum; - - return new DataCharacter(value, checksumPortion); - } - - private static boolean isNotA1left(FinderPattern pattern, boolean isOddPattern, boolean leftChar) { - // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char - return !(pattern.getValue() == 0 && isOddPattern && leftChar); - } - - private void adjustOddEvenCounts(int numModules) throws NotFoundException { - - int oddSum = count(this.getOddCounts()); - int evenSum = count(this.getEvenCounts()); - int mismatch = oddSum + evenSum - numModules; - boolean oddParityBad = (oddSum & 0x01) == 1; - boolean evenParityBad = (evenSum & 0x01) == 0; - - boolean incrementOdd = false; - boolean decrementOdd = false; - - if (oddSum > 13) { - decrementOdd = true; - } else if (oddSum < 4) { - incrementOdd = true; - } - boolean incrementEven = false; - boolean decrementEven = false; - if (evenSum > 13) { - decrementEven = true; - } else if (evenSum < 4) { - incrementEven = true; - } - - if (mismatch == 1) { - if (oddParityBad) { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - decrementOdd = true; - } else { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - decrementEven = true; - } - } else if (mismatch == -1) { - if (oddParityBad) { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - incrementOdd = true; - } else { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - incrementEven = true; - } - } else if (mismatch == 0) { - if (oddParityBad) { - if (!evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - // Both bad - if (oddSum < evenSum) { - incrementOdd = true; - decrementEven = true; - } else { - decrementOdd = true; - incrementEven = true; - } - } else { - if (evenParityBad) { - throw NotFoundException.getNotFoundInstance(); - } - // Nothing to do! - } - } else { - throw NotFoundException.getNotFoundInstance(); - } - - if (incrementOdd) { - if (decrementOdd) { - throw NotFoundException.getNotFoundInstance(); - } - increment(this.getOddCounts(), this.getOddRoundingErrors()); - } - if (decrementOdd) { - decrement(this.getOddCounts(), this.getOddRoundingErrors()); - } - if (incrementEven) { - if (decrementEven) { - throw NotFoundException.getNotFoundInstance(); - } - increment(this.getEvenCounts(), this.getOddRoundingErrors()); - } - if (decrementEven) { - decrement(this.getEvenCounts(), this.getEvenRoundingErrors()); - } - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java deleted file mode 100644 index 759cf96e0..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class AI013103decoder extends AI013x0xDecoder { - - AI013103decoder(BitArray information) { - super(information); - } - - @Override - protected void addWeightCode(StringBuilder buf, int weight) { - buf.append("(3103)"); - } - - @Override - protected int checkWeight(int weight) { - return weight; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java deleted file mode 100644 index f4e807e04..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class AI01320xDecoder extends AI013x0xDecoder { - - AI01320xDecoder(BitArray information) { - super(information); - } - - @Override - protected void addWeightCode(StringBuilder buf, int weight) { - if (weight < 10000) { - buf.append("(3202)"); - } else { - buf.append("(3203)"); - } - } - - @Override - protected int checkWeight(int weight) { - if(weight < 10000) { - return weight; - } - return weight - 10000; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java deleted file mode 100644 index 9ea5bba66..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class AI01392xDecoder extends AI01decoder { - - private static final int HEADER_SIZE = 5 + 1 + 2; - private static final int LAST_DIGIT_SIZE = 2; - - AI01392xDecoder(BitArray information) { - super(information); - } - - @Override - public String parseInformation() throws NotFoundException, FormatException { - if (this.getInformation().getSize() < HEADER_SIZE + GTIN_SIZE) { - throw NotFoundException.getNotFoundInstance(); - } - - StringBuilder buf = new StringBuilder(); - - encodeCompressedGtin(buf, HEADER_SIZE); - - int lastAIdigit = - this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE + GTIN_SIZE, LAST_DIGIT_SIZE); - buf.append("(392"); - buf.append(lastAIdigit); - buf.append(')'); - - DecodedInformation decodedInformation = - this.getGeneralDecoder().decodeGeneralPurposeField(HEADER_SIZE + GTIN_SIZE + LAST_DIGIT_SIZE, null); - buf.append(decodedInformation.getNewString()); - - return buf.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java deleted file mode 100644 index 649da3f37..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class AI01393xDecoder extends AI01decoder { - - private static final int HEADER_SIZE = 5 + 1 + 2; - private static final int LAST_DIGIT_SIZE = 2; - private static final int FIRST_THREE_DIGITS_SIZE = 10; - - AI01393xDecoder(BitArray information) { - super(information); - } - - @Override - public String parseInformation() throws NotFoundException, FormatException { - if(this.getInformation().getSize() < HEADER_SIZE + GTIN_SIZE) { - throw NotFoundException.getNotFoundInstance(); - } - - StringBuilder buf = new StringBuilder(); - - encodeCompressedGtin(buf, HEADER_SIZE); - - int lastAIdigit = - this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE + GTIN_SIZE, LAST_DIGIT_SIZE); - - buf.append("(393"); - buf.append(lastAIdigit); - buf.append(')'); - - int firstThreeDigits = - this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE + GTIN_SIZE + LAST_DIGIT_SIZE, FIRST_THREE_DIGITS_SIZE); - if(firstThreeDigits / 100 == 0) { - buf.append('0'); - } - if(firstThreeDigits / 10 == 0) { - buf.append('0'); - } - buf.append(firstThreeDigits); - - DecodedInformation generalInformation = - this.getGeneralDecoder().decodeGeneralPurposeField(HEADER_SIZE + GTIN_SIZE + LAST_DIGIT_SIZE + FIRST_THREE_DIGITS_SIZE, null); - buf.append(generalInformation.getNewString()); - - return buf.toString(); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java deleted file mode 100644 index 9bcf3e8b3..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class AI013x0x1xDecoder extends AI01weightDecoder { - - private static final int HEADER_SIZE = 7 + 1; - private static final int WEIGHT_SIZE = 20; - private static final int DATE_SIZE = 16; - - private final String dateCode; - private final String firstAIdigits; - - AI013x0x1xDecoder(BitArray information, String firstAIdigits, String dateCode) { - super(information); - this.dateCode = dateCode; - this.firstAIdigits = firstAIdigits; - } - - @Override - public String parseInformation() throws NotFoundException { - if (this.getInformation().getSize() != HEADER_SIZE + GTIN_SIZE + WEIGHT_SIZE + DATE_SIZE) { - throw NotFoundException.getNotFoundInstance(); - } - - StringBuilder buf = new StringBuilder(); - - encodeCompressedGtin(buf, HEADER_SIZE); - encodeCompressedWeight(buf, HEADER_SIZE + GTIN_SIZE, WEIGHT_SIZE); - encodeCompressedDate(buf, HEADER_SIZE + GTIN_SIZE + WEIGHT_SIZE); - - return buf.toString(); - } - - private void encodeCompressedDate(StringBuilder buf, int currentPos) { - int numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, DATE_SIZE); - if(numericDate == 38400) { - return; - } - - buf.append('('); - buf.append(this.dateCode); - buf.append(')'); - - int day = numericDate % 32; - numericDate /= 32; - int month = numericDate % 12 + 1; - numericDate /= 12; - int year = numericDate; - - if (year / 10 == 0) { - buf.append('0'); - } - buf.append(year); - if (month / 10 == 0) { - buf.append('0'); - } - buf.append(month); - if (day / 10 == 0) { - buf.append('0'); - } - buf.append(day); - } - - @Override - protected void addWeightCode(StringBuilder buf, int weight) { - int lastAI = weight / 100000; - buf.append('('); - buf.append(this.firstAIdigits); - buf.append(lastAI); - buf.append(')'); - } - - @Override - protected int checkWeight(int weight) { - return weight % 100000; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java deleted file mode 100644 index 54d32d6c9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -abstract class AI013x0xDecoder extends AI01weightDecoder { - - private static final int HEADER_SIZE = 4 + 1; - private static final int WEIGHT_SIZE = 15; - - AI013x0xDecoder(BitArray information) { - super(information); - } - - @Override - public String parseInformation() throws NotFoundException { - if (this.getInformation().getSize() != HEADER_SIZE + GTIN_SIZE + WEIGHT_SIZE) { - throw NotFoundException.getNotFoundInstance(); - } - - StringBuilder buf = new StringBuilder(); - - encodeCompressedGtin(buf, HEADER_SIZE); - encodeCompressedWeight(buf, HEADER_SIZE + GTIN_SIZE, WEIGHT_SIZE); - - return buf.toString(); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java deleted file mode 100644 index 27222a382..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class AI01AndOtherAIs extends AI01decoder { - - private static final int HEADER_SIZE = 1 + 1 + 2; //first bit encodes the linkage flag, - //the second one is the encodation method, and the other two are for the variable length - AI01AndOtherAIs(BitArray information) { - super(information); - } - - @Override - public String parseInformation() throws NotFoundException, FormatException { - StringBuilder buff = new StringBuilder(); - - buff.append("(01)"); - int initialGtinPosition = buff.length(); - int firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE, 4); - buff.append(firstGtinDigit); - - this.encodeCompressedGtinWithoutAI(buff, HEADER_SIZE + 4, initialGtinPosition); - - return this.getGeneralDecoder().decodeAllCodes(buff, HEADER_SIZE + 44); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java deleted file mode 100644 index 49bc9f9b1..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -abstract class AI01decoder extends AbstractExpandedDecoder { - - protected static final int GTIN_SIZE = 40; - - AI01decoder(BitArray information) { - super(information); - } - - protected final void encodeCompressedGtin(StringBuilder buf, int currentPos) { - buf.append("(01)"); - int initialPosition = buf.length(); - buf.append('9'); - - encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition); - } - - protected final void encodeCompressedGtinWithoutAI(StringBuilder buf, int currentPos, int initialBufferPosition) { - for(int i = 0; i < 4; ++i){ - int currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10); - if (currentBlock / 100 == 0) { - buf.append('0'); - } - if (currentBlock / 10 == 0) { - buf.append('0'); - } - buf.append(currentBlock); - } - - appendCheckDigit(buf, initialBufferPosition); - } - - private static void appendCheckDigit(StringBuilder buf, int currentPos){ - int checkDigit = 0; - for (int i = 0; i < 13; i++) { - int digit = buf.charAt(i + currentPos) - '0'; - checkDigit += (i & 0x01) == 0 ? 3 * digit : digit; - } - - checkDigit = 10 - (checkDigit % 10); - if (checkDigit == 10) { - checkDigit = 0; - } - - buf.append(checkDigit); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java deleted file mode 100644 index 357a13dcb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -abstract class AI01weightDecoder extends AI01decoder { - - AI01weightDecoder(BitArray information) { - super(information); - } - - protected final void encodeCompressedWeight(StringBuilder buf, int currentPos, int weightSize) { - int originalWeightNumeric = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, weightSize); - addWeightCode(buf, originalWeightNumeric); - - int weightNumeric = checkWeight(originalWeightNumeric); - - int currentDivisor = 100000; - for(int i = 0; i < 5; ++i){ - if (weightNumeric / currentDivisor == 0) { - buf.append('0'); - } - currentDivisor /= 10; - } - buf.append(weightNumeric); - } - - protected abstract void addWeightCode(StringBuilder buf, int weight); - - protected abstract int checkWeight(int weight); - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java deleted file mode 100644 index bdb7e1085..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -public abstract class AbstractExpandedDecoder { - - private final BitArray information; - private final GeneralAppIdDecoder generalDecoder; - - AbstractExpandedDecoder(BitArray information){ - this.information = information; - this.generalDecoder = new GeneralAppIdDecoder(information); - } - - protected final BitArray getInformation() { - return information; - } - - protected final GeneralAppIdDecoder getGeneralDecoder() { - return generalDecoder; - } - - public abstract String parseInformation() throws NotFoundException, FormatException; - - public static AbstractExpandedDecoder createDecoder(BitArray information){ - if (information.get(1)) { - return new AI01AndOtherAIs(information); - } - if (!information.get(2)) { - return new AnyAIDecoder(information); - } - - int fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4); - - switch(fourBitEncodationMethod){ - case 4: return new AI013103decoder(information); - case 5: return new AI01320xDecoder(information); - } - - int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5); - switch(fiveBitEncodationMethod){ - case 12: return new AI01392xDecoder(information); - case 13: return new AI01393xDecoder(information); - } - - int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7); - switch(sevenBitEncodationMethod){ - case 56: return new AI013x0x1xDecoder(information, "310", "11"); - case 57: return new AI013x0x1xDecoder(information, "320", "11"); - case 58: return new AI013x0x1xDecoder(information, "310", "13"); - case 59: return new AI013x0x1xDecoder(information, "320", "13"); - case 60: return new AI013x0x1xDecoder(information, "310", "15"); - case 61: return new AI013x0x1xDecoder(information, "320", "15"); - case 62: return new AI013x0x1xDecoder(information, "310", "17"); - case 63: return new AI013x0x1xDecoder(information, "320", "17"); - } - - throw new IllegalStateException("unknown decoder: " + information); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java deleted file mode 100644 index 2074d8f0b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class AnyAIDecoder extends AbstractExpandedDecoder { - - private static final int HEADER_SIZE = 2 + 1 + 2; - - AnyAIDecoder(BitArray information) { - super(information); - } - - @Override - public String parseInformation() throws NotFoundException, FormatException { - StringBuilder buf = new StringBuilder(); - return this.getGeneralDecoder().decodeAllCodes(buf, HEADER_SIZE); - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java deleted file mode 100644 index a9593553e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class BlockParsedResult { - - private final DecodedInformation decodedInformation; - private final boolean finished; - - BlockParsedResult(boolean finished) { - this(null, finished); - } - - BlockParsedResult(DecodedInformation information, boolean finished) { - this.finished = finished; - this.decodedInformation = information; - } - - DecodedInformation getDecodedInformation() { - return this.decodedInformation; - } - - boolean isFinished() { - return this.finished; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java deleted file mode 100644 index 463cee2bb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class CurrentParsingState { - - private int position; - private State encoding; - - private enum State { - NUMERIC, - ALPHA, - ISO_IEC_646 - } - - CurrentParsingState() { - this.position = 0; - this.encoding = State.NUMERIC; - } - - int getPosition() { - return position; - } - - void setPosition(int position) { - this.position = position; - } - - void incrementPosition(int delta) { - position += delta; - } - - boolean isAlpha(){ - return this.encoding == State.ALPHA; - } - - boolean isNumeric(){ - return this.encoding == State.NUMERIC; - } - - boolean isIsoIec646(){ - return this.encoding == State.ISO_IEC_646; - } - - void setNumeric() { - this.encoding = State.NUMERIC; - } - - void setAlpha() { - this.encoding = State.ALPHA; - } - - void setIsoIec646() { - this.encoding = State.ISO_IEC_646; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java deleted file mode 100644 index 790b6846e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class DecodedChar extends DecodedObject { - - private final char value; - - static final char FNC1 = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset - - DecodedChar(int newPosition, char value) { - super(newPosition); - this.value = value; - } - - char getValue(){ - return this.value; - } - - boolean isFNC1(){ - return this.value == FNC1; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java deleted file mode 100644 index cc2522592..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class DecodedInformation extends DecodedObject { - - private final String newString; - private final int remainingValue; - private final boolean remaining; - - DecodedInformation(int newPosition, String newString){ - super(newPosition); - this.newString = newString; - this.remaining = false; - this.remainingValue = 0; - } - - DecodedInformation(int newPosition, String newString, int remainingValue){ - super(newPosition); - this.remaining = true; - this.remainingValue = remainingValue; - this.newString = newString; - } - - String getNewString(){ - return this.newString; - } - - boolean isRemaining(){ - return this.remaining; - } - - int getRemainingValue(){ - return this.remainingValue; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java deleted file mode 100644 index 29a7e6721..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class DecodedNumeric extends DecodedObject { - - private final int firstDigit; - private final int secondDigit; - - static final int FNC1 = 10; - - DecodedNumeric(int newPosition, int firstDigit, int secondDigit) throws FormatException { - super(newPosition); - - if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) { - throw FormatException.getFormatInstance(); - } - - this.firstDigit = firstDigit; - this.secondDigit = secondDigit; - } - - int getFirstDigit(){ - return this.firstDigit; - } - - int getSecondDigit(){ - return this.secondDigit; - } - - int getValue(){ - return this.firstDigit * 10 + this.secondDigit; - } - - boolean isFirstDigitFNC1(){ - return this.firstDigit == FNC1; - } - - boolean isSecondDigitFNC1(){ - return this.secondDigit == FNC1; - } - - boolean isAnyFNC1(){ - return this.firstDigit == FNC1 || this.secondDigit == FNC1; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java deleted file mode 100644 index ea667aa5e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -abstract class DecodedObject { - - private final int newPosition; - - DecodedObject(int newPosition){ - this.newPosition = newPosition; - } - - final int getNewPosition() { - return this.newPosition; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java deleted file mode 100644 index 8de540b3d..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.NotFoundException; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class FieldParser { - - private static final Object VARIABLE_LENGTH = new Object(); - - private static final Object [][] TWO_DIGIT_DATA_LENGTH = { - // "DIGITS", new Integer(LENGTH) - // or - // "DIGITS", VARIABLE_LENGTH, new Integer(MAX_SIZE) - - { "00", 18}, - { "01", 14}, - { "02", 14}, - - { "10", VARIABLE_LENGTH, 20}, - { "11", 6}, - { "12", 6}, - { "13", 6}, - { "15", 6}, - { "17", 6}, - - { "20", 2}, - { "21", VARIABLE_LENGTH, 20}, - { "22", VARIABLE_LENGTH, 29}, - - { "30", VARIABLE_LENGTH, 8}, - { "37", VARIABLE_LENGTH, 8}, - - //internal company codes - { "90", VARIABLE_LENGTH, 30}, - { "91", VARIABLE_LENGTH, 30}, - { "92", VARIABLE_LENGTH, 30}, - { "93", VARIABLE_LENGTH, 30}, - { "94", VARIABLE_LENGTH, 30}, - { "95", VARIABLE_LENGTH, 30}, - { "96", VARIABLE_LENGTH, 30}, - { "97", VARIABLE_LENGTH, 30}, - { "98", VARIABLE_LENGTH, 30}, - { "99", VARIABLE_LENGTH, 30}, - }; - - private static final Object [][] THREE_DIGIT_DATA_LENGTH = { - // Same format as above - - { "240", VARIABLE_LENGTH, 30}, - { "241", VARIABLE_LENGTH, 30}, - { "242", VARIABLE_LENGTH, 6}, - { "250", VARIABLE_LENGTH, 30}, - { "251", VARIABLE_LENGTH, 30}, - { "253", VARIABLE_LENGTH, 17}, - { "254", VARIABLE_LENGTH, 20}, - - { "400", VARIABLE_LENGTH, 30}, - { "401", VARIABLE_LENGTH, 30}, - { "402", 17}, - { "403", VARIABLE_LENGTH, 30}, - { "410", 13}, - { "411", 13}, - { "412", 13}, - { "413", 13}, - { "414", 13}, - { "420", VARIABLE_LENGTH, 20}, - { "421", VARIABLE_LENGTH, 15}, - { "422", 3}, - { "423", VARIABLE_LENGTH, 15}, - { "424", 3}, - { "425", 3}, - { "426", 3}, - }; - - private static final Object [][] THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = { - // Same format as above - - { "310", 6}, - { "311", 6}, - { "312", 6}, - { "313", 6}, - { "314", 6}, - { "315", 6}, - { "316", 6}, - { "320", 6}, - { "321", 6}, - { "322", 6}, - { "323", 6}, - { "324", 6}, - { "325", 6}, - { "326", 6}, - { "327", 6}, - { "328", 6}, - { "329", 6}, - { "330", 6}, - { "331", 6}, - { "332", 6}, - { "333", 6}, - { "334", 6}, - { "335", 6}, - { "336", 6}, - { "340", 6}, - { "341", 6}, - { "342", 6}, - { "343", 6}, - { "344", 6}, - { "345", 6}, - { "346", 6}, - { "347", 6}, - { "348", 6}, - { "349", 6}, - { "350", 6}, - { "351", 6}, - { "352", 6}, - { "353", 6}, - { "354", 6}, - { "355", 6}, - { "356", 6}, - { "357", 6}, - { "360", 6}, - { "361", 6}, - { "362", 6}, - { "363", 6}, - { "364", 6}, - { "365", 6}, - { "366", 6}, - { "367", 6}, - { "368", 6}, - { "369", 6}, - { "390", VARIABLE_LENGTH, 15}, - { "391", VARIABLE_LENGTH, 18}, - { "392", VARIABLE_LENGTH, 15}, - { "393", VARIABLE_LENGTH, 18}, - { "703", VARIABLE_LENGTH, 30} - }; - - private static final Object [][] FOUR_DIGIT_DATA_LENGTH = { - // Same format as above - - { "7001", 13}, - { "7002", VARIABLE_LENGTH, 30}, - { "7003", 10}, - - { "8001", 14}, - { "8002", VARIABLE_LENGTH, 20}, - { "8003", VARIABLE_LENGTH, 30}, - { "8004", VARIABLE_LENGTH, 30}, - { "8005", 6}, - { "8006", 18}, - { "8007", VARIABLE_LENGTH, 30}, - { "8008", VARIABLE_LENGTH, 12}, - { "8018", 18}, - { "8020", VARIABLE_LENGTH, 25}, - { "8100", 6}, - { "8101", 10}, - { "8102", 2}, - { "8110", VARIABLE_LENGTH, 70}, - { "8200", VARIABLE_LENGTH, 70}, - }; - - private FieldParser() { - } - - static String parseFieldsInGeneralPurpose(String rawInformation) throws NotFoundException{ - if (rawInformation.isEmpty()) { - return null; - } - - // Processing 2-digit AIs - - if(rawInformation.length() < 2) { - throw NotFoundException.getNotFoundInstance(); - } - - String firstTwoDigits = rawInformation.substring(0, 2); - - for (Object[] dataLength : TWO_DIGIT_DATA_LENGTH) { - if (dataLength[0].equals(firstTwoDigits)) { - if (dataLength[1] == VARIABLE_LENGTH) { - return processVariableAI(2, (Integer) dataLength[2], rawInformation); - } - return processFixedAI(2, (Integer) dataLength[1], rawInformation); - } - } - - if(rawInformation.length() < 3) { - throw NotFoundException.getNotFoundInstance(); - } - - String firstThreeDigits = rawInformation.substring(0, 3); - - for (Object[] dataLength : THREE_DIGIT_DATA_LENGTH) { - if (dataLength[0].equals(firstThreeDigits)) { - if (dataLength[1] == VARIABLE_LENGTH) { - return processVariableAI(3, (Integer) dataLength[2], rawInformation); - } - return processFixedAI(3, (Integer) dataLength[1], rawInformation); - } - } - - - for (Object[] dataLength : THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH) { - if (dataLength[0].equals(firstThreeDigits)) { - if (dataLength[1] == VARIABLE_LENGTH) { - return processVariableAI(4, (Integer) dataLength[2], rawInformation); - } - return processFixedAI(4, (Integer) dataLength[1], rawInformation); - } - } - - if(rawInformation.length() < 4) { - throw NotFoundException.getNotFoundInstance(); - } - - String firstFourDigits = rawInformation.substring(0, 4); - - for (Object[] dataLength : FOUR_DIGIT_DATA_LENGTH) { - if (dataLength[0].equals(firstFourDigits)) { - if (dataLength[1] == VARIABLE_LENGTH) { - return processVariableAI(4, (Integer) dataLength[2], rawInformation); - } - return processFixedAI(4, (Integer) dataLength[1], rawInformation); - } - } - - throw NotFoundException.getNotFoundInstance(); - } - - private static String processFixedAI(int aiSize, int fieldSize, String rawInformation) throws NotFoundException{ - if (rawInformation.length() < aiSize) { - throw NotFoundException.getNotFoundInstance(); - } - - String ai = rawInformation.substring(0, aiSize); - - if(rawInformation.length() < aiSize + fieldSize) { - throw NotFoundException.getNotFoundInstance(); - } - - String field = rawInformation.substring(aiSize, aiSize + fieldSize); - String remaining = rawInformation.substring(aiSize + fieldSize); - String result = '(' + ai + ')' + field; - String parsedAI = parseFieldsInGeneralPurpose(remaining); - return parsedAI == null ? result : result + parsedAI; - } - - private static String processVariableAI(int aiSize, int variableFieldSize, String rawInformation) - throws NotFoundException { - String ai = rawInformation.substring(0, aiSize); - int maxSize; - if (rawInformation.length() < aiSize + variableFieldSize) { - maxSize = rawInformation.length(); - } else { - maxSize = aiSize + variableFieldSize; - } - String field = rawInformation.substring(aiSize, maxSize); - String remaining = rawInformation.substring(maxSize); - String result = '(' + ai + ')' + field; - String parsedAI = parseFieldsInGeneralPurpose(remaining); - return parsedAI == null ? result : result + parsedAI; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java deleted file mode 100644 index 916a708e8..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class GeneralAppIdDecoder { - - private final BitArray information; - private final CurrentParsingState current = new CurrentParsingState(); - private final StringBuilder buffer = new StringBuilder(); - - GeneralAppIdDecoder(BitArray information){ - this.information = information; - } - - String decodeAllCodes(StringBuilder buff, int initialPosition) throws NotFoundException, FormatException { - int currentPosition = initialPosition; - String remaining = null; - do{ - DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining); - String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString()); - if (parsedFields != null) { - buff.append(parsedFields); - } - if(info.isRemaining()) { - remaining = String.valueOf(info.getRemainingValue()); - } else { - remaining = null; - } - - if(currentPosition == info.getNewPosition()) {// No step forward! - break; - } - currentPosition = info.getNewPosition(); - }while(true); - - return buff.toString(); - } - - private boolean isStillNumeric(int pos) { - // It's numeric if it still has 7 positions - // and one of the first 4 bits is "1". - if(pos + 7 > this.information.getSize()){ - return pos + 4 <= this.information.getSize(); - } - - for (int i = pos; i < pos + 3; ++i) { - if (this.information.get(i)) { - return true; - } - } - - return this.information.get(pos + 3); - } - - private DecodedNumeric decodeNumeric(int pos) throws FormatException { - if(pos + 7 > this.information.getSize()){ - int numeric = extractNumericValueFromBitArray(pos, 4); - if(numeric == 0) { - return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1); - } - return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1); - } - int numeric = extractNumericValueFromBitArray(pos, 7); - - int digit1 = (numeric - 8) / 11; - int digit2 = (numeric - 8) % 11; - - return new DecodedNumeric(pos + 7, digit1, digit2); - } - - int extractNumericValueFromBitArray(int pos, int bits){ - return extractNumericValueFromBitArray(this.information, pos, bits); - } - - static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) { - int value = 0; - for (int i = 0; i < bits; ++i) { - if (information.get(pos + i)) { - value |= 1 << (bits - i - 1); - } - } - - return value; - } - - DecodedInformation decodeGeneralPurposeField(int pos, String remaining) throws FormatException { - this.buffer.setLength(0); - - if(remaining != null) { - this.buffer.append(remaining); - } - - this.current.setPosition(pos); - - DecodedInformation lastDecoded = parseBlocks(); - if(lastDecoded != null && lastDecoded.isRemaining()) { - return new DecodedInformation(this.current.getPosition(), this.buffer.toString(), lastDecoded.getRemainingValue()); - } - return new DecodedInformation(this.current.getPosition(), this.buffer.toString()); - } - - private DecodedInformation parseBlocks() throws FormatException { - boolean isFinished; - BlockParsedResult result; - do{ - int initialPosition = current.getPosition(); - - if (current.isAlpha()){ - result = parseAlphaBlock(); - isFinished = result.isFinished(); - }else if (current.isIsoIec646()){ - result = parseIsoIec646Block(); - isFinished = result.isFinished(); - }else{ // it must be numeric - result = parseNumericBlock(); - isFinished = result.isFinished(); - } - - boolean positionChanged = initialPosition != current.getPosition(); - if(!positionChanged && !isFinished) { - break; - } - } while (!isFinished); - - return result.getDecodedInformation(); - } - - private BlockParsedResult parseNumericBlock() throws FormatException { - while (isStillNumeric(current.getPosition())) { - DecodedNumeric numeric = decodeNumeric(current.getPosition()); - current.setPosition(numeric.getNewPosition()); - - if(numeric.isFirstDigitFNC1()){ - DecodedInformation information; - if (numeric.isSecondDigitFNC1()) { - information = new DecodedInformation(current.getPosition(), buffer.toString()); - } else { - information = new DecodedInformation(current.getPosition(), buffer.toString(), numeric.getSecondDigit()); - } - return new BlockParsedResult(information, true); - } - buffer.append(numeric.getFirstDigit()); - - if(numeric.isSecondDigitFNC1()){ - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedResult(information, true); - } - buffer.append(numeric.getSecondDigit()); - } - - if (isNumericToAlphaNumericLatch(current.getPosition())) { - current.setAlpha(); - current.incrementPosition(4); - } - return new BlockParsedResult(false); - } - - private BlockParsedResult parseIsoIec646Block() throws FormatException { - while (isStillIsoIec646(current.getPosition())) { - DecodedChar iso = decodeIsoIec646(current.getPosition()); - current.setPosition(iso.getNewPosition()); - - if (iso.isFNC1()) { - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedResult(information, true); - } - buffer.append(iso.getValue()); - } - - if (isAlphaOr646ToNumericLatch(current.getPosition())) { - current.incrementPosition(3); - current.setNumeric(); - } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) { - if (current.getPosition() + 5 < this.information.getSize()) { - current.incrementPosition(5); - } else { - current.setPosition(this.information.getSize()); - } - - current.setAlpha(); - } - return new BlockParsedResult(false); - } - - private BlockParsedResult parseAlphaBlock() { - while (isStillAlpha(current.getPosition())) { - DecodedChar alpha = decodeAlphanumeric(current.getPosition()); - current.setPosition(alpha.getNewPosition()); - - if(alpha.isFNC1()) { - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedResult(information, true); //end of the char block - } - - buffer.append(alpha.getValue()); - } - - if (isAlphaOr646ToNumericLatch(current.getPosition())) { - current.incrementPosition(3); - current.setNumeric(); - } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) { - if (current.getPosition() + 5 < this.information.getSize()) { - current.incrementPosition(5); - } else { - current.setPosition(this.information.getSize()); - } - - current.setIsoIec646(); - } - return new BlockParsedResult(false); - } - - private boolean isStillIsoIec646(int pos) { - if (pos + 5 > this.information.getSize()) { - return false; - } - - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue >= 5 && fiveBitValue < 16) { - return true; - } - - if (pos + 7 > this.information.getSize()) { - return false; - } - - int sevenBitValue = extractNumericValueFromBitArray(pos, 7); - if(sevenBitValue >= 64 && sevenBitValue < 116) { - return true; - } - - if (pos + 8 > this.information.getSize()) { - return false; - } - - int eightBitValue = extractNumericValueFromBitArray(pos, 8); - return eightBitValue >= 232 && eightBitValue < 253; - - } - - private DecodedChar decodeIsoIec646(int pos) throws FormatException { - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue == 15) { - return new DecodedChar(pos + 5, DecodedChar.FNC1); - } - - if (fiveBitValue >= 5 && fiveBitValue < 15) { - return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5)); - } - - int sevenBitValue = extractNumericValueFromBitArray(pos, 7); - - if (sevenBitValue >= 64 && sevenBitValue < 90) { - return new DecodedChar(pos + 7, (char) (sevenBitValue + 1)); - } - - if (sevenBitValue >= 90 && sevenBitValue < 116) { - return new DecodedChar(pos + 7, (char) (sevenBitValue + 7)); - } - - int eightBitValue = extractNumericValueFromBitArray(pos, 8); - char c; - switch (eightBitValue) { - case 232: - c = '!'; - break; - case 233: - c = '"'; - break; - case 234: - c = '%'; - break; - case 235: - c = '&'; - break; - case 236: - c = '\''; - break; - case 237: - c = '('; - break; - case 238: - c = ')'; - break; - case 239: - c = '*'; - break; - case 240: - c = '+'; - break; - case 241: - c = ','; - break; - case 242: - c = '-'; - break; - case 243: - c = '.'; - break; - case 244: - c = '/'; - break; - case 245: - c = ':'; - break; - case 246: - c = ';'; - break; - case 247: - c = '<'; - break; - case 248: - c = '='; - break; - case 249: - c = '>'; - break; - case 250: - c = '?'; - break; - case 251: - c = '_'; - break; - case 252: - c = ' '; - break; - default: - throw FormatException.getFormatInstance(); - } - return new DecodedChar(pos + 8, c); - } - - private boolean isStillAlpha(int pos) { - if(pos + 5 > this.information.getSize()) { - return false; - } - - // We now check if it's a valid 5-bit value (0..9 and FNC1) - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue >= 5 && fiveBitValue < 16) { - return true; - } - - if (pos + 6 > this.information.getSize()) { - return false; - } - - int sixBitValue = extractNumericValueFromBitArray(pos, 6); - return sixBitValue >= 16 && sixBitValue < 63; // 63 not included - } - - private DecodedChar decodeAlphanumeric(int pos) { - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue == 15) { - return new DecodedChar(pos + 5, DecodedChar.FNC1); - } - - if (fiveBitValue >= 5 && fiveBitValue < 15) { - return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5)); - } - - int sixBitValue = extractNumericValueFromBitArray(pos, 6); - - if (sixBitValue >= 32 && sixBitValue < 58) { - return new DecodedChar(pos + 6, (char) (sixBitValue + 33)); - } - - char c; - switch (sixBitValue){ - case 58: - c = '*'; - break; - case 59: - c = ','; - break; - case 60: - c = '-'; - break; - case 61: - c = '.'; - break; - case 62: - c = '/'; - break; - default: - throw new IllegalStateException("Decoding invalid alphanumeric value: " + sixBitValue); - } - return new DecodedChar(pos + 6, c); - } - - private boolean isAlphaTo646ToAlphaLatch(int pos) { - if (pos + 1 > this.information.getSize()) { - return false; - } - - for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) { - if(i == 2){ - if (!this.information.get(pos + 2)) { - return false; - } - } else if (this.information.get(pos + i)) { - return false; - } - } - - return true; - } - - private boolean isAlphaOr646ToNumericLatch(int pos) { - // Next is alphanumeric if there are 3 positions and they are all zeros - if (pos + 3 > this.information.getSize()) { - return false; - } - - for (int i = pos; i < pos + 3; ++i) { - if (this.information.get(i)) { - return false; - } - } - return true; - } - - private boolean isNumericToAlphaNumericLatch(int pos) { - // Next is alphanumeric if there are 4 positions and they are all zeros, or - // if there is a subset of this just before the end of the symbol - if (pos + 1 > this.information.getSize()) { - return false; - } - - for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) { - if (this.information.get(pos + i)) { - return false; - } - } - return true; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Common.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Common.java deleted file mode 100644 index 418f54cde..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Common.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.zxing.pdf417; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author Guenther Grau - */ -public final class PDF417Common { - - public static final int NUMBER_OF_CODEWORDS = 929; - // Maximum Codewords (Data + Error). - public static final int MAX_CODEWORDS_IN_BARCODE = NUMBER_OF_CODEWORDS - 1; - public static final int MIN_ROWS_IN_BARCODE = 3; - public static final int MAX_ROWS_IN_BARCODE = 90; - // One left row indication column + max 30 data columns + one right row indicator column - //public static final int MAX_CODEWORDS_IN_ROW = 32; - public static final int MODULES_IN_CODEWORD = 17; - public static final int MODULES_IN_STOP_PATTERN = 18; - public static final int BARS_IN_MODULE = 8; - - private static final int[] EMPTY_INT_ARRAY = {}; - - private PDF417Common() { - } - - public static int getBitCountSum(int[] moduleBitCount) { - int bitCountSum = 0; - for (int count : moduleBitCount) { - bitCountSum += count; - } - return bitCountSum; - } - - public static int[] toIntArray(Collection list) { - if (list == null || list.isEmpty()) { - return EMPTY_INT_ARRAY; - } - int[] result = new int[list.size()]; - int i = 0; - for (Integer integer : list) { - result[i++] = integer; - } - return result; - } - - /** - * @param symbol encoded symbol to translate to a codeword - * @return the codeword corresponding to the symbol. - */ - public static int getCodeword(int symbol) { - int i = Arrays.binarySearch(SYMBOL_TABLE, symbol & 0x3FFFF); - if (i < 0) { - return -1; - } - return (CODEWORD_TABLE[i] - 1) % NUMBER_OF_CODEWORDS; - } - - /** - * The sorted table of all possible symbols. Extracted from the PDF417 - * specification. The index of a symbol in this table corresponds to the - * index into the codeword table. - */ - public static final int[] SYMBOL_TABLE = { - 0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac, - 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482, - 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e, - 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2, - 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716, - 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6, - 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890, - 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e, - 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4, - 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c, - 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0, - 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c, - 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38, - 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8, - 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98, - 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44, - 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050, - 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee, - 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be, - 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c, - 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6, - 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618, - 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784, - 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e, - 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de, - 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e, - 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70, - 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98, - 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46, - 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8, - 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4, - 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28, - 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e, - 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c, - 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc, - 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0, - 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306, - 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6, - 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8, - 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8, - 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60, - 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08, - 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc, - 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de, - 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc, - 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308, - 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2, - 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8, - 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e, - 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816, - 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce, - 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c, - 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e, - 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e, - 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28, - 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0, - 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c, - 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6, - 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c, - 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46, - 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110, - 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8, - 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330, - 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410, - 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660, - 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0, - 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0, - 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0, - 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98, - 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0, - 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20, - 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e, - 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170, - 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4, - 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320, - 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4, - 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610, - 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e, - 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870, - 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0, - 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e, - 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046, - 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106, - 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8, - 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c, - 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc, - 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0, - 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e, - 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822, - 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884, - 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902, - 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0, - 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20, - 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e, - 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e, - 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0, - 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e, - 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58, - 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8, - 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274, - 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426, - 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc, - 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e, - 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614, - 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e, - 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796, - 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872, - 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c, - 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec, - 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e, - 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2, - 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82, - 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e, - 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32, - 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8, - 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94, - 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086, - 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e, - 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa, - 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390, - 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460, - 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708, - 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc, - 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882, - 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920, - 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e, - 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8, - 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8, - 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84, - 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58, - 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12, - 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae, - 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2, - 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c, - 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260, - 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e, - 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460, - 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704, - 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be, - 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0, - 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40, - 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8, - 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e, - 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c, - 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e, - 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8, - 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660, - 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e, - 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c, - 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4, - 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40, - 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72, - 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c, - 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa, - 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82, - 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34, - 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162, - 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268, - 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326, - 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462, - 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec, - 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc, - 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c, - 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2, - 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e, - 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c, - 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6, - 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc, - 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02, - 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe, - 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58, - 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18, - 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa, - 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e, - 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64, - 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c, - 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de, - 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e, - 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e, - 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386, - 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e, - 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706, - 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8, - 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874, - 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918, - 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c, - 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90, - 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66, - 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04, - 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4, - 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8, - 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58, - 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2, - 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142, - 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214, - 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282, - 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a, - 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428, - 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e, - 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510, - 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc, - 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668, - 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c, - 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6, - 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866, - 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8, - 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986, - 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08, - 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c, - 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e, - 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4, - 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88, - 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c, - 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2, - 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e, - 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca, - 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174, - 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246, - 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2, - 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350, - 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446, - 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc, - 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e, - 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612, - 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a, - 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e, - 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba, - 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934, - 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2, - 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e, - 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, - 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4, - 0x1fba8, 0x1fbb6, 0x1fbda}; - - /** - * This table contains to codewords for all symbols. - */ - private static final int[] CODEWORD_TABLE = { - 2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511, - 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, - 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752, - 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752, - 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651, - 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606, - 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909, - 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830, - 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629, - 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591, - 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466, - 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419, - 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155, - 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384, - 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756, - 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337, - 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653, - 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900, - 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713, - 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654, - 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142, - 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262, - 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052, - 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266, - 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171, - 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313, - 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529, - 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241, - 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414, - 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434, - 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785, - 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353, - 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689, - 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573, - 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539, - 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669, - 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133, - 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971, - 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78, - 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100, - 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64, - 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867, - 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989, - 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359, - 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308, - 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089, - 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279, - 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205, - 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232, - 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590, - 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262, - 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549, - 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480, - 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466, - 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427, - 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388, - 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751, - 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592, - 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569, - 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695, - 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818, - 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648, - 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892, - 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632, - 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486, - 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366, - 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412, - 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684, - 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527, - 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759, - 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342, - 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195, - 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997, - 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183, - 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268, - 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395, - 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779, - 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688, - 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718, - 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138, - 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108, - 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98, - 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920, - 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9, - 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975, - 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339, - 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090, - 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033, - 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284, - 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569, - 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467, - 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379, - 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579, - 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688, - 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636, - 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524, - 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361, - 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672, - 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849, - 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343, - 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210, - 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157, - 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458, - 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460, - 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919, - 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127, - 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060, - 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008, - 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952, - 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350, - 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086, - 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231, - 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499, - 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798, - 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546, - 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670, - 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504, - 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394, - 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281, - 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150, - 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582, - 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709, - 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094, - 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007, - 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940, - 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897, - 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185, - 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513, - 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706, - 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204, - 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207, - 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487, - 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062, - 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951, - 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275, - 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548, - 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208, - 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, - 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270, - 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700}; -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java deleted file mode 100644 index c0eeb288b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.multi.MultipleBarcodeReader; -import com.google.zxing.pdf417.decoder.PDF417ScanningDecoder; -import com.google.zxing.pdf417.detector.Detector; -import com.google.zxing.pdf417.detector.PDF417DetectorResult; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * This implementation can detect and decode PDF417 codes in an image. - * - * @author Guenther Grau - */ -public final class PDF417Reader implements Reader, MultipleBarcodeReader { - - /** - * Locates and decodes a PDF417 code in an image. - * - * @return a String representing the content encoded by the PDF417 code - * @throws NotFoundException if a PDF417 code cannot be found, - * @throws FormatException if a PDF417 cannot be decoded - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, FormatException, ChecksumException { - return decode(image, null); - } - - @Override - public Result decode(BinaryBitmap image, Map hints) throws NotFoundException, FormatException, - ChecksumException { - Result[] result = decode(image, hints, false); - if (result == null || result.length == 0 || result[0] == null) { - throw NotFoundException.getNotFoundInstance(); - } - return result[0]; - } - - @Override - public Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException { - return decodeMultiple(image, null); - } - - @Override - public Result[] decodeMultiple(BinaryBitmap image, Map hints) throws NotFoundException { - try { - return decode(image, hints, true); - } catch (FormatException | ChecksumException ignored) { - throw NotFoundException.getNotFoundInstance(); - } - } - - private static Result[] decode(BinaryBitmap image, Map hints, boolean multiple) - throws NotFoundException, FormatException, ChecksumException { - List results = new ArrayList<>(); - PDF417DetectorResult detectorResult = Detector.detect(image, hints, multiple); - for (ResultPoint[] points : detectorResult.getPoints()) { - DecoderResult decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], - points[6], points[7], getMinCodewordWidth(points), getMaxCodewordWidth(points)); - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.PDF_417); - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel()); - PDF417ResultMetadata pdf417ResultMetadata = (PDF417ResultMetadata) decoderResult.getOther(); - if (pdf417ResultMetadata != null) { - result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata); - } - results.add(result); - } - return results.toArray(new Result[results.size()]); - } - - private static int getMaxWidth(ResultPoint p1, ResultPoint p2) { - if (p1 == null || p2 == null) { - return 0; - } - return (int) Math.abs(p1.getX() - p2.getX()); - } - - private static int getMinWidth(ResultPoint p1, ResultPoint p2) { - if (p1 == null || p2 == null) { - return Integer.MAX_VALUE; - } - return (int) Math.abs(p1.getX() - p2.getX()); - } - - private static int getMaxCodewordWidth(ResultPoint[] p) { - return Math.max( - Math.max(getMaxWidth(p[0], p[4]), getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / - PDF417Common.MODULES_IN_STOP_PATTERN), - Math.max(getMaxWidth(p[1], p[5]), getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / - PDF417Common.MODULES_IN_STOP_PATTERN)); - } - - private static int getMinCodewordWidth(ResultPoint[] p) { - return Math.min( - Math.min(getMinWidth(p[0], p[4]), getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / - PDF417Common.MODULES_IN_STOP_PATTERN), - Math.min(getMinWidth(p[1], p[5]), getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / - PDF417Common.MODULES_IN_STOP_PATTERN)); - } - - @Override - public void reset() { - // nothing needs to be reset - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java deleted file mode 100644 index 2e1c4ee26..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417; - -/** - * @author Guenther Grau - */ -public final class PDF417ResultMetadata { - - private int segmentIndex; - private String fileId; - private int[] optionalData; - private boolean lastSegment; - - public int getSegmentIndex() { - return segmentIndex; - } - - public void setSegmentIndex(int segmentIndex) { - this.segmentIndex = segmentIndex; - } - - public String getFileId() { - return fileId; - } - - public void setFileId(String fileId) { - this.fileId = fileId; - } - - public int[] getOptionalData() { - return optionalData; - } - - public void setOptionalData(int[] optionalData) { - this.optionalData = optionalData; - } - - public boolean isLastSegment() { - return lastSegment; - } - - public void setLastSegment(boolean lastSegment) { - this.lastSegment = lastSegment; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java deleted file mode 100644 index cb37884a6..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.pdf417.encoder.Compaction; -import com.google.zxing.pdf417.encoder.Dimensions; -import com.google.zxing.pdf417.encoder.PDF417; - -import java.nio.charset.Charset; -import java.util.Map; - -/** - * @author Jacob Haynes - * @author qwandor@google.com (Andrew Walbran) - */ -public final class PDF417Writer implements Writer { - - /** - * default white space (margin) around the code - */ - static final int WHITE_SPACE = 30; - - /** - * default error correction level - */ - static final int DEFAULT_ERROR_CORRECTION_LEVEL = 2; - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - if (format != BarcodeFormat.PDF_417) { - throw new IllegalArgumentException("Can only encode PDF_417, but got " + format); - } - - PDF417 encoder = new PDF417(); - int margin = WHITE_SPACE; - int errorCorrectionLevel = DEFAULT_ERROR_CORRECTION_LEVEL; - - if (hints != null) { - if (hints.containsKey(EncodeHintType.PDF417_COMPACT)) { - encoder.setCompact((Boolean) hints.get(EncodeHintType.PDF417_COMPACT)); - } - if (hints.containsKey(EncodeHintType.PDF417_COMPACTION)) { - encoder.setCompaction((Compaction) hints.get(EncodeHintType.PDF417_COMPACTION)); - } - if (hints.containsKey(EncodeHintType.PDF417_DIMENSIONS)) { - Dimensions dimensions = (Dimensions) hints.get(EncodeHintType.PDF417_DIMENSIONS); - encoder.setDimensions(dimensions.getMaxCols(), - dimensions.getMinCols(), - dimensions.getMaxRows(), - dimensions.getMinRows()); - } - if (hints.containsKey(EncodeHintType.MARGIN)) { - margin = ((Number) hints.get(EncodeHintType.MARGIN)).intValue(); - } - if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) { - errorCorrectionLevel = ((Number) hints.get(EncodeHintType.ERROR_CORRECTION)).intValue(); - } - if (hints.containsKey(EncodeHintType.CHARACTER_SET)) { - String encoding = (String) hints.get(EncodeHintType.CHARACTER_SET); - encoder.setEncoding(Charset.forName(encoding)); - } - } - - return bitMatrixFromEncoder(encoder, contents, errorCorrectionLevel, width, height, margin); - } - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height) throws WriterException { - return encode(contents, format, width, height, null); - } - - /** - * Takes encoder, accounts for width/height, and retrieves bit matrix - */ - private static BitMatrix bitMatrixFromEncoder(PDF417 encoder, - String contents, - int errorCorrectionLevel, - int width, - int height, - int margin) throws WriterException { - encoder.generateBarcodeLogic(contents, errorCorrectionLevel); - - int aspectRatio = 4; - byte[][] originalScale = encoder.getBarcodeMatrix().getScaledMatrix(1, aspectRatio); - boolean rotated = false; - if ((height > width) ^ (originalScale[0].length < originalScale.length)) { - originalScale = rotateArray(originalScale); - rotated = true; - } - - int scaleX = width / originalScale[0].length; - int scaleY = height / originalScale.length; - - int scale; - if (scaleX < scaleY) { - scale = scaleX; - } else { - scale = scaleY; - } - - if (scale > 1) { - byte[][] scaledMatrix = - encoder.getBarcodeMatrix().getScaledMatrix(scale, scale * aspectRatio); - if (rotated) { - scaledMatrix = rotateArray(scaledMatrix); - } - return bitMatrixFrombitArray(scaledMatrix, margin); - } - return bitMatrixFrombitArray(originalScale, margin); - } - - /** - * This takes an array holding the values of the PDF 417 - * - * @param input a byte array of information with 0 is black, and 1 is white - * @param margin border around the barcode - * @return BitMatrix of the input - */ - private static BitMatrix bitMatrixFrombitArray(byte[][] input, int margin) { - // Creates the bitmatrix with extra space for whitespace - BitMatrix output = new BitMatrix(input[0].length + 2 * margin, input.length + 2 * margin); - output.clear(); - for (int y = 0, yOutput = output.getHeight() - margin - 1; y < input.length; y++, yOutput--) { - for (int x = 0; x < input[0].length; x++) { - // Zero is white in the bytematrix - if (input[y][x] == 1) { - output.set(x + margin, yOutput); - } - } - } - return output; - } - - /** - * Takes and rotates the it 90 degrees - */ - private static byte[][] rotateArray(byte[][] bitarray) { - byte[][] temp = new byte[bitarray[0].length][bitarray.length]; - for (int ii = 0; ii < bitarray.length; ii++) { - // This makes the direction consistent on screen when rotating the - // screen; - int inverseii = bitarray.length - ii - 1; - for (int jj = 0; jj < bitarray[0].length; jj++) { - temp[jj][inverseii] = bitarray[ii][jj]; - } - } - return temp; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java deleted file mode 100644 index 9c1acbf7b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -/** - * @author Guenther Grau - */ -final class BarcodeMetadata { - - private final int columnCount; - private final int errorCorrectionLevel; - private final int rowCountUpperPart; - private final int rowCountLowerPart; - private final int rowCount; - - BarcodeMetadata(int columnCount, int rowCountUpperPart, int rowCountLowerPart, int errorCorrectionLevel) { - this.columnCount = columnCount; - this.errorCorrectionLevel = errorCorrectionLevel; - this.rowCountUpperPart = rowCountUpperPart; - this.rowCountLowerPart = rowCountLowerPart; - this.rowCount = rowCountUpperPart + rowCountLowerPart; - } - - int getColumnCount() { - return columnCount; - } - - int getErrorCorrectionLevel() { - return errorCorrectionLevel; - } - - int getRowCount() { - return rowCount; - } - - int getRowCountUpperPart() { - return rowCountUpperPart; - } - - int getRowCountLowerPart() { - return rowCountLowerPart; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java deleted file mode 100644 index 79a8d23af..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.pdf417.PDF417Common; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -/** - * @author Guenther Grau - */ -final class BarcodeValue { - private final Map values = new HashMap<>(); - - /** - * Add an occurrence of a value - */ - void setValue(int value) { - Integer confidence = values.get(value); - if (confidence == null) { - confidence = 0; - } - confidence++; - values.put(value, confidence); - } - - /** - * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence. - * @return an array of int, containing the values with the highest occurrence, or null, if no value was set - */ - int[] getValue() { - int maxConfidence = -1; - Collection result = new ArrayList<>(); - for (Entry entry : values.entrySet()) { - if (entry.getValue() > maxConfidence) { - maxConfidence = entry.getValue(); - result.clear(); - result.add(entry.getKey()); - } else if (entry.getValue() == maxConfidence) { - result.add(entry.getKey()); - } - } - return PDF417Common.toIntArray(result); - } - - public Integer getConfidence(int value) { - return values.get(value); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java deleted file mode 100644 index b77314560..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; - -/** - * @author Guenther Grau - */ -final class BoundingBox { - - private BitMatrix image; - private ResultPoint topLeft; - private ResultPoint bottomLeft; - private ResultPoint topRight; - private ResultPoint bottomRight; - private int minX; - private int maxX; - private int minY; - private int maxY; - - BoundingBox(BitMatrix image, - ResultPoint topLeft, - ResultPoint bottomLeft, - ResultPoint topRight, - ResultPoint bottomRight) throws NotFoundException { - if ((topLeft == null && topRight == null) || - (bottomLeft == null && bottomRight == null) || - (topLeft != null && bottomLeft == null) || - (topRight != null && bottomRight == null)) { - throw NotFoundException.getNotFoundInstance(); - } - init(image, topLeft, bottomLeft, topRight, bottomRight); - } - - BoundingBox(BoundingBox boundingBox) { - init(boundingBox.image, boundingBox.topLeft, boundingBox.bottomLeft, boundingBox.topRight, boundingBox.bottomRight); - } - - private void init(BitMatrix image, - ResultPoint topLeft, - ResultPoint bottomLeft, - ResultPoint topRight, - ResultPoint bottomRight) { - this.image = image; - this.topLeft = topLeft; - this.bottomLeft = bottomLeft; - this.topRight = topRight; - this.bottomRight = bottomRight; - calculateMinMaxValues(); - } - - static BoundingBox merge(BoundingBox leftBox, BoundingBox rightBox) throws NotFoundException { - if (leftBox == null) { - return rightBox; - } - if (rightBox == null) { - return leftBox; - } - return new BoundingBox(leftBox.image, leftBox.topLeft, leftBox.bottomLeft, rightBox.topRight, rightBox.bottomRight); - } - - BoundingBox addMissingRows(int missingStartRows, int missingEndRows, boolean isLeft) throws NotFoundException { - ResultPoint newTopLeft = topLeft; - ResultPoint newBottomLeft = bottomLeft; - ResultPoint newTopRight = topRight; - ResultPoint newBottomRight = bottomRight; - - if (missingStartRows > 0) { - ResultPoint top = isLeft ? topLeft : topRight; - int newMinY = (int) top.getY() - missingStartRows; - if (newMinY < 0) { - newMinY = 0; - } - ResultPoint newTop = new ResultPoint(top.getX(), newMinY); - if (isLeft) { - newTopLeft = newTop; - } else { - newTopRight = newTop; - } - } - - if (missingEndRows > 0) { - ResultPoint bottom = isLeft ? bottomLeft : bottomRight; - int newMaxY = (int) bottom.getY() + missingEndRows; - if (newMaxY >= image.getHeight()) { - newMaxY = image.getHeight() - 1; - } - ResultPoint newBottom = new ResultPoint(bottom.getX(), newMaxY); - if (isLeft) { - newBottomLeft = newBottom; - } else { - newBottomRight = newBottom; - } - } - - calculateMinMaxValues(); - return new BoundingBox(image, newTopLeft, newBottomLeft, newTopRight, newBottomRight); - } - - private void calculateMinMaxValues() { - if (topLeft == null) { - topLeft = new ResultPoint(0, topRight.getY()); - bottomLeft = new ResultPoint(0, bottomRight.getY()); - } else if (topRight == null) { - topRight = new ResultPoint(image.getWidth() - 1, topLeft.getY()); - bottomRight = new ResultPoint(image.getWidth() - 1, bottomLeft.getY()); - } - - minX = (int) Math.min(topLeft.getX(), bottomLeft.getX()); - maxX = (int) Math.max(topRight.getX(), bottomRight.getX()); - minY = (int) Math.min(topLeft.getY(), topRight.getY()); - maxY = (int) Math.max(bottomLeft.getY(), bottomRight.getY()); - } - - /* - void setTopRight(ResultPoint topRight) { - this.topRight = topRight; - calculateMinMaxValues(); - } - - void setBottomRight(ResultPoint bottomRight) { - this.bottomRight = bottomRight; - calculateMinMaxValues(); - } - */ - - int getMinX() { - return minX; - } - - int getMaxX() { - return maxX; - } - - int getMinY() { - return minY; - } - - int getMaxY() { - return maxY; - } - - ResultPoint getTopLeft() { - return topLeft; - } - - ResultPoint getTopRight() { - return topRight; - } - - ResultPoint getBottomLeft() { - return bottomLeft; - } - - ResultPoint getBottomRight() { - return bottomRight; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java deleted file mode 100644 index bb5477da3..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -/** - * @author Guenther Grau - */ -final class Codeword { - - private static final int BARCODE_ROW_UNKNOWN = -1; - - private final int startX; - private final int endX; - private final int bucket; - private final int value; - private int rowNumber = BARCODE_ROW_UNKNOWN; - - Codeword(int startX, int endX, int bucket, int value) { - this.startX = startX; - this.endX = endX; - this.bucket = bucket; - this.value = value; - } - - boolean hasValidRowNumber() { - return isValidRowNumber(rowNumber); - } - - boolean isValidRowNumber(int rowNumber) { - return rowNumber != BARCODE_ROW_UNKNOWN && bucket == (rowNumber % 3) * 3; - } - - void setRowNumberAsRowIndicatorColumn() { - rowNumber = (value / 30) * 3 + bucket / 3; - } - - int getWidth() { - return endX - startX; - } - - int getStartX() { - return startX; - } - - int getEndX() { - return endX; - } - - int getBucket() { - return bucket; - } - - int getValue() { - return value; - } - - int getRowNumber() { - return rowNumber; - } - - void setRowNumber(int rowNumber) { - this.rowNumber = rowNumber; - } - - @Override - public String toString() { - return rowNumber + "|" + value; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java deleted file mode 100644 index 876b324af..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.common.CharacterSetECI; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.pdf417.PDF417ResultMetadata; - -import java.io.ByteArrayOutputStream; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.util.Arrays; - -/** - *

    This class contains the methods for decoding the PDF417 codewords.

    - * - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author Guenther Grau - */ -final class DecodedBitStreamParser { - - private enum Mode { - ALPHA, - LOWER, - MIXED, - PUNCT, - ALPHA_SHIFT, - PUNCT_SHIFT - } - - private static final int TEXT_COMPACTION_MODE_LATCH = 900; - private static final int BYTE_COMPACTION_MODE_LATCH = 901; - private static final int NUMERIC_COMPACTION_MODE_LATCH = 902; - private static final int BYTE_COMPACTION_MODE_LATCH_6 = 924; - private static final int ECI_USER_DEFINED = 925; - private static final int ECI_GENERAL_PURPOSE = 926; - private static final int ECI_CHARSET = 927; - private static final int BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928; - private static final int BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923; - private static final int MACRO_PDF417_TERMINATOR = 922; - private static final int MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913; - private static final int MAX_NUMERIC_CODEWORDS = 15; - - private static final int PL = 25; - private static final int LL = 27; - private static final int AS = 27; - private static final int ML = 28; - private static final int AL = 28; - private static final int PS = 29; - private static final int PAL = 29; - - private static final char[] PUNCT_CHARS = { - ';', '<', '>', '@', '[', '\\', ']', '_', '`', '~', '!', - '\r', '\t', ',', ':', '\n', '-', '.', '$', '/', '"', '|', '*', - '(', ')', '?', '{', '}', '\''}; - - private static final char[] MIXED_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', - '\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*', - '=', '^'}; - - private static final Charset DEFAULT_ENCODING = Charset.forName("ISO-8859-1"); - - /** - * Table containing values for the exponent of 900. - * This is used in the numeric compaction decode algorithm. - */ - private static final BigInteger[] EXP900; - static { - EXP900 = new BigInteger[16]; - EXP900[0] = BigInteger.ONE; - BigInteger nineHundred = BigInteger.valueOf(900); - EXP900[1] = nineHundred; - for (int i = 2; i < EXP900.length; i++) { - EXP900[i] = EXP900[i - 1].multiply(nineHundred); - } - } - - private static final int NUMBER_OF_SEQUENCE_CODEWORDS = 2; - - private DecodedBitStreamParser() { - } - - static DecoderResult decode(int[] codewords, String ecLevel) throws FormatException { - StringBuilder result = new StringBuilder(codewords.length * 2); - Charset encoding = DEFAULT_ENCODING; - // Get compaction mode - int codeIndex = 1; - int code = codewords[codeIndex++]; - PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - while (codeIndex < codewords[0]) { - switch (code) { - case TEXT_COMPACTION_MODE_LATCH: - codeIndex = textCompaction(codewords, codeIndex, result); - break; - case BYTE_COMPACTION_MODE_LATCH: - case BYTE_COMPACTION_MODE_LATCH_6: - codeIndex = byteCompaction(code, codewords, encoding, codeIndex, result); - break; - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.append((char) codewords[codeIndex++]); - break; - case NUMERIC_COMPACTION_MODE_LATCH: - codeIndex = numericCompaction(codewords, codeIndex, result); - break; - case ECI_CHARSET: - CharacterSetECI charsetECI = - CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); - encoding = Charset.forName(charsetECI.name()); - break; - case ECI_GENERAL_PURPOSE: - // Can't do anything with generic ECI; skip its 2 characters - codeIndex += 2; - break; - case ECI_USER_DEFINED: - // Can't do anything with user ECI; skip its 1 character - codeIndex ++; - break; - case BEGIN_MACRO_PDF417_CONTROL_BLOCK: - codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata); - break; - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - case MACRO_PDF417_TERMINATOR: - // Should not see these outside a macro block - throw FormatException.getFormatInstance(); - default: - // Default to text compaction. During testing numerous barcodes - // appeared to be missing the starting mode. In these cases defaulting - // to text compaction seems to work. - codeIndex--; - codeIndex = textCompaction(codewords, codeIndex, result); - break; - } - if (codeIndex < codewords.length) { - code = codewords[codeIndex++]; - } else { - throw FormatException.getFormatInstance(); - } - } - if (result.length() == 0) { - throw FormatException.getFormatInstance(); - } - DecoderResult decoderResult = new DecoderResult(null, result.toString(), null, ecLevel); - decoderResult.setOther(resultMetadata); - return decoderResult; - } - - private static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) - throws FormatException { - if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) { - // we must have at least two bytes left for the segment index - throw FormatException.getFormatInstance(); - } - int[] segmentIndexArray = new int[NUMBER_OF_SEQUENCE_CODEWORDS]; - for (int i = 0; i < NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) { - segmentIndexArray[i] = codewords[codeIndex]; - } - resultMetadata.setSegmentIndex(Integer.parseInt(decodeBase900toBase10(segmentIndexArray, - NUMBER_OF_SEQUENCE_CODEWORDS))); - - StringBuilder fileId = new StringBuilder(); - codeIndex = textCompaction(codewords, codeIndex, fileId); - resultMetadata.setFileId(fileId.toString()); - - if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) { - codeIndex++; - int[] additionalOptionCodeWords = new int[codewords[0] - codeIndex]; - int additionalOptionCodeWordsIndex = 0; - - boolean end = false; - while ((codeIndex < codewords[0]) && !end) { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) { - additionalOptionCodeWords[additionalOptionCodeWordsIndex++] = code; - } else { - switch (code) { - case MACRO_PDF417_TERMINATOR: - resultMetadata.setLastSegment(true); - codeIndex++; - end = true; - break; - default: - throw FormatException.getFormatInstance(); - } - } - } - - resultMetadata.setOptionalData(Arrays.copyOf(additionalOptionCodeWords, additionalOptionCodeWordsIndex)); - } else if (codewords[codeIndex] == MACRO_PDF417_TERMINATOR) { - resultMetadata.setLastSegment(true); - codeIndex++; - } - - return codeIndex; - } - - /** - * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be - * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as - * well as selected control characters. - * - * @param codewords The array of codewords (data + error) - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - private static int textCompaction(int[] codewords, int codeIndex, StringBuilder result) { - // 2 character per codeword - int[] textCompactionData = new int[(codewords[0] - codeIndex) * 2]; - // Used to hold the byte compaction value if there is a mode shift - int[] byteCompactionData = new int[(codewords[0] - codeIndex) * 2]; - - int index = 0; - boolean end = false; - while ((codeIndex < codewords[0]) && !end) { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) { - textCompactionData[index] = code / 30; - textCompactionData[index + 1] = code % 30; - index += 2; - } else { - switch (code) { - case TEXT_COMPACTION_MODE_LATCH: - // reinitialize text compaction mode to alpha sub mode - textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH; - break; - case BYTE_COMPACTION_MODE_LATCH: - case BYTE_COMPACTION_MODE_LATCH_6: - case NUMERIC_COMPACTION_MODE_LATCH: - case BEGIN_MACRO_PDF417_CONTROL_BLOCK: - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - case MACRO_PDF417_TERMINATOR: - codeIndex--; - end = true; - break; - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - // The Mode Shift codeword 913 shall cause a temporary - // switch from Text Compaction mode to Byte Compaction mode. - // This switch shall be in effect for only the next codeword, - // after which the mode shall revert to the prevailing sub-mode - // of the Text Compaction mode. Codeword 913 is only available - // in Text Compaction mode; its use is described in 5.4.2.4. - textCompactionData[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE; - code = codewords[codeIndex++]; - byteCompactionData[index] = code; - index++; - break; - } - } - } - decodeTextCompaction(textCompactionData, byteCompactionData, index, result); - return codeIndex; - } - - /** - * The Text Compaction mode includes all the printable ASCII characters - * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab - * (ASCII value 9), LF or line feed (ASCII value 10), and CR or carriage - * return (ASCII value 13). The Text Compaction mode also includes various latch - * and shift characters which are used exclusively within the mode. The Text - * Compaction mode encodes up to 2 characters per codeword. The compaction rules - * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode - * switches are defined in 5.4.2.3. - * - * @param textCompactionData The text compaction data. - * @param byteCompactionData The byte compaction data if there - * was a mode shift. - * @param length The size of the text compaction and byte compaction data. - * @param result The decoded data is appended to the result. - */ - private static void decodeTextCompaction(int[] textCompactionData, - int[] byteCompactionData, - int length, - StringBuilder result) { - // Beginning from an initial state of the Alpha sub-mode - // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text - // Compaction mode Alpha sub-mode (uppercase alphabetic). A latch codeword from another mode to the Text - // Compaction mode shall always switch to the Text Compaction Alpha sub-mode. - Mode subMode = Mode.ALPHA; - Mode priorToShiftMode = Mode.ALPHA; - int i = 0; - while (i < length) { - int subModeCh = textCompactionData[i]; - char ch = 0; - switch (subMode) { - case ALPHA: - // Alpha (uppercase alphabetic) - if (subModeCh < 26) { - // Upper case Alpha Character - ch = (char) ('A' + subModeCh); - } else { - if (subModeCh == 26) { - ch = ' '; - } else if (subModeCh == LL) { - subMode = Mode.LOWER; - } else if (subModeCh == ML) { - subMode = Mode.MIXED; - } else if (subModeCh == PS) { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) { - result.append((char) byteCompactionData[i]); - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - - case LOWER: - // Lower (lowercase alphabetic) - if (subModeCh < 26) { - ch = (char) ('a' + subModeCh); - } else { - if (subModeCh == 26) { - ch = ' '; - } else if (subModeCh == AS) { - // Shift to alpha - priorToShiftMode = subMode; - subMode = Mode.ALPHA_SHIFT; - } else if (subModeCh == ML) { - subMode = Mode.MIXED; - } else if (subModeCh == PS) { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) { - // TODO Does this need to use the current character encoding? See other occurrences below - result.append((char) byteCompactionData[i]); - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - - case MIXED: - // Mixed (numeric and some punctuation) - if (subModeCh < PL) { - ch = MIXED_CHARS[subModeCh]; - } else { - if (subModeCh == PL) { - subMode = Mode.PUNCT; - } else if (subModeCh == 26) { - ch = ' '; - } else if (subModeCh == LL) { - subMode = Mode.LOWER; - } else if (subModeCh == AL) { - subMode = Mode.ALPHA; - } else if (subModeCh == PS) { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) { - result.append((char) byteCompactionData[i]); - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - - case PUNCT: - // Punctuation - if (subModeCh < PAL) { - ch = PUNCT_CHARS[subModeCh]; - } else { - if (subModeCh == PAL) { - subMode = Mode.ALPHA; - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) { - result.append((char) byteCompactionData[i]); - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - - case ALPHA_SHIFT: - // Restore sub-mode - subMode = priorToShiftMode; - if (subModeCh < 26) { - ch = (char) ('A' + subModeCh); - } else { - if (subModeCh == 26) { - ch = ' '; - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - - case PUNCT_SHIFT: - // Restore sub-mode - subMode = priorToShiftMode; - if (subModeCh < PAL) { - ch = PUNCT_CHARS[subModeCh]; - } else { - if (subModeCh == PAL) { - subMode = Mode.ALPHA; - } else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) { - // PS before Shift-to-Byte is used as a padding character, - // see 5.4.2.4 of the specification - result.append((char) byteCompactionData[i]); - } else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) { - subMode = Mode.ALPHA; - } - } - break; - } - if (ch != 0) { - // Append decoded character to result - result.append(ch); - } - i++; - } - } - - /** - * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded. - * This includes all ASCII characters value 0 to 127 inclusive and provides for international - * character set support. - * - * @param mode The byte compaction mode i.e. 901 or 924 - * @param codewords The array of codewords (data + error) - * @param encoding Currently active character encoding - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - private static int byteCompaction(int mode, - int[] codewords, - Charset encoding, - int codeIndex, - StringBuilder result) { - ByteArrayOutputStream decodedBytes = new ByteArrayOutputStream(); - if (mode == BYTE_COMPACTION_MODE_LATCH) { - // Total number of Byte Compaction characters to be encoded - // is not a multiple of 6 - int count = 0; - long value = 0; - int[] byteCompactedCodewords = new int[6]; - boolean end = false; - int nextCode = codewords[codeIndex++]; - while ((codeIndex < codewords[0]) && !end) { - byteCompactedCodewords[count++] = nextCode; - // Base 900 - value = 900 * value + nextCode; - nextCode = codewords[codeIndex++]; - // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH - if (nextCode == TEXT_COMPACTION_MODE_LATCH || - nextCode == BYTE_COMPACTION_MODE_LATCH || - nextCode == NUMERIC_COMPACTION_MODE_LATCH || - nextCode == BYTE_COMPACTION_MODE_LATCH_6 || - nextCode == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - nextCode == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - nextCode == MACRO_PDF417_TERMINATOR) { - codeIndex--; - end = true; - } else { - if ((count % 5 == 0) && (count > 0)) { - // Decode every 5 codewords - // Convert to Base 256 - for (int j = 0; j < 6; ++j) { - decodedBytes.write((byte) (value >> (8 * (5 - j)))); - } - value = 0; - count = 0; - } - } - } - - // if the end of all codewords is reached the last codeword needs to be added - if (codeIndex == codewords[0] && nextCode < TEXT_COMPACTION_MODE_LATCH) { - byteCompactedCodewords[count++] = nextCode; - } - - // If Byte Compaction mode is invoked with codeword 901, - // the last group of codewords is interpreted directly - // as one byte per codeword, without compaction. - for (int i = 0; i < count; i++) { - decodedBytes.write((byte) byteCompactedCodewords[i]); - } - - } else if (mode == BYTE_COMPACTION_MODE_LATCH_6) { - // Total number of Byte Compaction characters to be encoded - // is an integer multiple of 6 - int count = 0; - long value = 0; - boolean end = false; - while (codeIndex < codewords[0] && !end) { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) { - count++; - // Base 900 - value = 900 * value + code; - } else { - if (code == TEXT_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH || - code == NUMERIC_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH_6 || - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - code == MACRO_PDF417_TERMINATOR) { - codeIndex--; - end = true; - } - } - if ((count % 5 == 0) && (count > 0)) { - // Decode every 5 codewords - // Convert to Base 256 - for (int j = 0; j < 6; ++j) { - decodedBytes.write((byte) (value >> (8 * (5 - j)))); - } - value = 0; - count = 0; - } - } - } - result.append(new String(decodedBytes.toByteArray(), encoding)); - return codeIndex; - } - - /** - * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings. - * - * @param codewords The array of codewords (data + error) - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - private static int numericCompaction(int[] codewords, int codeIndex, StringBuilder result) throws FormatException { - int count = 0; - boolean end = false; - - int[] numericCodewords = new int[MAX_NUMERIC_CODEWORDS]; - - while (codeIndex < codewords[0] && !end) { - int code = codewords[codeIndex++]; - if (codeIndex == codewords[0]) { - end = true; - } - if (code < TEXT_COMPACTION_MODE_LATCH) { - numericCodewords[count] = code; - count++; - } else { - if (code == TEXT_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH_6 || - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - code == MACRO_PDF417_TERMINATOR) { - codeIndex--; - end = true; - } - } - if (count % MAX_NUMERIC_CODEWORDS == 0 || - code == NUMERIC_COMPACTION_MODE_LATCH || - end) { - // Re-invoking Numeric Compaction mode (by using codeword 902 - // while in Numeric Compaction mode) serves to terminate the - // current Numeric Compaction mode grouping as described in 5.4.4.2, - // and then to start a new one grouping. - if (count > 0) { - String s = decodeBase900toBase10(numericCodewords, count); - result.append(s); - count = 0; - } - } - } - return codeIndex; - } - - /** - * Convert a list of Numeric Compacted codewords from Base 900 to Base 10. - * - * @param codewords The array of codewords - * @param count The number of codewords - * @return The decoded string representing the Numeric data. - */ - /* - EXAMPLE - Encode the fifteen digit numeric string 000213298174000 - Prefix the numeric string with a 1 and set the initial value of - t = 1 000 213 298 174 000 - Calculate codeword 0 - d0 = 1 000 213 298 174 000 mod 900 = 200 - - t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082 - Calculate codeword 1 - d1 = 1 111 348 109 082 mod 900 = 282 - - t = 1 111 348 109 082 div 900 = 1 234 831 232 - Calculate codeword 2 - d2 = 1 234 831 232 mod 900 = 632 - - t = 1 234 831 232 div 900 = 1 372 034 - Calculate codeword 3 - d3 = 1 372 034 mod 900 = 434 - - t = 1 372 034 div 900 = 1 524 - Calculate codeword 4 - d4 = 1 524 mod 900 = 624 - - t = 1 524 div 900 = 1 - Calculate codeword 5 - d5 = 1 mod 900 = 1 - t = 1 div 900 = 0 - Codeword sequence is: 1, 624, 434, 632, 282, 200 - - Decode the above codewords involves - 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 + - 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000 - - Remove leading 1 => Result is 000213298174000 - */ - private static String decodeBase900toBase10(int[] codewords, int count) throws FormatException { - BigInteger result = BigInteger.ZERO; - for (int i = 0; i < count; i++) { - result = result.add(EXP900[count - i - 1].multiply(BigInteger.valueOf(codewords[i]))); - } - String resultString = result.toString(); - if (resultString.charAt(0) != '1') { - throw FormatException.getFormatInstance(); - } - return resultString.substring(1); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java deleted file mode 100644 index 74892ee54..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.pdf417.PDF417Common; - -import java.util.Formatter; - -/** - * @author Guenther Grau - */ -final class DetectionResult { - - private static final int ADJUST_ROW_NUMBER_SKIP = 2; - - private final BarcodeMetadata barcodeMetadata; - private final DetectionResultColumn[] detectionResultColumns; - private BoundingBox boundingBox; - private final int barcodeColumnCount; - - DetectionResult(BarcodeMetadata barcodeMetadata, BoundingBox boundingBox) { - this.barcodeMetadata = barcodeMetadata; - this.barcodeColumnCount = barcodeMetadata.getColumnCount(); - this.boundingBox = boundingBox; - detectionResultColumns = new DetectionResultColumn[barcodeColumnCount + 2]; - } - - DetectionResultColumn[] getDetectionResultColumns() { - adjustIndicatorColumnRowNumbers(detectionResultColumns[0]); - adjustIndicatorColumnRowNumbers(detectionResultColumns[barcodeColumnCount + 1]); - int unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE; - int previousUnadjustedCount; - do { - previousUnadjustedCount = unadjustedCodewordCount; - unadjustedCodewordCount = adjustRowNumbers(); - } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount); - return detectionResultColumns; - } - - private void adjustIndicatorColumnRowNumbers(DetectionResultColumn detectionResultColumn) { - if (detectionResultColumn != null) { - ((DetectionResultRowIndicatorColumn) detectionResultColumn) - .adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata); - } - } - - // TODO ensure that no detected codewords with unknown row number are left - // we should be able to estimate the row height and use it as a hint for the row number - // we should also fill the rows top to bottom and bottom to top - /** - * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords - * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers - */ - private int adjustRowNumbers() { - int unadjustedCount = adjustRowNumbersByRow(); - if (unadjustedCount == 0) { - return 0; - } - for (int barcodeColumn = 1; barcodeColumn < barcodeColumnCount + 1; barcodeColumn++) { - Codeword[] codewords = detectionResultColumns[barcodeColumn].getCodewords(); - for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) { - if (codewords[codewordsRow] == null) { - continue; - } - if (!codewords[codewordsRow].hasValidRowNumber()) { - adjustRowNumbers(barcodeColumn, codewordsRow, codewords); - } - } - } - return unadjustedCount; - } - - private int adjustRowNumbersByRow() { - adjustRowNumbersFromBothRI(); - // TODO we should only do full row adjustments if row numbers of left and right row indicator column match. - // Maybe it's even better to calculated the height (in codeword rows) and divide it by the number of barcode - // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row - // number starts and ends. - int unadjustedCount = adjustRowNumbersFromLRI(); - return unadjustedCount + adjustRowNumbersFromRRI(); - } - - private void adjustRowNumbersFromBothRI() { - if (detectionResultColumns[0] == null || detectionResultColumns[barcodeColumnCount + 1] == null) { - return; - } - Codeword[] LRIcodewords = detectionResultColumns[0].getCodewords(); - Codeword[] RRIcodewords = detectionResultColumns[barcodeColumnCount + 1].getCodewords(); - for (int codewordsRow = 0; codewordsRow < LRIcodewords.length; codewordsRow++) { - if (LRIcodewords[codewordsRow] != null && - RRIcodewords[codewordsRow] != null && - LRIcodewords[codewordsRow].getRowNumber() == RRIcodewords[codewordsRow].getRowNumber()) { - for (int barcodeColumn = 1; barcodeColumn <= barcodeColumnCount; barcodeColumn++) { - Codeword codeword = detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; - if (codeword == null) { - continue; - } - codeword.setRowNumber(LRIcodewords[codewordsRow].getRowNumber()); - if (!codeword.hasValidRowNumber()) { - detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow] = null; - } - } - } - } - } - - private int adjustRowNumbersFromRRI() { - if (detectionResultColumns[barcodeColumnCount + 1] == null) { - return 0; - } - int unadjustedCount = 0; - Codeword[] codewords = detectionResultColumns[barcodeColumnCount + 1].getCodewords(); - for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) { - if (codewords[codewordsRow] == null) { - continue; - } - int rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber(); - int invalidRowCounts = 0; - for (int barcodeColumn = barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) { - Codeword codeword = detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; - if (codeword != null) { - invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); - if (!codeword.hasValidRowNumber()) { - unadjustedCount++; - } - } - } - } - return unadjustedCount; - } - - private int adjustRowNumbersFromLRI() { - if (detectionResultColumns[0] == null) { - return 0; - } - int unadjustedCount = 0; - Codeword[] codewords = detectionResultColumns[0].getCodewords(); - for (int codewordsRow = 0; codewordsRow < codewords.length; codewordsRow++) { - if (codewords[codewordsRow] == null) { - continue; - } - int rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber(); - int invalidRowCounts = 0; - for (int barcodeColumn = 1; barcodeColumn < barcodeColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) { - Codeword codeword = detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; - if (codeword != null) { - invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); - if (!codeword.hasValidRowNumber()) { - unadjustedCount++; - } - } - } - } - return unadjustedCount; - } - - private static int adjustRowNumberIfValid(int rowIndicatorRowNumber, int invalidRowCounts, Codeword codeword) { - if (codeword == null) { - return invalidRowCounts; - } - if (!codeword.hasValidRowNumber()) { - if (codeword.isValidRowNumber(rowIndicatorRowNumber)) { - codeword.setRowNumber(rowIndicatorRowNumber); - invalidRowCounts = 0; - } else { - ++invalidRowCounts; - } - } - return invalidRowCounts; - } - - private void adjustRowNumbers(int barcodeColumn, int codewordsRow, Codeword[] codewords) { - Codeword codeword = codewords[codewordsRow]; - Codeword[] previousColumnCodewords = detectionResultColumns[barcodeColumn - 1].getCodewords(); - Codeword[] nextColumnCodewords = previousColumnCodewords; - if (detectionResultColumns[barcodeColumn + 1] != null) { - nextColumnCodewords = detectionResultColumns[barcodeColumn + 1].getCodewords(); - } - - Codeword[] otherCodewords = new Codeword[14]; - - otherCodewords[2] = previousColumnCodewords[codewordsRow]; - otherCodewords[3] = nextColumnCodewords[codewordsRow]; - - if (codewordsRow > 0) { - otherCodewords[0] = codewords[codewordsRow - 1]; - otherCodewords[4] = previousColumnCodewords[codewordsRow - 1]; - otherCodewords[5] = nextColumnCodewords[codewordsRow - 1]; - } - if (codewordsRow > 1) { - otherCodewords[8] = codewords[codewordsRow - 2]; - otherCodewords[10] = previousColumnCodewords[codewordsRow - 2]; - otherCodewords[11] = nextColumnCodewords[codewordsRow - 2]; - } - if (codewordsRow < codewords.length - 1) { - otherCodewords[1] = codewords[codewordsRow + 1]; - otherCodewords[6] = previousColumnCodewords[codewordsRow + 1]; - otherCodewords[7] = nextColumnCodewords[codewordsRow + 1]; - } - if (codewordsRow < codewords.length - 2) { - otherCodewords[9] = codewords[codewordsRow + 2]; - otherCodewords[12] = previousColumnCodewords[codewordsRow + 2]; - otherCodewords[13] = nextColumnCodewords[codewordsRow + 2]; - } - for (Codeword otherCodeword : otherCodewords) { - if (adjustRowNumber(codeword, otherCodeword)) { - return; - } - } - } - - /** - * @return true, if row number was adjusted, false otherwise - */ - private static boolean adjustRowNumber(Codeword codeword, Codeword otherCodeword) { - if (otherCodeword == null) { - return false; - } - if (otherCodeword.hasValidRowNumber() && otherCodeword.getBucket() == codeword.getBucket()) { - codeword.setRowNumber(otherCodeword.getRowNumber()); - return true; - } - return false; - } - - int getBarcodeColumnCount() { - return barcodeColumnCount; - } - - int getBarcodeRowCount() { - return barcodeMetadata.getRowCount(); - } - - int getBarcodeECLevel() { - return barcodeMetadata.getErrorCorrectionLevel(); - } - - public void setBoundingBox(BoundingBox boundingBox) { - this.boundingBox = boundingBox; - } - - BoundingBox getBoundingBox() { - return boundingBox; - } - - void setDetectionResultColumn(int barcodeColumn, DetectionResultColumn detectionResultColumn) { - detectionResultColumns[barcodeColumn] = detectionResultColumn; - } - - DetectionResultColumn getDetectionResultColumn(int barcodeColumn) { - return detectionResultColumns[barcodeColumn]; - } - - @Override - public String toString() { - DetectionResultColumn rowIndicatorColumn = detectionResultColumns[0]; - if (rowIndicatorColumn == null) { - rowIndicatorColumn = detectionResultColumns[barcodeColumnCount + 1]; - } - Formatter formatter = new Formatter(); - for (int codewordsRow = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) { - formatter.format("CW %3d:", codewordsRow); - for (int barcodeColumn = 0; barcodeColumn < barcodeColumnCount + 2; barcodeColumn++) { - if (detectionResultColumns[barcodeColumn] == null) { - formatter.format(" | "); - continue; - } - Codeword codeword = detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow]; - if (codeword == null) { - formatter.format(" | "); - continue; - } - formatter.format(" %3d|%3d", codeword.getRowNumber(), codeword.getValue()); - } - formatter.format("%n"); - } - String result = formatter.toString(); - formatter.close(); - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java deleted file mode 100644 index bda0b398f..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import java.util.Formatter; - -/** - * @author Guenther Grau - */ -class DetectionResultColumn { - - private static final int MAX_NEARBY_DISTANCE = 5; - - private final BoundingBox boundingBox; - private final Codeword[] codewords; - - DetectionResultColumn(BoundingBox boundingBox) { - this.boundingBox = new BoundingBox(boundingBox); - codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1]; - } - - final Codeword getCodewordNearby(int imageRow) { - Codeword codeword = getCodeword(imageRow); - if (codeword != null) { - return codeword; - } - for (int i = 1; i < MAX_NEARBY_DISTANCE; i++) { - int nearImageRow = imageRowToCodewordIndex(imageRow) - i; - if (nearImageRow >= 0) { - codeword = codewords[nearImageRow]; - if (codeword != null) { - return codeword; - } - } - nearImageRow = imageRowToCodewordIndex(imageRow) + i; - if (nearImageRow < codewords.length) { - codeword = codewords[nearImageRow]; - if (codeword != null) { - return codeword; - } - } - } - return null; - } - - final int imageRowToCodewordIndex(int imageRow) { - return imageRow - boundingBox.getMinY(); - } - - final void setCodeword(int imageRow, Codeword codeword) { - codewords[imageRowToCodewordIndex(imageRow)] = codeword; - } - - final Codeword getCodeword(int imageRow) { - return codewords[imageRowToCodewordIndex(imageRow)]; - } - - final BoundingBox getBoundingBox() { - return boundingBox; - } - - final Codeword[] getCodewords() { - return codewords; - } - - @Override - public String toString() { - Formatter formatter = new Formatter(); - int row = 0; - for (Codeword codeword : codewords) { - if (codeword == null) { - formatter.format("%3d: | %n", row++); - continue; - } - formatter.format("%3d: %3d|%3d%n", row++, codeword.getRowNumber(), codeword.getValue()); - } - String result = formatter.toString(); - formatter.close(); - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java deleted file mode 100644 index b9484c0c0..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.ResultPoint; -import com.google.zxing.pdf417.PDF417Common; - -/** - * @author Guenther Grau - */ -final class DetectionResultRowIndicatorColumn extends DetectionResultColumn { - - private final boolean isLeft; - - DetectionResultRowIndicatorColumn(BoundingBox boundingBox, boolean isLeft) { - super(boundingBox); - this.isLeft = isLeft; - } - - void setRowNumbers() { - for (Codeword codeword : getCodewords()) { - if (codeword != null) { - codeword.setRowNumberAsRowIndicatorColumn(); - } - } - } - - // TODO implement properly - // TODO maybe we should add missing codewords to store the correct row number to make - // finding row numbers for other columns easier - // use row height count to make detection of invalid row numbers more reliable - int adjustCompleteIndicatorColumnRowNumbers(BarcodeMetadata barcodeMetadata) { - Codeword[] codewords = getCodewords(); - setRowNumbers(); - removeIncorrectCodewords(codewords, barcodeMetadata); - BoundingBox boundingBox = getBoundingBox(); - ResultPoint top = isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); - ResultPoint bottom = isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); - int firstRow = imageRowToCodewordIndex((int) top.getY()); - int lastRow = imageRowToCodewordIndex((int) bottom.getY()); - // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and - // taller rows - float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); - int barcodeRow = -1; - int maxRowHeight = 1; - int currentRowHeight = 0; - for (int codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) { - if (codewords[codewordsRow] == null) { - continue; - } - Codeword codeword = codewords[codewordsRow]; - - // float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight; - // if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) { - // SimpleLog.log(LEVEL.WARNING, - // "Removing codeword, rowNumberSkew too high, codeword[" + codewordsRow + "]: Expected Row: " + - // expectedRowNumber + ", RealRow: " + codeword.getRowNumber() + ", value: " + codeword.getValue()); - // codewords[codewordsRow] = null; - // } - - int rowDifference = codeword.getRowNumber() - barcodeRow; - - // TODO improve handling with case where first row indicator doesn't start with 0 - - if (rowDifference == 0) { - currentRowHeight++; - } else if (rowDifference == 1) { - maxRowHeight = Math.max(maxRowHeight, currentRowHeight); - currentRowHeight = 1; - barcodeRow = codeword.getRowNumber(); - } else if (rowDifference < 0 || - codeword.getRowNumber() >= barcodeMetadata.getRowCount() || - rowDifference > codewordsRow) { - codewords[codewordsRow] = null; - } else { - int checkedRows; - if (maxRowHeight > 2) { - checkedRows = (maxRowHeight - 2) * rowDifference; - } else { - checkedRows = rowDifference; - } - boolean closePreviousCodewordFound = checkedRows >= codewordsRow; - for (int i = 1; i <= checkedRows && !closePreviousCodewordFound; i++) { - // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1. - // This should hopefully get rid of most problems already. - closePreviousCodewordFound = codewords[codewordsRow - i] != null; - } - if (closePreviousCodewordFound) { - codewords[codewordsRow] = null; - } else { - barcodeRow = codeword.getRowNumber(); - currentRowHeight = 1; - } - } - } - return (int) (averageRowHeight + 0.5); - } - - int[] getRowHeights() throws FormatException { - BarcodeMetadata barcodeMetadata = getBarcodeMetadata(); - if (barcodeMetadata == null) { - return null; - } - adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata); - int[] result = new int[barcodeMetadata.getRowCount()]; - for (Codeword codeword : getCodewords()) { - if (codeword != null) { - int rowNumber = codeword.getRowNumber(); - if (rowNumber >= result.length) { - throw FormatException.getFormatInstance(); - } - result[rowNumber]++; - } // else throw exception? - } - return result; - } - - // TODO maybe we should add missing codewords to store the correct row number to make - // finding row numbers for other columns easier - // use row height count to make detection of invalid row numbers more reliable - int adjustIncompleteIndicatorColumnRowNumbers(BarcodeMetadata barcodeMetadata) { - BoundingBox boundingBox = getBoundingBox(); - ResultPoint top = isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight(); - ResultPoint bottom = isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight(); - int firstRow = imageRowToCodewordIndex((int) top.getY()); - int lastRow = imageRowToCodewordIndex((int) bottom.getY()); - float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); - Codeword[] codewords = getCodewords(); - int barcodeRow = -1; - int maxRowHeight = 1; - int currentRowHeight = 0; - for (int codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) { - if (codewords[codewordsRow] == null) { - continue; - } - Codeword codeword = codewords[codewordsRow]; - - codeword.setRowNumberAsRowIndicatorColumn(); - - int rowDifference = codeword.getRowNumber() - barcodeRow; - - // TODO improve handling with case where first row indicator doesn't start with 0 - - if (rowDifference == 0) { - currentRowHeight++; - } else if (rowDifference == 1) { - maxRowHeight = Math.max(maxRowHeight, currentRowHeight); - currentRowHeight = 1; - barcodeRow = codeword.getRowNumber(); - } else if (codeword.getRowNumber() >= barcodeMetadata.getRowCount()) { - codewords[codewordsRow] = null; - } else { - barcodeRow = codeword.getRowNumber(); - currentRowHeight = 1; - } - } - return (int) (averageRowHeight + 0.5); - } - - BarcodeMetadata getBarcodeMetadata() { - Codeword[] codewords = getCodewords(); - BarcodeValue barcodeColumnCount = new BarcodeValue(); - BarcodeValue barcodeRowCountUpperPart = new BarcodeValue(); - BarcodeValue barcodeRowCountLowerPart = new BarcodeValue(); - BarcodeValue barcodeECLevel = new BarcodeValue(); - for (Codeword codeword : codewords) { - if (codeword == null) { - continue; - } - codeword.setRowNumberAsRowIndicatorColumn(); - int rowIndicatorValue = codeword.getValue() % 30; - int codewordRowNumber = codeword.getRowNumber(); - if (!isLeft) { - codewordRowNumber += 2; - } - switch (codewordRowNumber % 3) { - case 0: - barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1); - break; - case 1: - barcodeECLevel.setValue(rowIndicatorValue / 3); - barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3); - break; - case 2: - barcodeColumnCount.setValue(rowIndicatorValue + 1); - break; - } - } - // Maybe we should check if we have ambiguous values? - if ((barcodeColumnCount.getValue().length == 0) || - (barcodeRowCountUpperPart.getValue().length == 0) || - (barcodeRowCountLowerPart.getValue().length == 0) || - (barcodeECLevel.getValue().length == 0) || - barcodeColumnCount.getValue()[0] < 1 || - barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE || - barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) { - return null; - } - BarcodeMetadata barcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], - barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]); - removeIncorrectCodewords(codewords, barcodeMetadata); - return barcodeMetadata; - } - - private void removeIncorrectCodewords(Codeword[] codewords, BarcodeMetadata barcodeMetadata) { - // Remove codewords which do not match the metadata - // TODO Maybe we should keep the incorrect codewords for the start and end positions? - for (int codewordRow = 0; codewordRow < codewords.length; codewordRow++) { - Codeword codeword = codewords[codewordRow]; - if (codewords[codewordRow] == null) { - continue; - } - int rowIndicatorValue = codeword.getValue() % 30; - int codewordRowNumber = codeword.getRowNumber(); - if (codewordRowNumber > barcodeMetadata.getRowCount()) { - codewords[codewordRow] = null; - continue; - } - if (!isLeft) { - codewordRowNumber += 2; - } - switch (codewordRowNumber % 3) { - case 0: - if (rowIndicatorValue * 3 + 1 != barcodeMetadata.getRowCountUpperPart()) { - codewords[codewordRow] = null; - } - break; - case 1: - if (rowIndicatorValue / 3 != barcodeMetadata.getErrorCorrectionLevel() || - rowIndicatorValue % 3 != barcodeMetadata.getRowCountLowerPart()) { - codewords[codewordRow] = null; - } - break; - case 2: - if (rowIndicatorValue + 1 != barcodeMetadata.getColumnCount()) { - codewords[codewordRow] = null; - } - break; - } - } - } - - boolean isLeft() { - return isLeft; - } - - @Override - public String toString() { - return "IsLeft: " + isLeft + '\n' + super.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java deleted file mode 100644 index 017f3f399..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.pdf417.PDF417Common; - -/** - * @author Guenther Grau - * @author creatale GmbH (christoph.schulz@creatale.de) - */ -final class PDF417CodewordDecoder { - - private static final float[][] RATIOS_TABLE = - new float[PDF417Common.SYMBOL_TABLE.length][PDF417Common.BARS_IN_MODULE]; - - static { - // Pre-computes the symbol ratio table. - for (int i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) { - int currentSymbol = PDF417Common.SYMBOL_TABLE[i]; - int currentBit = currentSymbol & 0x1; - for (int j = 0; j < PDF417Common.BARS_IN_MODULE; j++) { - float size = 0.0f; - while ((currentSymbol & 0x1) == currentBit) { - size += 1.0f; - currentSymbol >>= 1; - } - currentBit = currentSymbol & 0x1; - RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = size / PDF417Common.MODULES_IN_CODEWORD; - } - } - } - - private PDF417CodewordDecoder() { - } - - static int getDecodedValue(int[] moduleBitCount) { - int decodedValue = getDecodedCodewordValue(sampleBitCounts(moduleBitCount)); - if (decodedValue != -1) { - return decodedValue; - } - return getClosestDecodedValue(moduleBitCount); - } - - private static int[] sampleBitCounts(int[] moduleBitCount) { - float bitCountSum = PDF417Common.getBitCountSum(moduleBitCount); - int[] result = new int[PDF417Common.BARS_IN_MODULE]; - int bitCountIndex = 0; - int sumPreviousBits = 0; - for (int i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) { - float sampleIndex = - bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) + - (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD; - if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) { - sumPreviousBits += moduleBitCount[bitCountIndex]; - bitCountIndex++; - } - result[bitCountIndex]++; - } - return result; - } - - private static int getDecodedCodewordValue(int[] moduleBitCount) { - int decodedValue = getBitValue(moduleBitCount); - return PDF417Common.getCodeword(decodedValue) == -1 ? -1 : decodedValue; - } - - private static int getBitValue(int[] moduleBitCount) { - long result = 0; - for (int i = 0; i < moduleBitCount.length; i++) { - for (int bit = 0; bit < moduleBitCount[i]; bit++) { - result = (result << 1) | (i % 2 == 0 ? 1 : 0); - } - } - return (int) result; - } - - private static int getClosestDecodedValue(int[] moduleBitCount) { - int bitCountSum = PDF417Common.getBitCountSum(moduleBitCount); - float[] bitCountRatios = new float[PDF417Common.BARS_IN_MODULE]; - for (int i = 0; i < bitCountRatios.length; i++) { - bitCountRatios[i] = moduleBitCount[i] / (float) bitCountSum; - } - float bestMatchError = Float.MAX_VALUE; - int bestMatch = -1; - for (int j = 0; j < RATIOS_TABLE.length; j++) { - float error = 0.0f; - float[] ratioTableRow = RATIOS_TABLE[j]; - for (int k = 0; k < PDF417Common.BARS_IN_MODULE; k++) { - float diff = ratioTableRow[k] - bitCountRatios[k]; - error += diff * diff; - if (error >= bestMatchError) { - break; - } - } - if (error < bestMatchError) { - bestMatchError = error; - bestMatch = PDF417Common.SYMBOL_TABLE[j]; - } - } - return bestMatch; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java deleted file mode 100644 index 56ead37cb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.ChecksumException; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.pdf417.PDF417Common; -import com.google.zxing.pdf417.decoder.ec.ErrorCorrection; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Formatter; -import java.util.List; - -/** - * @author Guenther Grau - */ -public final class PDF417ScanningDecoder { - - private static final int CODEWORD_SKEW_SIZE = 2; - - private static final int MAX_ERRORS = 3; - private static final int MAX_EC_CODEWORDS = 512; - private static final ErrorCorrection errorCorrection = new ErrorCorrection(); - - private PDF417ScanningDecoder() { - } - - // TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern - // columns. That way width can be deducted from the pattern column. - // This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider - // than it should be. This can happen if the scanner used a bad blackpoint. - public static DecoderResult decode(BitMatrix image, - ResultPoint imageTopLeft, - ResultPoint imageBottomLeft, - ResultPoint imageTopRight, - ResultPoint imageBottomRight, - int minCodewordWidth, - int maxCodewordWidth) throws NotFoundException, FormatException, ChecksumException { - BoundingBox boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight); - DetectionResultRowIndicatorColumn leftRowIndicatorColumn = null; - DetectionResultRowIndicatorColumn rightRowIndicatorColumn = null; - DetectionResult detectionResult = null; - for (int i = 0; i < 2; i++) { - if (imageTopLeft != null) { - leftRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, - maxCodewordWidth); - } - if (imageTopRight != null) { - rightRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, - maxCodewordWidth); - } - detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn); - if (detectionResult == null) { - throw NotFoundException.getNotFoundInstance(); - } - if (i == 0 && detectionResult.getBoundingBox() != null && - (detectionResult.getBoundingBox().getMinY() < boundingBox.getMinY() || detectionResult.getBoundingBox() - .getMaxY() > boundingBox.getMaxY())) { - boundingBox = detectionResult.getBoundingBox(); - } else { - detectionResult.setBoundingBox(boundingBox); - break; - } - } - int maxBarcodeColumn = detectionResult.getBarcodeColumnCount() + 1; - detectionResult.setDetectionResultColumn(0, leftRowIndicatorColumn); - detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn); - - boolean leftToRight = leftRowIndicatorColumn != null; - for (int barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) { - int barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount; - if (detectionResult.getDetectionResultColumn(barcodeColumn) != null) { - // This will be the case for the opposite row indicator column, which doesn't need to be decoded again. - continue; - } - DetectionResultColumn detectionResultColumn; - if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) { - detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn == 0); - } else { - detectionResultColumn = new DetectionResultColumn(boundingBox); - } - detectionResult.setDetectionResultColumn(barcodeColumn, detectionResultColumn); - int startColumn = -1; - int previousStartColumn = startColumn; - // TODO start at a row for which we know the start position, then detect upwards and downwards from there. - for (int imageRow = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) { - startColumn = getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); - if (startColumn < 0 || startColumn > boundingBox.getMaxX()) { - if (previousStartColumn == -1) { - continue; - } - startColumn = previousStartColumn; - } - Codeword codeword = detectCodeword(image, boundingBox.getMinX(), boundingBox.getMaxX(), leftToRight, - startColumn, imageRow, minCodewordWidth, maxCodewordWidth); - if (codeword != null) { - detectionResultColumn.setCodeword(imageRow, codeword); - previousStartColumn = startColumn; - minCodewordWidth = Math.min(minCodewordWidth, codeword.getWidth()); - maxCodewordWidth = Math.max(maxCodewordWidth, codeword.getWidth()); - } - } - } - return createDecoderResult(detectionResult); - } - - private static DetectionResult merge(DetectionResultRowIndicatorColumn leftRowIndicatorColumn, - DetectionResultRowIndicatorColumn rightRowIndicatorColumn) - throws NotFoundException, FormatException { - if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) { - return null; - } - BarcodeMetadata barcodeMetadata = getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn); - if (barcodeMetadata == null) { - return null; - } - BoundingBox boundingBox = BoundingBox.merge(adjustBoundingBox(leftRowIndicatorColumn), - adjustBoundingBox(rightRowIndicatorColumn)); - return new DetectionResult(barcodeMetadata, boundingBox); - } - - private static BoundingBox adjustBoundingBox(DetectionResultRowIndicatorColumn rowIndicatorColumn) - throws NotFoundException, FormatException { - if (rowIndicatorColumn == null) { - return null; - } - int[] rowHeights = rowIndicatorColumn.getRowHeights(); - if (rowHeights == null) { - return null; - } - int maxRowHeight = getMax(rowHeights); - int missingStartRows = 0; - for (int rowHeight : rowHeights) { - missingStartRows += maxRowHeight - rowHeight; - if (rowHeight > 0) { - break; - } - } - Codeword[] codewords = rowIndicatorColumn.getCodewords(); - for (int row = 0; missingStartRows > 0 && codewords[row] == null; row++) { - missingStartRows--; - } - int missingEndRows = 0; - for (int row = rowHeights.length - 1; row >= 0; row--) { - missingEndRows += maxRowHeight - rowHeights[row]; - if (rowHeights[row] > 0) { - break; - } - } - for (int row = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) { - missingEndRows--; - } - return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, - rowIndicatorColumn.isLeft()); - } - - private static int getMax(int[] values) { - int maxValue = -1; - for (int value : values) { - maxValue = Math.max(maxValue, value); - } - return maxValue; - } - - private static BarcodeMetadata getBarcodeMetadata(DetectionResultRowIndicatorColumn leftRowIndicatorColumn, - DetectionResultRowIndicatorColumn rightRowIndicatorColumn) { - BarcodeMetadata leftBarcodeMetadata; - if (leftRowIndicatorColumn == null || - (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) { - return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata(); - } - BarcodeMetadata rightBarcodeMetadata; - if (rightRowIndicatorColumn == null || - (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) { - return leftBarcodeMetadata; - } - - if (leftBarcodeMetadata.getColumnCount() != rightBarcodeMetadata.getColumnCount() && - leftBarcodeMetadata.getErrorCorrectionLevel() != rightBarcodeMetadata.getErrorCorrectionLevel() && - leftBarcodeMetadata.getRowCount() != rightBarcodeMetadata.getRowCount()) { - return null; - } - return leftBarcodeMetadata; - } - - private static DetectionResultRowIndicatorColumn getRowIndicatorColumn(BitMatrix image, - BoundingBox boundingBox, - ResultPoint startPoint, - boolean leftToRight, - int minCodewordWidth, - int maxCodewordWidth) { - DetectionResultRowIndicatorColumn rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, - leftToRight); - for (int i = 0; i < 2; i++) { - int increment = i == 0 ? 1 : -1; - int startColumn = (int) startPoint.getX(); - for (int imageRow = (int) startPoint.getY(); imageRow <= boundingBox.getMaxY() && - imageRow >= boundingBox.getMinY(); imageRow += increment) { - Codeword codeword = detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, - minCodewordWidth, maxCodewordWidth); - if (codeword != null) { - rowIndicatorColumn.setCodeword(imageRow, codeword); - if (leftToRight) { - startColumn = codeword.getStartX(); - } else { - startColumn = codeword.getEndX(); - } - } - } - } - return rowIndicatorColumn; - } - - private static void adjustCodewordCount(DetectionResult detectionResult, BarcodeValue[][] barcodeMatrix) - throws NotFoundException { - int[] numberOfCodewords = barcodeMatrix[0][1].getValue(); - int calculatedNumberOfCodewords = detectionResult.getBarcodeColumnCount() * - detectionResult.getBarcodeRowCount() - - getNumberOfECCodeWords(detectionResult.getBarcodeECLevel()); - if (numberOfCodewords.length == 0) { - if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) { - throw NotFoundException.getNotFoundInstance(); - } - barcodeMatrix[0][1].setValue(calculatedNumberOfCodewords); - } else if (numberOfCodewords[0] != calculatedNumberOfCodewords) { - // The calculated one is more reliable as it is derived from the row indicator columns - barcodeMatrix[0][1].setValue(calculatedNumberOfCodewords); - } - } - - private static DecoderResult createDecoderResult(DetectionResult detectionResult) throws FormatException, - ChecksumException, NotFoundException { - BarcodeValue[][] barcodeMatrix = createBarcodeMatrix(detectionResult); - adjustCodewordCount(detectionResult, barcodeMatrix); - Collection erasures = new ArrayList<>(); - int[] codewords = new int[detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount()]; - List ambiguousIndexValuesList = new ArrayList<>(); - List ambiguousIndexesList = new ArrayList<>(); - for (int row = 0; row < detectionResult.getBarcodeRowCount(); row++) { - for (int column = 0; column < detectionResult.getBarcodeColumnCount(); column++) { - int[] values = barcodeMatrix[row][column + 1].getValue(); - int codewordIndex = row * detectionResult.getBarcodeColumnCount() + column; - if (values.length == 0) { - erasures.add(codewordIndex); - } else if (values.length == 1) { - codewords[codewordIndex] = values[0]; - } else { - ambiguousIndexesList.add(codewordIndex); - ambiguousIndexValuesList.add(values); - } - } - } - int[][] ambiguousIndexValues = new int[ambiguousIndexValuesList.size()][]; - for (int i = 0; i < ambiguousIndexValues.length; i++) { - ambiguousIndexValues[i] = ambiguousIndexValuesList.get(i); - } - return createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, - PDF417Common.toIntArray(erasures), PDF417Common.toIntArray(ambiguousIndexesList), ambiguousIndexValues); - } - - /** - * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The - * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value - * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of - * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the - * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes, - * so decoding the normal barcodes is not affected by this. - * - * @param erasureArray contains the indexes of erasures - * @param ambiguousIndexes array with the indexes that have more than one most likely value - * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must - * be the same length as the ambiguousIndexes array - */ - private static DecoderResult createDecoderResultFromAmbiguousValues(int ecLevel, - int[] codewords, - int[] erasureArray, - int[] ambiguousIndexes, - int[][] ambiguousIndexValues) - throws FormatException, ChecksumException { - int[] ambiguousIndexCount = new int[ambiguousIndexes.length]; - - int tries = 100; - while (tries-- > 0) { - for (int i = 0; i < ambiguousIndexCount.length; i++) { - codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]]; - } - try { - return decodeCodewords(codewords, ecLevel, erasureArray); - } catch (ChecksumException ignored) { - // - } - if (ambiguousIndexCount.length == 0) { - throw ChecksumException.getChecksumInstance(); - } - for (int i = 0; i < ambiguousIndexCount.length; i++) { - if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) { - ambiguousIndexCount[i]++; - break; - } else { - ambiguousIndexCount[i] = 0; - if (i == ambiguousIndexCount.length - 1) { - throw ChecksumException.getChecksumInstance(); - } - } - } - } - throw ChecksumException.getChecksumInstance(); - } - - private static BarcodeValue[][] createBarcodeMatrix(DetectionResult detectionResult) throws FormatException { - BarcodeValue[][] barcodeMatrix = - new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2]; - for (int row = 0; row < barcodeMatrix.length; row++) { - for (int column = 0; column < barcodeMatrix[row].length; column++) { - barcodeMatrix[row][column] = new BarcodeValue(); - } - } - - int column = 0; - for (DetectionResultColumn detectionResultColumn : detectionResult.getDetectionResultColumns()) { - if (detectionResultColumn != null) { - for (Codeword codeword : detectionResultColumn.getCodewords()) { - if (codeword != null) { - int rowNumber = codeword.getRowNumber(); - if (rowNumber >= 0) { - if (rowNumber >= barcodeMatrix.length) { - throw FormatException.getFormatInstance(); - } - barcodeMatrix[rowNumber][column].setValue(codeword.getValue()); - } - } - } - } - column++; - } - return barcodeMatrix; - } - - private static boolean isValidBarcodeColumn(DetectionResult detectionResult, int barcodeColumn) { - return barcodeColumn >= 0 && barcodeColumn <= detectionResult.getBarcodeColumnCount() + 1; - } - - private static int getStartColumn(DetectionResult detectionResult, - int barcodeColumn, - int imageRow, - boolean leftToRight) { - int offset = leftToRight ? 1 : -1; - Codeword codeword = null; - if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { - codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodeword(imageRow); - } - if (codeword != null) { - return leftToRight ? codeword.getEndX() : codeword.getStartX(); - } - codeword = detectionResult.getDetectionResultColumn(barcodeColumn).getCodewordNearby(imageRow); - if (codeword != null) { - return leftToRight ? codeword.getStartX() : codeword.getEndX(); - } - if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { - codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodewordNearby(imageRow); - } - if (codeword != null) { - return leftToRight ? codeword.getEndX() : codeword.getStartX(); - } - int skippedColumns = 0; - - while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { - barcodeColumn -= offset; - for (Codeword previousRowCodeword : detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) { - if (previousRowCodeword != null) { - return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) + - offset * - skippedColumns * - (previousRowCodeword.getEndX() - previousRowCodeword.getStartX()); - } - } - skippedColumns++; - } - return leftToRight ? detectionResult.getBoundingBox().getMinX() : detectionResult.getBoundingBox().getMaxX(); - } - - private static Codeword detectCodeword(BitMatrix image, - int minColumn, - int maxColumn, - boolean leftToRight, - int startColumn, - int imageRow, - int minCodewordWidth, - int maxCodewordWidth) { - startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow); - // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length - // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels. - // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate - // for the current position - int[] moduleBitCount = getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow); - if (moduleBitCount == null) { - return null; - } - int endColumn; - int codewordBitCount = PDF417Common.getBitCountSum(moduleBitCount); - if (leftToRight) { - endColumn = startColumn + codewordBitCount; - } else { - for (int i = 0; i < moduleBitCount.length / 2; i++) { - int tmpCount = moduleBitCount[i]; - moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i]; - moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount; - } - endColumn = startColumn; - startColumn = endColumn - codewordBitCount; - } - // TODO implement check for width and correction of black and white bars - // use start (and maybe stop pattern) to determine if blackbars are wider than white bars. If so, adjust. - // should probably done only for codewords with a lot more than 17 bits. - // The following fixes 10-1.png, which has wide black bars and small white bars - // for (int i = 0; i < moduleBitCount.length; i++) { - // if (i % 2 == 0) { - // moduleBitCount[i]--; - // } else { - // moduleBitCount[i]++; - // } - // } - - // We could also use the width of surrounding codewords for more accurate results, but this seems - // sufficient for now - if (!checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) { - // We could try to use the startX and endX position of the codeword in the same column in the previous row, - // create the bit count from it and normalize it to 8. This would help with single pixel errors. - return null; - } - - int decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount); - int codeword = PDF417Common.getCodeword(decodedValue); - if (codeword == -1) { - return null; - } - return new Codeword(startColumn, endColumn, getCodewordBucketNumber(decodedValue), codeword); - } - - private static int[] getModuleBitCount(BitMatrix image, - int minColumn, - int maxColumn, - boolean leftToRight, - int startColumn, - int imageRow) { - int imageColumn = startColumn; - int[] moduleBitCount = new int[8]; - int moduleNumber = 0; - int increment = leftToRight ? 1 : -1; - boolean previousPixelValue = leftToRight; - while (((leftToRight && imageColumn < maxColumn) || (!leftToRight && imageColumn >= minColumn)) && - moduleNumber < moduleBitCount.length) { - if (image.get(imageColumn, imageRow) == previousPixelValue) { - moduleBitCount[moduleNumber]++; - imageColumn += increment; - } else { - moduleNumber++; - previousPixelValue = !previousPixelValue; - } - } - if (moduleNumber == moduleBitCount.length || - (((leftToRight && imageColumn == maxColumn) || (!leftToRight && imageColumn == minColumn)) && moduleNumber == moduleBitCount.length - 1)) { - return moduleBitCount; - } - return null; - } - - private static int getNumberOfECCodeWords(int barcodeECLevel) { - return 2 << barcodeECLevel; - } - - private static int adjustCodewordStartColumn(BitMatrix image, - int minColumn, - int maxColumn, - boolean leftToRight, - int codewordStartColumn, - int imageRow) { - int correctedStartColumn = codewordStartColumn; - int increment = leftToRight ? -1 : 1; - // there should be no black pixels before the start column. If there are, then we need to start earlier. - for (int i = 0; i < 2; i++) { - while (((leftToRight && correctedStartColumn >= minColumn) || (!leftToRight && correctedStartColumn < maxColumn)) && - leftToRight == image.get(correctedStartColumn, imageRow)) { - if (Math.abs(codewordStartColumn - correctedStartColumn) > CODEWORD_SKEW_SIZE) { - return codewordStartColumn; - } - correctedStartColumn += increment; - } - increment = -increment; - leftToRight = !leftToRight; - } - return correctedStartColumn; - } - - private static boolean checkCodewordSkew(int codewordSize, int minCodewordWidth, int maxCodewordWidth) { - return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && - codewordSize <= maxCodewordWidth + CODEWORD_SKEW_SIZE; - } - - private static DecoderResult decodeCodewords(int[] codewords, int ecLevel, int[] erasures) throws FormatException, - ChecksumException { - if (codewords.length == 0) { - throw FormatException.getFormatInstance(); - } - - int numECCodewords = 1 << (ecLevel + 1); - int correctedErrorsCount = correctErrors(codewords, erasures, numECCodewords); - verifyCodewordCount(codewords, numECCodewords); - - // Decode the codewords - DecoderResult decoderResult = DecodedBitStreamParser.decode(codewords, String.valueOf(ecLevel)); - decoderResult.setErrorsCorrected(correctedErrorsCount); - decoderResult.setErasures(erasures.length); - return decoderResult; - } - - /** - *

    Given data and error-correction codewords received, possibly corrupted by errors, attempts to - * correct the errors in-place.

    - * - * @param codewords data and error correction codewords - * @param erasures positions of any known erasures - * @param numECCodewords number of error correction codewords that are available in codewords - * @throws ChecksumException if error correction fails - */ - private static int correctErrors(int[] codewords, int[] erasures, int numECCodewords) throws ChecksumException { - if (erasures != null && - erasures.length > numECCodewords / 2 + MAX_ERRORS || - numECCodewords < 0 || - numECCodewords > MAX_EC_CODEWORDS) { - // Too many errors or EC Codewords is corrupted - throw ChecksumException.getChecksumInstance(); - } - return errorCorrection.decode(codewords, numECCodewords, erasures); - } - - /** - * Verify that all is OK with the codeword array. - */ - private static void verifyCodewordCount(int[] codewords, int numECCodewords) throws FormatException { - if (codewords.length < 4) { - // Codeword array size should be at least 4 allowing for - // Count CW, At least one Data CW, Error Correction CW, Error Correction CW - throw FormatException.getFormatInstance(); - } - // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data - // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad - // codewords, but excluding the number of error correction codewords. - int numberOfCodewords = codewords[0]; - if (numberOfCodewords > codewords.length) { - throw FormatException.getFormatInstance(); - } - if (numberOfCodewords == 0) { - // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords) - if (numECCodewords < codewords.length) { - codewords[0] = codewords.length - numECCodewords; - } else { - throw FormatException.getFormatInstance(); - } - } - } - - private static int[] getBitCountForCodeword(int codeword) { - int[] result = new int[8]; - int previousValue = 0; - int i = result.length - 1; - while (true) { - if ((codeword & 0x1) != previousValue) { - previousValue = codeword & 0x1; - i--; - if (i < 0) { - break; - } - } - result[i]++; - codeword >>= 1; - } - return result; - } - - private static int getCodewordBucketNumber(int codeword) { - return getCodewordBucketNumber(getBitCountForCodeword(codeword)); - } - - private static int getCodewordBucketNumber(int[] moduleBitCount) { - return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9) % 9; - } - - public static String toString(BarcodeValue[][] barcodeMatrix) { - Formatter formatter = new Formatter(); - for (int row = 0; row < barcodeMatrix.length; row++) { - formatter.format("Row %2d: ", row); - for (int column = 0; column < barcodeMatrix[row].length; column++) { - BarcodeValue barcodeValue = barcodeMatrix[row][column]; - if (barcodeValue.getValue().length == 0) { - formatter.format(" ", (Object[]) null); - } else { - formatter.format("%4d(%2d)", barcodeValue.getValue()[0], - barcodeValue.getConfidence(barcodeValue.getValue()[0])); - } - } - formatter.format("%n"); - } - String result = formatter.toString(); - formatter.close(); - return result; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java deleted file mode 100644 index e34cb7fea..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder.ec; - -import com.google.zxing.ChecksumException; - -/** - *

    PDF417 error correction implementation.

    - * - *

    This example - * is quite useful in understanding the algorithm.

    - * - * @author Sean Owen - * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder - */ -public final class ErrorCorrection { - - private final ModulusGF field; - - public ErrorCorrection() { - this.field = ModulusGF.PDF417_GF; - } - - /** - * @param received received codewords - * @param numECCodewords number of those codewords used for EC - * @param erasures location of erasures - * @return number of errors - * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors - */ - public int decode(int[] received, - int numECCodewords, - int[] erasures) throws ChecksumException { - - ModulusPoly poly = new ModulusPoly(field, received); - int[] S = new int[numECCodewords]; - boolean error = false; - for (int i = numECCodewords; i > 0; i--) { - int eval = poly.evaluateAt(field.exp(i)); - S[numECCodewords - i] = eval; - if (eval != 0) { - error = true; - } - } - - if (!error) { - return 0; - } - - ModulusPoly knownErrors = field.getOne(); - if (erasures != null) { - for (int erasure : erasures) { - int b = field.exp(received.length - 1 - erasure); - // Add (1 - bx) term: - ModulusPoly term = new ModulusPoly(field, new int[]{field.subtract(0, b), 1}); - knownErrors = knownErrors.multiply(term); - } - } - - ModulusPoly syndrome = new ModulusPoly(field, S); - //syndrome = syndrome.multiply(knownErrors); - - ModulusPoly[] sigmaOmega = - runEuclideanAlgorithm(field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords); - ModulusPoly sigma = sigmaOmega[0]; - ModulusPoly omega = sigmaOmega[1]; - - //sigma = sigma.multiply(knownErrors); - - int[] errorLocations = findErrorLocations(sigma); - int[] errorMagnitudes = findErrorMagnitudes(omega, sigma, errorLocations); - - for (int i = 0; i < errorLocations.length; i++) { - int position = received.length - 1 - field.log(errorLocations[i]); - if (position < 0) { - throw ChecksumException.getChecksumInstance(); - } - received[position] = field.subtract(received[position], errorMagnitudes[i]); - } - return errorLocations.length; - } - - private ModulusPoly[] runEuclideanAlgorithm(ModulusPoly a, ModulusPoly b, int R) - throws ChecksumException { - // Assume a's degree is >= b's - if (a.getDegree() < b.getDegree()) { - ModulusPoly temp = a; - a = b; - b = temp; - } - - ModulusPoly rLast = a; - ModulusPoly r = b; - ModulusPoly tLast = field.getZero(); - ModulusPoly t = field.getOne(); - - // Run Euclidean algorithm until r's degree is less than R/2 - while (r.getDegree() >= R / 2) { - ModulusPoly rLastLast = rLast; - ModulusPoly tLastLast = tLast; - rLast = r; - tLast = t; - - // Divide rLastLast by rLast, with quotient in q and remainder in r - if (rLast.isZero()) { - // Oops, Euclidean algorithm already terminated? - throw ChecksumException.getChecksumInstance(); - } - r = rLastLast; - ModulusPoly q = field.getZero(); - int denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree()); - int dltInverse = field.inverse(denominatorLeadingTerm); - while (r.getDegree() >= rLast.getDegree() && !r.isZero()) { - int degreeDiff = r.getDegree() - rLast.getDegree(); - int scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse); - q = q.add(field.buildMonomial(degreeDiff, scale)); - r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale)); - } - - t = q.multiply(tLast).subtract(tLastLast).negative(); - } - - int sigmaTildeAtZero = t.getCoefficient(0); - if (sigmaTildeAtZero == 0) { - throw ChecksumException.getChecksumInstance(); - } - - int inverse = field.inverse(sigmaTildeAtZero); - ModulusPoly sigma = t.multiply(inverse); - ModulusPoly omega = r.multiply(inverse); - return new ModulusPoly[]{sigma, omega}; - } - - private int[] findErrorLocations(ModulusPoly errorLocator) throws ChecksumException { - // This is a direct application of Chien's search - int numErrors = errorLocator.getDegree(); - int[] result = new int[numErrors]; - int e = 0; - for (int i = 1; i < field.getSize() && e < numErrors; i++) { - if (errorLocator.evaluateAt(i) == 0) { - result[e] = field.inverse(i); - e++; - } - } - if (e != numErrors) { - throw ChecksumException.getChecksumInstance(); - } - return result; - } - - private int[] findErrorMagnitudes(ModulusPoly errorEvaluator, - ModulusPoly errorLocator, - int[] errorLocations) { - int errorLocatorDegree = errorLocator.getDegree(); - int[] formalDerivativeCoefficients = new int[errorLocatorDegree]; - for (int i = 1; i <= errorLocatorDegree; i++) { - formalDerivativeCoefficients[errorLocatorDegree - i] = - field.multiply(i, errorLocator.getCoefficient(i)); - } - ModulusPoly formalDerivative = new ModulusPoly(field, formalDerivativeCoefficients); - - // This is directly applying Forney's Formula - int s = errorLocations.length; - int[] result = new int[s]; - for (int i = 0; i < s; i++) { - int xiInverse = field.inverse(errorLocations[i]); - int numerator = field.subtract(0, errorEvaluator.evaluateAt(xiInverse)); - int denominator = field.inverse(formalDerivative.evaluateAt(xiInverse)); - result[i] = field.multiply(numerator, denominator); - } - return result; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java deleted file mode 100644 index 4b66d57fb..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder.ec; - -import com.google.zxing.pdf417.PDF417Common; - -/** - *

    A field based on powers of a generator integer, modulo some modulus.

    - * - * @author Sean Owen - * @see com.google.zxing.common.reedsolomon.GenericGF - */ -public final class ModulusGF { - - public static final ModulusGF PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3); - - private final int[] expTable; - private final int[] logTable; - private final ModulusPoly zero; - private final ModulusPoly one; - private final int modulus; - - private ModulusGF(int modulus, int generator) { - this.modulus = modulus; - expTable = new int[modulus]; - logTable = new int[modulus]; - int x = 1; - for (int i = 0; i < modulus; i++) { - expTable[i] = x; - x = (x * generator) % modulus; - } - for (int i = 0; i < modulus-1; i++) { - logTable[expTable[i]] = i; - } - // logTable[0] == 0 but this should never be used - zero = new ModulusPoly(this, new int[]{0}); - one = new ModulusPoly(this, new int[]{1}); - } - - - ModulusPoly getZero() { - return zero; - } - - ModulusPoly getOne() { - return one; - } - - ModulusPoly buildMonomial(int degree, int coefficient) { - if (degree < 0) { - throw new IllegalArgumentException(); - } - if (coefficient == 0) { - return zero; - } - int[] coefficients = new int[degree + 1]; - coefficients[0] = coefficient; - return new ModulusPoly(this, coefficients); - } - - int add(int a, int b) { - return (a + b) % modulus; - } - - int subtract(int a, int b) { - return (modulus + a - b) % modulus; - } - - int exp(int a) { - return expTable[a]; - } - - int log(int a) { - if (a == 0) { - throw new IllegalArgumentException(); - } - return logTable[a]; - } - - int inverse(int a) { - if (a == 0) { - throw new ArithmeticException(); - } - return expTable[modulus - logTable[a] - 1]; - } - - int multiply(int a, int b) { - if (a == 0 || b == 0) { - return 0; - } - return expTable[(logTable[a] + logTable[b]) % (modulus - 1)]; - } - - int getSize() { - return modulus; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java deleted file mode 100644 index 053bbf7a9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.decoder.ec; - -/** - * @author Sean Owen - * @see com.google.zxing.common.reedsolomon.GenericGFPoly - */ -final class ModulusPoly { - - private final ModulusGF field; - private final int[] coefficients; - - ModulusPoly(ModulusGF field, int[] coefficients) { - if (coefficients.length == 0) { - throw new IllegalArgumentException(); - } - this.field = field; - int coefficientsLength = coefficients.length; - if (coefficientsLength > 1 && coefficients[0] == 0) { - // Leading term must be non-zero for anything except the constant polynomial "0" - int firstNonZero = 1; - while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) { - firstNonZero++; - } - if (firstNonZero == coefficientsLength) { - this.coefficients = new int[]{0}; - } else { - this.coefficients = new int[coefficientsLength - firstNonZero]; - System.arraycopy(coefficients, - firstNonZero, - this.coefficients, - 0, - this.coefficients.length); - } - } else { - this.coefficients = coefficients; - } - } - - int[] getCoefficients() { - return coefficients; - } - - /** - * @return degree of this polynomial - */ - int getDegree() { - return coefficients.length - 1; - } - - /** - * @return true iff this polynomial is the monomial "0" - */ - boolean isZero() { - return coefficients[0] == 0; - } - - /** - * @return coefficient of x^degree term in this polynomial - */ - int getCoefficient(int degree) { - return coefficients[coefficients.length - 1 - degree]; - } - - /** - * @return evaluation of this polynomial at a given point - */ - int evaluateAt(int a) { - if (a == 0) { - // Just return the x^0 coefficient - return getCoefficient(0); - } - int size = coefficients.length; - if (a == 1) { - // Just the sum of the coefficients - int result = 0; - for (int coefficient : coefficients) { - result = field.add(result, coefficient); - } - return result; - } - int result = coefficients[0]; - for (int i = 1; i < size; i++) { - result = field.add(field.multiply(a, result), coefficients[i]); - } - return result; - } - - ModulusPoly add(ModulusPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (isZero()) { - return other; - } - if (other.isZero()) { - return this; - } - - int[] smallerCoefficients = this.coefficients; - int[] largerCoefficients = other.coefficients; - if (smallerCoefficients.length > largerCoefficients.length) { - int[] temp = smallerCoefficients; - smallerCoefficients = largerCoefficients; - largerCoefficients = temp; - } - int[] sumDiff = new int[largerCoefficients.length]; - int lengthDiff = largerCoefficients.length - smallerCoefficients.length; - // Copy high-order terms only found in higher-degree polynomial's coefficients - System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - - for (int i = lengthDiff; i < largerCoefficients.length; i++) { - sumDiff[i] = field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); - } - - return new ModulusPoly(field, sumDiff); - } - - ModulusPoly subtract(ModulusPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (other.isZero()) { - return this; - } - return add(other.negative()); - } - - ModulusPoly multiply(ModulusPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (isZero() || other.isZero()) { - return field.getZero(); - } - int[] aCoefficients = this.coefficients; - int aLength = aCoefficients.length; - int[] bCoefficients = other.coefficients; - int bLength = bCoefficients.length; - int[] product = new int[aLength + bLength - 1]; - for (int i = 0; i < aLength; i++) { - int aCoeff = aCoefficients[i]; - for (int j = 0; j < bLength; j++) { - product[i + j] = field.add(product[i + j], field.multiply(aCoeff, bCoefficients[j])); - } - } - return new ModulusPoly(field, product); - } - - ModulusPoly negative() { - int size = coefficients.length; - int[] negativeCoefficients = new int[size]; - for (int i = 0; i < size; i++) { - negativeCoefficients[i] = field.subtract(0, coefficients[i]); - } - return new ModulusPoly(field, negativeCoefficients); - } - - ModulusPoly multiply(int scalar) { - if (scalar == 0) { - return field.getZero(); - } - if (scalar == 1) { - return this; - } - int size = coefficients.length; - int[] product = new int[size]; - for (int i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], scalar); - } - return new ModulusPoly(field, product); - } - - ModulusPoly multiplyByMonomial(int degree, int coefficient) { - if (degree < 0) { - throw new IllegalArgumentException(); - } - if (coefficient == 0) { - return field.getZero(); - } - int size = coefficients.length; - int[] product = new int[size + degree]; - for (int i = 0; i < size; i++) { - product[i] = field.multiply(coefficients[i], coefficient); - } - return new ModulusPoly(field, product); - } - - ModulusPoly[] divide(ModulusPoly other) { - if (!field.equals(other.field)) { - throw new IllegalArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (other.isZero()) { - throw new IllegalArgumentException("Divide by 0"); - } - - ModulusPoly quotient = field.getZero(); - ModulusPoly remainder = this; - - int denominatorLeadingTerm = other.getCoefficient(other.getDegree()); - int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); - - while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) { - int degreeDifference = remainder.getDegree() - other.getDegree(); - int scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm); - ModulusPoly term = other.multiplyByMonomial(degreeDifference, scale); - ModulusPoly iterationQuotient = field.buildMonomial(degreeDifference, scale); - quotient = quotient.add(iterationQuotient); - remainder = remainder.subtract(term); - } - - return new ModulusPoly[] { quotient, remainder }; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(8 * getDegree()); - for (int degree = getDegree(); degree >= 0; degree--) { - int coefficient = getCoefficient(degree); - if (coefficient != 0) { - if (coefficient < 0) { - result.append(" - "); - coefficient = -coefficient; - } else { - if (result.length() > 0) { - result.append(" + "); - } - } - if (degree == 0 || coefficient != 1) { - result.append(coefficient); - } - if (degree != 0) { - if (degree == 1) { - result.append('x'); - } else { - result.append("x^"); - result.append(degree); - } - } - } - } - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/Detector.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/Detector.java deleted file mode 100644 index 1538e4a9c..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/Detector.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.detector; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - *

    Encapsulates logic that can detect a PDF417 Code in an image, even if the - * PDF417 Code is rotated or skewed, or partially obscured.

    - * - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author dswitkin@google.com (Daniel Switkin) - * @author Guenther Grau - */ -public final class Detector { - - private static final int[] INDEXES_START_PATTERN = {0, 4, 1, 5}; - private static final int[] INDEXES_STOP_PATTERN = {6, 2, 7, 3}; - private static final float MAX_AVG_VARIANCE = 0.42f; - private static final float MAX_INDIVIDUAL_VARIANCE = 0.8f; - - // B S B S B S B S Bar/Space pattern - // 11111111 0 1 0 1 0 1 000 - private static final int[] START_PATTERN = {8, 1, 1, 1, 1, 1, 1, 3}; - // 1111111 0 1 000 1 0 1 00 1 - private static final int[] STOP_PATTERN = {7, 1, 1, 3, 1, 1, 1, 2, 1}; - private static final int MAX_PIXEL_DRIFT = 3; - private static final int MAX_PATTERN_DRIFT = 5; - // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged. - // if we set the value too high, then we might detect the start pattern from a neighbor barcode. - private static final int SKIPPED_ROW_COUNT_MAX = 25; - // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least - // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it. - private static final int ROW_STEP = 5; - private static final int BARCODE_MIN_HEIGHT = 10; - - private Detector() { - } - - /** - *

    Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.

    - * - * @param image barcode image to decode - * @param hints optional hints to detector - * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will - * be found and returned - * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code - * @throws NotFoundException if no PDF417 Code can be found - */ - public static PDF417DetectorResult detect(BinaryBitmap image, Map hints, boolean multiple) - throws NotFoundException { - // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even - // different binarizers - //boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - - BitMatrix bitMatrix = image.getBlackMatrix(); - - List barcodeCoordinates = detect(multiple, bitMatrix); - if (barcodeCoordinates.isEmpty()) { - bitMatrix = bitMatrix.clone(); - bitMatrix.rotate180(); - barcodeCoordinates = detect(multiple, bitMatrix); - } - return new PDF417DetectorResult(bitMatrix, barcodeCoordinates); - } - - /** - * Detects PDF417 codes in an image. Only checks 0 degree rotation - * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will - * be found and returned - * @param bitMatrix bit matrix to detect barcodes in - * @return List of ResultPoint arrays containing the coordinates of found barcodes - */ - private static List detect(boolean multiple, BitMatrix bitMatrix) { - List barcodeCoordinates = new ArrayList<>(); - int row = 0; - int column = 0; - boolean foundBarcodeInRow = false; - while (row < bitMatrix.getHeight()) { - ResultPoint[] vertices = findVertices(bitMatrix, row, column); - - if (vertices[0] == null && vertices[3] == null) { - if (!foundBarcodeInRow) { - // we didn't find any barcode so that's the end of searching - break; - } - // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly - // below the lowest barcode we found so far. - foundBarcodeInRow = false; - column = 0; - for (ResultPoint[] barcodeCoordinate : barcodeCoordinates) { - if (barcodeCoordinate[1] != null) { - row = (int) Math.max(row, barcodeCoordinate[1].getY()); - } - if (barcodeCoordinate[3] != null) { - row = Math.max(row, (int) barcodeCoordinate[3].getY()); - } - } - row += ROW_STEP; - continue; - } - foundBarcodeInRow = true; - barcodeCoordinates.add(vertices); - if (!multiple) { - break; - } - // if we didn't find a right row indicator column, then continue the search for the next barcode after the - // start pattern of the barcode just found. - if (vertices[2] != null) { - column = (int) vertices[2].getX(); - row = (int) vertices[2].getY(); - } else { - column = (int) vertices[4].getX(); - row = (int) vertices[4].getY(); - } - } - return barcodeCoordinates; - } - - /** - * Locate the vertices and the codewords area of a black blob using the Start - * and Stop patterns as locators. - * - * @param matrix the scanned barcode image. - * @return an array containing the vertices: - * vertices[0] x, y top left barcode - * vertices[1] x, y bottom left barcode - * vertices[2] x, y top right barcode - * vertices[3] x, y bottom right barcode - * vertices[4] x, y top left codeword area - * vertices[5] x, y bottom left codeword area - * vertices[6] x, y top right codeword area - * vertices[7] x, y bottom right codeword area - */ - private static ResultPoint[] findVertices(BitMatrix matrix, int startRow, int startColumn) { - int height = matrix.getHeight(); - int width = matrix.getWidth(); - - ResultPoint[] result = new ResultPoint[8]; - copyToResult(result, findRowsWithPattern(matrix, height, width, startRow, startColumn, START_PATTERN), - INDEXES_START_PATTERN); - - if (result[4] != null) { - startColumn = (int) result[4].getX(); - startRow = (int) result[4].getY(); - } - copyToResult(result, findRowsWithPattern(matrix, height, width, startRow, startColumn, STOP_PATTERN), - INDEXES_STOP_PATTERN); - return result; - } - - private static void copyToResult(ResultPoint[] result, ResultPoint[] tmpResult, int[] destinationIndexes) { - for (int i = 0; i < destinationIndexes.length; i++) { - result[destinationIndexes[i]] = tmpResult[i]; - } - } - - private static ResultPoint[] findRowsWithPattern(BitMatrix matrix, - int height, - int width, - int startRow, - int startColumn, - int[] pattern) { - ResultPoint[] result = new ResultPoint[4]; - boolean found = false; - int[] counters = new int[pattern.length]; - for (; startRow < height; startRow += ROW_STEP) { - int[] loc = findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters); - if (loc != null) { - while (startRow > 0) { - int[] previousRowLoc = findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters); - if (previousRowLoc != null) { - loc = previousRowLoc; - } else { - startRow++; - break; - } - } - result[0] = new ResultPoint(loc[0], startRow); - result[1] = new ResultPoint(loc[1], startRow); - found = true; - break; - } - } - int stopRow = startRow + 1; - // Last row of the current symbol that contains pattern - if (found) { - int skippedRowCount = 0; - int[] previousRowLoc = {(int) result[0].getX(), (int) result[1].getX()}; - for (; stopRow < height; stopRow++) { - int[] loc = findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters); - // a found pattern is only considered to belong to the same barcode if the start and end positions - // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With - // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly - // larger drift and don't check for skipped rows. - if (loc != null && - Math.abs(previousRowLoc[0] - loc[0]) < MAX_PATTERN_DRIFT && - Math.abs(previousRowLoc[1] - loc[1]) < MAX_PATTERN_DRIFT) { - previousRowLoc = loc; - skippedRowCount = 0; - } else { - if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) { - break; - } else { - skippedRowCount++; - } - } - } - stopRow -= skippedRowCount + 1; - result[2] = new ResultPoint(previousRowLoc[0], stopRow); - result[3] = new ResultPoint(previousRowLoc[1], stopRow); - } - if (stopRow - startRow < BARCODE_MIN_HEIGHT) { - for (int i = 0; i < result.length; i++) { - result[i] = null; - } - } - return result; - } - - /** - * @param matrix row of black/white values to search - * @param column x position to start search - * @param row y position to start search - * @param width the number of pixels to search on this row - * @param pattern pattern of counts of number of black and white pixels that are - * being searched for as a pattern - * @param counters array of counters, as long as pattern, to re-use - * @return start/end horizontal offset of guard pattern, as an array of two ints. - */ - private static int[] findGuardPattern(BitMatrix matrix, - int column, - int row, - int width, - boolean whiteFirst, - int[] pattern, - int[] counters) { - Arrays.fill(counters, 0, counters.length, 0); - int patternLength = pattern.length; - boolean isWhite = whiteFirst; - int patternStart = column; - int pixelDrift = 0; - - // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels - while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < MAX_PIXEL_DRIFT) { - patternStart--; - } - int x = patternStart; - int counterPosition = 0; - for (; x < width; x++) { - boolean pixel = matrix.get(x, row); - if (pixel ^ isWhite) { - counters[counterPosition]++; - } else { - if (counterPosition == patternLength - 1) { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { - return new int[] {patternStart, x}; - } - patternStart += counters[0] + counters[1]; - System.arraycopy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } else { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - if (counterPosition == patternLength - 1) { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { - return new int[] {patternStart, x - 1}; - } - } - return null; - } - - /** - * Determines how closely a set of observed counts of runs of black/white - * values matches a given target pattern. This is reported as the ratio of - * the total variance from the expected pattern proportions across all - * pattern elements, to the length of the pattern. - * - * @param counters observed counters - * @param pattern expected pattern - * @param maxIndividualVariance The most any counter can differ before we give up - * @return ratio of total variance between counters and pattern compared to total pattern size - */ - private static float patternMatchVariance(int[] counters, int[] pattern, float maxIndividualVariance) { - int numCounters = counters.length; - int total = 0; - int patternLength = 0; - for (int i = 0; i < numCounters; i++) { - total += counters[i]; - patternLength += pattern[i]; - } - if (total < patternLength) { - // If we don't even have one pixel per unit of bar width, assume this - // is too small to reliably match, so fail: - return Float.POSITIVE_INFINITY; - } - // We're going to fake floating-point math in integers. We just need to use more bits. - // Scale up patternLength so that intermediate values below like scaledCounter will have - // more "significant digits". - float unitBarWidth = (float) total / patternLength; - maxIndividualVariance *= unitBarWidth; - - float totalVariance = 0.0f; - for (int x = 0; x < numCounters; x++) { - int counter = counters[x]; - float scaledPattern = pattern[x] * unitBarWidth; - float variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; - if (variance > maxIndividualVariance) { - return Float.POSITIVE_INFINITY; - } - totalVariance += variance; - } - return totalVariance / total; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java deleted file mode 100644 index 081b77803..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.detector; - -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; - -import java.util.List; - -/** - * @author Guenther Grau - */ -public final class PDF417DetectorResult { - - private final BitMatrix bits; - private final List points; - - public PDF417DetectorResult(BitMatrix bits, List points) { - this.bits = bits; - this.points = points; - } - - public BitMatrix getBits() { - return bits; - } - - public List getPoints() { - return points; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java deleted file mode 100644 index 1cff11359..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.encoder; - -/** - * Holds all of the information for a barcode in a format where it can be easily accessable - * - * @author Jacob Haynes - */ -public final class BarcodeMatrix { - - private final BarcodeRow[] matrix; - private int currentRow; - private final int height; - private final int width; - - /** - * @param height the height of the matrix (Rows) - * @param width the width of the matrix (Cols) - */ - BarcodeMatrix(int height, int width) { - matrix = new BarcodeRow[height]; - //Initializes the array to the correct width - for (int i = 0, matrixLength = matrix.length; i < matrixLength; i++) { - matrix[i] = new BarcodeRow((width + 4) * 17 + 1); - } - this.width = width * 17; - this.height = height; - this.currentRow = -1; - } - - void set(int x, int y, byte value) { - matrix[y].set(x, value); - } - - /* - void setMatrix(int x, int y, boolean black) { - set(x, y, (byte) (black ? 1 : 0)); - } - */ - - void startRow() { - ++currentRow; - } - - BarcodeRow getCurrentRow() { - return matrix[currentRow]; - } - - public byte[][] getMatrix() { - return getScaledMatrix(1, 1); - } - - /* - public byte[][] getScaledMatrix(int scale) { - return getScaledMatrix(scale, scale); - } - */ - - public byte[][] getScaledMatrix(int xScale, int yScale) { - byte[][] matrixOut = new byte[height * yScale][width * xScale]; - int yMax = height * yScale; - for (int i = 0; i < yMax; i++) { - matrixOut[yMax - i - 1] = matrix[i / yScale].getScaledRow(xScale); - } - return matrixOut; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java deleted file mode 100644 index 3ec70d580..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.encoder; - -/** - * @author Jacob Haynes - */ -final class BarcodeRow { - - private final byte[] row; - //A tacker for position in the bar - private int currentLocation; - - /** - * Creates a Barcode row of the width - */ - BarcodeRow(int width) { - this.row = new byte[width]; - currentLocation = 0; - } - - /** - * Sets a specific location in the bar - * - * @param x The location in the bar - * @param value Black if true, white if false; - */ - void set(int x, byte value) { - row[x] = value; - } - - /** - * Sets a specific location in the bar - * - * @param x The location in the bar - * @param black Black if true, white if false; - */ - void set(int x, boolean black) { - row[x] = (byte) (black ? 1 : 0); - } - - /** - * @param black A boolean which is true if the bar black false if it is white - * @param width How many spots wide the bar is. - */ - void addBar(boolean black, int width) { - for (int ii = 0; ii < width; ii++) { - set(currentLocation++, black); - } - } - - /* - byte[] getRow() { - return row; - } - */ - - /** - * This function scales the row - * - * @param scale How much you want the image to be scaled, must be greater than or equal to 1. - * @return the scaled row - */ - byte[] getScaledRow(int scale) { - byte[] output = new byte[row.length * scale]; - for (int i = 0; i < output.length; i++) { - output[i] = row[i / scale]; - } - return output; - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java deleted file mode 100644 index d0a85d600..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.encoder; - -public enum Compaction { - - AUTO, - TEXT, - BYTE, - NUMERIC - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java deleted file mode 100644 index 83a736bd4..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.pdf417.encoder; - -/** - * Data object to specify the minimum and maximum number of rows and columns for a PDF417 barcode. - * - * @author qwandor@google.com (Andrew Walbran) - */ -public final class Dimensions { - - private final int minCols; - private final int maxCols; - private final int minRows; - private final int maxRows; - - public Dimensions(int minCols, int maxCols, int minRows, int maxRows) { - this.minCols = minCols; - this.maxCols = maxCols; - this.minRows = minRows; - this.maxRows = maxRows; - } - - public int getMinCols() { - return minCols; - } - - public int getMaxCols() { - return maxCols; - } - - public int getMinRows() { - return minRows; - } - - public int getMaxRows() { - return maxRows; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java deleted file mode 100644 index 2c7555c24..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -package com.google.zxing.pdf417.encoder; - -import com.google.zxing.WriterException; - -import java.nio.charset.Charset; - -/** - * Top-level class for the logic part of the PDF417 implementation. - */ -public final class PDF417 { - - /** - * The start pattern (17 bits) - */ - private static final int START_PATTERN = 0x1fea8; - /** - * The stop pattern (18 bits) - */ - private static final int STOP_PATTERN = 0x3fa29; - - /** - * The codeword table from the Annex A of ISO/IEC 15438:2001(E). - */ - private static final int[][] CODEWORD_TABLE = { - {0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, - 0x1a8c0, 0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, - 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, - 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c, - 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, - 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, - 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460, - 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, - 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, - 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, - 0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, - 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0, - 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, - 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408, - 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, - 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, - 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, - 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, - 0x1d08e, 0x14210, 0x1a10c, 0x14208, 0x1a106, 0x14360, - 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, - 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, - 0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, - 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, - 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0, - 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, - 0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, - 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c, 0x12c60, - 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, - 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, - 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, - 0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, - 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970, - 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, - 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218, 0x1c90e, - 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, - 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, - 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, - 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, - 0x127bc, 0x16fbc, 0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, - 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, - 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, - 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640, - 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, - 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, - 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, - 0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, - 0x167b8, 0x1239c, 0x1679c, 0x1238e, 0x1678e, 0x167de, - 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, - 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, - 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, - 0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, - 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc, - 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, - 0x12186, 0x16386, 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, - 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, - 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, - 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, - 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, - 0x1d82c, 0x1d826, 0x1b042, 0x1902c, 0x12048, 0x160c8, - 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, - 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, - 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc, 0x11660, - 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, - 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, - 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, - 0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, - 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, 0x1e25e, 0x19b60, - 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, - 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, - 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, - 0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, - 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, - 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, - 0x1ee98, 0x1f74e, 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, - 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, - 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, - 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, - 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, - 0x17740, 0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, - 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, - 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, - 0x177b0, 0x13398, 0x199ce, 0x17798, 0x1bbce, 0x11186, - 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, - 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, - 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, - 0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, - 0x1b988, 0x19884, 0x1b984, 0x19882, 0x1b982, 0x110a0, - 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, - 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, - 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, - 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, - 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, - 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, - 0x19848, 0x1cc26, 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, - 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, - 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, - 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, - 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, - 0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, - 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, - 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, - 0x1859c, 0x10b18, 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, - 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, - 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08, - 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, - 0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, - 0x11b10, 0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, - 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, - 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, - 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, - 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, - 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646, - 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, - 0x18458, 0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, - 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, - 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, - 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, - 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, - 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, - 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, - 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, - 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, - 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, - 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0, - 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, - 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, - 0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, - 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, - 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, - 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, - 0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, - 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2, - 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, - 0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, - 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, - 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, - 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, - 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, - 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6, 0x10d84, - 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, - 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, - 0x1c748, 0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, - 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, - 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8, - 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, - 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, - 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6, - 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, - 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, - 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, - 0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, - 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4, - 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, - 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614, - 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4}, - {0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, - 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, - 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, - 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, - 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, - 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, - 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60, - 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, - 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, - 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, - 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, - 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e, - 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, - 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, - 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, - 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, - 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, - 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, - 0x14f10, 0x1a78c, 0x14f08, 0x1a786, 0x14f04, 0x14fb0, - 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, - 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, - 0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, - 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, - 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, - 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, - 0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, - 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6, 0x147ee, - 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, - 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, - 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, - 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, - 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822, - 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, - 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, - 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, - 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, - 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, - 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, - 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, - 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, - 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, - 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, - 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, - 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, - 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, - 0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, - 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, 0x1e490, 0x1fb6e, - 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, - 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, - 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, - 0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, - 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, - 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, - 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, - 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, - 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, - 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, - 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, - 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, - 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, - 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, - 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, - 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, - 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, - 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, - 0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, - 0x1627e, 0x1f622, 0x1e428, 0x1f216, 0x1ec68, 0x1f636, - 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, - 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, - 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, - 0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, - 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, - 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, - 0x1d872, 0x19074, 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, - 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, - 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, - 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, - 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, - 0x1c588, 0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, - 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, - 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, - 0x11788, 0x18bc6, 0x11784, 0x11782, 0x117d8, 0x18bee, - 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, - 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342, - 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, - 0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, - 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, - 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, - 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, - 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, - 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, - 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, - 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, - 0x1f996, 0x132fc, 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, - 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, - 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, - 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, - 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, - 0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, - 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, - 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, - 0x133e2, 0x177e2, 0x111f6, 0x133f6, 0x1fb94, 0x172f8, - 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, - 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634, - 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, - 0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, - 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, - 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, - 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, - 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, - 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, - 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c, - 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, - 0x185c8, 0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, - 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, - 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, - 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, - 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, - 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4, - 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, - 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, - 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, - 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, - 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772, - 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, - 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, - 0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, - 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, - 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, - 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, - 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, - 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa, - 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, - 0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, - 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, - 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, - 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, - 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, - 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4, 0x10df4, - 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, - 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, - 0x1c77a, 0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, - 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, - 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, - 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, - 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, - 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172, - 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, - 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, - 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, - 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, - 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e, - 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, - 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, - 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26}, - {0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, - 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, - 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, - 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, - 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, - 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, - 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4, - 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, - 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, - 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, - 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, - 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4, - 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, - 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, - 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, - 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, - 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, - 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, - 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c, 0x14278, 0x1a13e, - 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, - 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, - 0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, - 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, - 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964, - 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, - 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, - 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6, 0x1cbe4, - 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, - 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, - 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, - 0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, - 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c, - 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, - 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, - 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, - 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, - 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, - 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, - 0x16470, 0x1b23c, 0x16438, 0x1b21e, 0x1641c, 0x1640e, - 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, - 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, - 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, - 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, - 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, - 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, - 0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, - 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, 0x1610e, 0x120bc, - 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, - 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, - 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, - 0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, - 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4, - 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, - 0x19af0, 0x1cd7c, 0x134e0, 0x19a78, 0x1cd3e, 0x13470, - 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, - 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, - 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, - 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, - 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, - 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, - 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, - 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270, 0x1993c, - 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, - 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, - 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, - 0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, - 0x17260, 0x1b938, 0x1dc9e, 0x17230, 0x1b91c, 0x17218, - 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, - 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, - 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, - 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, - 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, - 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, - 0x130de, 0x171de, 0x170b0, 0x1b85c, 0x17098, 0x1b84e, - 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, - 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, - 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, - 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, - 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, - 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, - 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, - 0x109be, 0x11bbe, 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, - 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, - 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938, - 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, - 0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, - 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, - 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, - 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, - 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, - 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, - 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, - 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, - 0x17940, 0x1bcb0, 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, - 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, - 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, - 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, - 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, - 0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, - 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, - 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, - 0x1bc2c, 0x17848, 0x1bc26, 0x17844, 0x17842, 0x1382c, - 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, - 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c, - 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, - 0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, - 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, - 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, - 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, - 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, - 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, - 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e, - 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, - 0x11cdc, 0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, - 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, - 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, - 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, - 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, - 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, - 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, - 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, - 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, - 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, - 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16, - 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, - 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, - 0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, - 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, - 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, - 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, - 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, - 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8, - 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, - 0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, - 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, - 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, - 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, - 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, - 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28, 0x18f16, - 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, - 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, - 0x1df94, 0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, - 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, - 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, - 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, - 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, - 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66, - 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, - 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, - 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, - 0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, - 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a, - 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, - 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2, - 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea}}; - - private static final float PREFERRED_RATIO = 3.0f; - private static final float DEFAULT_MODULE_WIDTH = 0.357f; //1px in mm - private static final float HEIGHT = 2.0f; //mm - - private BarcodeMatrix barcodeMatrix; - private boolean compact; - private Compaction compaction; - private Charset encoding; - private int minCols; - private int maxCols; - private int maxRows; - private int minRows; - - public PDF417() { - this(false); - } - - public PDF417(boolean compact) { - this.compact = compact; - compaction = Compaction.AUTO; - encoding = null; // Use default - minCols = 2; - maxCols = 30; - maxRows = 30; - minRows = 2; - } - - public BarcodeMatrix getBarcodeMatrix() { - return barcodeMatrix; - } - - /** - * Calculates the necessary number of rows as described in annex Q of ISO/IEC 15438:2001(E). - * - * @param m the number of source codewords prior to the additional of the Symbol Length - * Descriptor and any pad codewords - * @param k the number of error correction codewords - * @param c the number of columns in the symbol in the data region (excluding start, stop and - * row indicator codewords) - * @return the number of rows in the symbol (r) - */ - private static int calculateNumberOfRows(int m, int k, int c) { - int r = ((m + 1 + k) / c) + 1; - if (c * r >= (m + 1 + k + c)) { - r--; - } - return r; - } - - /** - * Calculates the number of pad codewords as described in 4.9.2 of ISO/IEC 15438:2001(E). - * - * @param m the number of source codewords prior to the additional of the Symbol Length - * Descriptor and any pad codewords - * @param k the number of error correction codewords - * @param c the number of columns in the symbol in the data region (excluding start, stop and - * row indicator codewords) - * @param r the number of rows in the symbol - * @return the number of pad codewords - */ - private static int getNumberOfPadCodewords(int m, int k, int c, int r) { - int n = c * r - k; - return n > m + 1 ? n - m - 1 : 0; - } - - private static void encodeChar(int pattern, int len, BarcodeRow logic) { - int map = 1 << len - 1; - boolean last = (pattern & map) != 0; //Initialize to inverse of first bit - int width = 0; - for (int i = 0; i < len; i++) { - boolean black = (pattern & map) != 0; - if (last == black) { - width++; - } else { - logic.addBar(last, width); - - last = black; - width = 1; - } - map >>= 1; - } - logic.addBar(last, width); - } - - private void encodeLowLevel(CharSequence fullCodewords, - int c, - int r, - int errorCorrectionLevel, - BarcodeMatrix logic) { - - int idx = 0; - for (int y = 0; y < r; y++) { - int cluster = y % 3; - logic.startRow(); - encodeChar(START_PATTERN, 17, logic.getCurrentRow()); - - int left; - int right; - if (cluster == 0) { - left = (30 * (y / 3)) + ((r - 1) / 3); - right = (30 * (y / 3)) + (c - 1); - } else if (cluster == 1) { - left = (30 * (y / 3)) + (errorCorrectionLevel * 3) + ((r - 1) % 3); - right = (30 * (y / 3)) + ((r - 1) / 3); - } else { - left = (30 * (y / 3)) + (c - 1); - right = (30 * (y / 3)) + (errorCorrectionLevel * 3) + ((r - 1) % 3); - } - - int pattern = CODEWORD_TABLE[cluster][left]; - encodeChar(pattern, 17, logic.getCurrentRow()); - - for (int x = 0; x < c; x++) { - pattern = CODEWORD_TABLE[cluster][fullCodewords.charAt(idx)]; - encodeChar(pattern, 17, logic.getCurrentRow()); - idx++; - } - - if (compact) { - encodeChar(STOP_PATTERN, 1, logic.getCurrentRow()); // encodes stop line for compact pdf417 - } else { - pattern = CODEWORD_TABLE[cluster][right]; - encodeChar(pattern, 17, logic.getCurrentRow()); - - encodeChar(STOP_PATTERN, 18, logic.getCurrentRow()); - } - } - } - - /** - * @param msg message to encode - * @param errorCorrectionLevel PDF417 error correction level to use - * @throws WriterException if the contents cannot be encoded in this format - */ - public void generateBarcodeLogic(String msg, int errorCorrectionLevel) throws WriterException { - - //1. step: High-level encoding - int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel); - String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, compaction, encoding); - int sourceCodeWords = highLevel.length(); - - int[] dimension = determineDimensions(sourceCodeWords, errorCorrectionCodeWords); - - int cols = dimension[0]; - int rows = dimension[1]; - - int pad = getNumberOfPadCodewords(sourceCodeWords, errorCorrectionCodeWords, cols, rows); - - //2. step: construct data codewords - if (sourceCodeWords + errorCorrectionCodeWords + 1 > 929) { // +1 for symbol length CW - throw new WriterException( - "Encoded message contains to many code words, message to big (" + msg.length() + " bytes)"); - } - int n = sourceCodeWords + pad + 1; - StringBuilder sb = new StringBuilder(n); - sb.append((char) n); - sb.append(highLevel); - for (int i = 0; i < pad; i++) { - sb.append((char) 900); //PAD characters - } - String dataCodewords = sb.toString(); - - //3. step: Error correction - String ec = PDF417ErrorCorrection.generateErrorCorrection(dataCodewords, errorCorrectionLevel); - String fullCodewords = dataCodewords + ec; - - //4. step: low-level encoding - barcodeMatrix = new BarcodeMatrix(rows, cols); - encodeLowLevel(fullCodewords, cols, rows, errorCorrectionLevel, barcodeMatrix); - } - - /** - * Determine optimal nr of columns and rows for the specified number of - * codewords. - * - * @param sourceCodeWords number of code words - * @param errorCorrectionCodeWords number of error correction code words - * @return dimension object containing cols as width and rows as height - */ - private int[] determineDimensions(int sourceCodeWords, int errorCorrectionCodeWords) throws WriterException { - float ratio = 0.0f; - int[] dimension = null; - - for (int cols = minCols; cols <= maxCols; cols++) { - - int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, cols); - - if (rows < minRows) { - break; - } - - if (rows > maxRows) { - continue; - } - - float newRatio = ((17 * cols + 69) * DEFAULT_MODULE_WIDTH) / (rows * HEIGHT); - - // ignore if previous ratio is closer to preferred ratio - if (dimension != null && Math.abs(newRatio - PREFERRED_RATIO) > Math.abs(ratio - PREFERRED_RATIO)) { - continue; - } - - ratio = newRatio; - dimension = new int[] {cols, rows}; - } - - // Handle case when min values were larger than necessary - if (dimension == null) { - int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, minCols); - if (rows < minRows) { - dimension = new int[]{minCols, minRows}; - } - } - - if (dimension == null) { - throw new WriterException("Unable to fit message in columns"); - } - - return dimension; - } - - /** - * Sets max/min row/col values - * - * @param maxCols maximum allowed columns - * @param minCols minimum allowed columns - * @param maxRows maximum allowed rows - * @param minRows minimum allowed rows - */ - public void setDimensions(int maxCols, int minCols, int maxRows, int minRows) { - this.maxCols = maxCols; - this.minCols = minCols; - this.maxRows = maxRows; - this.minRows = minRows; - } - - /** - * @param compaction compaction mode to use - */ - public void setCompaction(Compaction compaction) { - this.compaction = compaction; - } - - /** - * @param compact if true, enables compaction - */ - public void setCompact(boolean compact) { - this.compact = compact; - } - - /** - * @param encoding sets character encoding to use - */ - public void setEncoding(Charset encoding) { - this.encoding = encoding; - } - -} - diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java deleted file mode 100644 index 65281727b..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -package com.google.zxing.pdf417.encoder; - -import com.google.zxing.WriterException; - -/** - * PDF417 error correction code following the algorithm described in ISO/IEC 15438:2001(E) in - * chapter 4.10. - */ -final class PDF417ErrorCorrection { - - /** - * Tables of coefficients for calculating error correction words - * (see annex F, ISO/IEC 15438:2001(E)) - */ - private static final int[][] EC_COEFFICIENTS = { - {27, 917}, - {522, 568, 723, 809}, - {237, 308, 436, 284, 646, 653, 428, 379}, - {274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, - 42, 176, 65}, - {361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, - 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, - 133, 231, 390, 685, 330, 63, 410}, - {539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, - 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, - 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, - 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, - 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, - 623, 264, 543}, - {521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, - 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, - 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, - 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, - 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, - 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, - 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, - 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, - 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, - 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, - 315, 550, 86, 801, 4, 108, 539}, - {524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, - 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, - 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, - 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, - 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, - 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, - 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, - 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, - 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, - 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, - 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, - 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, - 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, - 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, - 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, - 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, - 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, - 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, - 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, - 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, - 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, - 55, 497, 10}, - {352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, - 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, - 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, - 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, - 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, - 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, - 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, - 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, - 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, - 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, - 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, - 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, - 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, - 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, - 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, - 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, - 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, - 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, - 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, - 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, - 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, - 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, - 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, - 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, - 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, - 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, - 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, - 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, - 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, - 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, - 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, - 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, - 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, - 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, - 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, - 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, - 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, - 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, - 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, - 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, - 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, - 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, - 410, 389, 244, 31, 121, 303, 263}}; - - private PDF417ErrorCorrection() { - } - - /** - * Determines the number of error correction codewords for a specified error correction - * level. - * - * @param errorCorrectionLevel the error correction level (0-8) - * @return the number of codewords generated for error correction - */ - static int getErrorCorrectionCodewordCount(int errorCorrectionLevel) { - if (errorCorrectionLevel < 0 || errorCorrectionLevel > 8) { - throw new IllegalArgumentException("Error correction level must be between 0 and 8!"); - } - return 1 << (errorCorrectionLevel + 1); - } - - /** - * Returns the recommended minimum error correction level as described in annex E of - * ISO/IEC 15438:2001(E). - * - * @param n the number of data codewords - * @return the recommended minimum error correction level - */ - static int getRecommendedMinimumErrorCorrectionLevel(int n) throws WriterException { - if (n <= 0) { - throw new IllegalArgumentException("n must be > 0"); - } - if (n <= 40) { - return 2; - } - if (n <= 160) { - return 3; - } - if (n <= 320) { - return 4; - } - if (n <= 863) { - return 5; - } - throw new WriterException("No recommendation possible"); - } - - /** - * Generates the error correction codewords according to 4.10 in ISO/IEC 15438:2001(E). - * - * @param dataCodewords the data codewords - * @param errorCorrectionLevel the error correction level (0-8) - * @return the String representing the error correction codewords - */ - static String generateErrorCorrection(CharSequence dataCodewords, int errorCorrectionLevel) { - int k = getErrorCorrectionCodewordCount(errorCorrectionLevel); - char[] e = new char[k]; - int sld = dataCodewords.length(); - for (int i = 0; i < sld; i++) { - int t1 = (dataCodewords.charAt(i) + e[e.length - 1]) % 929; - int t2; - int t3; - for (int j = k - 1; j >= 1; j--) { - t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][j]) % 929; - t3 = 929 - t2; - e[j] = (char) ((e[j - 1] + t3) % 929); - } - t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][0]) % 929; - t3 = 929 - t2; - e[0] = (char) (t3 % 929); - } - StringBuilder sb = new StringBuilder(k); - for (int j = k - 1; j >= 0; j--) { - if (e[j] != 0) { - e[j] = (char) (929 - e[j]); - } - sb.append(e[j]); - } - return sb.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java b/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java deleted file mode 100644 index 125017c00..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -package com.google.zxing.pdf417.encoder; - -import com.google.zxing.WriterException; -import com.google.zxing.common.CharacterSetECI; - -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.util.Arrays; - -/** - * PDF417 high-level encoder following the algorithm described in ISO/IEC 15438:2001(E) in - * annex P. - */ -final class PDF417HighLevelEncoder { - - /** - * code for Text compaction - */ - private static final int TEXT_COMPACTION = 0; - - /** - * code for Byte compaction - */ - private static final int BYTE_COMPACTION = 1; - - /** - * code for Numeric compaction - */ - private static final int NUMERIC_COMPACTION = 2; - - /** - * Text compaction submode Alpha - */ - private static final int SUBMODE_ALPHA = 0; - - /** - * Text compaction submode Lower - */ - private static final int SUBMODE_LOWER = 1; - - /** - * Text compaction submode Mixed - */ - private static final int SUBMODE_MIXED = 2; - - /** - * Text compaction submode Punctuation - */ - private static final int SUBMODE_PUNCTUATION = 3; - - /** - * mode latch to Text Compaction mode - */ - private static final int LATCH_TO_TEXT = 900; - - /** - * mode latch to Byte Compaction mode (number of characters NOT a multiple of 6) - */ - private static final int LATCH_TO_BYTE_PADDED = 901; - - /** - * mode latch to Numeric Compaction mode - */ - private static final int LATCH_TO_NUMERIC = 902; - - /** - * mode shift to Byte Compaction mode - */ - private static final int SHIFT_TO_BYTE = 913; - - /** - * mode latch to Byte Compaction mode (number of characters a multiple of 6) - */ - private static final int LATCH_TO_BYTE = 924; - - /** - * identifier for a user defined Extended Channel Interpretation (ECI) - */ - private static final int ECI_USER_DEFINED = 925; - - /** - * identifier for a general purpose ECO format - */ - private static final int ECI_GENERAL_PURPOSE = 926; - - /** - * identifier for an ECI of a character set of code page - */ - private static final int ECI_CHARSET = 927; - - /** - * Raw code table for text compaction Mixed sub-mode - */ - private static final byte[] TEXT_MIXED_RAW = { - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, - 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0}; - - /** - * Raw code table for text compaction: Punctuation sub-mode - */ - private static final byte[] TEXT_PUNCTUATION_RAW = { - 59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, - 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0}; - - private static final byte[] MIXED = new byte[128]; - private static final byte[] PUNCTUATION = new byte[128]; - - private static final Charset DEFAULT_ENCODING = Charset.forName("ISO-8859-1"); - - private PDF417HighLevelEncoder() { - } - - static { - //Construct inverse lookups - Arrays.fill(MIXED, (byte) -1); - for (byte i = 0; i < TEXT_MIXED_RAW.length; i++) { - byte b = TEXT_MIXED_RAW[i]; - if (b > 0) { - MIXED[b] = i; - } - } - Arrays.fill(PUNCTUATION, (byte) -1); - for (byte i = 0; i < TEXT_PUNCTUATION_RAW.length; i++) { - byte b = TEXT_PUNCTUATION_RAW[i]; - if (b > 0) { - PUNCTUATION[b] = i; - } - } - } - - /** - * Performs high-level encoding of a PDF417 message using the algorithm described in annex P - * of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction - * is used. - * - * @param msg the message - * @param compaction compaction mode to use - * @param encoding character encoding used to encode in default or byte compaction - * or {@code null} for default / not applicable - * @return the encoded message (the char values range from 0 to 928) - */ - static String encodeHighLevel(String msg, Compaction compaction, Charset encoding) throws WriterException { - - //the codewords 0..928 are encoded as Unicode characters - StringBuilder sb = new StringBuilder(msg.length()); - - if (encoding == null) { - encoding = DEFAULT_ENCODING; - } else if (!DEFAULT_ENCODING.equals(encoding)) { - CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.name()); - if (eci != null) { - encodingECI(eci.getValue(), sb); - } - } - - int len = msg.length(); - int p = 0; - int textSubMode = SUBMODE_ALPHA; - - // User selected encoding mode - if (compaction == Compaction.TEXT) { - encodeText(msg, p, len, sb, textSubMode); - - } else if (compaction == Compaction.BYTE) { - byte[] bytes = msg.getBytes(encoding); - encodeBinary(bytes, p, bytes.length, BYTE_COMPACTION, sb); - - } else if (compaction == Compaction.NUMERIC) { - sb.append((char) LATCH_TO_NUMERIC); - encodeNumeric(msg, p, len, sb); - - } else { - int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1 - while (p < len) { - int n = determineConsecutiveDigitCount(msg, p); - if (n >= 13) { - sb.append((char) LATCH_TO_NUMERIC); - encodingMode = NUMERIC_COMPACTION; - textSubMode = SUBMODE_ALPHA; //Reset after latch - encodeNumeric(msg, p, n, sb); - p += n; - } else { - int t = determineConsecutiveTextCount(msg, p); - if (t >= 5 || n == len) { - if (encodingMode != TEXT_COMPACTION) { - sb.append((char) LATCH_TO_TEXT); - encodingMode = TEXT_COMPACTION; - textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch - } - textSubMode = encodeText(msg, p, t, sb, textSubMode); - p += t; - } else { - int b = determineConsecutiveBinaryCount(msg, p, encoding); - if (b == 0) { - b = 1; - } - byte[] bytes = msg.substring(p, p + b).getBytes(encoding); - if (bytes.length == 1 && encodingMode == TEXT_COMPACTION) { - //Switch for one byte (instead of latch) - encodeBinary(bytes, 0, 1, TEXT_COMPACTION, sb); - } else { - //Mode latch performed by encodeBinary() - encodeBinary(bytes, 0, bytes.length, encodingMode, sb); - encodingMode = BYTE_COMPACTION; - textSubMode = SUBMODE_ALPHA; //Reset after latch - } - p += b; - } - } - } - } - - return sb.toString(); - } - - /** - * Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E), - * chapter 4.4.2. - * - * @param msg the message - * @param startpos the start position within the message - * @param count the number of characters to encode - * @param sb receives the encoded codewords - * @param initialSubmode should normally be SUBMODE_ALPHA - * @return the text submode in which this method ends - */ - private static int encodeText(CharSequence msg, - int startpos, - int count, - StringBuilder sb, - int initialSubmode) { - StringBuilder tmp = new StringBuilder(count); - int submode = initialSubmode; - int idx = 0; - while (true) { - char ch = msg.charAt(startpos + idx); - switch (submode) { - case SUBMODE_ALPHA: - if (isAlphaUpper(ch)) { - if (ch == ' ') { - tmp.append((char) 26); //space - } else { - tmp.append((char) (ch - 65)); - } - } else { - if (isAlphaLower(ch)) { - submode = SUBMODE_LOWER; - tmp.append((char) 27); //ll - continue; - } else if (isMixed(ch)) { - submode = SUBMODE_MIXED; - tmp.append((char) 28); //ml - continue; - } else { - tmp.append((char) 29); //ps - tmp.append((char) PUNCTUATION[ch]); - break; - } - } - break; - case SUBMODE_LOWER: - if (isAlphaLower(ch)) { - if (ch == ' ') { - tmp.append((char) 26); //space - } else { - tmp.append((char) (ch - 97)); - } - } else { - if (isAlphaUpper(ch)) { - tmp.append((char) 27); //as - tmp.append((char) (ch - 65)); - //space cannot happen here, it is also in "Lower" - break; - } else if (isMixed(ch)) { - submode = SUBMODE_MIXED; - tmp.append((char) 28); //ml - continue; - } else { - tmp.append((char) 29); //ps - tmp.append((char) PUNCTUATION[ch]); - break; - } - } - break; - case SUBMODE_MIXED: - if (isMixed(ch)) { - tmp.append((char) MIXED[ch]); - } else { - if (isAlphaUpper(ch)) { - submode = SUBMODE_ALPHA; - tmp.append((char) 28); //al - continue; - } else if (isAlphaLower(ch)) { - submode = SUBMODE_LOWER; - tmp.append((char) 27); //ll - continue; - } else { - if (startpos + idx + 1 < count) { - char next = msg.charAt(startpos + idx + 1); - if (isPunctuation(next)) { - submode = SUBMODE_PUNCTUATION; - tmp.append((char) 25); //pl - continue; - } - } - tmp.append((char) 29); //ps - tmp.append((char) PUNCTUATION[ch]); - } - } - break; - default: //SUBMODE_PUNCTUATION - if (isPunctuation(ch)) { - tmp.append((char) PUNCTUATION[ch]); - } else { - submode = SUBMODE_ALPHA; - tmp.append((char) 29); //al - continue; - } - } - idx++; - if (idx >= count) { - break; - } - } - char h = 0; - int len = tmp.length(); - for (int i = 0; i < len; i++) { - boolean odd = (i % 2) != 0; - if (odd) { - h = (char) ((h * 30) + tmp.charAt(i)); - sb.append(h); - } else { - h = tmp.charAt(i); - } - } - if ((len % 2) != 0) { - sb.append((char) ((h * 30) + 29)); //ps - } - return submode; - } - - /** - * Encode parts of the message using Byte Compaction as described in ISO/IEC 15438:2001(E), - * chapter 4.4.3. The Unicode characters will be converted to binary using the cp437 - * codepage. - * - * @param bytes the message converted to a byte array - * @param startpos the start position within the message - * @param count the number of bytes to encode - * @param startmode the mode from which this method starts - * @param sb receives the encoded codewords - */ - private static void encodeBinary(byte[] bytes, - int startpos, - int count, - int startmode, - StringBuilder sb) { - if (count == 1 && startmode == TEXT_COMPACTION) { - sb.append((char) SHIFT_TO_BYTE); - } else { - boolean sixpack = ((count % 6) == 0); - if (sixpack) { - sb.append((char)LATCH_TO_BYTE); - } else { - sb.append((char)LATCH_TO_BYTE_PADDED); - } - } - - int idx = startpos; - // Encode sixpacks - if (count >= 6) { - char[] chars = new char[5]; - while ((startpos + count - idx) >= 6) { - long t = 0; - for (int i = 0; i < 6; i++) { - t <<= 8; - t += bytes[idx + i] & 0xff; - } - for (int i = 0; i < 5; i++) { - chars[i] = (char) (t % 900); - t /= 900; - } - for (int i = chars.length - 1; i >= 0; i--) { - sb.append(chars[i]); - } - idx += 6; - } - } - //Encode rest (remaining n<5 bytes if any) - for (int i = idx; i < startpos + count; i++) { - int ch = bytes[i] & 0xff; - sb.append((char) ch); - } - } - - private static void encodeNumeric(String msg, int startpos, int count, StringBuilder sb) { - int idx = 0; - StringBuilder tmp = new StringBuilder(count / 3 + 1); - BigInteger num900 = BigInteger.valueOf(900); - BigInteger num0 = BigInteger.valueOf(0); - while (idx < count) { - tmp.setLength(0); - int len = Math.min(44, count - idx); - String part = '1' + msg.substring(startpos + idx, startpos + idx + len); - BigInteger bigint = new BigInteger(part); - do { - tmp.append((char) bigint.mod(num900).intValue()); - bigint = bigint.divide(num900); - } while (!bigint.equals(num0)); - - //Reverse temporary string - for (int i = tmp.length() - 1; i >= 0; i--) { - sb.append(tmp.charAt(i)); - } - idx += len; - } - } - - - private static boolean isDigit(char ch) { - return ch >= '0' && ch <= '9'; - } - - private static boolean isAlphaUpper(char ch) { - return ch == ' ' || (ch >= 'A' && ch <= 'Z'); - } - - private static boolean isAlphaLower(char ch) { - return ch == ' ' || (ch >= 'a' && ch <= 'z'); - } - - private static boolean isMixed(char ch) { - return MIXED[ch] != -1; - } - - private static boolean isPunctuation(char ch) { - return PUNCTUATION[ch] != -1; - } - - private static boolean isText(char ch) { - return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); - } - - /** - * Determines the number of consecutive characters that are encodable using numeric compaction. - * - * @param msg the message - * @param startpos the start position within the message - * @return the requested character count - */ - private static int determineConsecutiveDigitCount(CharSequence msg, int startpos) { - int count = 0; - int len = msg.length(); - int idx = startpos; - if (idx < len) { - char ch = msg.charAt(idx); - while (isDigit(ch) && idx < len) { - count++; - idx++; - if (idx < len) { - ch = msg.charAt(idx); - } - } - } - return count; - } - - /** - * Determines the number of consecutive characters that are encodable using text compaction. - * - * @param msg the message - * @param startpos the start position within the message - * @return the requested character count - */ - private static int determineConsecutiveTextCount(CharSequence msg, int startpos) { - int len = msg.length(); - int idx = startpos; - while (idx < len) { - char ch = msg.charAt(idx); - int numericCount = 0; - while (numericCount < 13 && isDigit(ch) && idx < len) { - numericCount++; - idx++; - if (idx < len) { - ch = msg.charAt(idx); - } - } - if (numericCount >= 13) { - return idx - startpos - numericCount; - } - if (numericCount > 0) { - //Heuristic: All text-encodable chars or digits are binary encodable - continue; - } - ch = msg.charAt(idx); - - //Check if character is encodable - if (!isText(ch)) { - break; - } - idx++; - } - return idx - startpos; - } - - /** - * Determines the number of consecutive characters that are encodable using binary compaction. - * - * @param msg the message - * @param startpos the start position within the message - * @param encoding the charset used to convert the message to a byte array - * @return the requested character count - */ - private static int determineConsecutiveBinaryCount(String msg, int startpos, Charset encoding) - throws WriterException { - final CharsetEncoder encoder = encoding.newEncoder(); - int len = msg.length(); - int idx = startpos; - while (idx < len) { - char ch = msg.charAt(idx); - int numericCount = 0; - - while (numericCount < 13 && isDigit(ch)) { - numericCount++; - //textCount++; - int i = idx + numericCount; - if (i >= len) { - break; - } - ch = msg.charAt(i); - } - if (numericCount >= 13) { - return idx - startpos; - } - ch = msg.charAt(idx); - - if (!encoder.canEncode(ch)) { - throw new WriterException("Non-encodable character detected: " + ch + " (Unicode: " + (int) ch + ')'); - } - idx++; - } - return idx - startpos; - } - - private static void encodingECI(int eci, StringBuilder sb) throws WriterException { - if (eci >= 0 && eci < 900) { - sb.append((char) ECI_CHARSET); - sb.append((char) eci); - } else if (eci < 810900) { - sb.append((char) ECI_GENERAL_PURPOSE); - sb.append((char) (eci / 900 - 1)); - sb.append((char) (eci % 900)); - } else if (eci < 811800) { - sb.append((char) ECI_USER_DEFINED); - sb.append((char) (810900 - eci)); - } else { - throw new WriterException("ECI number not in valid range from 0..811799, but was " + eci); - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeReader.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeReader.java deleted file mode 100644 index 310a40926..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeReader.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.Reader; -import com.google.zxing.Result; -import com.google.zxing.ResultMetadataType; -import com.google.zxing.ResultPoint; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.qrcode.decoder.Decoder; -import com.google.zxing.qrcode.decoder.QRCodeDecoderMetaData; -import com.google.zxing.qrcode.detector.Detector; - -import java.util.List; -import java.util.Map; - -/** - * This implementation can detect and decode QR Codes in an image. - * - * @author Sean Owen - */ -public class QRCodeReader implements Reader { - - private static final ResultPoint[] NO_POINTS = new ResultPoint[0]; - - private final Decoder decoder = new Decoder(); - - protected final Decoder getDecoder() { - return decoder; - } - - /** - * Locates and decodes a QR code in an image. - * - * @return a String representing the content encoded by the QR code - * @throws NotFoundException if a QR code cannot be found - * @throws FormatException if a QR code cannot be decoded - * @throws ChecksumException if error correction fails - */ - @Override - public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException { - return decode(image, null); - } - - @Override - public final Result decode(BinaryBitmap image, Map hints) - throws NotFoundException, ChecksumException, FormatException { - DecoderResult decoderResult; - ResultPoint[] points; - if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { - BitMatrix bits = extractPureBits(image.getBlackMatrix()); - decoderResult = decoder.decode(bits, hints); - points = NO_POINTS; - } else { - DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(hints); - decoderResult = decoder.decode(detectorResult.getBits(), hints); - points = detectorResult.getPoints(); - } - - // If the code was mirrored: swap the bottom-left and the top-right points. - if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) { - ((QRCodeDecoderMetaData) decoderResult.getOther()).applyMirroredCorrection(points); - } - - Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE); - List byteSegments = decoderResult.getByteSegments(); - if (byteSegments != null) { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - String ecLevel = decoderResult.getECLevel(); - if (ecLevel != null) { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - if (decoderResult.hasStructuredAppend()) { - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, - decoderResult.getStructuredAppendSequenceNumber()); - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, - decoderResult.getStructuredAppendParity()); - } - return result; - } - - @Override - public void reset() { - // do nothing - } - - /** - * This method detects a code in a "pure" image -- that is, pure monochrome image - * which contains only an unrotated, unskewed, image of a code, with some white border - * around it. This is a specialized method that works exceptionally fast in this special - * case. - * - * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix) - */ - private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException { - - int[] leftTopBlack = image.getTopLeftOnBit(); - int[] rightBottomBlack = image.getBottomRightOnBit(); - if (leftTopBlack == null || rightBottomBlack == null) { - throw NotFoundException.getNotFoundInstance(); - } - - float moduleSize = moduleSize(leftTopBlack, image); - - int top = leftTopBlack[1]; - int bottom = rightBottomBlack[1]; - int left = leftTopBlack[0]; - int right = rightBottomBlack[0]; - - // Sanity check! - if (left >= right || top >= bottom) { - throw NotFoundException.getNotFoundInstance(); - } - - if (bottom - top != right - left) { - // Special case, where bottom-right module wasn't black so we found something else in the last row - // Assume it's a square, so use height as the width - right = left + (bottom - top); - } - - int matrixWidth = Math.round((right - left + 1) / moduleSize); - int matrixHeight = Math.round((bottom - top + 1) / moduleSize); - if (matrixWidth <= 0 || matrixHeight <= 0) { - throw NotFoundException.getNotFoundInstance(); - } - if (matrixHeight != matrixWidth) { - // Only possibly decode square regions - throw NotFoundException.getNotFoundInstance(); - } - - // Push in the "border" by half the module width so that we start - // sampling in the middle of the module. Just in case the image is a - // little off, this will help recover. - int nudge = (int) (moduleSize / 2.0f); - top += nudge; - left += nudge; - - // But careful that this does not sample off the edge - // "right" is the farthest-right valid pixel location -- right+1 is not necessarily - // This is positive by how much the inner x loop below would be too large - int nudgedTooFarRight = left + (int) ((matrixWidth - 1) * moduleSize) - right; - if (nudgedTooFarRight > 0) { - if (nudgedTooFarRight > nudge) { - // Neither way fits; abort - throw NotFoundException.getNotFoundInstance(); - } - left -= nudgedTooFarRight; - } - // See logic above - int nudgedTooFarDown = top + (int) ((matrixHeight - 1) * moduleSize) - bottom; - if (nudgedTooFarDown > 0) { - if (nudgedTooFarDown > nudge) { - // Neither way fits; abort - throw NotFoundException.getNotFoundInstance(); - } - top -= nudgedTooFarDown; - } - - // Now just read off the bits - BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight); - for (int y = 0; y < matrixHeight; y++) { - int iOffset = top + (int) (y * moduleSize); - for (int x = 0; x < matrixWidth; x++) { - if (image.get(left + (int) (x * moduleSize), iOffset)) { - bits.set(x, y); - } - } - } - return bits; - } - - private static float moduleSize(int[] leftTopBlack, BitMatrix image) throws NotFoundException { - int height = image.getHeight(); - int width = image.getWidth(); - int x = leftTopBlack[0]; - int y = leftTopBlack[1]; - boolean inBlack = true; - int transitions = 0; - while (x < width && y < height) { - if (inBlack != image.get(x, y)) { - if (++transitions == 5) { - break; - } - inBlack = !inBlack; - } - x++; - y++; - } - if (x == width || y == height) { - throw NotFoundException.getNotFoundInstance(); - } - return (x - leftTopBlack[0]) / 7.0f; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeWriter.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeWriter.java deleted file mode 100644 index f5dcf089e..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/QRCodeWriter.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.Writer; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.encoder.ByteMatrix; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; -import com.google.zxing.qrcode.encoder.Encoder; -import com.google.zxing.qrcode.encoder.QRCode; - -import java.util.Map; - -/** - * This object renders a QR Code as a BitMatrix 2D array of greyscale values. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class QRCodeWriter implements Writer { - - private static final int QUIET_ZONE_SIZE = 4; - - @Override - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - throws WriterException { - - return encode(contents, format, width, height, null); - } - - @Override - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - Map hints) throws WriterException { - - if (contents.isEmpty()) { - throw new IllegalArgumentException("Found empty contents"); - } - - if (format != BarcodeFormat.QR_CODE) { - throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format); - } - - if (width < 0 || height < 0) { - throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' + - height); - } - - ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L; - int quietZone = QUIET_ZONE_SIZE; - if (hints != null) { - ErrorCorrectionLevel requestedECLevel = (ErrorCorrectionLevel) hints.get(EncodeHintType.ERROR_CORRECTION); - if (requestedECLevel != null) { - errorCorrectionLevel = requestedECLevel; - } - Integer quietZoneInt = (Integer) hints.get(EncodeHintType.MARGIN); - if (quietZoneInt != null) { - quietZone = quietZoneInt; - } - } - - QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints); - return renderResult(code, width, height, quietZone); - } - - // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses - // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). - private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) { - ByteMatrix input = code.getMatrix(); - if (input == null) { - throw new IllegalStateException(); - } - int inputWidth = input.getWidth(); - int inputHeight = input.getHeight(); - int qrWidth = inputWidth + (quietZone * 2); - int qrHeight = inputHeight + (quietZone * 2); - int outputWidth = Math.max(width, qrWidth); - int outputHeight = Math.max(height, qrHeight); - - int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight); - // Padding includes both the quiet zone and the extra white pixels to accommodate the requested - // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. - // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will - // handle all the padding from 100x100 (the actual QR) up to 200x160. - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - int topPadding = (outputHeight - (inputHeight * multiple)) / 2; - - BitMatrix output = new BitMatrix(outputWidth, outputHeight); - - for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) { - // Write the contents of this row of the barcode - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { - if (input.get(inputX, inputY) == 1) { - output.setRegion(outputX, outputY, multiple, multiple); - } - } - } - - return output; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/BitMatrixParser.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/BitMatrixParser.java deleted file mode 100644 index 10cb475a9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/BitMatrixParser.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; - -/** - * @author Sean Owen - */ -final class BitMatrixParser { - - private final BitMatrix bitMatrix; - private Version parsedVersion; - private FormatInformation parsedFormatInfo; - private boolean mirror; - - /** - * @param bitMatrix {@link BitMatrix} to parse - * @throws FormatException if dimension is not >= 21 and 1 mod 4 - */ - BitMatrixParser(BitMatrix bitMatrix) throws FormatException { - int dimension = bitMatrix.getHeight(); - if (dimension < 21 || (dimension & 0x03) != 1) { - throw FormatException.getFormatInstance(); - } - this.bitMatrix = bitMatrix; - } - - /** - *

    Reads format information from one of its two locations within the QR Code.

    - * - * @return {@link FormatInformation} encapsulating the QR Code's format info - * @throws FormatException if both format information locations cannot be parsed as - * the valid encoding of format information - */ - FormatInformation readFormatInformation() throws FormatException { - - if (parsedFormatInfo != null) { - return parsedFormatInfo; - } - - // Read top-left format info bits - int formatInfoBits1 = 0; - for (int i = 0; i < 6; i++) { - formatInfoBits1 = copyBit(i, 8, formatInfoBits1); - } - // .. and skip a bit in the timing pattern ... - formatInfoBits1 = copyBit(7, 8, formatInfoBits1); - formatInfoBits1 = copyBit(8, 8, formatInfoBits1); - formatInfoBits1 = copyBit(8, 7, formatInfoBits1); - // .. and skip a bit in the timing pattern ... - for (int j = 5; j >= 0; j--) { - formatInfoBits1 = copyBit(8, j, formatInfoBits1); - } - - // Read the top-right/bottom-left pattern too - int dimension = bitMatrix.getHeight(); - int formatInfoBits2 = 0; - int jMin = dimension - 7; - for (int j = dimension - 1; j >= jMin; j--) { - formatInfoBits2 = copyBit(8, j, formatInfoBits2); - } - for (int i = dimension - 8; i < dimension; i++) { - formatInfoBits2 = copyBit(i, 8, formatInfoBits2); - } - - parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2); - if (parsedFormatInfo != null) { - return parsedFormatInfo; - } - throw FormatException.getFormatInstance(); - } - - /** - *

    Reads version information from one of its two locations within the QR Code.

    - * - * @return {@link Version} encapsulating the QR Code's version - * @throws FormatException if both version information locations cannot be parsed as - * the valid encoding of version information - */ - Version readVersion() throws FormatException { - - if (parsedVersion != null) { - return parsedVersion; - } - - int dimension = bitMatrix.getHeight(); - - int provisionalVersion = (dimension - 17) / 4; - if (provisionalVersion <= 6) { - return Version.getVersionForNumber(provisionalVersion); - } - - // Read top-right version info: 3 wide by 6 tall - int versionBits = 0; - int ijMin = dimension - 11; - for (int j = 5; j >= 0; j--) { - for (int i = dimension - 9; i >= ijMin; i--) { - versionBits = copyBit(i, j, versionBits); - } - } - - Version theParsedVersion = Version.decodeVersionInformation(versionBits); - if (theParsedVersion != null && theParsedVersion.getDimensionForVersion() == dimension) { - parsedVersion = theParsedVersion; - return theParsedVersion; - } - - // Hmm, failed. Try bottom left: 6 wide by 3 tall - versionBits = 0; - for (int i = 5; i >= 0; i--) { - for (int j = dimension - 9; j >= ijMin; j--) { - versionBits = copyBit(i, j, versionBits); - } - } - - theParsedVersion = Version.decodeVersionInformation(versionBits); - if (theParsedVersion != null && theParsedVersion.getDimensionForVersion() == dimension) { - parsedVersion = theParsedVersion; - return theParsedVersion; - } - throw FormatException.getFormatInstance(); - } - - private int copyBit(int i, int j, int versionBits) { - boolean bit = mirror ? bitMatrix.get(j, i) : bitMatrix.get(i, j); - return bit ? (versionBits << 1) | 0x1 : versionBits << 1; - } - - /** - *

    Reads the bits in the {@link BitMatrix} representing the finder pattern in the - * correct order in order to reconstruct the codewords bytes contained within the - * QR Code.

    - * - * @return bytes encoded within the QR Code - * @throws FormatException if the exact number of bytes expected is not read - */ - byte[] readCodewords() throws FormatException { - - FormatInformation formatInfo = readFormatInformation(); - Version version = readVersion(); - - // Get the data mask for the format used in this QR Code. This will exclude - // some bits from reading as we wind through the bit matrix. - DataMask dataMask = DataMask.forReference(formatInfo.getDataMask()); - int dimension = bitMatrix.getHeight(); - dataMask.unmaskBitMatrix(bitMatrix, dimension); - - BitMatrix functionPattern = version.buildFunctionPattern(); - - boolean readingUp = true; - byte[] result = new byte[version.getTotalCodewords()]; - int resultOffset = 0; - int currentByte = 0; - int bitsRead = 0; - // Read columns in pairs, from right to left - for (int j = dimension - 1; j > 0; j -= 2) { - if (j == 6) { - // Skip whole column with vertical alignment pattern; - // saves time and makes the other code proceed more cleanly - j--; - } - // Read alternatingly from bottom to top then top to bottom - for (int count = 0; count < dimension; count++) { - int i = readingUp ? dimension - 1 - count : count; - for (int col = 0; col < 2; col++) { - // Ignore bits covered by the function pattern - if (!functionPattern.get(j - col, i)) { - // Read a bit - bitsRead++; - currentByte <<= 1; - if (bitMatrix.get(j - col, i)) { - currentByte |= 1; - } - // If we've made a whole byte, save it off - if (bitsRead == 8) { - result[resultOffset++] = (byte) currentByte; - bitsRead = 0; - currentByte = 0; - } - } - } - } - readingUp ^= true; // readingUp = !readingUp; // switch directions - } - if (resultOffset != version.getTotalCodewords()) { - throw FormatException.getFormatInstance(); - } - return result; - } - - /** - * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state. - */ - void remask() { - if (parsedFormatInfo == null) { - return; // We have no format information, and have no data mask - } - DataMask dataMask = DataMask.forReference(parsedFormatInfo.getDataMask()); - int dimension = bitMatrix.getHeight(); - dataMask.unmaskBitMatrix(bitMatrix, dimension); - } - - /** - * Prepare the parser for a mirrored operation. - * This flag has effect only on the {@link #readFormatInformation()} and the - * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the - * {@link #mirror()} method should be called. - * - * @param mirror Whether to read version and format information mirrored. - */ - void setMirror(boolean mirror) { - parsedVersion = null; - parsedFormatInfo = null; - this.mirror = mirror; - } - - /** Mirror the bit matrix in order to attempt a second reading. */ - void mirror() { - for (int x = 0; x < bitMatrix.getWidth(); x++) { - for (int y = x + 1; y < bitMatrix.getHeight(); y++) { - if (bitMatrix.get(x, y) != bitMatrix.get(y, x)) { - bitMatrix.flip(y, x); - bitMatrix.flip(x, y); - } - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataBlock.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataBlock.java deleted file mode 100755 index 8f5cdcba7..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataBlock.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -/** - *

    Encapsulates a block of data within a QR Code. QR Codes may split their data into - * multiple blocks, each of which is a unit of data and error-correction codewords. Each - * is represented by an instance of this class.

    - * - * @author Sean Owen - */ -final class DataBlock { - - private final int numDataCodewords; - private final byte[] codewords; - - private DataBlock(int numDataCodewords, byte[] codewords) { - this.numDataCodewords = numDataCodewords; - this.codewords = codewords; - } - - /** - *

    When QR Codes use multiple data blocks, they are actually interleaved. - * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This - * method will separate the data into original blocks.

    - * - * @param rawCodewords bytes as read directly from the QR Code - * @param version version of the QR Code - * @param ecLevel error-correction level of the QR Code - * @return DataBlocks containing original bytes, "de-interleaved" from representation in the - * QR Code - */ - static DataBlock[] getDataBlocks(byte[] rawCodewords, - Version version, - ErrorCorrectionLevel ecLevel) { - - if (rawCodewords.length != version.getTotalCodewords()) { - throw new IllegalArgumentException(); - } - - // Figure out the number and size of data blocks used by this version and - // error correction level - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - - // First count the total number of data blocks - int totalBlocks = 0; - Version.ECB[] ecBlockArray = ecBlocks.getECBlocks(); - for (Version.ECB ecBlock : ecBlockArray) { - totalBlocks += ecBlock.getCount(); - } - - // Now establish DataBlocks of the appropriate size and number of data codewords - DataBlock[] result = new DataBlock[totalBlocks]; - int numResultBlocks = 0; - for (Version.ECB ecBlock : ecBlockArray) { - for (int i = 0; i < ecBlock.getCount(); i++) { - int numDataCodewords = ecBlock.getDataCodewords(); - int numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords; - result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]); - } - } - - // All blocks have the same amount of data, except that the last n - // (where n may be 0) have 1 more byte. Figure out where these start. - int shorterBlocksTotalCodewords = result[0].codewords.length; - int longerBlocksStartAt = result.length - 1; - while (longerBlocksStartAt >= 0) { - int numCodewords = result[longerBlocksStartAt].codewords.length; - if (numCodewords == shorterBlocksTotalCodewords) { - break; - } - longerBlocksStartAt--; - } - longerBlocksStartAt++; - - int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock(); - // The last elements of result may be 1 element longer; - // first fill out as many elements as all of them have - int rawCodewordsOffset = 0; - for (int i = 0; i < shorterBlocksNumDataCodewords; i++) { - for (int j = 0; j < numResultBlocks; j++) { - result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; - } - } - // Fill out the last data block in the longer ones - for (int j = longerBlocksStartAt; j < numResultBlocks; j++) { - result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; - } - // Now add in error correction blocks - int max = result[0].codewords.length; - for (int i = shorterBlocksNumDataCodewords; i < max; i++) { - for (int j = 0; j < numResultBlocks; j++) { - int iOffset = j < longerBlocksStartAt ? i : i + 1; - result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; - } - } - return result; - } - - int getNumDataCodewords() { - return numDataCodewords; - } - - byte[] getCodewords() { - return codewords; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataMask.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataMask.java deleted file mode 100755 index c1dbbb798..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DataMask.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.common.BitMatrix; - -/** - *

    Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations - * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix, - * including areas used for finder patterns, timing patterns, etc. These areas should be unused - * after the point they are unmasked anyway.

    - * - *

    Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position - * and j is row position. In fact, as the text says, i is row position and j is column position.

    - * - * @author Sean Owen - */ -abstract class DataMask { - - /** - * See ISO 18004:2006 6.8.1 - */ - private static final DataMask[] DATA_MASKS = { - new DataMask000(), - new DataMask001(), - new DataMask010(), - new DataMask011(), - new DataMask100(), - new DataMask101(), - new DataMask110(), - new DataMask111(), - }; - - private DataMask() { - } - - /** - *

    Implementations of this method reverse the data masking process applied to a QR Code and - * make its bits ready to read.

    - * - * @param bits representation of QR Code bits - * @param dimension dimension of QR Code, represented by bits, being unmasked - */ - final void unmaskBitMatrix(BitMatrix bits, int dimension) { - for (int i = 0; i < dimension; i++) { - for (int j = 0; j < dimension; j++) { - if (isMasked(i, j)) { - bits.flip(j, i); - } - } - } - } - - abstract boolean isMasked(int i, int j); - - /** - * @param reference a value between 0 and 7 indicating one of the eight possible - * data mask patterns a QR Code may use - * @return DataMask encapsulating the data mask pattern - */ - static DataMask forReference(int reference) { - if (reference < 0 || reference > 7) { - throw new IllegalArgumentException(); - } - return DATA_MASKS[reference]; - } - - /** - * 000: mask bits for which (x + y) mod 2 == 0 - */ - private static final class DataMask000 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return ((i + j) & 0x01) == 0; - } - } - - /** - * 001: mask bits for which x mod 2 == 0 - */ - private static final class DataMask001 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return (i & 0x01) == 0; - } - } - - /** - * 010: mask bits for which y mod 3 == 0 - */ - private static final class DataMask010 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return j % 3 == 0; - } - } - - /** - * 011: mask bits for which (x + y) mod 3 == 0 - */ - private static final class DataMask011 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return (i + j) % 3 == 0; - } - } - - /** - * 100: mask bits for which (x/2 + y/3) mod 2 == 0 - */ - private static final class DataMask100 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return (((i / 2) + (j /3)) & 0x01) == 0; - } - } - - /** - * 101: mask bits for which xy mod 2 + xy mod 3 == 0 - */ - private static final class DataMask101 extends DataMask { - @Override - boolean isMasked(int i, int j) { - int temp = i * j; - return (temp & 0x01) + (temp % 3) == 0; - } - } - - /** - * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 - */ - private static final class DataMask110 extends DataMask { - @Override - boolean isMasked(int i, int j) { - int temp = i * j; - return (((temp & 0x01) + (temp % 3)) & 0x01) == 0; - } - } - - /** - * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 - */ - private static final class DataMask111 extends DataMask { - @Override - boolean isMasked(int i, int j) { - return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0; - } - } -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java deleted file mode 100644 index 319495802..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.common.BitSource; -import com.google.zxing.common.CharacterSetECI; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.StringUtils; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - *

    QR Codes can encode text as bits in one of several modes, and can use multiple modes - * in one QR Code. This class decodes the bits back into text.

    - * - *

    See ISO 18004:2006, 6.4.3 - 6.4.7

    - * - * @author Sean Owen - */ -final class DecodedBitStreamParser { - - /** - * See ISO 18004:2006, 6.4.4 Table 5 - */ - private static final char[] ALPHANUMERIC_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - ' ', '$', '%', '*', '+', '-', '.', '/', ':' - }; - private static final int GB2312_SUBSET = 1; - - private DecodedBitStreamParser() { - } - - static DecoderResult decode(byte[] bytes, - Version version, - ErrorCorrectionLevel ecLevel, - Map hints) throws FormatException { - BitSource bits = new BitSource(bytes); - StringBuilder result = new StringBuilder(50); - List byteSegments = new ArrayList<>(1); - int symbolSequence = -1; - int parityData = -1; - - try { - CharacterSetECI currentCharacterSetECI = null; - boolean fc1InEffect = false; - Mode mode; - do { - // While still another segment to read... - if (bits.available() < 4) { - // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here - mode = Mode.TERMINATOR; - } else { - mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits - } - if (mode != Mode.TERMINATOR) { - if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION) { - // We do little with FNC1 except alter the parsed result a bit according to the spec - fc1InEffect = true; - } else if (mode == Mode.STRUCTURED_APPEND) { - if (bits.available() < 16) { - throw FormatException.getFormatInstance(); - } - // sequence number and parity is added later to the result metadata - // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue - symbolSequence = bits.readBits(8); - parityData = bits.readBits(8); - } else if (mode == Mode.ECI) { - // Count doesn't apply to ECI - int value = parseECIValue(bits); - currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); - if (currentCharacterSetECI == null) { - throw FormatException.getFormatInstance(); - } - } else { - // First handle Hanzi mode which does not start with character count - if (mode == Mode.HANZI) { - //chinese mode contains a sub set indicator right after mode indicator - int subset = bits.readBits(4); - int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); - if (subset == GB2312_SUBSET) { - decodeHanziSegment(bits, result, countHanzi); - } - } else { - // "Normal" QR code modes: - // How many characters will follow, encoded in this mode? - int count = bits.readBits(mode.getCharacterCountBits(version)); - if (mode == Mode.NUMERIC) { - decodeNumericSegment(bits, result, count); - } else if (mode == Mode.ALPHANUMERIC) { - decodeAlphanumericSegment(bits, result, count, fc1InEffect); - } else if (mode == Mode.BYTE) { - decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints); - } else if (mode == Mode.KANJI) { - decodeKanjiSegment(bits, result, count); - } else { - throw FormatException.getFormatInstance(); - } - } - } - } - } while (mode != Mode.TERMINATOR); - } catch (IllegalArgumentException iae) { - // from readBits() calls - throw FormatException.getFormatInstance(); - } - - return new DecoderResult(bytes, - result.toString(), - byteSegments.isEmpty() ? null : byteSegments, - ecLevel == null ? null : ecLevel.toString(), - symbolSequence, - parityData); - } - - /** - * See specification GBT 18284-2000 - */ - private static void decodeHanziSegment(BitSource bits, - StringBuilder result, - int count) throws FormatException { - // Don't crash trying to read more bits than we have available. - if (count * 13 > bits.available()) { - throw FormatException.getFormatInstance(); - } - - // Each character will require 2 bytes. Read the characters as 2-byte pairs - // and decode as GB2312 afterwards - byte[] buffer = new byte[2 * count]; - int offset = 0; - while (count > 0) { - // Each 13 bits encodes a 2-byte character - int twoBytes = bits.readBits(13); - int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060); - if (assembledTwoBytes < 0x003BF) { - // In the 0xA1A1 to 0xAAFE range - assembledTwoBytes += 0x0A1A1; - } else { - // In the 0xB0A1 to 0xFAFE range - assembledTwoBytes += 0x0A6A1; - } - buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF); - buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF); - offset += 2; - count--; - } - - try { - result.append(new String(buffer, StringUtils.GB2312)); - } catch (UnsupportedEncodingException ignored) { - throw FormatException.getFormatInstance(); - } - } - - private static void decodeKanjiSegment(BitSource bits, - StringBuilder result, - int count) throws FormatException { - // Don't crash trying to read more bits than we have available. - if (count * 13 > bits.available()) { - throw FormatException.getFormatInstance(); - } - - // Each character will require 2 bytes. Read the characters as 2-byte pairs - // and decode as Shift_JIS afterwards - byte[] buffer = new byte[2 * count]; - int offset = 0; - while (count > 0) { - // Each 13 bits encodes a 2-byte character - int twoBytes = bits.readBits(13); - int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0); - if (assembledTwoBytes < 0x01F00) { - // In the 0x8140 to 0x9FFC range - assembledTwoBytes += 0x08140; - } else { - // In the 0xE040 to 0xEBBF range - assembledTwoBytes += 0x0C140; - } - buffer[offset] = (byte) (assembledTwoBytes >> 8); - buffer[offset + 1] = (byte) assembledTwoBytes; - offset += 2; - count--; - } - // Shift_JIS may not be supported in some environments: - try { - result.append(new String(buffer, StringUtils.SHIFT_JIS)); - } catch (UnsupportedEncodingException ignored) { - throw FormatException.getFormatInstance(); - } - } - - private static void decodeByteSegment(BitSource bits, - StringBuilder result, - int count, - CharacterSetECI currentCharacterSetECI, - Collection byteSegments, - Map hints) throws FormatException { - // Don't crash trying to read more bits than we have available. - if (8 * count > bits.available()) { - throw FormatException.getFormatInstance(); - } - - byte[] readBytes = new byte[count]; - for (int i = 0; i < count; i++) { - readBytes[i] = (byte) bits.readBits(8); - } - String encoding; - if (currentCharacterSetECI == null) { - // The spec isn't clear on this mode; see - // section 6.4.5: t does not say which encoding to assuming - // upon decoding. I have seen ISO-8859-1 used as well as - // Shift_JIS -- without anything like an ECI designator to - // give a hint. - encoding = StringUtils.guessEncoding(readBytes, hints); - } else { - encoding = currentCharacterSetECI.name(); - } - try { - result.append(new String(readBytes, encoding)); - } catch (UnsupportedEncodingException ignored) { - throw FormatException.getFormatInstance(); - } - byteSegments.add(readBytes); - } - - private static char toAlphaNumericChar(int value) throws FormatException { - if (value >= ALPHANUMERIC_CHARS.length) { - throw FormatException.getFormatInstance(); - } - return ALPHANUMERIC_CHARS[value]; - } - - private static void decodeAlphanumericSegment(BitSource bits, - StringBuilder result, - int count, - boolean fc1InEffect) throws FormatException { - // Read two characters at a time - int start = result.length(); - while (count > 1) { - if (bits.available() < 11) { - throw FormatException.getFormatInstance(); - } - int nextTwoCharsBits = bits.readBits(11); - result.append(toAlphaNumericChar(nextTwoCharsBits / 45)); - result.append(toAlphaNumericChar(nextTwoCharsBits % 45)); - count -= 2; - } - if (count == 1) { - // special case: one character left - if (bits.available() < 6) { - throw FormatException.getFormatInstance(); - } - result.append(toAlphaNumericChar(bits.readBits(6))); - } - // See section 6.4.8.1, 6.4.8.2 - if (fc1InEffect) { - // We need to massage the result a bit if in an FNC1 mode: - for (int i = start; i < result.length(); i++) { - if (result.charAt(i) == '%') { - if (i < result.length() - 1 && result.charAt(i + 1) == '%') { - // %% is rendered as % - result.deleteCharAt(i + 1); - } else { - // In alpha mode, % should be converted to FNC1 separator 0x1D - result.setCharAt(i, (char) 0x1D); - } - } - } - } - } - - private static void decodeNumericSegment(BitSource bits, - StringBuilder result, - int count) throws FormatException { - // Read three digits at a time - while (count >= 3) { - // Each 10 bits encodes three digits - if (bits.available() < 10) { - throw FormatException.getFormatInstance(); - } - int threeDigitsBits = bits.readBits(10); - if (threeDigitsBits >= 1000) { - throw FormatException.getFormatInstance(); - } - result.append(toAlphaNumericChar(threeDigitsBits / 100)); - result.append(toAlphaNumericChar((threeDigitsBits / 10) % 10)); - result.append(toAlphaNumericChar(threeDigitsBits % 10)); - count -= 3; - } - if (count == 2) { - // Two digits left over to read, encoded in 7 bits - if (bits.available() < 7) { - throw FormatException.getFormatInstance(); - } - int twoDigitsBits = bits.readBits(7); - if (twoDigitsBits >= 100) { - throw FormatException.getFormatInstance(); - } - result.append(toAlphaNumericChar(twoDigitsBits / 10)); - result.append(toAlphaNumericChar(twoDigitsBits % 10)); - } else if (count == 1) { - // One digit left over to read - if (bits.available() < 4) { - throw FormatException.getFormatInstance(); - } - int digitBits = bits.readBits(4); - if (digitBits >= 10) { - throw FormatException.getFormatInstance(); - } - result.append(toAlphaNumericChar(digitBits)); - } - } - - private static int parseECIValue(BitSource bits) throws FormatException { - int firstByte = bits.readBits(8); - if ((firstByte & 0x80) == 0) { - // just one byte - return firstByte & 0x7F; - } - if ((firstByte & 0xC0) == 0x80) { - // two bytes - int secondByte = bits.readBits(8); - return ((firstByte & 0x3F) << 8) | secondByte; - } - if ((firstByte & 0xE0) == 0xC0) { - // three bytes - int secondThirdBytes = bits.readBits(16); - return ((firstByte & 0x1F) << 16) | secondThirdBytes; - } - throw FormatException.getFormatInstance(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Decoder.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Decoder.java deleted file mode 100644 index b28267e20..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Decoder.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.ChecksumException; -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DecoderResult; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonDecoder; -import com.google.zxing.common.reedsolomon.ReedSolomonException; - -import java.util.Map; - -/** - *

    The main class which implements QR Code decoding -- as opposed to locating and extracting - * the QR Code from an image.

    - * - * @author Sean Owen - */ -public final class Decoder { - - private final ReedSolomonDecoder rsDecoder; - - public Decoder() { - rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256); - } - - public DecoderResult decode(boolean[][] image) throws ChecksumException, FormatException { - return decode(image, null); - } - - /** - *

    Convenience method that can decode a QR Code represented as a 2D array of booleans. - * "true" is taken to mean a black module.

    - * - * @param image booleans representing white/black QR Code modules - * @param hints decoding hints that should be used to influence decoding - * @return text and bytes encoded within the QR Code - * @throws FormatException if the QR Code cannot be decoded - * @throws ChecksumException if error correction fails - */ - public DecoderResult decode(boolean[][] image, Map hints) - throws ChecksumException, FormatException { - int dimension = image.length; - BitMatrix bits = new BitMatrix(dimension); - for (int i = 0; i < dimension; i++) { - for (int j = 0; j < dimension; j++) { - if (image[i][j]) { - bits.set(j, i); - } - } - } - return decode(bits, hints); - } - - public DecoderResult decode(BitMatrix bits) throws ChecksumException, FormatException { - return decode(bits, null); - } - - /** - *

    Decodes a QR Code represented as a {@link BitMatrix}. A 1 or "true" is taken to mean a black module.

    - * - * @param bits booleans representing white/black QR Code modules - * @param hints decoding hints that should be used to influence decoding - * @return text and bytes encoded within the QR Code - * @throws FormatException if the QR Code cannot be decoded - * @throws ChecksumException if error correction fails - */ - public DecoderResult decode(BitMatrix bits, Map hints) - throws FormatException, ChecksumException { - - // Construct a parser and read version, error-correction level - BitMatrixParser parser = new BitMatrixParser(bits); - FormatException fe = null; - ChecksumException ce = null; - try { - return decode(parser, hints); - } catch (FormatException e) { - fe = e; - } catch (ChecksumException e) { - ce = e; - } - - try { - - // Revert the bit matrix - parser.remask(); - - // Will be attempting a mirrored reading of the version and format info. - parser.setMirror(true); - - // Preemptively read the version. - parser.readVersion(); - - // Preemptively read the format information. - parser.readFormatInformation(); - - /* - * Since we're here, this means we have successfully detected some kind - * of version and format information when mirrored. This is a good sign, - * that the QR code may be mirrored, and we should try once more with a - * mirrored content. - */ - // Prepare for a mirrored reading. - parser.mirror(); - - DecoderResult result = decode(parser, hints); - - // Success! Notify the caller that the code was mirrored. - result.setOther(new QRCodeDecoderMetaData(true)); - - return result; - - } catch (FormatException | ChecksumException e) { - // Throw the exception from the original reading - if (fe != null) { - throw fe; - } - if (ce != null) { - throw ce; - } - throw e; - - } - } - - private DecoderResult decode(BitMatrixParser parser, Map hints) - throws FormatException, ChecksumException { - Version version = parser.readVersion(); - ErrorCorrectionLevel ecLevel = parser.readFormatInformation().getErrorCorrectionLevel(); - - // Read codewords - byte[] codewords = parser.readCodewords(); - // Separate into data blocks - DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel); - - // Count total number of data bytes - int totalBytes = 0; - for (DataBlock dataBlock : dataBlocks) { - totalBytes += dataBlock.getNumDataCodewords(); - } - byte[] resultBytes = new byte[totalBytes]; - int resultOffset = 0; - - // Error-correct and copy data blocks together into a stream of bytes - for (DataBlock dataBlock : dataBlocks) { - byte[] codewordBytes = dataBlock.getCodewords(); - int numDataCodewords = dataBlock.getNumDataCodewords(); - correctErrors(codewordBytes, numDataCodewords); - for (int i = 0; i < numDataCodewords; i++) { - resultBytes[resultOffset++] = codewordBytes[i]; - } - } - - // Decode the contents of that stream of bytes - return DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints); - } - - /** - *

    Given data and error-correction codewords received, possibly corrupted by errors, attempts to - * correct the errors in-place using Reed-Solomon error correction.

    - * - * @param codewordBytes data and error correction codewords - * @param numDataCodewords number of codewords that are data bytes - * @throws ChecksumException if error correction fails - */ - private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException { - int numCodewords = codewordBytes.length; - // First read into an array of ints - int[] codewordsInts = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++) { - codewordsInts[i] = codewordBytes[i] & 0xFF; - } - int numECCodewords = codewordBytes.length - numDataCodewords; - try { - rsDecoder.decode(codewordsInts, numECCodewords); - } catch (ReedSolomonException ignored) { - throw ChecksumException.getChecksumInstance(); - } - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < numDataCodewords; i++) { - codewordBytes[i] = (byte) codewordsInts[i]; - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java deleted file mode 100644 index 0f1e11387..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -/** - *

    See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels - * defined by the QR code standard.

    - * - * @author Sean Owen - */ -public enum ErrorCorrectionLevel { - - /** L = ~7% correction */ - L(0x01), - /** M = ~15% correction */ - M(0x00), - /** Q = ~25% correction */ - Q(0x03), - /** H = ~30% correction */ - H(0x02); - - private static final ErrorCorrectionLevel[] FOR_BITS = {M, L, H, Q}; - - private final int bits; - - ErrorCorrectionLevel(int bits) { - this.bits = bits; - } - - public int getBits() { - return bits; - } - - /** - * @param bits int containing the two bits encoding a QR Code's error correction level - * @return ErrorCorrectionLevel representing the encoded error correction level - */ - public static ErrorCorrectionLevel forBits(int bits) { - if (bits < 0 || bits >= FOR_BITS.length) { - throw new IllegalArgumentException(); - } - return FOR_BITS[bits]; - } - - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/FormatInformation.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/FormatInformation.java deleted file mode 100644 index 894e32175..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/FormatInformation.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -/** - *

    Encapsulates a QR Code's format information, including the data mask used and - * error correction level.

    - * - * @author Sean Owen - * @see DataMask - * @see ErrorCorrectionLevel - */ -final class FormatInformation { - - private static final int FORMAT_INFO_MASK_QR = 0x5412; - - /** - * See ISO 18004:2006, Annex C, Table C.1 - */ - private static final int[][] FORMAT_INFO_DECODE_LOOKUP = { - {0x5412, 0x00}, - {0x5125, 0x01}, - {0x5E7C, 0x02}, - {0x5B4B, 0x03}, - {0x45F9, 0x04}, - {0x40CE, 0x05}, - {0x4F97, 0x06}, - {0x4AA0, 0x07}, - {0x77C4, 0x08}, - {0x72F3, 0x09}, - {0x7DAA, 0x0A}, - {0x789D, 0x0B}, - {0x662F, 0x0C}, - {0x6318, 0x0D}, - {0x6C41, 0x0E}, - {0x6976, 0x0F}, - {0x1689, 0x10}, - {0x13BE, 0x11}, - {0x1CE7, 0x12}, - {0x19D0, 0x13}, - {0x0762, 0x14}, - {0x0255, 0x15}, - {0x0D0C, 0x16}, - {0x083B, 0x17}, - {0x355F, 0x18}, - {0x3068, 0x19}, - {0x3F31, 0x1A}, - {0x3A06, 0x1B}, - {0x24B4, 0x1C}, - {0x2183, 0x1D}, - {0x2EDA, 0x1E}, - {0x2BED, 0x1F}, - }; - - /** - * Offset i holds the number of 1 bits in the binary representation of i - */ - private static final int[] BITS_SET_IN_HALF_BYTE = - {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; - - private final ErrorCorrectionLevel errorCorrectionLevel; - private final byte dataMask; - - private FormatInformation(int formatInfo) { - // Bits 3,4 - errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); - // Bottom 3 bits - dataMask = (byte) (formatInfo & 0x07); - } - - static int numBitsDiffering(int a, int b) { - a ^= b; // a now has a 1 bit exactly where its bit differs with b's - // Count bits set quickly with a series of lookups: - return BITS_SET_IN_HALF_BYTE[a & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >>> 4 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 8 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 12 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 16 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 20 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 24 & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(a >>> 28 & 0x0F)]; - } - - /** - * @param maskedFormatInfo1 format info indicator, with mask still applied - * @param maskedFormatInfo2 second copy of same info; both are checked at the same time - * to establish best match - * @return information about the format it specifies, or {@code null} - * if doesn't seem to match any known pattern - */ - static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) { - FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); - if (formatInfo != null) { - return formatInfo; - } - // Should return null, but, some QR codes apparently - // do not mask this info. Try again by actually masking the pattern - // first - return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR, - maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR); - } - - private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) { - // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing - int bestDifference = Integer.MAX_VALUE; - int bestFormatInfo = 0; - for (int[] decodeInfo : FORMAT_INFO_DECODE_LOOKUP) { - int targetInfo = decodeInfo[0]; - if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) { - // Found an exact match - return new FormatInformation(decodeInfo[1]); - } - int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo); - if (bitsDifference < bestDifference) { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - if (maskedFormatInfo1 != maskedFormatInfo2) { - // also try the other option - bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo); - if (bitsDifference < bestDifference) { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - } - } - // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits - // differing means we found a match - if (bestDifference <= 3) { - return new FormatInformation(bestFormatInfo); - } - return null; - } - - ErrorCorrectionLevel getErrorCorrectionLevel() { - return errorCorrectionLevel; - } - - byte getDataMask() { - return dataMask; - } - - @Override - public int hashCode() { - return (errorCorrectionLevel.ordinal() << 3) | (int) dataMask; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof FormatInformation)) { - return false; - } - FormatInformation other = (FormatInformation) o; - return this.errorCorrectionLevel == other.errorCorrectionLevel && - this.dataMask == other.dataMask; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Mode.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Mode.java deleted file mode 100644 index b7e9ab3a9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Mode.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -/** - *

    See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which - * data can be encoded to bits in the QR code standard.

    - * - * @author Sean Owen - */ -public enum Mode { - - TERMINATOR(new int[]{0, 0, 0}, 0x00), // Not really a mode... - NUMERIC(new int[]{10, 12, 14}, 0x01), - ALPHANUMERIC(new int[]{9, 11, 13}, 0x02), - STRUCTURED_APPEND(new int[]{0, 0, 0}, 0x03), // Not supported - BYTE(new int[]{8, 16, 16}, 0x04), - ECI(new int[]{0, 0, 0}, 0x07), // character counts don't apply - KANJI(new int[]{8, 10, 12}, 0x08), - FNC1_FIRST_POSITION(new int[]{0, 0, 0}, 0x05), - FNC1_SECOND_POSITION(new int[]{0, 0, 0}, 0x09), - /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ - HANZI(new int[]{8, 10, 12}, 0x0D); - - private final int[] characterCountBitsForVersions; - private final int bits; - - Mode(int[] characterCountBitsForVersions, int bits) { - this.characterCountBitsForVersions = characterCountBitsForVersions; - this.bits = bits; - } - - /** - * @param bits four bits encoding a QR Code data mode - * @return Mode encoded by these bits - * @throws IllegalArgumentException if bits do not correspond to a known mode - */ - public static Mode forBits(int bits) { - switch (bits) { - case 0x0: - return TERMINATOR; - case 0x1: - return NUMERIC; - case 0x2: - return ALPHANUMERIC; - case 0x3: - return STRUCTURED_APPEND; - case 0x4: - return BYTE; - case 0x5: - return FNC1_FIRST_POSITION; - case 0x7: - return ECI; - case 0x8: - return KANJI; - case 0x9: - return FNC1_SECOND_POSITION; - case 0xD: - // 0xD is defined in GBT 18284-2000, may not be supported in foreign country - return HANZI; - default: - throw new IllegalArgumentException(); - } - } - - /** - * @param version version in question - * @return number of bits used, in this QR Code symbol {@link Version}, to encode the - * count of characters that will follow encoded in this Mode - */ - public int getCharacterCountBits(Version version) { - int number = version.getVersionNumber(); - int offset; - if (number <= 9) { - offset = 0; - } else if (number <= 26) { - offset = 1; - } else { - offset = 2; - } - return characterCountBitsForVersions[offset]; - } - - public int getBits() { - return bits; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/QRCodeDecoderMetaData.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/QRCodeDecoderMetaData.java deleted file mode 100644 index 75821e300..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/QRCodeDecoderMetaData.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.ResultPoint; - -/** - * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the - * decoding caller. Callers are expected to process this. - * - * @see com.google.zxing.common.DecoderResult#getOther() - */ -public final class QRCodeDecoderMetaData { - - private final boolean mirrored; - - QRCodeDecoderMetaData(boolean mirrored) { - this.mirrored = mirrored; - } - - /** - * @return true if the QR Code was mirrored. - */ - public boolean isMirrored() { - return mirrored; - } - - /** - * Apply the result points' order correction due to mirroring. - * - * @param points Array of points to apply mirror correction to. - */ - public void applyMirroredCorrection(ResultPoint[] points) { - if (!mirrored || points == null || points.length < 3) { - return; - } - ResultPoint bottomLeft = points[0]; - points[0] = points[2]; - points[2] = bottomLeft; - // No need to 'fix' top-left and alignment pattern. - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Version.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Version.java deleted file mode 100755 index cc4052508..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/decoder/Version.java +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.common.BitMatrix; - -/** - * See ISO 18004:2006 Annex D - * - * @author Sean Owen - */ -public final class Version { - - /** - * See ISO 18004:2006 Annex D. - * Element i represents the raw version bits that specify version i + 7 - */ - private static final int[] VERSION_DECODE_INFO = { - 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, - 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, - 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, - 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, - 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, - 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, - 0x2542E, 0x26A64, 0x27541, 0x28C69 - }; - - private static final Version[] VERSIONS = buildVersions(); - - private final int versionNumber; - private final int[] alignmentPatternCenters; - private final ECBlocks[] ecBlocks; - private final int totalCodewords; - - private Version(int versionNumber, - int[] alignmentPatternCenters, - ECBlocks... ecBlocks) { - this.versionNumber = versionNumber; - this.alignmentPatternCenters = alignmentPatternCenters; - this.ecBlocks = ecBlocks; - int total = 0; - int ecCodewords = ecBlocks[0].getECCodewordsPerBlock(); - ECB[] ecbArray = ecBlocks[0].getECBlocks(); - for (ECB ecBlock : ecbArray) { - total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); - } - this.totalCodewords = total; - } - - public int getVersionNumber() { - return versionNumber; - } - - public int[] getAlignmentPatternCenters() { - return alignmentPatternCenters; - } - - public int getTotalCodewords() { - return totalCodewords; - } - - public int getDimensionForVersion() { - return 17 + 4 * versionNumber; - } - - public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) { - return ecBlocks[ecLevel.ordinal()]; - } - - /** - *

    Deduces version information purely from QR Code dimensions.

    - * - * @param dimension dimension in modules - * @return Version for a QR Code of that dimension - * @throws FormatException if dimension is not 1 mod 4 - */ - public static Version getProvisionalVersionForDimension(int dimension) throws FormatException { - if (dimension % 4 != 1) { - throw FormatException.getFormatInstance(); - } - try { - return getVersionForNumber((dimension - 17) / 4); - } catch (IllegalArgumentException ignored) { - throw FormatException.getFormatInstance(); - } - } - - public static Version getVersionForNumber(int versionNumber) { - if (versionNumber < 1 || versionNumber > 40) { - throw new IllegalArgumentException(); - } - return VERSIONS[versionNumber - 1]; - } - - static Version decodeVersionInformation(int versionBits) { - int bestDifference = Integer.MAX_VALUE; - int bestVersion = 0; - for (int i = 0; i < VERSION_DECODE_INFO.length; i++) { - int targetVersion = VERSION_DECODE_INFO[i]; - // Do the version info bits match exactly? done. - if (targetVersion == versionBits) { - return getVersionForNumber(i + 7); - } - // Otherwise see if this is the closest to a real version info bit string - // we have seen so far - int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); - if (bitsDifference < bestDifference) { - bestVersion = i + 7; - bestDifference = bitsDifference; - } - } - // We can tolerate up to 3 bits of error since no two version info codewords will - // differ in less than 8 bits. - if (bestDifference <= 3) { - return getVersionForNumber(bestVersion); - } - // If we didn't find a close enough match, fail - return null; - } - - /** - * See ISO 18004:2006 Annex E - */ - BitMatrix buildFunctionPattern() { - int dimension = getDimensionForVersion(); - BitMatrix bitMatrix = new BitMatrix(dimension); - - // Top left finder pattern + separator + format - bitMatrix.setRegion(0, 0, 9, 9); - // Top right finder pattern + separator + format - bitMatrix.setRegion(dimension - 8, 0, 8, 9); - // Bottom left finder pattern + separator + format - bitMatrix.setRegion(0, dimension - 8, 9, 8); - - // Alignment patterns - int max = alignmentPatternCenters.length; - for (int x = 0; x < max; x++) { - int i = alignmentPatternCenters[x] - 2; - for (int y = 0; y < max; y++) { - if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) { - // No alignment patterns near the three finder paterns - continue; - } - bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5); - } - } - - // Vertical timing pattern - bitMatrix.setRegion(6, 9, 1, dimension - 17); - // Horizontal timing pattern - bitMatrix.setRegion(9, 6, dimension - 17, 1); - - if (versionNumber > 6) { - // Version info, top right - bitMatrix.setRegion(dimension - 11, 0, 3, 6); - // Version info, bottom left - bitMatrix.setRegion(0, dimension - 11, 6, 3); - } - - return bitMatrix; - } - - /** - *

    Encapsulates a set of error-correction blocks in one symbol version. Most versions will - * use blocks of differing sizes within one version, so, this encapsulates the parameters for - * each set of blocks. It also holds the number of error-correction codewords per block since it - * will be the same across all blocks within one version.

    - */ - public static final class ECBlocks { - private final int ecCodewordsPerBlock; - private final ECB[] ecBlocks; - - ECBlocks(int ecCodewordsPerBlock, ECB... ecBlocks) { - this.ecCodewordsPerBlock = ecCodewordsPerBlock; - this.ecBlocks = ecBlocks; - } - - public int getECCodewordsPerBlock() { - return ecCodewordsPerBlock; - } - - public int getNumBlocks() { - int total = 0; - for (ECB ecBlock : ecBlocks) { - total += ecBlock.getCount(); - } - return total; - } - - public int getTotalECCodewords() { - return ecCodewordsPerBlock * getNumBlocks(); - } - - public ECB[] getECBlocks() { - return ecBlocks; - } - } - - /** - *

    Encapsualtes the parameters for one error-correction block in one symbol version. - * This includes the number of data codewords, and the number of times a block with these - * parameters is used consecutively in the QR code version's format.

    - */ - public static final class ECB { - private final int count; - private final int dataCodewords; - - ECB(int count, int dataCodewords) { - this.count = count; - this.dataCodewords = dataCodewords; - } - - public int getCount() { - return count; - } - - public int getDataCodewords() { - return dataCodewords; - } - } - - @Override - public String toString() { - return String.valueOf(versionNumber); - } - - /** - * See ISO 18004:2006 6.5.1 Table 9 - */ - private static Version[] buildVersions() { - return new Version[]{ - new Version(1, new int[]{}, - new ECBlocks(7, new ECB(1, 19)), - new ECBlocks(10, new ECB(1, 16)), - new ECBlocks(13, new ECB(1, 13)), - new ECBlocks(17, new ECB(1, 9))), - new Version(2, new int[]{6, 18}, - new ECBlocks(10, new ECB(1, 34)), - new ECBlocks(16, new ECB(1, 28)), - new ECBlocks(22, new ECB(1, 22)), - new ECBlocks(28, new ECB(1, 16))), - new Version(3, new int[]{6, 22}, - new ECBlocks(15, new ECB(1, 55)), - new ECBlocks(26, new ECB(1, 44)), - new ECBlocks(18, new ECB(2, 17)), - new ECBlocks(22, new ECB(2, 13))), - new Version(4, new int[]{6, 26}, - new ECBlocks(20, new ECB(1, 80)), - new ECBlocks(18, new ECB(2, 32)), - new ECBlocks(26, new ECB(2, 24)), - new ECBlocks(16, new ECB(4, 9))), - new Version(5, new int[]{6, 30}, - new ECBlocks(26, new ECB(1, 108)), - new ECBlocks(24, new ECB(2, 43)), - new ECBlocks(18, new ECB(2, 15), - new ECB(2, 16)), - new ECBlocks(22, new ECB(2, 11), - new ECB(2, 12))), - new Version(6, new int[]{6, 34}, - new ECBlocks(18, new ECB(2, 68)), - new ECBlocks(16, new ECB(4, 27)), - new ECBlocks(24, new ECB(4, 19)), - new ECBlocks(28, new ECB(4, 15))), - new Version(7, new int[]{6, 22, 38}, - new ECBlocks(20, new ECB(2, 78)), - new ECBlocks(18, new ECB(4, 31)), - new ECBlocks(18, new ECB(2, 14), - new ECB(4, 15)), - new ECBlocks(26, new ECB(4, 13), - new ECB(1, 14))), - new Version(8, new int[]{6, 24, 42}, - new ECBlocks(24, new ECB(2, 97)), - new ECBlocks(22, new ECB(2, 38), - new ECB(2, 39)), - new ECBlocks(22, new ECB(4, 18), - new ECB(2, 19)), - new ECBlocks(26, new ECB(4, 14), - new ECB(2, 15))), - new Version(9, new int[]{6, 26, 46}, - new ECBlocks(30, new ECB(2, 116)), - new ECBlocks(22, new ECB(3, 36), - new ECB(2, 37)), - new ECBlocks(20, new ECB(4, 16), - new ECB(4, 17)), - new ECBlocks(24, new ECB(4, 12), - new ECB(4, 13))), - new Version(10, new int[]{6, 28, 50}, - new ECBlocks(18, new ECB(2, 68), - new ECB(2, 69)), - new ECBlocks(26, new ECB(4, 43), - new ECB(1, 44)), - new ECBlocks(24, new ECB(6, 19), - new ECB(2, 20)), - new ECBlocks(28, new ECB(6, 15), - new ECB(2, 16))), - new Version(11, new int[]{6, 30, 54}, - new ECBlocks(20, new ECB(4, 81)), - new ECBlocks(30, new ECB(1, 50), - new ECB(4, 51)), - new ECBlocks(28, new ECB(4, 22), - new ECB(4, 23)), - new ECBlocks(24, new ECB(3, 12), - new ECB(8, 13))), - new Version(12, new int[]{6, 32, 58}, - new ECBlocks(24, new ECB(2, 92), - new ECB(2, 93)), - new ECBlocks(22, new ECB(6, 36), - new ECB(2, 37)), - new ECBlocks(26, new ECB(4, 20), - new ECB(6, 21)), - new ECBlocks(28, new ECB(7, 14), - new ECB(4, 15))), - new Version(13, new int[]{6, 34, 62}, - new ECBlocks(26, new ECB(4, 107)), - new ECBlocks(22, new ECB(8, 37), - new ECB(1, 38)), - new ECBlocks(24, new ECB(8, 20), - new ECB(4, 21)), - new ECBlocks(22, new ECB(12, 11), - new ECB(4, 12))), - new Version(14, new int[]{6, 26, 46, 66}, - new ECBlocks(30, new ECB(3, 115), - new ECB(1, 116)), - new ECBlocks(24, new ECB(4, 40), - new ECB(5, 41)), - new ECBlocks(20, new ECB(11, 16), - new ECB(5, 17)), - new ECBlocks(24, new ECB(11, 12), - new ECB(5, 13))), - new Version(15, new int[]{6, 26, 48, 70}, - new ECBlocks(22, new ECB(5, 87), - new ECB(1, 88)), - new ECBlocks(24, new ECB(5, 41), - new ECB(5, 42)), - new ECBlocks(30, new ECB(5, 24), - new ECB(7, 25)), - new ECBlocks(24, new ECB(11, 12), - new ECB(7, 13))), - new Version(16, new int[]{6, 26, 50, 74}, - new ECBlocks(24, new ECB(5, 98), - new ECB(1, 99)), - new ECBlocks(28, new ECB(7, 45), - new ECB(3, 46)), - new ECBlocks(24, new ECB(15, 19), - new ECB(2, 20)), - new ECBlocks(30, new ECB(3, 15), - new ECB(13, 16))), - new Version(17, new int[]{6, 30, 54, 78}, - new ECBlocks(28, new ECB(1, 107), - new ECB(5, 108)), - new ECBlocks(28, new ECB(10, 46), - new ECB(1, 47)), - new ECBlocks(28, new ECB(1, 22), - new ECB(15, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(17, 15))), - new Version(18, new int[]{6, 30, 56, 82}, - new ECBlocks(30, new ECB(5, 120), - new ECB(1, 121)), - new ECBlocks(26, new ECB(9, 43), - new ECB(4, 44)), - new ECBlocks(28, new ECB(17, 22), - new ECB(1, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(19, 15))), - new Version(19, new int[]{6, 30, 58, 86}, - new ECBlocks(28, new ECB(3, 113), - new ECB(4, 114)), - new ECBlocks(26, new ECB(3, 44), - new ECB(11, 45)), - new ECBlocks(26, new ECB(17, 21), - new ECB(4, 22)), - new ECBlocks(26, new ECB(9, 13), - new ECB(16, 14))), - new Version(20, new int[]{6, 34, 62, 90}, - new ECBlocks(28, new ECB(3, 107), - new ECB(5, 108)), - new ECBlocks(26, new ECB(3, 41), - new ECB(13, 42)), - new ECBlocks(30, new ECB(15, 24), - new ECB(5, 25)), - new ECBlocks(28, new ECB(15, 15), - new ECB(10, 16))), - new Version(21, new int[]{6, 28, 50, 72, 94}, - new ECBlocks(28, new ECB(4, 116), - new ECB(4, 117)), - new ECBlocks(26, new ECB(17, 42)), - new ECBlocks(28, new ECB(17, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(19, 16), - new ECB(6, 17))), - new Version(22, new int[]{6, 26, 50, 74, 98}, - new ECBlocks(28, new ECB(2, 111), - new ECB(7, 112)), - new ECBlocks(28, new ECB(17, 46)), - new ECBlocks(30, new ECB(7, 24), - new ECB(16, 25)), - new ECBlocks(24, new ECB(34, 13))), - new Version(23, new int[]{6, 30, 54, 78, 102}, - new ECBlocks(30, new ECB(4, 121), - new ECB(5, 122)), - new ECBlocks(28, new ECB(4, 47), - new ECB(14, 48)), - new ECBlocks(30, new ECB(11, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(16, 15), - new ECB(14, 16))), - new Version(24, new int[]{6, 28, 54, 80, 106}, - new ECBlocks(30, new ECB(6, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(6, 45), - new ECB(14, 46)), - new ECBlocks(30, new ECB(11, 24), - new ECB(16, 25)), - new ECBlocks(30, new ECB(30, 16), - new ECB(2, 17))), - new Version(25, new int[]{6, 32, 58, 84, 110}, - new ECBlocks(26, new ECB(8, 106), - new ECB(4, 107)), - new ECBlocks(28, new ECB(8, 47), - new ECB(13, 48)), - new ECBlocks(30, new ECB(7, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(13, 16))), - new Version(26, new int[]{6, 30, 58, 86, 114}, - new ECBlocks(28, new ECB(10, 114), - new ECB(2, 115)), - new ECBlocks(28, new ECB(19, 46), - new ECB(4, 47)), - new ECBlocks(28, new ECB(28, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(33, 16), - new ECB(4, 17))), - new Version(27, new int[]{6, 34, 62, 90, 118}, - new ECBlocks(30, new ECB(8, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(22, 45), - new ECB(3, 46)), - new ECBlocks(30, new ECB(8, 23), - new ECB(26, 24)), - new ECBlocks(30, new ECB(12, 15), - new ECB(28, 16))), - new Version(28, new int[]{6, 26, 50, 74, 98, 122}, - new ECBlocks(30, new ECB(3, 117), - new ECB(10, 118)), - new ECBlocks(28, new ECB(3, 45), - new ECB(23, 46)), - new ECBlocks(30, new ECB(4, 24), - new ECB(31, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(31, 16))), - new Version(29, new int[]{6, 30, 54, 78, 102, 126}, - new ECBlocks(30, new ECB(7, 116), - new ECB(7, 117)), - new ECBlocks(28, new ECB(21, 45), - new ECB(7, 46)), - new ECBlocks(30, new ECB(1, 23), - new ECB(37, 24)), - new ECBlocks(30, new ECB(19, 15), - new ECB(26, 16))), - new Version(30, new int[]{6, 26, 52, 78, 104, 130}, - new ECBlocks(30, new ECB(5, 115), - new ECB(10, 116)), - new ECBlocks(28, new ECB(19, 47), - new ECB(10, 48)), - new ECBlocks(30, new ECB(15, 24), - new ECB(25, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(25, 16))), - new Version(31, new int[]{6, 30, 56, 82, 108, 134}, - new ECBlocks(30, new ECB(13, 115), - new ECB(3, 116)), - new ECBlocks(28, new ECB(2, 46), - new ECB(29, 47)), - new ECBlocks(30, new ECB(42, 24), - new ECB(1, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(28, 16))), - new Version(32, new int[]{6, 34, 60, 86, 112, 138}, - new ECBlocks(30, new ECB(17, 115)), - new ECBlocks(28, new ECB(10, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(10, 24), - new ECB(35, 25)), - new ECBlocks(30, new ECB(19, 15), - new ECB(35, 16))), - new Version(33, new int[]{6, 30, 58, 86, 114, 142}, - new ECBlocks(30, new ECB(17, 115), - new ECB(1, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(21, 47)), - new ECBlocks(30, new ECB(29, 24), - new ECB(19, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(46, 16))), - new Version(34, new int[]{6, 34, 62, 90, 118, 146}, - new ECBlocks(30, new ECB(13, 115), - new ECB(6, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(44, 24), - new ECB(7, 25)), - new ECBlocks(30, new ECB(59, 16), - new ECB(1, 17))), - new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150}, - new ECBlocks(30, new ECB(12, 121), - new ECB(7, 122)), - new ECBlocks(28, new ECB(12, 47), - new ECB(26, 48)), - new ECBlocks(30, new ECB(39, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(41, 16))), - new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154}, - new ECBlocks(30, new ECB(6, 121), - new ECB(14, 122)), - new ECBlocks(28, new ECB(6, 47), - new ECB(34, 48)), - new ECBlocks(30, new ECB(46, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(2, 15), - new ECB(64, 16))), - new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158}, - new ECBlocks(30, new ECB(17, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(29, 46), - new ECB(14, 47)), - new ECBlocks(30, new ECB(49, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(24, 15), - new ECB(46, 16))), - new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162}, - new ECBlocks(30, new ECB(4, 122), - new ECB(18, 123)), - new ECBlocks(28, new ECB(13, 46), - new ECB(32, 47)), - new ECBlocks(30, new ECB(48, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(42, 15), - new ECB(32, 16))), - new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166}, - new ECBlocks(30, new ECB(20, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(40, 47), - new ECB(7, 48)), - new ECBlocks(30, new ECB(43, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(10, 15), - new ECB(67, 16))), - new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170}, - new ECBlocks(30, new ECB(19, 118), - new ECB(6, 119)), - new ECBlocks(28, new ECB(18, 47), - new ECB(31, 48)), - new ECBlocks(30, new ECB(34, 24), - new ECB(34, 25)), - new ECBlocks(30, new ECB(20, 15), - new ECB(61, 16))) - }; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPattern.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPattern.java deleted file mode 100644 index 96d919422..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPattern.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -import com.google.zxing.ResultPoint; - -/** - *

    Encapsulates an alignment pattern, which are the smaller square patterns found in - * all but the simplest QR Codes.

    - * - * @author Sean Owen - */ -public final class AlignmentPattern extends ResultPoint { - - private final float estimatedModuleSize; - - AlignmentPattern(float posX, float posY, float estimatedModuleSize) { - super(posX, posY); - this.estimatedModuleSize = estimatedModuleSize; - } - - /** - *

    Determines if this alignment pattern "about equals" an alignment pattern at the stated - * position and size -- meaning, it is at nearly the same center with nearly the same size.

    - */ - boolean aboutEquals(float moduleSize, float i, float j) { - if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) { - float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize); - return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; - } - return false; - } - - /** - * Combines this object's current estimate of a finder pattern position and module size - * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. - */ - AlignmentPattern combineEstimate(float i, float j, float newModuleSize) { - float combinedX = (getX() + j) / 2.0f; - float combinedY = (getY() + i) / 2.0f; - float combinedModuleSize = (estimatedModuleSize + newModuleSize) / 2.0f; - return new AlignmentPattern(combinedX, combinedY, combinedModuleSize); - } - -} \ No newline at end of file diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java deleted file mode 100644 index b6e1b5dbe..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitMatrix; - -import java.util.ArrayList; -import java.util.List; - -/** - *

    This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder - * patterns but are smaller and appear at regular intervals throughout the image.

    - * - *

    At the moment this only looks for the bottom-right alignment pattern.

    - * - *

    This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied, - * pasted and stripped down here for maximum performance but does unfortunately duplicate - * some code.

    - * - *

    This class is thread-safe but not reentrant. Each thread must allocate its own object.

    - * - * @author Sean Owen - */ -final class AlignmentPatternFinder { - - private final BitMatrix image; - private final List possibleCenters; - private final int startX; - private final int startY; - private final int width; - private final int height; - private final float moduleSize; - private final int[] crossCheckStateCount; - private final ResultPointCallback resultPointCallback; - - /** - *

    Creates a finder that will look in a portion of the whole image.

    - * - * @param image image to search - * @param startX left column from which to start searching - * @param startY top row from which to start searching - * @param width width of region to search - * @param height height of region to search - * @param moduleSize estimated module size so far - */ - AlignmentPatternFinder(BitMatrix image, - int startX, - int startY, - int width, - int height, - float moduleSize, - ResultPointCallback resultPointCallback) { - this.image = image; - this.possibleCenters = new ArrayList<>(5); - this.startX = startX; - this.startY = startY; - this.width = width; - this.height = height; - this.moduleSize = moduleSize; - this.crossCheckStateCount = new int[3]; - this.resultPointCallback = resultPointCallback; - } - - /** - *

    This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since - * it's pretty performance-critical and so is written to be fast foremost.

    - * - * @return {@link AlignmentPattern} if found - * @throws NotFoundException if not found - */ - AlignmentPattern find() throws NotFoundException { - int startX = this.startX; - int height = this.height; - int maxJ = startX + width; - int middleI = startY + (height / 2); - // We are looking for black/white/black modules in 1:1:1 ratio; - // this tracks the number of black/white/black modules seen so far - int[] stateCount = new int[3]; - for (int iGen = 0; iGen < height; iGen++) { - // Search from middle outwards - int i = middleI + ((iGen & 0x01) == 0 ? (iGen + 1) / 2 : -((iGen + 1) / 2)); - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - int j = startX; - // Burn off leading white pixels before anything else; if we start in the middle of - // a white run, it doesn't make sense to count its length, since we don't know if the - // white run continued to the left of the start point - while (j < maxJ && !image.get(j, i)) { - j++; - } - int currentState = 0; - while (j < maxJ) { - if (image.get(j, i)) { - // Black pixel - if (currentState == 1) { // Counting black pixels - stateCount[currentState]++; - } else { // Counting white pixels - if (currentState == 2) { // A winner? - if (foundPatternCross(stateCount)) { // Yes - AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, j); - if (confirmed != null) { - return confirmed; - } - } - stateCount[0] = stateCount[2]; - stateCount[1] = 1; - stateCount[2] = 0; - currentState = 1; - } else { - stateCount[++currentState]++; - } - } - } else { // White pixel - if (currentState == 1) { // Counting black pixels - currentState++; - } - stateCount[currentState]++; - } - j++; - } - if (foundPatternCross(stateCount)) { - AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, maxJ); - if (confirmed != null) { - return confirmed; - } - } - - } - - // Hmm, nothing we saw was observed and confirmed twice. If we had - // any guess at all, return it. - if (!possibleCenters.isEmpty()) { - return possibleCenters.get(0); - } - - throw NotFoundException.getNotFoundInstance(); - } - - /** - * Given a count of black/white/black pixels just seen and an end position, - * figures the location of the center of this black/white/black run. - */ - private static float centerFromEnd(int[] stateCount, int end) { - return (float) (end - stateCount[2]) - stateCount[1] / 2.0f; - } - - /** - * @param stateCount count of black/white/black pixels just read - * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios - * used by alignment patterns to be considered a match - */ - private boolean foundPatternCross(int[] stateCount) { - float moduleSize = this.moduleSize; - float maxVariance = moduleSize / 2.0f; - for (int i = 0; i < 3; i++) { - if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) { - return false; - } - } - return true; - } - - /** - *

    After a horizontal scan finds a potential alignment pattern, this method - * "cross-checks" by scanning down vertically through the center of the possible - * alignment pattern to see if the same proportion is detected.

    - * - * @param startI row where an alignment pattern was detected - * @param centerJ center of the section that appears to cross an alignment pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @return vertical center of alignment pattern, or {@link Float#NaN} if not found - */ - private float crossCheckVertical(int startI, int centerJ, int maxCount, - int originalStateCountTotal) { - BitMatrix image = this.image; - - int maxI = image.getHeight(); - int[] stateCount = crossCheckStateCount; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - - // Start counting up from center - int i = startI; - while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) { - return Float.NaN; - } - while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) { - return Float.NaN; - } - - // Now also count down from center - i = startI + 1; - while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i++; - } - if (i == maxI || stateCount[1] > maxCount) { - return Float.NaN; - } - while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) { - stateCount[2]++; - i++; - } - if (stateCount[2] > maxCount) { - return Float.NaN; - } - - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return Float.NaN; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN; - } - - /** - *

    This is called when a horizontal scan finds a possible alignment pattern. It will - * cross check with a vertical scan, and if successful, will see if this pattern had been - * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have - * found the alignment pattern.

    - * - * @param stateCount reading state module counts from horizontal scan - * @param i row where alignment pattern may be found - * @param j end of possible alignment pattern in row - * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not - */ - private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) { - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - float centerJ = centerFromEnd(stateCount, j); - float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1], stateCountTotal); - if (!Float.isNaN(centerI)) { - float estimatedModuleSize = (float) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f; - for (AlignmentPattern center : possibleCenters) { - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { - return center.combineEstimate(centerI, centerJ, estimatedModuleSize); - } - } - // Hadn't found this before; save it - AlignmentPattern point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize); - possibleCenters.add(point); - if (resultPointCallback != null) { - resultPointCallback.foundPossibleResultPoint(point); - } - } - return null; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/Detector.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/Detector.java deleted file mode 100644 index d3367bac2..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/Detector.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -import com.google.zxing.DecodeHintType; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.common.DetectorResult; -import com.google.zxing.common.GridSampler; -import com.google.zxing.common.PerspectiveTransform; -import com.google.zxing.common.detector.MathUtils; -import com.google.zxing.qrcode.decoder.Version; - -import java.util.Map; - -/** - *

    Encapsulates logic that can detect a QR Code in an image, even if the QR Code - * is rotated or skewed, or partially obscured.

    - * - * @author Sean Owen - */ -public class Detector { - - private final BitMatrix image; - private ResultPointCallback resultPointCallback; - - public Detector(BitMatrix image) { - this.image = image; - } - - protected final BitMatrix getImage() { - return image; - } - - protected final ResultPointCallback getResultPointCallback() { - return resultPointCallback; - } - - /** - *

    Detects a QR Code in an image.

    - * - * @return {@link DetectorResult} encapsulating results of detecting a QR Code - * @throws NotFoundException if QR Code cannot be found - * @throws FormatException if a QR Code cannot be decoded - */ - public DetectorResult detect() throws NotFoundException, FormatException { - return detect(null); - } - - /** - *

    Detects a QR Code in an image.

    - * - * @param hints optional hints to detector - * @return {@link DetectorResult} encapsulating results of detecting a QR Code - * @throws NotFoundException if QR Code cannot be found - * @throws FormatException if a QR Code cannot be decoded - */ - public final DetectorResult detect(Map hints) throws NotFoundException, FormatException { - - resultPointCallback = hints == null ? null : - (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); - - FinderPatternFinder finder = new FinderPatternFinder(image, resultPointCallback); - FinderPatternInfo info = finder.find(hints); - - return processFinderPatternInfo(info); - } - - protected final DetectorResult processFinderPatternInfo(FinderPatternInfo info) - throws NotFoundException, FormatException { - - FinderPattern topLeft = info.getTopLeft(); - FinderPattern topRight = info.getTopRight(); - FinderPattern bottomLeft = info.getBottomLeft(); - - float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft); - if (moduleSize < 1.0f) { - throw NotFoundException.getNotFoundInstance(); - } - int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize); - Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension); - int modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7; - - AlignmentPattern alignmentPattern = null; - // Anything above version 1 has an alignment pattern - if (provisionalVersion.getAlignmentPatternCenters().length > 0) { - - // Guess where a "bottom right" finder pattern would have been - float bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX(); - float bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY(); - - // Estimate that alignment pattern is closer by 3 modules - // from "bottom right" to known top left location - float correctionToTopLeft = 1.0f - 3.0f / (float) modulesBetweenFPCenters; - int estAlignmentX = (int) (topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX())); - int estAlignmentY = (int) (topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY())); - - // Kind of arbitrary -- expand search radius before giving up - for (int i = 4; i <= 16; i <<= 1) { - try { - alignmentPattern = findAlignmentInRegion(moduleSize, - estAlignmentX, - estAlignmentY, - (float) i); - break; - } catch (NotFoundException re) { - // try next round - } - } - // If we didn't find alignment pattern... well try anyway without it - } - - PerspectiveTransform transform = - createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); - - BitMatrix bits = sampleGrid(image, transform, dimension); - - ResultPoint[] points; - if (alignmentPattern == null) { - points = new ResultPoint[]{bottomLeft, topLeft, topRight}; - } else { - points = new ResultPoint[]{bottomLeft, topLeft, topRight, alignmentPattern}; - } - return new DetectorResult(bits, points); - } - - private static PerspectiveTransform createTransform(ResultPoint topLeft, - ResultPoint topRight, - ResultPoint bottomLeft, - ResultPoint alignmentPattern, - int dimension) { - float dimMinusThree = (float) dimension - 3.5f; - float bottomRightX; - float bottomRightY; - float sourceBottomRightX; - float sourceBottomRightY; - if (alignmentPattern != null) { - bottomRightX = alignmentPattern.getX(); - bottomRightY = alignmentPattern.getY(); - sourceBottomRightX = dimMinusThree - 3.0f; - sourceBottomRightY = sourceBottomRightX; - } else { - // Don't have an alignment pattern, just make up the bottom-right point - bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX(); - bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY(); - sourceBottomRightX = dimMinusThree; - sourceBottomRightY = dimMinusThree; - } - - return PerspectiveTransform.quadrilateralToQuadrilateral( - 3.5f, - 3.5f, - dimMinusThree, - 3.5f, - sourceBottomRightX, - sourceBottomRightY, - 3.5f, - dimMinusThree, - topLeft.getX(), - topLeft.getY(), - topRight.getX(), - topRight.getY(), - bottomRightX, - bottomRightY, - bottomLeft.getX(), - bottomLeft.getY()); - } - - private static BitMatrix sampleGrid(BitMatrix image, - PerspectiveTransform transform, - int dimension) throws NotFoundException { - - GridSampler sampler = GridSampler.getInstance(); - return sampler.sampleGrid(image, dimension, dimension, transform); - } - - /** - *

    Computes the dimension (number of modules on a size) of the QR Code based on the position - * of the finder patterns and estimated module size.

    - */ - private static int computeDimension(ResultPoint topLeft, - ResultPoint topRight, - ResultPoint bottomLeft, - float moduleSize) throws NotFoundException { - int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize); - int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize); - int dimension = ((tltrCentersDimension + tlblCentersDimension) / 2) + 7; - switch (dimension & 0x03) { // mod 4 - case 0: - dimension++; - break; - // 1? do nothing - case 2: - dimension--; - break; - case 3: - throw NotFoundException.getNotFoundInstance(); - } - return dimension; - } - - /** - *

    Computes an average estimated module size based on estimated derived from the positions - * of the three finder patterns.

    - * - * @param topLeft detected top-left finder pattern center - * @param topRight detected top-right finder pattern center - * @param bottomLeft detected bottom-left finder pattern center - * @return estimated module size - */ - protected final float calculateModuleSize(ResultPoint topLeft, - ResultPoint topRight, - ResultPoint bottomLeft) { - // Take the average - return (calculateModuleSizeOneWay(topLeft, topRight) + - calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f; - } - - /** - *

    Estimates module size based on two finder patterns -- it uses - * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the - * width of each, measuring along the axis between their centers.

    - */ - private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern) { - float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int) pattern.getX(), - (int) pattern.getY(), - (int) otherPattern.getX(), - (int) otherPattern.getY()); - float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int) otherPattern.getX(), - (int) otherPattern.getY(), - (int) pattern.getX(), - (int) pattern.getY()); - if (Float.isNaN(moduleSizeEst1)) { - return moduleSizeEst2 / 7.0f; - } - if (Float.isNaN(moduleSizeEst2)) { - return moduleSizeEst1 / 7.0f; - } - // Average them, and divide by 7 since we've counted the width of 3 black modules, - // and 1 white and 1 black module on either side. Ergo, divide sum by 14. - return (moduleSizeEst1 + moduleSizeEst2) / 14.0f; - } - - /** - * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of - * a finder pattern by looking for a black-white-black run from the center in the direction - * of another point (another finder pattern center), and in the opposite direction too. - */ - private float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) { - - float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); - - // Now count other way -- don't run off image though of course - float scale = 1.0f; - int otherToX = fromX - (toX - fromX); - if (otherToX < 0) { - scale = (float) fromX / (float) (fromX - otherToX); - otherToX = 0; - } else if (otherToX >= image.getWidth()) { - scale = (float) (image.getWidth() - 1 - fromX) / (float) (otherToX - fromX); - otherToX = image.getWidth() - 1; - } - int otherToY = (int) (fromY - (toY - fromY) * scale); - - scale = 1.0f; - if (otherToY < 0) { - scale = (float) fromY / (float) (fromY - otherToY); - otherToY = 0; - } else if (otherToY >= image.getHeight()) { - scale = (float) (image.getHeight() - 1 - fromY) / (float) (otherToY - fromY); - otherToY = image.getHeight() - 1; - } - otherToX = (int) (fromX + (otherToX - fromX) * scale); - - result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); - - // Middle pixel is double-counted this way; subtract 1 - return result - 1.0f; - } - - /** - *

    This method traces a line from a point in the image, in the direction towards another point. - * It begins in a black region, and keeps going until it finds white, then black, then white again. - * It reports the distance from the start to this point.

    - * - *

    This is used when figuring out how wide a finder pattern is, when the finder pattern - * may be skewed or rotated.

    - */ - private float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) { - // Mild variant of Bresenham's algorithm; - // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm - boolean steep = Math.abs(toY - fromY) > Math.abs(toX - fromX); - if (steep) { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } - - int dx = Math.abs(toX - fromX); - int dy = Math.abs(toY - fromY); - int error = -dx / 2; - int xstep = fromX < toX ? 1 : -1; - int ystep = fromY < toY ? 1 : -1; - - // In black pixels, looking for white, first or second time. - int state = 0; - // Loop up until x == toX, but not beyond - int xLimit = toX + xstep; - for (int x = fromX, y = fromY; x != xLimit; x += xstep) { - int realX = steep ? y : x; - int realY = steep ? x : y; - - // Does current pixel mean we have moved white to black or vice versa? - // Scanning black in state 0,2 and white in state 1, so if we find the wrong - // color, advance to next state or end if we are in state 2 already - if ((state == 1) == image.get(realX, realY)) { - if (state == 2) { - return MathUtils.distance(x, y, fromX, fromY); - } - state++; - } - - error += dy; - if (error > 0) { - if (y == toY) { - break; - } - y += ystep; - error -= dx; - } - } - // Found black-white-black; give the benefit of the doubt that the next pixel outside the image - // is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a - // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. - if (state == 2) { - return MathUtils.distance(toX + xstep, toY, fromX, fromY); - } - // else we didn't find even black-white-black; no estimate is really possible - return Float.NaN; - } - - /** - *

    Attempts to locate an alignment pattern in a limited region of the image, which is - * guessed to contain it. This method uses {@link AlignmentPattern}.

    - * - * @param overallEstModuleSize estimated module size so far - * @param estAlignmentX x coordinate of center of area probably containing alignment pattern - * @param estAlignmentY y coordinate of above - * @param allowanceFactor number of pixels in all directions to search from the center - * @return {@link AlignmentPattern} if found, or null otherwise - * @throws NotFoundException if an unexpected error occurs during detection - */ - protected final AlignmentPattern findAlignmentInRegion(float overallEstModuleSize, - int estAlignmentX, - int estAlignmentY, - float allowanceFactor) - throws NotFoundException { - // Look for an alignment pattern (3 modules in size) around where it - // should be - int allowance = (int) (allowanceFactor * overallEstModuleSize); - int alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance); - int alignmentAreaRightX = Math.min(image.getWidth() - 1, estAlignmentX + allowance); - if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) { - throw NotFoundException.getNotFoundInstance(); - } - - int alignmentAreaTopY = Math.max(0, estAlignmentY - allowance); - int alignmentAreaBottomY = Math.min(image.getHeight() - 1, estAlignmentY + allowance); - if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) { - throw NotFoundException.getNotFoundInstance(); - } - - AlignmentPatternFinder alignmentFinder = - new AlignmentPatternFinder( - image, - alignmentAreaLeftX, - alignmentAreaTopY, - alignmentAreaRightX - alignmentAreaLeftX, - alignmentAreaBottomY - alignmentAreaTopY, - overallEstModuleSize, - resultPointCallback); - return alignmentFinder.find(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPattern.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPattern.java deleted file mode 100644 index a64e7c2b3..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPattern.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -import com.google.zxing.ResultPoint; - -/** - *

    Encapsulates a finder pattern, which are the three square patterns found in - * the corners of QR Codes. It also encapsulates a count of similar finder patterns, - * as a convenience to the finder's bookkeeping.

    - * - * @author Sean Owen - */ -public final class FinderPattern extends ResultPoint { - - private final float estimatedModuleSize; - private final int count; - - FinderPattern(float posX, float posY, float estimatedModuleSize) { - this(posX, posY, estimatedModuleSize, 1); - } - - private FinderPattern(float posX, float posY, float estimatedModuleSize, int count) { - super(posX, posY); - this.estimatedModuleSize = estimatedModuleSize; - this.count = count; - } - - public float getEstimatedModuleSize() { - return estimatedModuleSize; - } - - int getCount() { - return count; - } - - /* - void incrementCount() { - this.count++; - } - */ - - /** - *

    Determines if this finder pattern "about equals" a finder pattern at the stated - * position and size -- meaning, it is at nearly the same center with nearly the same size.

    - */ - boolean aboutEquals(float moduleSize, float i, float j) { - if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) { - float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize); - return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; - } - return false; - } - - /** - * Combines this object's current estimate of a finder pattern position and module size - * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average - * based on count. - */ - FinderPattern combineEstimate(float i, float j, float newModuleSize) { - int combinedCount = count + 1; - float combinedX = (count * getX() + j) / combinedCount; - float combinedY = (count * getY() + i) / combinedCount; - float combinedModuleSize = (count * estimatedModuleSize + newModuleSize) / combinedCount; - return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternFinder.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternFinder.java deleted file mode 100755 index 9c0c59f89..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternFinder.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -import com.google.zxing.DecodeHintType; -import com.google.zxing.NotFoundException; -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; -import com.google.zxing.common.BitMatrix; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -/** - *

    This class attempts to find finder patterns in a QR Code. Finder patterns are the square - * markers at three corners of a QR Code.

    - * - *

    This class is thread-safe but not reentrant. Each thread must allocate its own object. - * - * @author Sean Owen - */ -public class FinderPatternFinder { - - private static final int CENTER_QUORUM = 2; - protected static final int MIN_SKIP = 3; // 1 pixel/module times 3 modules/center - protected static final int MAX_MODULES = 57; // support up to version 10 for mobile clients - - private final BitMatrix image; - private final List possibleCenters; - private boolean hasSkipped; - private final int[] crossCheckStateCount; - private final ResultPointCallback resultPointCallback; - - /** - *

    Creates a finder that will search the image for three finder patterns.

    - * - * @param image image to search - */ - public FinderPatternFinder(BitMatrix image) { - this(image, null); - } - - public FinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) { - this.image = image; - this.possibleCenters = new ArrayList<>(); - this.crossCheckStateCount = new int[5]; - this.resultPointCallback = resultPointCallback; - } - - protected final BitMatrix getImage() { - return image; - } - - protected final List getPossibleCenters() { - return possibleCenters; - } - - final FinderPatternInfo find(Map hints) throws NotFoundException { - boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - boolean pureBarcode = hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE); - int maxI = image.getHeight(); - int maxJ = image.getWidth(); - // We are looking for black/white/black/white/black modules in - // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far - - // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the - // image, and then account for the center being 3 modules in size. This gives the smallest - // number of pixels the center could be, so skip this often. When trying harder, look for all - // QR versions regardless of how dense they are. - int iSkip = (3 * maxI) / (4 * MAX_MODULES); - if (iSkip < MIN_SKIP || tryHarder) { - iSkip = MIN_SKIP; - } - - boolean done = false; - int[] stateCount = new int[5]; - for (int i = iSkip - 1; i < maxI && !done; i += iSkip) { - // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - int currentState = 0; - for (int j = 0; j < maxJ; j++) { - if (image.get(j, i)) { - // Black pixel - if ((currentState & 1) == 1) { // Counting white pixels - currentState++; - } - stateCount[currentState]++; - } else { // White pixel - if ((currentState & 1) == 0) { // Counting black pixels - if (currentState == 4) { // A winner? - if (foundPatternCross(stateCount)) { // Yes - boolean confirmed = handlePossibleCenter(stateCount, i, j, pureBarcode); - if (confirmed) { - // Start examining every other line. Checking each line turned out to be too - // expensive and didn't improve performance. - iSkip = 2; - if (hasSkipped) { - done = haveMultiplyConfirmedCenters(); - } else { - int rowSkip = findRowSkip(); - if (rowSkip > stateCount[2]) { - // Skip rows between row of lower confirmed center - // and top of presumed third confirmed center - // but back up a bit to get a full chance of detecting - // it, entire width of center of finder pattern - - // Skip by rowSkip, but back off by stateCount[2] (size of last center - // of pattern we saw) to be conservative, and also back off by iSkip which - // is about to be re-added - i += rowSkip - stateCount[2] - iSkip; - j = maxJ - 1; - } - } - } else { - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - continue; - } - // Clear state to start looking again - currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - } else { // No, shift counts back by two - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - } - } else { - stateCount[++currentState]++; - } - } else { // Counting white pixels - stateCount[currentState]++; - } - } - } - if (foundPatternCross(stateCount)) { - boolean confirmed = handlePossibleCenter(stateCount, i, maxJ, pureBarcode); - if (confirmed) { - iSkip = stateCount[0]; - if (hasSkipped) { - // Found a third one - done = haveMultiplyConfirmedCenters(); - } - } - } - } - - FinderPattern[] patternInfo = selectBestPatterns(); - ResultPoint.orderBestPatterns(patternInfo); - - return new FinderPatternInfo(patternInfo); - } - - /** - * Given a count of black/white/black/white/black pixels just seen and an end position, - * figures the location of the center of this run. - */ - private static float centerFromEnd(int[] stateCount, int end) { - return (float) (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f; - } - - /** - * @param stateCount count of black/white/black/white/black pixels just read - * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios - * used by finder patterns to be considered a match - */ - protected static boolean foundPatternCross(int[] stateCount) { - int totalModuleSize = 0; - for (int i = 0; i < 5; i++) { - int count = stateCount[i]; - if (count == 0) { - return false; - } - totalModuleSize += count; - } - if (totalModuleSize < 7) { - return false; - } - float moduleSize = totalModuleSize / 7.0f; - float maxVariance = moduleSize / 2.0f; - // Allow less than 50% variance from 1-1-3-1-1 proportions - return - Math.abs(moduleSize - stateCount[0]) < maxVariance && - Math.abs(moduleSize - stateCount[1]) < maxVariance && - Math.abs(3.0f * moduleSize - stateCount[2]) < 3 * maxVariance && - Math.abs(moduleSize - stateCount[3]) < maxVariance && - Math.abs(moduleSize - stateCount[4]) < maxVariance; - } - - private int[] getCrossCheckStateCount() { - crossCheckStateCount[0] = 0; - crossCheckStateCount[1] = 0; - crossCheckStateCount[2] = 0; - crossCheckStateCount[3] = 0; - crossCheckStateCount[4] = 0; - return crossCheckStateCount; - } - - /** - * After a vertical and horizontal scan finds a potential finder pattern, this method - * "cross-cross-cross-checks" by scanning down diagonally through the center of the possible - * finder pattern to see if the same proportion is detected. - * - * @param startI row where a finder pattern was detected - * @param centerJ center of the section that appears to cross a finder pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @param originalStateCountTotal The original state count total. - * @return true if proportions are withing expected limits - */ - private boolean crossCheckDiagonal(int startI, int centerJ, int maxCount, int originalStateCountTotal) { - int[] stateCount = getCrossCheckStateCount(); - - // Start counting up, left from center finding black center mass - int i = 0; - while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) { - stateCount[2]++; - i++; - } - - if (startI < i || centerJ < i) { - return false; - } - - // Continue up, left finding white space - while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) && - stateCount[1] <= maxCount) { - stateCount[1]++; - i++; - } - - // If already too many modules in this state or ran off the edge: - if (startI < i || centerJ < i || stateCount[1] > maxCount) { - return false; - } - - // Continue up, left finding black border - while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) && - stateCount[0] <= maxCount) { - stateCount[0]++; - i++; - } - if (stateCount[0] > maxCount) { - return false; - } - - int maxI = image.getHeight(); - int maxJ = image.getWidth(); - - // Now also count down, right from center - i = 1; - while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) { - stateCount[2]++; - i++; - } - - // Ran off the edge? - if (startI + i >= maxI || centerJ + i >= maxJ) { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) && - stateCount[3] < maxCount) { - stateCount[3]++; - i++; - } - - if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) && - stateCount[4] < maxCount) { - stateCount[4]++; - i++; - } - - if (stateCount[4] >= maxCount) { - return false; - } - - // If we found a finder-pattern-like section, but its size is more than 100% different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; - return - Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal && - foundPatternCross(stateCount); - } - - /** - *

    After a horizontal scan finds a potential finder pattern, this method - * "cross-checks" by scanning down vertically through the center of the possible - * finder pattern to see if the same proportion is detected.

    - * - * @param startI row where a finder pattern was detected - * @param centerJ center of the section that appears to cross a finder pattern - * @param maxCount maximum reasonable number of modules that should be - * observed in any reading state, based on the results of the horizontal scan - * @return vertical center of finder pattern, or {@link Float#NaN} if not found - */ - private float crossCheckVertical(int startI, int centerJ, int maxCount, - int originalStateCountTotal) { - BitMatrix image = this.image; - - int maxI = image.getHeight(); - int[] stateCount = getCrossCheckStateCount(); - - // Start counting up from center - int i = startI; - while (i >= 0 && image.get(centerJ, i)) { - stateCount[2]++; - i--; - } - if (i < 0) { - return Float.NaN; - } - while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) { - return Float.NaN; - } - while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) { - return Float.NaN; - } - - // Now also count down from center - i = startI + 1; - while (i < maxI && image.get(centerJ, i)) { - stateCount[2]++; - i++; - } - if (i == maxI) { - return Float.NaN; - } - while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) { - stateCount[3]++; - i++; - } - if (i == maxI || stateCount[3] >= maxCount) { - return Float.NaN; - } - while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) { - stateCount[4]++; - i++; - } - if (stateCount[4] >= maxCount) { - return Float.NaN; - } - - // If we found a finder-pattern-like section, but its size is more than 40% different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return Float.NaN; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN; - } - - /** - *

    Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical, - * except it reads horizontally instead of vertically. This is used to cross-cross - * check a vertical cross check and locate the real center of the alignment pattern.

    - */ - private float crossCheckHorizontal(int startJ, int centerI, int maxCount, - int originalStateCountTotal) { - BitMatrix image = this.image; - - int maxJ = image.getWidth(); - int[] stateCount = getCrossCheckStateCount(); - - int j = startJ; - while (j >= 0 && image.get(j, centerI)) { - stateCount[2]++; - j--; - } - if (j < 0) { - return Float.NaN; - } - while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) { - stateCount[1]++; - j--; - } - if (j < 0 || stateCount[1] > maxCount) { - return Float.NaN; - } - while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) { - stateCount[0]++; - j--; - } - if (stateCount[0] > maxCount) { - return Float.NaN; - } - - j = startJ + 1; - while (j < maxJ && image.get(j, centerI)) { - stateCount[2]++; - j++; - } - if (j == maxJ) { - return Float.NaN; - } - while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) { - stateCount[3]++; - j++; - } - if (j == maxJ || stateCount[3] >= maxCount) { - return Float.NaN; - } - while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) { - stateCount[4]++; - j++; - } - if (stateCount[4] >= maxCount) { - return Float.NaN; - } - - // If we found a finder-pattern-like section, but its size is significantly different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) { - return Float.NaN; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : Float.NaN; - } - - /** - *

    This is called when a horizontal scan finds a possible alignment pattern. It will - * cross check with a vertical scan, and if successful, will, ah, cross-cross-check - * with another horizontal scan. This is needed primarily to locate the real horizontal - * center of the pattern in cases of extreme skew. - * And then we cross-cross-cross check with another diagonal scan.

    - * - *

    If that succeeds the finder pattern location is added to a list that tracks - * the number of times each location has been nearly-matched as a finder pattern. - * Each additional find is more evidence that the location is in fact a finder - * pattern center - * - * @param stateCount reading state module counts from horizontal scan - * @param i row where finder pattern may be found - * @param j end of possible finder pattern in row - * @param pureBarcode true if in "pure barcode" mode - * @return true if a finder pattern candidate was found this time - */ - protected final boolean handlePossibleCenter(int[] stateCount, int i, int j, boolean pureBarcode) { - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - float centerJ = centerFromEnd(stateCount, j); - float centerI = crossCheckVertical(i, (int) centerJ, stateCount[2], stateCountTotal); - if (!Float.isNaN(centerI)) { - // Re-cross check - centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2], stateCountTotal); - if (!Float.isNaN(centerJ) && - (!pureBarcode || crossCheckDiagonal((int) centerI, (int) centerJ, stateCount[2], stateCountTotal))) { - float estimatedModuleSize = (float) stateCountTotal / 7.0f; - boolean found = false; - for (int index = 0; index < possibleCenters.size(); index++) { - FinderPattern center = possibleCenters.get(index); - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { - possibleCenters.set(index, center.combineEstimate(centerI, centerJ, estimatedModuleSize)); - found = true; - break; - } - } - if (!found) { - FinderPattern point = new FinderPattern(centerJ, centerI, estimatedModuleSize); - possibleCenters.add(point); - if (resultPointCallback != null) { - resultPointCallback.foundPossibleResultPoint(point); - } - } - return true; - } - } - return false; - } - - /** - * @return number of rows we could safely skip during scanning, based on the first - * two finder patterns that have been located. In some cases their position will - * allow us to infer that the third pattern must lie below a certain point farther - * down in the image. - */ - private int findRowSkip() { - int max = possibleCenters.size(); - if (max <= 1) { - return 0; - } - ResultPoint firstConfirmedCenter = null; - for (FinderPattern center : possibleCenters) { - if (center.getCount() >= CENTER_QUORUM) { - if (firstConfirmedCenter == null) { - firstConfirmedCenter = center; - } else { - // We have two confirmed centers - // How far down can we skip before resuming looking for the next - // pattern? In the worst case, only the difference between the - // difference in the x / y coordinates of the two centers. - // This is the case where you find top left last. - hasSkipped = true; - return (int) (Math.abs(firstConfirmedCenter.getX() - center.getX()) - - Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2; - } - } - } - return 0; - } - - /** - * @return true iff we have found at least 3 finder patterns that have been detected - * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the - * candidates is "pretty similar" - */ - private boolean haveMultiplyConfirmedCenters() { - int confirmedCount = 0; - float totalModuleSize = 0.0f; - int max = possibleCenters.size(); - for (FinderPattern pattern : possibleCenters) { - if (pattern.getCount() >= CENTER_QUORUM) { - confirmedCount++; - totalModuleSize += pattern.getEstimatedModuleSize(); - } - } - if (confirmedCount < 3) { - return false; - } - // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" - // and that we need to keep looking. We detect this by asking if the estimated module sizes - // vary too much. We arbitrarily say that when the total deviation from average exceeds - // 5% of the total module size estimates, it's too much. - float average = totalModuleSize / (float) max; - float totalDeviation = 0.0f; - for (FinderPattern pattern : possibleCenters) { - totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average); - } - return totalDeviation <= 0.05f * totalModuleSize; - } - - /** - * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are - * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module - * size differs from the average among those patterns the least - * @throws NotFoundException if 3 such finder patterns do not exist - */ - private FinderPattern[] selectBestPatterns() throws NotFoundException { - - int startSize = possibleCenters.size(); - if (startSize < 3) { - // Couldn't find enough finder patterns - throw NotFoundException.getNotFoundInstance(); - } - - // Filter outlier possibilities whose module size is too different - if (startSize > 3) { - // But we can only afford to do so if we have at least 4 possibilities to choose from - float totalModuleSize = 0.0f; - float square = 0.0f; - for (FinderPattern center : possibleCenters) { - float size = center.getEstimatedModuleSize(); - totalModuleSize += size; - square += size * size; - } - float average = totalModuleSize / (float) startSize; - float stdDev = (float) Math.sqrt(square / startSize - average * average); - - Collections.sort(possibleCenters, new FurthestFromAverageComparator(average)); - - float limit = Math.max(0.2f * average, stdDev); - - for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) { - FinderPattern pattern = possibleCenters.get(i); - if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) { - possibleCenters.remove(i); - i--; - } - } - } - - if (possibleCenters.size() > 3) { - // Throw away all but those first size candidate points we found. - - float totalModuleSize = 0.0f; - for (FinderPattern possibleCenter : possibleCenters) { - totalModuleSize += possibleCenter.getEstimatedModuleSize(); - } - - float average = totalModuleSize / (float) possibleCenters.size(); - - Collections.sort(possibleCenters, new CenterComparator(average)); - - possibleCenters.subList(3, possibleCenters.size()).clear(); - } - - return new FinderPattern[]{ - possibleCenters.get(0), - possibleCenters.get(1), - possibleCenters.get(2) - }; - } - - /** - *

    Orders by furthest from average

    - */ - private static final class FurthestFromAverageComparator implements Comparator, Serializable { - private final float average; - private FurthestFromAverageComparator(float f) { - average = f; - } - @Override - public int compare(FinderPattern center1, FinderPattern center2) { - float dA = Math.abs(center2.getEstimatedModuleSize() - average); - float dB = Math.abs(center1.getEstimatedModuleSize() - average); - return dA < dB ? -1 : dA == dB ? 0 : 1; - } - } - - /** - *

    Orders by {@link FinderPattern#getCount()}, descending.

    - */ - private static final class CenterComparator implements Comparator, Serializable { - private final float average; - private CenterComparator(float f) { - average = f; - } - @Override - public int compare(FinderPattern center1, FinderPattern center2) { - if (center2.getCount() == center1.getCount()) { - float dA = Math.abs(center2.getEstimatedModuleSize() - average); - float dB = Math.abs(center1.getEstimatedModuleSize() - average); - return dA < dB ? 1 : dA == dB ? 0 : -1; - } else { - return center2.getCount() - center1.getCount(); - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternInfo.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternInfo.java deleted file mode 100644 index 3c3401085..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/detector/FinderPatternInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.detector; - -/** - *

    Encapsulates information about finder patterns in an image, including the location of - * the three finder patterns, and their estimated module size.

    - * - * @author Sean Owen - */ -public final class FinderPatternInfo { - - private final FinderPattern bottomLeft; - private final FinderPattern topLeft; - private final FinderPattern topRight; - - public FinderPatternInfo(FinderPattern[] patternCenters) { - this.bottomLeft = patternCenters[0]; - this.topLeft = patternCenters[1]; - this.topRight = patternCenters[2]; - } - - public FinderPattern getBottomLeft() { - return bottomLeft; - } - - public FinderPattern getTopLeft() { - return topLeft; - } - - public FinderPattern getTopRight() { - return topRight; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/BlockPair.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/BlockPair.java deleted file mode 100644 index 5714d9c3a..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/BlockPair.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -final class BlockPair { - - private final byte[] dataBytes; - private final byte[] errorCorrectionBytes; - - BlockPair(byte[] data, byte[] errorCorrection) { - dataBytes = data; - errorCorrectionBytes = errorCorrection; - } - - public byte[] getDataBytes() { - return dataBytes; - } - - public byte[] getErrorCorrectionBytes() { - return errorCorrectionBytes; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/ByteMatrix.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/ByteMatrix.java deleted file mode 100644 index d7fef0601..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/ByteMatrix.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -/** - * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned - * -1, 0, and 1, I'm going to use less memory and go with bytes. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class ByteMatrix { - - private final byte[][] bytes; - private final int width; - private final int height; - - public ByteMatrix(int width, int height) { - bytes = new byte[height][width]; - this.width = width; - this.height = height; - } - - public int getHeight() { - return height; - } - - public int getWidth() { - return width; - } - - public byte get(int x, int y) { - return bytes[y][x]; - } - - /** - * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) - */ - public byte[][] getArray() { - return bytes; - } - - public void set(int x, int y, byte value) { - bytes[y][x] = value; - } - - public void set(int x, int y, int value) { - bytes[y][x] = (byte) value; - } - - public void set(int x, int y, boolean value) { - bytes[y][x] = (byte) (value ? 1 : 0); - } - - public void clear(byte value) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - bytes[y][x] = value; - } - } - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(2 * width * height + 2); - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - switch (bytes[y][x]) { - case 0: - result.append(" 0"); - break; - case 1: - result.append(" 1"); - break; - default: - result.append(" "); - break; - } - } - result.append('\n'); - } - return result.toString(); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java deleted file mode 100644 index ae2fc5456..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitArray; -import com.google.zxing.common.CharacterSetECI; -import com.google.zxing.common.reedsolomon.GenericGF; -import com.google.zxing.common.reedsolomon.ReedSolomonEncoder; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; -import com.google.zxing.qrcode.decoder.Mode; -import com.google.zxing.qrcode.decoder.Version; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -/** - * @author satorux@google.com (Satoru Takabayashi) - creator - * @author dswitkin@google.com (Daniel Switkin) - ported from C++ - */ -public final class Encoder { - - // The original table is defined in the table 5 of JISX0510:2004 (p.19). - private static final int[] ALPHANUMERIC_TABLE = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f - }; - - static final String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1"; - - private Encoder() { - } - - // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. - // Basically it applies four rules and summate all penalties. - private static int calculateMaskPenalty(ByteMatrix matrix) { - return MaskUtil.applyMaskPenaltyRule1(matrix) - + MaskUtil.applyMaskPenaltyRule2(matrix) - + MaskUtil.applyMaskPenaltyRule3(matrix) - + MaskUtil.applyMaskPenaltyRule4(matrix); - } - - /** - * @param content text to encode - * @param ecLevel error correction level to use - * @return {@link QRCode} representing the encoded QR code - * @throws WriterException if encoding can't succeed, because of for example invalid content - * or configuration - */ - public static QRCode encode(String content, ErrorCorrectionLevel ecLevel) throws WriterException { - return encode(content, ecLevel, null); - } - - public static QRCode encode(String content, - ErrorCorrectionLevel ecLevel, - Map hints) throws WriterException { - - // Determine what character encoding has been specified by the caller, if any - String encoding = hints == null ? null : (String) hints.get(EncodeHintType.CHARACTER_SET); - if (encoding == null) { - encoding = DEFAULT_BYTE_MODE_ENCODING; - } - - // Pick an encoding mode appropriate for the content. Note that this will not attempt to use - // multiple modes / segments even if that were more efficient. Twould be nice. - Mode mode = chooseMode(content, encoding); - - // This will store the header information, like mode and - // length, as well as "header" segments like an ECI segment. - BitArray headerBits = new BitArray(); - - // Append ECI segment if applicable - if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.equals(encoding)) { - CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding); - if (eci != null) { - appendECI(eci, headerBits); - } - } - - // (With ECI in place,) Write the mode marker - appendModeInfo(mode, headerBits); - - // Collect data within the main segment, separately, to count its size if needed. Don't add it to - // main payload yet. - BitArray dataBits = new BitArray(); - appendBytes(content, mode, dataBits, encoding); - - // Hard part: need to know version to know how many bits length takes. But need to know how many - // bits it takes to know version. First we take a guess at version by assuming version will be - // the minimum, 1: - - int provisionalBitsNeeded = headerBits.getSize() - + mode.getCharacterCountBits(Version.getVersionForNumber(1)) - + dataBits.getSize(); - Version provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel); - - // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. - - int bitsNeeded = headerBits.getSize() - + mode.getCharacterCountBits(provisionalVersion) - + dataBits.getSize(); - Version version = chooseVersion(bitsNeeded, ecLevel); - - BitArray headerAndDataBits = new BitArray(); - headerAndDataBits.appendBitArray(headerBits); - // Find "length" of main segment and write it - int numLetters = mode == Mode.BYTE ? dataBits.getSizeInBytes() : content.length(); - appendLengthInfo(numLetters, version, mode, headerAndDataBits); - // Put data together into the overall payload - headerAndDataBits.appendBitArray(dataBits); - - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - int numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords(); - - // Terminate the bits properly. - terminateBits(numDataBytes, headerAndDataBits); - - // Interleave data bits with error correction code. - BitArray finalBits = interleaveWithECBytes(headerAndDataBits, - version.getTotalCodewords(), - numDataBytes, - ecBlocks.getNumBlocks()); - - QRCode qrCode = new QRCode(); - - qrCode.setECLevel(ecLevel); - qrCode.setMode(mode); - qrCode.setVersion(version); - - // Choose the mask pattern and set to "qrCode". - int dimension = version.getDimensionForVersion(); - ByteMatrix matrix = new ByteMatrix(dimension, dimension); - int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix); - qrCode.setMaskPattern(maskPattern); - - // Build the matrix and set it to "qrCode". - MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); - qrCode.setMatrix(matrix); - - return qrCode; - } - - /** - * @return the code point of the table used in alphanumeric mode or - * -1 if there is no corresponding code in the table. - */ - static int getAlphanumericCode(int code) { - if (code < ALPHANUMERIC_TABLE.length) { - return ALPHANUMERIC_TABLE[code]; - } - return -1; - } - - public static Mode chooseMode(String content) { - return chooseMode(content, null); - } - - /** - * Choose the best mode by examining the content. Note that 'encoding' is used as a hint; - * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. - */ - private static Mode chooseMode(String content, String encoding) { - if ("Shift_JIS".equals(encoding)) { - // Choose Kanji mode if all input are double-byte characters - return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE; - } - boolean hasNumeric = false; - boolean hasAlphanumeric = false; - for (int i = 0; i < content.length(); ++i) { - char c = content.charAt(i); - if (c >= '0' && c <= '9') { - hasNumeric = true; - } else if (getAlphanumericCode(c) != -1) { - hasAlphanumeric = true; - } else { - return Mode.BYTE; - } - } - if (hasAlphanumeric) { - return Mode.ALPHANUMERIC; - } - if (hasNumeric) { - return Mode.NUMERIC; - } - return Mode.BYTE; - } - - private static boolean isOnlyDoubleByteKanji(String content) { - byte[] bytes; - try { - bytes = content.getBytes("Shift_JIS"); - } catch (UnsupportedEncodingException ignored) { - return false; - } - int length = bytes.length; - if (length % 2 != 0) { - return false; - } - for (int i = 0; i < length; i += 2) { - int byte1 = bytes[i] & 0xFF; - if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) { - return false; - } - } - return true; - } - - private static int chooseMaskPattern(BitArray bits, - ErrorCorrectionLevel ecLevel, - Version version, - ByteMatrix matrix) throws WriterException { - - int minPenalty = Integer.MAX_VALUE; // Lower penalty is better. - int bestMaskPattern = -1; - // We try all mask patterns to choose the best one. - for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) { - MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); - int penalty = calculateMaskPenalty(matrix); - if (penalty < minPenalty) { - minPenalty = penalty; - bestMaskPattern = maskPattern; - } - } - return bestMaskPattern; - } - - private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel) throws WriterException { - // In the following comments, we use numbers of Version 7-H. - for (int versionNum = 1; versionNum <= 40; versionNum++) { - Version version = Version.getVersionForNumber(versionNum); - // numBytes = 196 - int numBytes = version.getTotalCodewords(); - // getNumECBytes = 130 - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - int numEcBytes = ecBlocks.getTotalECCodewords(); - // getNumDataBytes = 196 - 130 = 66 - int numDataBytes = numBytes - numEcBytes; - int totalInputBytes = (numInputBits + 7) / 8; - if (numDataBytes >= totalInputBytes) { - return version; - } - } - throw new WriterException("Data too big"); - } - - /** - * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). - */ - static void terminateBits(int numDataBytes, BitArray bits) throws WriterException { - int capacity = numDataBytes * 8; - if (bits.getSize() > capacity) { - throw new WriterException("data bits cannot fit in the QR Code" + bits.getSize() + " > " + - capacity); - } - for (int i = 0; i < 4 && bits.getSize() < capacity; ++i) { - bits.appendBit(false); - } - // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. - // If the last byte isn't 8-bit aligned, we'll add padding bits. - int numBitsInLastByte = bits.getSize() & 0x07; - if (numBitsInLastByte > 0) { - for (int i = numBitsInLastByte; i < 8; i++) { - bits.appendBit(false); - } - } - // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). - int numPaddingBytes = numDataBytes - bits.getSizeInBytes(); - for (int i = 0; i < numPaddingBytes; ++i) { - bits.appendBits((i & 0x01) == 0 ? 0xEC : 0x11, 8); - } - if (bits.getSize() != capacity) { - throw new WriterException("Bits size does not equal capacity"); - } - } - - /** - * Get number of data bytes and number of error correction bytes for block id "blockID". Store - * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of - * JISX0510:2004 (p.30) - */ - static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, - int numDataBytes, - int numRSBlocks, - int blockID, - int[] numDataBytesInBlock, - int[] numECBytesInBlock) throws WriterException { - if (blockID >= numRSBlocks) { - throw new WriterException("Block ID too large"); - } - // numRsBlocksInGroup2 = 196 % 5 = 1 - int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; - // numRsBlocksInGroup1 = 5 - 1 = 4 - int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; - // numTotalBytesInGroup1 = 196 / 5 = 39 - int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; - // numTotalBytesInGroup2 = 39 + 1 = 40 - int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; - // numDataBytesInGroup1 = 66 / 5 = 13 - int numDataBytesInGroup1 = numDataBytes / numRSBlocks; - // numDataBytesInGroup2 = 13 + 1 = 14 - int numDataBytesInGroup2 = numDataBytesInGroup1 + 1; - // numEcBytesInGroup1 = 39 - 13 = 26 - int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; - // numEcBytesInGroup2 = 40 - 14 = 26 - int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; - // Sanity checks. - // 26 = 26 - if (numEcBytesInGroup1 != numEcBytesInGroup2) { - throw new WriterException("EC bytes mismatch"); - } - // 5 = 4 + 1. - if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2) { - throw new WriterException("RS blocks mismatch"); - } - // 196 = (13 + 26) * 4 + (14 + 26) * 1 - if (numTotalBytes != - ((numDataBytesInGroup1 + numEcBytesInGroup1) * - numRsBlocksInGroup1) + - ((numDataBytesInGroup2 + numEcBytesInGroup2) * - numRsBlocksInGroup2)) { - throw new WriterException("Total bytes mismatch"); - } - - if (blockID < numRsBlocksInGroup1) { - numDataBytesInBlock[0] = numDataBytesInGroup1; - numECBytesInBlock[0] = numEcBytesInGroup1; - } else { - numDataBytesInBlock[0] = numDataBytesInGroup2; - numECBytesInBlock[0] = numEcBytesInGroup2; - } - } - - /** - * Interleave "bits" with corresponding error correction bytes. On success, store the result in - * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details. - */ - static BitArray interleaveWithECBytes(BitArray bits, - int numTotalBytes, - int numDataBytes, - int numRSBlocks) throws WriterException { - - // "bits" must have "getNumDataBytes" bytes of data. - if (bits.getSizeInBytes() != numDataBytes) { - throw new WriterException("Number of bits and data bytes does not match"); - } - - // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll - // store the divided data bytes blocks and error correction bytes blocks into "blocks". - int dataBytesOffset = 0; - int maxNumDataBytes = 0; - int maxNumEcBytes = 0; - - // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number. - Collection blocks = new ArrayList<>(numRSBlocks); - - for (int i = 0; i < numRSBlocks; ++i) { - int[] numDataBytesInBlock = new int[1]; - int[] numEcBytesInBlock = new int[1]; - getNumDataBytesAndNumECBytesForBlockID( - numTotalBytes, numDataBytes, numRSBlocks, i, - numDataBytesInBlock, numEcBytesInBlock); - - int size = numDataBytesInBlock[0]; - byte[] dataBytes = new byte[size]; - bits.toBytes(8*dataBytesOffset, dataBytes, 0, size); - byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]); - blocks.add(new BlockPair(dataBytes, ecBytes)); - - maxNumDataBytes = Math.max(maxNumDataBytes, size); - maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length); - dataBytesOffset += numDataBytesInBlock[0]; - } - if (numDataBytes != dataBytesOffset) { - throw new WriterException("Data bytes does not match offset"); - } - - BitArray result = new BitArray(); - - // First, place data blocks. - for (int i = 0; i < maxNumDataBytes; ++i) { - for (BlockPair block : blocks) { - byte[] dataBytes = block.getDataBytes(); - if (i < dataBytes.length) { - result.appendBits(dataBytes[i], 8); - } - } - } - // Then, place error correction blocks. - for (int i = 0; i < maxNumEcBytes; ++i) { - for (BlockPair block : blocks) { - byte[] ecBytes = block.getErrorCorrectionBytes(); - if (i < ecBytes.length) { - result.appendBits(ecBytes[i], 8); - } - } - } - if (numTotalBytes != result.getSizeInBytes()) { // Should be same. - throw new WriterException("Interleaving error: " + numTotalBytes + " and " + - result.getSizeInBytes() + " differ."); - } - - return result; - } - - static byte[] generateECBytes(byte[] dataBytes, int numEcBytesInBlock) { - int numDataBytes = dataBytes.length; - int[] toEncode = new int[numDataBytes + numEcBytesInBlock]; - for (int i = 0; i < numDataBytes; i++) { - toEncode[i] = dataBytes[i] & 0xFF; - } - new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock); - - byte[] ecBytes = new byte[numEcBytesInBlock]; - for (int i = 0; i < numEcBytesInBlock; i++) { - ecBytes[i] = (byte) toEncode[numDataBytes + i]; - } - return ecBytes; - } - - /** - * Append mode info. On success, store the result in "bits". - */ - static void appendModeInfo(Mode mode, BitArray bits) { - bits.appendBits(mode.getBits(), 4); - } - - - /** - * Append length info. On success, store the result in "bits". - */ - static void appendLengthInfo(int numLetters, Version version, Mode mode, BitArray bits) throws WriterException { - int numBits = mode.getCharacterCountBits(version); - if (numLetters >= (1 << numBits)) { - throw new WriterException(numLetters + " is bigger than " + ((1 << numBits) - 1)); - } - bits.appendBits(numLetters, numBits); - } - - /** - * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". - */ - static void appendBytes(String content, - Mode mode, - BitArray bits, - String encoding) throws WriterException { - switch (mode) { - case NUMERIC: - appendNumericBytes(content, bits); - break; - case ALPHANUMERIC: - appendAlphanumericBytes(content, bits); - break; - case BYTE: - append8BitBytes(content, bits, encoding); - break; - case KANJI: - appendKanjiBytes(content, bits); - break; - default: - throw new WriterException("Invalid mode: " + mode); - } - } - - static void appendNumericBytes(CharSequence content, BitArray bits) { - int length = content.length(); - int i = 0; - while (i < length) { - int num1 = content.charAt(i) - '0'; - if (i + 2 < length) { - // Encode three numeric letters in ten bits. - int num2 = content.charAt(i + 1) - '0'; - int num3 = content.charAt(i + 2) - '0'; - bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); - i += 3; - } else if (i + 1 < length) { - // Encode two numeric letters in seven bits. - int num2 = content.charAt(i + 1) - '0'; - bits.appendBits(num1 * 10 + num2, 7); - i += 2; - } else { - // Encode one numeric letter in four bits. - bits.appendBits(num1, 4); - i++; - } - } - } - - static void appendAlphanumericBytes(CharSequence content, BitArray bits) throws WriterException { - int length = content.length(); - int i = 0; - while (i < length) { - int code1 = getAlphanumericCode(content.charAt(i)); - if (code1 == -1) { - throw new WriterException(); - } - if (i + 1 < length) { - int code2 = getAlphanumericCode(content.charAt(i + 1)); - if (code2 == -1) { - throw new WriterException(); - } - // Encode two alphanumeric letters in 11 bits. - bits.appendBits(code1 * 45 + code2, 11); - i += 2; - } else { - // Encode one alphanumeric letter in six bits. - bits.appendBits(code1, 6); - i++; - } - } - } - - static void append8BitBytes(String content, BitArray bits, String encoding) - throws WriterException { - byte[] bytes; - try { - bytes = content.getBytes(encoding); - } catch (UnsupportedEncodingException uee) { - throw new WriterException(uee); - } - for (byte b : bytes) { - bits.appendBits(b, 8); - } - } - - static void appendKanjiBytes(String content, BitArray bits) throws WriterException { - byte[] bytes; - try { - bytes = content.getBytes("Shift_JIS"); - } catch (UnsupportedEncodingException uee) { - throw new WriterException(uee); - } - int length = bytes.length; - for (int i = 0; i < length; i += 2) { - int byte1 = bytes[i] & 0xFF; - int byte2 = bytes[i + 1] & 0xFF; - int code = (byte1 << 8) | byte2; - int subtracted = -1; - if (code >= 0x8140 && code <= 0x9ffc) { - subtracted = code - 0x8140; - } else if (code >= 0xe040 && code <= 0xebbf) { - subtracted = code - 0xc140; - } - if (subtracted == -1) { - throw new WriterException("Invalid byte sequence"); - } - int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); - bits.appendBits(encoded, 13); - } - } - - private static void appendECI(CharacterSetECI eci, BitArray bits) { - bits.appendBits(Mode.ECI.getBits(), 4); - // This is correct for values up to 127, which is all we need now. - bits.appendBits(eci.getValue(), 8); - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MaskUtil.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MaskUtil.java deleted file mode 100644 index b2204d4a9..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MaskUtil.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -/** - * @author Satoru Takabayashi - * @author Daniel Switkin - * @author Sean Owen - */ -final class MaskUtil { - - // Penalty weights from section 6.8.2.1 - private static final int N1 = 3; - private static final int N2 = 3; - private static final int N3 = 40; - private static final int N4 = 10; - - private MaskUtil() { - // do nothing - } - - /** - * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and - * give penalty to them. Example: 00000 or 11111. - */ - static int applyMaskPenaltyRule1(ByteMatrix matrix) { - return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false); - } - - /** - * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give - * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a - * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block. - */ - static int applyMaskPenaltyRule2(ByteMatrix matrix) { - int penalty = 0; - byte[][] array = matrix.getArray(); - int width = matrix.getWidth(); - int height = matrix.getHeight(); - for (int y = 0; y < height - 1; y++) { - for (int x = 0; x < width - 1; x++) { - int value = array[y][x]; - if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1]) { - penalty++; - } - } - } - return N2 * penalty; - } - - /** - * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4 - * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we - * find patterns like 000010111010000, we give penalty once. - */ - static int applyMaskPenaltyRule3(ByteMatrix matrix) { - int numPenalties = 0; - byte[][] array = matrix.getArray(); - int width = matrix.getWidth(); - int height = matrix.getHeight(); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - byte[] arrayY = array[y]; // We can at least optimize this access - if (x + 6 < width && - arrayY[x] == 1 && - arrayY[x + 1] == 0 && - arrayY[x + 2] == 1 && - arrayY[x + 3] == 1 && - arrayY[x + 4] == 1 && - arrayY[x + 5] == 0 && - arrayY[x + 6] == 1 && - (isWhiteHorizontal(arrayY, x - 4, x) || isWhiteHorizontal(arrayY, x + 7, x + 11))) { - numPenalties++; - } - if (y + 6 < height && - array[y][x] == 1 && - array[y + 1][x] == 0 && - array[y + 2][x] == 1 && - array[y + 3][x] == 1 && - array[y + 4][x] == 1 && - array[y + 5][x] == 0 && - array[y + 6][x] == 1 && - (isWhiteVertical(array, x, y - 4, y) || isWhiteVertical(array, x, y + 7, y + 11))) { - numPenalties++; - } - } - } - return numPenalties * N3; - } - - private static boolean isWhiteHorizontal(byte[] rowArray, int from, int to) { - for (int i = from; i < to; i++) { - if (i >= 0 && i < rowArray.length && rowArray[i] == 1) { - return false; - } - } - return true; - } - - private static boolean isWhiteVertical(byte[][] array, int col, int from, int to) { - for (int i = from; i < to; i++) { - if (i >= 0 && i < array.length && array[i][col] == 1) { - return false; - } - } - return true; - } - - /** - * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give - * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. - */ - static int applyMaskPenaltyRule4(ByteMatrix matrix) { - int numDarkCells = 0; - byte[][] array = matrix.getArray(); - int width = matrix.getWidth(); - int height = matrix.getHeight(); - for (int y = 0; y < height; y++) { - byte[] arrayY = array[y]; - for (int x = 0; x < width; x++) { - if (arrayY[x] == 1) { - numDarkCells++; - } - } - } - int numTotalCells = matrix.getHeight() * matrix.getWidth(); - int fivePercentVariances = Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells; - return fivePercentVariances * N4; - } - - /** - * Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask - * pattern conditions. - */ - static boolean getDataMaskBit(int maskPattern, int x, int y) { - int intermediate; - int temp; - switch (maskPattern) { - case 0: - intermediate = (y + x) & 0x1; - break; - case 1: - intermediate = y & 0x1; - break; - case 2: - intermediate = x % 3; - break; - case 3: - intermediate = (y + x) % 3; - break; - case 4: - intermediate = ((y / 2) + (x / 3)) & 0x1; - break; - case 5: - temp = y * x; - intermediate = (temp & 0x1) + (temp % 3); - break; - case 6: - temp = y * x; - intermediate = ((temp & 0x1) + (temp % 3)) & 0x1; - break; - case 7: - temp = y * x; - intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1; - break; - default: - throw new IllegalArgumentException("Invalid mask pattern: " + maskPattern); - } - return intermediate == 0; - } - - /** - * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both - * vertical and horizontal orders respectively. - */ - private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, boolean isHorizontal) { - int penalty = 0; - int iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth(); - int jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight(); - byte[][] array = matrix.getArray(); - for (int i = 0; i < iLimit; i++) { - int numSameBitCells = 0; - int prevBit = -1; - for (int j = 0; j < jLimit; j++) { - int bit = isHorizontal ? array[i][j] : array[j][i]; - if (bit == prevBit) { - numSameBitCells++; - } else { - if (numSameBitCells >= 5) { - penalty += N1 + (numSameBitCells - 5); - } - numSameBitCells = 1; // Include the cell itself. - prevBit = bit; - } - } - if (numSameBitCells >= 5) { - penalty += N1 + (numSameBitCells - 5); - } - } - return penalty; - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MatrixUtil.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MatrixUtil.java deleted file mode 100644 index dac25f8de..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/MatrixUtil.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -import com.google.zxing.WriterException; -import com.google.zxing.common.BitArray; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; -import com.google.zxing.qrcode.decoder.Version; - -/** - * @author satorux@google.com (Satoru Takabayashi) - creator - * @author dswitkin@google.com (Daniel Switkin) - ported from C++ - */ -final class MatrixUtil { - - private MatrixUtil() { - // do nothing - } - - private static final int[][] POSITION_DETECTION_PATTERN = { - {1, 1, 1, 1, 1, 1, 1}, - {1, 0, 0, 0, 0, 0, 1}, - {1, 0, 1, 1, 1, 0, 1}, - {1, 0, 1, 1, 1, 0, 1}, - {1, 0, 1, 1, 1, 0, 1}, - {1, 0, 0, 0, 0, 0, 1}, - {1, 1, 1, 1, 1, 1, 1}, - }; - - private static final int[][] POSITION_ADJUSTMENT_PATTERN = { - {1, 1, 1, 1, 1}, - {1, 0, 0, 0, 1}, - {1, 0, 1, 0, 1}, - {1, 0, 0, 0, 1}, - {1, 1, 1, 1, 1}, - }; - - // From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu. - private static final int[][] POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = { - {-1, -1, -1, -1, -1, -1, -1}, // Version 1 - { 6, 18, -1, -1, -1, -1, -1}, // Version 2 - { 6, 22, -1, -1, -1, -1, -1}, // Version 3 - { 6, 26, -1, -1, -1, -1, -1}, // Version 4 - { 6, 30, -1, -1, -1, -1, -1}, // Version 5 - { 6, 34, -1, -1, -1, -1, -1}, // Version 6 - { 6, 22, 38, -1, -1, -1, -1}, // Version 7 - { 6, 24, 42, -1, -1, -1, -1}, // Version 8 - { 6, 26, 46, -1, -1, -1, -1}, // Version 9 - { 6, 28, 50, -1, -1, -1, -1}, // Version 10 - { 6, 30, 54, -1, -1, -1, -1}, // Version 11 - { 6, 32, 58, -1, -1, -1, -1}, // Version 12 - { 6, 34, 62, -1, -1, -1, -1}, // Version 13 - { 6, 26, 46, 66, -1, -1, -1}, // Version 14 - { 6, 26, 48, 70, -1, -1, -1}, // Version 15 - { 6, 26, 50, 74, -1, -1, -1}, // Version 16 - { 6, 30, 54, 78, -1, -1, -1}, // Version 17 - { 6, 30, 56, 82, -1, -1, -1}, // Version 18 - { 6, 30, 58, 86, -1, -1, -1}, // Version 19 - { 6, 34, 62, 90, -1, -1, -1}, // Version 20 - { 6, 28, 50, 72, 94, -1, -1}, // Version 21 - { 6, 26, 50, 74, 98, -1, -1}, // Version 22 - { 6, 30, 54, 78, 102, -1, -1}, // Version 23 - { 6, 28, 54, 80, 106, -1, -1}, // Version 24 - { 6, 32, 58, 84, 110, -1, -1}, // Version 25 - { 6, 30, 58, 86, 114, -1, -1}, // Version 26 - { 6, 34, 62, 90, 118, -1, -1}, // Version 27 - { 6, 26, 50, 74, 98, 122, -1}, // Version 28 - { 6, 30, 54, 78, 102, 126, -1}, // Version 29 - { 6, 26, 52, 78, 104, 130, -1}, // Version 30 - { 6, 30, 56, 82, 108, 134, -1}, // Version 31 - { 6, 34, 60, 86, 112, 138, -1}, // Version 32 - { 6, 30, 58, 86, 114, 142, -1}, // Version 33 - { 6, 34, 62, 90, 118, 146, -1}, // Version 34 - { 6, 30, 54, 78, 102, 126, 150}, // Version 35 - { 6, 24, 50, 76, 102, 128, 154}, // Version 36 - { 6, 28, 54, 80, 106, 132, 158}, // Version 37 - { 6, 32, 58, 84, 110, 136, 162}, // Version 38 - { 6, 26, 54, 82, 110, 138, 166}, // Version 39 - { 6, 30, 58, 86, 114, 142, 170}, // Version 40 - }; - - // Type info cells at the left top corner. - private static final int[][] TYPE_INFO_COORDINATES = { - {8, 0}, - {8, 1}, - {8, 2}, - {8, 3}, - {8, 4}, - {8, 5}, - {8, 7}, - {8, 8}, - {7, 8}, - {5, 8}, - {4, 8}, - {3, 8}, - {2, 8}, - {1, 8}, - {0, 8}, - }; - - // From Appendix D in JISX0510:2004 (p. 67) - private static final int VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101 - - // From Appendix C in JISX0510:2004 (p.65). - private static final int TYPE_INFO_POLY = 0x537; - private static final int TYPE_INFO_MASK_PATTERN = 0x5412; - - // Set all cells to -1. -1 means that the cell is empty (not set yet). - // - // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding - // with the ByteMatrix initialized all to zero. - static void clearMatrix(ByteMatrix matrix) { - matrix.clear((byte) -1); - } - - // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On - // success, store the result in "matrix" and return true. - static void buildMatrix(BitArray dataBits, - ErrorCorrectionLevel ecLevel, - Version version, - int maskPattern, - ByteMatrix matrix) throws WriterException { - clearMatrix(matrix); - embedBasicPatterns(version, matrix); - // Type information appear with any version. - embedTypeInfo(ecLevel, maskPattern, matrix); - // Version info appear if version >= 7. - maybeEmbedVersionInfo(version, matrix); - // Data should be embedded at end. - embedDataBits(dataBits, maskPattern, matrix); - } - - // Embed basic patterns. On success, modify the matrix and return true. - // The basic patterns are: - // - Position detection patterns - // - Timing patterns - // - Dark dot at the left bottom corner - // - Position adjustment patterns, if need be - static void embedBasicPatterns(Version version, ByteMatrix matrix) throws WriterException { - // Let's get started with embedding big squares at corners. - embedPositionDetectionPatternsAndSeparators(matrix); - // Then, embed the dark dot at the left bottom corner. - embedDarkDotAtLeftBottomCorner(matrix); - - // Position adjustment patterns appear if version >= 2. - maybeEmbedPositionAdjustmentPatterns(version, matrix); - // Timing patterns should be embedded after position adj. patterns. - embedTimingPatterns(matrix); - } - - // Embed type information. On success, modify the matrix. - static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix) - throws WriterException { - BitArray typeInfoBits = new BitArray(); - makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); - - for (int i = 0; i < typeInfoBits.getSize(); ++i) { - // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in - // "typeInfoBits". - boolean bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i); - - // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). - int x1 = TYPE_INFO_COORDINATES[i][0]; - int y1 = TYPE_INFO_COORDINATES[i][1]; - matrix.set(x1, y1, bit); - - if (i < 8) { - // Right top corner. - int x2 = matrix.getWidth() - i - 1; - int y2 = 8; - matrix.set(x2, y2, bit); - } else { - // Left bottom corner. - int x2 = 8; - int y2 = matrix.getHeight() - 7 + (i - 8); - matrix.set(x2, y2, bit); - } - } - } - - // Embed version information if need be. On success, modify the matrix and return true. - // See 8.10 of JISX0510:2004 (p.47) for how to embed version information. - static void maybeEmbedVersionInfo(Version version, ByteMatrix matrix) throws WriterException { - if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7. - return; // Don't need version info. - } - BitArray versionInfoBits = new BitArray(); - makeVersionInfoBits(version, versionInfoBits); - - int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. - for (int i = 0; i < 6; ++i) { - for (int j = 0; j < 3; ++j) { - // Place bits in LSB (least significant bit) to MSB order. - boolean bit = versionInfoBits.get(bitIndex); - bitIndex--; - // Left bottom corner. - matrix.set(i, matrix.getHeight() - 11 + j, bit); - // Right bottom corner. - matrix.set(matrix.getHeight() - 11 + j, i, bit); - } - } - } - - // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. - // For debugging purposes, it skips masking process if "getMaskPattern" is -1. - // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. - static void embedDataBits(BitArray dataBits, int maskPattern, ByteMatrix matrix) - throws WriterException { - int bitIndex = 0; - int direction = -1; - // Start from the right bottom cell. - int x = matrix.getWidth() - 1; - int y = matrix.getHeight() - 1; - while (x > 0) { - // Skip the vertical timing pattern. - if (x == 6) { - x -= 1; - } - while (y >= 0 && y < matrix.getHeight()) { - for (int i = 0; i < 2; ++i) { - int xx = x - i; - // Skip the cell if it's not empty. - if (!isEmpty(matrix.get(xx, y))) { - continue; - } - boolean bit; - if (bitIndex < dataBits.getSize()) { - bit = dataBits.get(bitIndex); - ++bitIndex; - } else { - // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described - // in 8.4.9 of JISX0510:2004 (p. 24). - bit = false; - } - - // Skip masking if mask_pattern is -1. - if (maskPattern != -1 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) { - bit = !bit; - } - matrix.set(xx, y, bit); - } - y += direction; - } - direction = -direction; // Reverse the direction. - y += direction; - x -= 2; // Move to the left. - } - // All bits should be consumed. - if (bitIndex != dataBits.getSize()) { - throw new WriterException("Not all bits consumed: " + bitIndex + '/' + dataBits.getSize()); - } - } - - // Return the position of the most significant bit set (to one) in the "value". The most - // significant bit is position 32. If there is no bit set, return 0. Examples: - // - findMSBSet(0) => 0 - // - findMSBSet(1) => 1 - // - findMSBSet(255) => 8 - static int findMSBSet(int value) { - int numDigits = 0; - while (value != 0) { - value >>>= 1; - ++numDigits; - } - return numDigits; - } - - // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH - // code is used for encoding type information and version information. - // Example: Calculation of version information of 7. - // f(x) is created from 7. - // - 7 = 000111 in 6 bits - // - f(x) = x^2 + x^1 + x^0 - // g(x) is given by the standard (p. 67) - // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 - // Multiply f(x) by x^(18 - 6) - // - f'(x) = f(x) * x^(18 - 6) - // - f'(x) = x^14 + x^13 + x^12 - // Calculate the remainder of f'(x) / g(x) - // x^2 - // __________________________________________________ - // g(x) )x^14 + x^13 + x^12 - // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2 - // -------------------------------------------------- - // x^11 + x^10 + x^7 + x^4 + x^2 - // - // The remainder is x^11 + x^10 + x^7 + x^4 + x^2 - // Encode it in binary: 110010010100 - // The return value is 0xc94 (1100 1001 0100) - // - // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit - // operations. We don't care if cofficients are positive or negative. - static int calculateBCHCode(int value, int poly) { - if (poly == 0) { - throw new IllegalArgumentException("0 polynomial"); - } - // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1 - // from 13 to make it 12. - int msbSetInPoly = findMSBSet(poly); - value <<= msbSetInPoly - 1; - // Do the division business using exclusive-or operations. - while (findMSBSet(value) >= msbSetInPoly) { - value ^= poly << (findMSBSet(value) - msbSetInPoly); - } - // Now the "value" is the remainder (i.e. the BCH code) - return value; - } - - // Make bit vector of type information. On success, store the result in "bits" and return true. - // Encode error correction level and mask pattern. See 8.9 of - // JISX0510:2004 (p.45) for details. - static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits) - throws WriterException { - if (!QRCode.isValidMaskPattern(maskPattern)) { - throw new WriterException("Invalid mask pattern"); - } - int typeInfo = (ecLevel.getBits() << 3) | maskPattern; - bits.appendBits(typeInfo, 5); - - int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY); - bits.appendBits(bchCode, 10); - - BitArray maskBits = new BitArray(); - maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15); - bits.xor(maskBits); - - if (bits.getSize() != 15) { // Just in case. - throw new WriterException("should not happen but we got: " + bits.getSize()); - } - } - - // Make bit vector of version information. On success, store the result in "bits" and return true. - // See 8.10 of JISX0510:2004 (p.45) for details. - static void makeVersionInfoBits(Version version, BitArray bits) throws WriterException { - bits.appendBits(version.getVersionNumber(), 6); - int bchCode = calculateBCHCode(version.getVersionNumber(), VERSION_INFO_POLY); - bits.appendBits(bchCode, 12); - - if (bits.getSize() != 18) { // Just in case. - throw new WriterException("should not happen but we got: " + bits.getSize()); - } - } - - // Check if "value" is empty. - private static boolean isEmpty(int value) { - return value == -1; - } - - private static void embedTimingPatterns(ByteMatrix matrix) { - // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical - // separation patterns (size 1). Thus, 8 = 7 + 1. - for (int i = 8; i < matrix.getWidth() - 8; ++i) { - int bit = (i + 1) % 2; - // Horizontal line. - if (isEmpty(matrix.get(i, 6))) { - matrix.set(i, 6, bit); - } - // Vertical line. - if (isEmpty(matrix.get(6, i))) { - matrix.set(6, i, bit); - } - } - } - - // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) - private static void embedDarkDotAtLeftBottomCorner(ByteMatrix matrix) throws WriterException { - if (matrix.get(8, matrix.getHeight() - 8) == 0) { - throw new WriterException(); - } - matrix.set(8, matrix.getHeight() - 8, 1); - } - - private static void embedHorizontalSeparationPattern(int xStart, - int yStart, - ByteMatrix matrix) throws WriterException { - for (int x = 0; x < 8; ++x) { - if (!isEmpty(matrix.get(xStart + x, yStart))) { - throw new WriterException(); - } - matrix.set(xStart + x, yStart, 0); - } - } - - private static void embedVerticalSeparationPattern(int xStart, - int yStart, - ByteMatrix matrix) throws WriterException { - for (int y = 0; y < 7; ++y) { - if (!isEmpty(matrix.get(xStart, yStart + y))) { - throw new WriterException(); - } - matrix.set(xStart, yStart + y, 0); - } - } - - // Note that we cannot unify the function with embedPositionDetectionPattern() despite they are - // almost identical, since we cannot write a function that takes 2D arrays in different sizes in - // C/C++. We should live with the fact. - private static void embedPositionAdjustmentPattern(int xStart, int yStart, ByteMatrix matrix) { - for (int y = 0; y < 5; ++y) { - for (int x = 0; x < 5; ++x) { - matrix.set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]); - } - } - } - - private static void embedPositionDetectionPattern(int xStart, int yStart, ByteMatrix matrix) { - for (int y = 0; y < 7; ++y) { - for (int x = 0; x < 7; ++x) { - matrix.set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]); - } - } - } - - // Embed position detection patterns and surrounding vertical/horizontal separators. - private static void embedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) throws WriterException { - // Embed three big squares at corners. - int pdpWidth = POSITION_DETECTION_PATTERN[0].length; - // Left top corner. - embedPositionDetectionPattern(0, 0, matrix); - // Right top corner. - embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix); - // Left bottom corner. - embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix); - - // Embed horizontal separation patterns around the squares. - int hspWidth = 8; - // Left top corner. - embedHorizontalSeparationPattern(0, hspWidth - 1, matrix); - // Right top corner. - embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, - hspWidth - 1, matrix); - // Left bottom corner. - embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix); - - // Embed vertical separation patterns around the squares. - int vspSize = 7; - // Left top corner. - embedVerticalSeparationPattern(vspSize, 0, matrix); - // Right top corner. - embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix); - // Left bottom corner. - embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, - matrix); - } - - // Embed position adjustment patterns if need be. - private static void maybeEmbedPositionAdjustmentPatterns(Version version, ByteMatrix matrix) { - if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2 - return; - } - int index = version.getVersionNumber() - 1; - int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; - int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].length; - for (int i = 0; i < numCoordinates; ++i) { - for (int j = 0; j < numCoordinates; ++j) { - int y = coordinates[i]; - int x = coordinates[j]; - if (x == -1 || y == -1) { - continue; - } - // If the cell is unset, we embed the position adjustment pattern here. - if (isEmpty(matrix.get(x, y))) { - // -2 is necessary since the x/y coordinates point to the center of the pattern, not the - // left top corner. - embedPositionAdjustmentPattern(x - 2, y - 2, matrix); - } - } - } - } - -} diff --git a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/QRCode.java b/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/QRCode.java deleted file mode 100644 index b560de92f..000000000 --- a/extern/zxing-core/src/main/java/com/google/zxing/qrcode/encoder/QRCode.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; -import com.google.zxing.qrcode.decoder.Mode; -import com.google.zxing.qrcode.decoder.Version; - -/** - * @author satorux@google.com (Satoru Takabayashi) - creator - * @author dswitkin@google.com (Daniel Switkin) - ported from C++ - */ -public final class QRCode { - - public static final int NUM_MASK_PATTERNS = 8; - - private Mode mode; - private ErrorCorrectionLevel ecLevel; - private Version version; - private int maskPattern; - private ByteMatrix matrix; - - public QRCode() { - maskPattern = -1; - } - - public Mode getMode() { - return mode; - } - - public ErrorCorrectionLevel getECLevel() { - return ecLevel; - } - - public Version getVersion() { - return version; - } - - public int getMaskPattern() { - return maskPattern; - } - - public ByteMatrix getMatrix() { - return matrix; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(200); - result.append("<<\n"); - result.append(" mode: "); - result.append(mode); - result.append("\n ecLevel: "); - result.append(ecLevel); - result.append("\n version: "); - result.append(version); - result.append("\n maskPattern: "); - result.append(maskPattern); - if (matrix == null) { - result.append("\n matrix: null\n"); - } else { - result.append("\n matrix:\n"); - result.append(matrix); - } - result.append(">>\n"); - return result.toString(); - } - - public void setMode(Mode value) { - mode = value; - } - - public void setECLevel(ErrorCorrectionLevel value) { - ecLevel = value; - } - - public void setVersion(Version version) { - this.version = version; - } - - public void setMaskPattern(int value) { - maskPattern = value; - } - - public void setMatrix(ByteMatrix value) { - matrix = value; - } - - // Check if "mask_pattern" is valid. - public static boolean isValidMaskPattern(int maskPattern) { - return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS; - } - -}