rhodes 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (1413) hide show
  1. data/CHANGELOG +17 -0
  2. data/Rakefile +189 -110
  3. data/bin/rhodes +4 -0
  4. data/bin/rhodes.bat +1 -0
  5. data/lib/build/compileERB/default.rb +1 -1
  6. data/lib/build/jake.rb +54 -2
  7. data/lib/extensions/barcode/ext/barcode/platform/android/Rakefile +84 -0
  8. data/lib/extensions/barcode/ext/barcode/platform/android/jni/src/imageprovider.cpp +164 -0
  9. data/lib/extensions/barcode/ext/barcode/platform/bb/Barcode.files +146 -0
  10. data/lib/extensions/barcode/ext/barcode/platform/bb/Rakefile +93 -0
  11. data/lib/extensions/barcode/ext/barcode/platform/bb/Rhode/com/rho/rubyext/BarcodeRecognizer.java +177 -0
  12. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/AUTHORS +35 -0
  13. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/COPYING +201 -0
  14. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/README +11 -0
  15. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/BarcodeFormat.java +88 -0
  16. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/Binarizer.java +80 -0
  17. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/BinaryBitmap.java +128 -0
  18. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/ChecksumException.java +37 -0
  19. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/DecodeHintType.java +79 -0
  20. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/EncodeHintType.java +39 -0
  21. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/FormatException.java +38 -0
  22. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/LuminanceSource.java +113 -0
  23. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/MultiFormatReader.java +164 -0
  24. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/MultiFormatWriter.java +55 -0
  25. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/NotFoundException.java +37 -0
  26. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/Reader.java +64 -0
  27. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/ReaderException.java +98 -0
  28. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/Result.java +102 -0
  29. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/ResultMetadataType.java +63 -0
  30. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/ResultPoint.java +127 -0
  31. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/ResultPointCallback.java +29 -0
  32. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/Writer.java +54 -0
  33. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/WriterException.java +35 -0
  34. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/AbstractDoCoMoResultParser.java +39 -0
  35. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/AddressBookAUResultParser.java +73 -0
  36. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/AddressBookDoCoMoResultParser.java +85 -0
  37. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/AddressBookParsedResult.java +122 -0
  38. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/BizcardResultParser.java +94 -0
  39. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/BookmarkDoCoMoResultParser.java +46 -0
  40. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/CalendarParsedResult.java +130 -0
  41. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/EmailAddressParsedResult.java +61 -0
  42. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/EmailAddressResultParser.java +64 -0
  43. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/EmailDoCoMoResultParser.java +87 -0
  44. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/GeoParsedResult.java +107 -0
  45. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/GeoResultParser.java +64 -0
  46. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ISBNParsedResult.java +39 -0
  47. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ISBNResultParser.java +54 -0
  48. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ParsedResult.java +73 -0
  49. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ParsedResultType.java +52 -0
  50. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ProductParsedResult.java +49 -0
  51. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ProductResultParser.java +66 -0
  52. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/ResultParser.java +313 -0
  53. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/SMSMMSResultParser.java +103 -0
  54. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/SMSParsedResult.java +75 -0
  55. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/TelParsedResult.java +54 -0
  56. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/TelResultParser.java +44 -0
  57. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/TextParsedResult.java +48 -0
  58. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/URIParsedResult.java +113 -0
  59. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/URIResultParser.java +87 -0
  60. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/URLTOResultParser.java +47 -0
  61. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/VCardResultParser.java +195 -0
  62. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/VEventResultParser.java +56 -0
  63. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/AbstractNDEFResultParser.java +45 -0
  64. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/NDEFRecord.java +87 -0
  65. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/NDEFSmartPosterParsedResult.java +63 -0
  66. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/NDEFSmartPosterResultParser.java +81 -0
  67. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/NDEFTextResultParser.java +57 -0
  68. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/client/result/optional/NDEFURIResultParser.java +95 -0
  69. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/BitArray.java +174 -0
  70. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/BitMatrix.java +190 -0
  71. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/BitSource.java +97 -0
  72. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/ByteArray.java +95 -0
  73. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/ByteMatrix.java +93 -0
  74. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/CharacterSetECI.java +110 -0
  75. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/Collections.java +53 -0
  76. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/Comparator.java +27 -0
  77. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/DecoderResult.java +63 -0
  78. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/DefaultGridSampler.java +81 -0
  79. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/DetectorResult.java +46 -0
  80. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/ECI.java +52 -0
  81. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/GlobalHistogramBinarizer.java +196 -0
  82. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/GridSampler.java +171 -0
  83. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/HybridBinarizer.java +158 -0
  84. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/PerspectiveTransform.java +148 -0
  85. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/detector/MonochromeRectangleDetector.java +209 -0
  86. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/reedsolomon/GF256.java +142 -0
  87. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/reedsolomon/GF256Poly.java +263 -0
  88. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java +189 -0
  89. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java +75 -0
  90. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/common/reedsolomon/ReedSolomonException.java +31 -0
  91. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/DataMatrixReader.java +159 -0
  92. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/decoder/BitMatrixParser.java +446 -0
  93. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/decoder/DataBlock.java +118 -0
  94. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java +456 -0
  95. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/decoder/Decoder.java +134 -0
  96. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/decoder/Version.java +242 -0
  97. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/datamatrix/detector/Detector.java +283 -0
  98. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/ByQuadrantReader.java +96 -0
  99. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/GenericMultipleBarcodeReader.java +156 -0
  100. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/MultipleBarcodeReader.java +37 -0
  101. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/qrcode/QRCodeMultiReader.java +80 -0
  102. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/qrcode/detector/MultiDetector.java +72 -0
  103. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java +324 -0
  104. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/Code128Reader.java +473 -0
  105. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/Code39Reader.java +330 -0
  106. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/EAN13Reader.java +135 -0
  107. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/EAN13Writer.java +82 -0
  108. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/EAN8Reader.java +72 -0
  109. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/EAN8Writer.java +77 -0
  110. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/ITFReader.java +348 -0
  111. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/MultiFormatOneDReader.java +96 -0
  112. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/MultiFormatUPCEANReader.java +107 -0
  113. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/OneDReader.java +297 -0
  114. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/UPCAReader.java +75 -0
  115. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/UPCEANReader.java +332 -0
  116. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/UPCEANWriter.java +129 -0
  117. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/UPCEReader.java +153 -0
  118. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/rss/DataCharacter.java +37 -0
  119. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/rss/FinderPattern.java +48 -0
  120. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/rss/Pair.java +32 -0
  121. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/rss/RSS14Reader.java +557 -0
  122. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/oned/rss/RSSUtils.java +155 -0
  123. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/pdf417/PDF417Reader.java +149 -0
  124. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/pdf417/decoder/BitMatrixParser.java +1157 -0
  125. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +627 -0
  126. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/pdf417/decoder/Decoder.java +149 -0
  127. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/pdf417/detector/Detector.java +501 -0
  128. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/QRCodeReader.java +164 -0
  129. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/QRCodeWriter.java +151 -0
  130. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java +203 -0
  131. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/DataBlock.java +123 -0
  132. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/DataMask.java +155 -0
  133. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java +361 -0
  134. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/Decoder.java +150 -0
  135. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java +86 -0
  136. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/FormatInformation.java +171 -0
  137. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/Mode.java +112 -0
  138. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/decoder/Version.java +586 -0
  139. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/AlignmentPattern.java +48 -0
  140. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java +279 -0
  141. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/Detector.java +396 -0
  142. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/FinderPattern.java +63 -0
  143. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java +540 -0
  144. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/detector/FinderPatternInfo.java +49 -0
  145. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/BitVector.java +155 -0
  146. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/BlockPair.java +39 -0
  147. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/Encoder.java +568 -0
  148. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java +219 -0
  149. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java +524 -0
  150. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/core/src/com/google/zxing/qrcode/encoder/QRCode.java +240 -0
  151. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/AdvancedMultimediaManager.java +153 -0
  152. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/DefaultMultimediaManager.java +40 -0
  153. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/LCDUIImageLuminanceSource.java +95 -0
  154. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/MANIFEST.MF.template +11 -0
  155. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/Menu.java +96 -0
  156. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/MultimediaManager.java +39 -0
  157. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/SnapshotThread.java +143 -0
  158. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/SplashThread.java +127 -0
  159. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/VideoCanvas.java +71 -0
  160. data/lib/extensions/barcode/ext/barcode/platform/bb/ZXing/javame/src/com/google/zxing/client/j2me/ZXingMIDlet.java +292 -0
  161. data/lib/extensions/barcode/ext/barcode/platform/bb/barcode.jdp +193 -0
  162. data/lib/extensions/barcode/ext/barcode/platform/bb/run.bat +3 -0
  163. data/lib/extensions/barcode/ext/barcode/platform/iphone/Barcode.xcodeproj/project.pbxproj +596 -0
  164. data/lib/extensions/barcode/ext/barcode/platform/iphone/Barcode_Prefix.pch +7 -0
  165. data/lib/extensions/barcode/ext/barcode/platform/iphone/Classes/ImageProvider.cpp +25 -0
  166. data/lib/extensions/barcode/ext/barcode/platform/iphone/Classes/ImageProvider.h +15 -0
  167. data/lib/extensions/barcode/ext/barcode/platform/iphone/Classes/ImageProvider.mm +159 -0
  168. data/lib/extensions/barcode/ext/barcode/platform/iphone/Rakefile +61 -0
  169. data/lib/extensions/barcode/ext/barcode/platform/wm/Barcode.vcproj +271 -0
  170. data/lib/extensions/barcode/ext/barcode/platform/wm/Rakefile +46 -0
  171. data/lib/extensions/barcode/ext/barcode/platform/wm/src/wm_imageprovider.cpp +159 -0
  172. data/lib/extensions/barcode/ext/barcode/shared/ruby/barcode.i +8 -0
  173. data/lib/extensions/barcode/ext/barcode/shared/ruby/barcode_wrap.c +2200 -0
  174. data/lib/extensions/barcode/ext/barcode/shared/src/rho_imageprovider.h +16 -0
  175. data/lib/extensions/barcode/ext/barcode/shared/src/zbar.c +69 -0
  176. data/lib/extensions/barcode/ext/barcode/shared/zbar/config.h +264 -0
  177. data/lib/extensions/barcode/ext/barcode/shared/zbar/inttypes.h +259 -0
  178. data/lib/extensions/barcode/ext/barcode/shared/zbar/rho_bridge.c +29 -0
  179. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/COPYING +27 -0
  180. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/README +95 -0
  181. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Decoder.h +201 -0
  182. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Exception.h +187 -0
  183. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Image.h +321 -0
  184. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ImageScanner.h +130 -0
  185. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Processor.h +223 -0
  186. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/QZBar.h +169 -0
  187. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/QZBarImage.h +72 -0
  188. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Scanner.h +162 -0
  189. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Symbol.h +529 -0
  190. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Video.h +170 -0
  191. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/Window.h +136 -0
  192. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarCaptureReader.h +99 -0
  193. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarImage.h +69 -0
  194. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarImageScanner.h +50 -0
  195. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarReaderController.h +142 -0
  196. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarReaderView.h +119 -0
  197. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarReaderViewController.h +99 -0
  198. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/ZBarSymbol.h +67 -0
  199. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar/zbargtk.h +205 -0
  200. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/include/zbar.h +1415 -0
  201. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/config.c +157 -0
  202. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/convert.c +1172 -0
  203. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/debug.h +87 -0
  204. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/code128.c +528 -0
  205. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/code128.h +49 -0
  206. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/code39.c +335 -0
  207. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/code39.h +50 -0
  208. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/ean.c +660 -0
  209. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/ean.h +86 -0
  210. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/i25.c +243 -0
  211. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/i25.h +50 -0
  212. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/pdf417.c +223 -0
  213. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/pdf417.h +49 -0
  214. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/pdf417_hash.h +545 -0
  215. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/qr_finder.c +102 -0
  216. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder/qr_finder.h +23 -0
  217. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder.c +409 -0
  218. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/decoder.h +219 -0
  219. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/error.c +183 -0
  220. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/error.h +226 -0
  221. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/event.h +62 -0
  222. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/image.c +358 -0
  223. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/image.h +142 -0
  224. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/img_scanner.c +819 -0
  225. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/img_scanner.h +38 -0
  226. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/jpeg.c +241 -0
  227. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/mutex.h +160 -0
  228. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/lock.c +227 -0
  229. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/null.c +62 -0
  230. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/posix.c +337 -0
  231. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/posix.h +138 -0
  232. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/win.c +335 -0
  233. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor/x.c +269 -0
  234. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor.c +700 -0
  235. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/processor.h +126 -0
  236. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/bch15_5.c +184 -0
  237. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/bch15_5.h +20 -0
  238. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/binarize.c +639 -0
  239. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/binarize.h +17 -0
  240. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/isaac.c +139 -0
  241. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/isaac.h +41 -0
  242. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/qrdec.c +3957 -0
  243. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/qrdec.h +168 -0
  244. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/qrdectxt.c +405 -0
  245. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/rs.c +799 -0
  246. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/rs.h +66 -0
  247. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/util.c +140 -0
  248. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode/util.h +48 -0
  249. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/qrcode.h +66 -0
  250. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/refcnt.c +48 -0
  251. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/refcnt.h +96 -0
  252. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/scanner.c +317 -0
  253. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/svg.c +184 -0
  254. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/svg.h +65 -0
  255. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/symbol.c +325 -0
  256. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/symbol.h +93 -0
  257. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/thread.h +127 -0
  258. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/timer.h +151 -0
  259. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/unistd.h +1 -0
  260. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video/null.c +37 -0
  261. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video/v4l1.c +435 -0
  262. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video/v4l2.c +509 -0
  263. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video/vfw.c +494 -0
  264. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video.c +384 -0
  265. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/video.h +160 -0
  266. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/dib.c +75 -0
  267. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/null.c +103 -0
  268. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/vfw.c +104 -0
  269. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/win.c +334 -0
  270. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/win.h +46 -0
  271. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/x.c +356 -0
  272. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/x.h +74 -0
  273. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/ximage.c +219 -0
  274. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window/xv.c +273 -0
  275. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window.c +318 -0
  276. data/lib/extensions/barcode/ext/barcode/shared/zbar/zbar/zbar/window.h +144 -0
  277. data/lib/extensions/barcode/ext/build +17 -0
  278. data/lib/extensions/barcode/ext/build.bat +29 -0
  279. data/lib/extensions/barcode/ext.yml +3 -0
  280. data/lib/extensions/crypt/crypt/rijndael.rb +4 -0
  281. data/lib/extensions/digest/ext/Rakefile +18 -0
  282. data/lib/extensions/digest/ext/digest.vcproj +134 -0
  283. data/lib/extensions/digest-md5/ext/Rakefile +18 -0
  284. data/lib/extensions/digest-md5/ext/digest-md5.vcproj +132 -0
  285. data/lib/extensions/digest-md5/ext/md5init.c +2 -2
  286. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/expectations/expectations.rb +0 -0
  287. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/expectations/should.rb +0 -0
  288. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/expectations.rb +0 -0
  289. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/fileutils.rb +0 -0
  290. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/background.rb +0 -0
  291. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/bug.rb +0 -0
  292. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/compliance.rb +0 -0
  293. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/conflict.rb +0 -0
  294. data/{spec/framework_spec/app → lib/extensions/mspec}/mspec/guards/endian.rb +0 -0
  295. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/extensions.rb +0 -0
  296. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/guard.rb +0 -0
  297. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/noncompliance.rb +0 -0
  298. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/platform.rb +0 -0
  299. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/quarantine.rb +0 -0
  300. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/runner.rb +0 -0
  301. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/superuser.rb +0 -0
  302. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/support.rb +0 -0
  303. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/tty.rb +0 -0
  304. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards/version.rb +0 -0
  305. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/guards.rb +0 -0
  306. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/argv.rb +0 -0
  307. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/bignum.rb +0 -0
  308. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/const_lookup.rb +0 -0
  309. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/ducktype.rb +0 -0
  310. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/enumerator_class.rb +0 -0
  311. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/environment.rb +0 -0
  312. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/fixture.rb +0 -0
  313. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/flunk.rb +0 -0
  314. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/fs.rb +0 -0
  315. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/hash.rb +0 -0
  316. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/infinity.rb +0 -0
  317. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/io.rb +0 -0
  318. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/language_version.rb +0 -0
  319. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/metaclass.rb +0 -0
  320. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/mock_to_path.rb +0 -0
  321. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/nan.rb +0 -0
  322. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/ruby_exe.rb +0 -0
  323. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/scratch.rb +0 -0
  324. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers/tmp.rb +0 -0
  325. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/helpers.rb +0 -0
  326. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/base.rb +0 -0
  327. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_an_instance_of.rb +0 -0
  328. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_ancestor_of.rb +0 -0
  329. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_close.rb +0 -0
  330. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_empty.rb +0 -0
  331. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_false.rb +0 -0
  332. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_kind_of.rb +0 -0
  333. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_nil.rb +0 -0
  334. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/be_true.rb +0 -0
  335. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/complain.rb +0 -0
  336. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/eql.rb +0 -0
  337. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/equal.rb +0 -0
  338. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/equal_element.rb +0 -0
  339. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/equal_utf16.rb +0 -0
  340. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/have_constant.rb +0 -0
  341. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/have_instance_method.rb +0 -0
  342. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/have_method.rb +0 -0
  343. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/have_private_instance_method.rb +0 -0
  344. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/have_public_instance_method.rb +0 -0
  345. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/include.rb +0 -0
  346. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/match_yaml.rb +0 -0
  347. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/method.rb +0 -0
  348. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/output.rb +0 -0
  349. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/output_to_fd.rb +0 -0
  350. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/raise_error.rb +0 -0
  351. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/respond_to.rb +0 -0
  352. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers/stringsymboladapter.rb +0 -0
  353. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/matchers.rb +0 -0
  354. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/mocks/mock.rb +0 -0
  355. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/mocks/object.rb +0 -0
  356. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/mocks/proxy.rb +0 -0
  357. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/mocks.rb +0 -0
  358. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/pp.rb +0 -0
  359. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/debug.rb +0 -0
  360. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/filter.rb +0 -0
  361. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/gdb.rb +0 -0
  362. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/tag.rb +0 -0
  363. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/taglist.rb +0 -0
  364. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/tagpurge.rb +0 -0
  365. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/tally.rb +0 -0
  366. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions/timer.rb +0 -0
  367. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/actions.rb +0 -0
  368. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/context.rb +0 -0
  369. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/example.rb +0 -0
  370. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/exception.rb +0 -0
  371. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/filters/match.rb +0 -0
  372. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/filters/profile.rb +0 -0
  373. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/filters/regexp.rb +0 -0
  374. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/filters/tag.rb +0 -0
  375. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/filters.rb +0 -0
  376. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/describe.rb +0 -0
  377. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/dotted.rb +0 -0
  378. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/file.rb +0 -0
  379. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/html.rb +0 -0
  380. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/method.rb +0 -0
  381. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/specdoc.rb +0 -0
  382. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/spinner.rb +0 -0
  383. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/summary.rb +0 -0
  384. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/unit.rb +0 -0
  385. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters/yaml.rb +0 -0
  386. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/formatters.rb +0 -0
  387. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/mspec.rb +0 -0
  388. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/object.rb +0 -0
  389. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/shared.rb +0 -0
  390. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner/tag.rb +0 -0
  391. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/runner.rb +0 -0
  392. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/utils/name_map.rb +0 -0
  393. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/utils/options.rb +0 -0
  394. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/utils/ruby_name.rb +0 -0
  395. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/utils/script.rb +0 -0
  396. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/utils/version.rb +0 -0
  397. data/{res/generators/templates/spec/app → lib/extensions/mspec}/mspec/version.rb +0 -0
  398. data/lib/extensions/rexml/rexml/parsers/xpathparser.rb +2 -1
  399. data/lib/extensions/rexml/rexml/xpath_parser.rb +10 -5
  400. data/lib/extensions/rhospec/rhospec.rb +348 -0
  401. data/lib/extensions/rhoxml/rexml/attribute.rb +188 -0
  402. data/lib/extensions/rhoxml/rexml/element.rb +57 -1
  403. data/lib/extensions/rhoxml/rexml/parsers/streamparser.rb +2 -2
  404. data/lib/extensions/rhoxml/rexml/xpath_parser.rb +10 -5
  405. data/lib/framework/builtinME.rb +40 -2
  406. data/lib/framework/rho/render.rb +19 -15
  407. data/lib/framework/rho/rho.rb +88 -50
  408. data/lib/framework/rho/rhoapplication.rb +11 -3
  409. data/lib/framework/rho/rhocontact.rb +5 -2
  410. data/lib/framework/rho/rhosupport.rb +2 -2
  411. data/lib/framework/rho/rhoutils.rb +6 -4
  412. data/lib/framework/rhodes.rb +2 -2
  413. data/lib/framework/rhoframework.rb +2 -1
  414. data/lib/framework/rholang/lang_es.rb +120 -0
  415. data/lib/framework/rholang/localization_simplified.rb +7 -10
  416. data/lib/framework/rholang/rhoerror_es.rb +36 -0
  417. data/lib/framework/rholang/rhomsg_es.rb +28 -0
  418. data/lib/framework/rhom/rhom_db_adapter.rb +113 -33
  419. data/lib/framework/rhom/rhom_object_factory.rb +347 -134
  420. data/lib/framework/version.rb +2 -2
  421. data/lib/rhodes.rb +2 -2
  422. data/platform/android/Rhodes/AndroidManifest.xml +3 -2
  423. data/platform/android/Rhodes/gen/com/rhomobile/rhodes/R.java +40 -28
  424. data/platform/android/Rhodes/jni/include/rhodes/JNIRhodes.h +2 -0
  425. data/platform/android/Rhodes/jni/include/rhodes/RhoClassFactory.h +0 -2
  426. data/platform/android/Rhodes/jni/include/rhodes/details/rhojava.inc +6 -1
  427. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_RhodesService.h +155 -0
  428. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_file_RhoFileApi.h +55 -0
  429. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_geolocation_GeoLocationImpl.h +8 -0
  430. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_signature_Signature.h +21 -0
  431. data/platform/android/Rhodes/jni/include/rhodes.h +3 -0
  432. data/platform/android/Rhodes/jni/src/RhoClassFactory.cpp +0 -6
  433. data/platform/android/Rhodes/jni/src/callbacks.cpp +5 -5
  434. data/platform/android/Rhodes/jni/src/fileapi.cpp +987 -0
  435. data/platform/android/Rhodes/jni/src/geolocation.cpp +13 -0
  436. data/platform/android/Rhodes/jni/src/logconf.cpp +1 -1
  437. data/platform/android/Rhodes/jni/src/nativeview.cpp +35 -0
  438. data/platform/android/Rhodes/jni/src/phonebook.cpp +2 -0
  439. data/platform/android/Rhodes/jni/src/rhodes.cpp +111 -29
  440. data/platform/android/Rhodes/jni/src/signature.cpp +33 -0
  441. data/platform/android/Rhodes/jni/src/webview.cpp +6 -0
  442. data/platform/android/Rhodes/res/drawable/signature_cancel.png +0 -0
  443. data/platform/android/Rhodes/res/drawable/signature_clear.png +0 -0
  444. data/platform/android/Rhodes/res/drawable/signature_ok.png +0 -0
  445. data/platform/android/Rhodes/res/layout/signature.xml +54 -0
  446. data/platform/android/Rhodes/res/values/strings.xml +22 -20
  447. data/platform/android/Rhodes/src/com/rhomobile/rhodes/AndroidR.java +8 -0
  448. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +6 -5
  449. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NavBar.java +6 -4
  450. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhoActivity.java +18 -0
  451. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhoMenu.java +4 -4
  452. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +26 -689
  453. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesService.java +599 -0
  454. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RingtoneManager.java +1 -1
  455. data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +7 -16
  456. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Utils.java +30 -14
  457. data/platform/android/Rhodes/src/com/rhomobile/rhodes/WebView.java +11 -27
  458. data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/Alert.java +24 -21
  459. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/Camera.java +8 -8
  460. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/FileList.java +5 -5
  461. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/ImageCapture.java +27 -5
  462. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/ImageCaptureCallback.java +4 -1
  463. data/platform/android/Rhodes/src/com/rhomobile/rhodes/datetime/DateTimePicker.java +4 -5
  464. data/platform/android/Rhodes/src/com/rhomobile/rhodes/datetime/DateTimePickerScreen.java +4 -4
  465. data/platform/android/Rhodes/src/com/rhomobile/rhodes/file/RhoFileApi.java +192 -0
  466. data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocation.java +18 -1
  467. data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocationImpl.java +48 -6
  468. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/MainView.java +2 -0
  469. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +39 -40
  470. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +47 -17
  471. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +23 -11
  472. data/platform/android/Rhodes/src/com/rhomobile/rhodes/nativeview/RhoNativeViewManager.java +14 -0
  473. data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorNew.java +5 -5
  474. data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorOld.java +4 -7
  475. data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/Phonebook.java +2 -1
  476. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/ImageCapture.java +182 -0
  477. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/Signature.java +89 -0
  478. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/SignatureView.java +286 -0
  479. data/platform/android/Rhodes/src/com/rhomobile/rhodes/ui/LogOptionsDialog.java +12 -8
  480. data/platform/android/Rhodes/src/com/rhomobile/rhodes/ui/LogViewDialog.java +5 -5
  481. data/platform/android/Rhodes/src/com/rhomobile/rhodes/util/PerformOnUiThread.java +55 -0
  482. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/ChromeClientNew.java +14 -0
  483. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/ChromeClientOld.java +37 -0
  484. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoWebSettings.java +10 -0
  485. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoWebSettingsNew.java +17 -0
  486. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoWebSettingsOld.java +29 -0
  487. data/platform/android/build/RhodesSRC_build.files +13 -1
  488. data/platform/android/build/android.rake +136 -69
  489. data/platform/android/build/androidcommon.rb +1 -1
  490. data/platform/android/build/librhocommon_build.files +2 -3
  491. data/platform/android/build/librhodes_build.files +3 -1
  492. data/platform/android/build/librhomain_build.files +1 -0
  493. data/platform/android/build/libruby_build.files +1 -0
  494. data/platform/bb/Hsqldb/src/com/rho/db/HsqlDBResult.java +1 -1
  495. data/platform/bb/RubyVM/RubyVM.jdp +415 -416
  496. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/Capabilities.java +0 -0
  497. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/DateTimeTokenizer.java +0 -0
  498. data/platform/bb/RubyVM/src/com/rho/Extensions.java +11 -0
  499. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/FilePath.java +0 -0
  500. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/IRhoLogSink.java +0 -0
  501. data/platform/bb/RubyVM/src/com/rho/IRhoRubyHelper.java +35 -0
  502. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/Mutex.java +0 -0
  503. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/Properties.java +0 -0
  504. data/platform/bb/RubyVM/src/com/rho/RhoAppAdapter.java +96 -0
  505. data/platform/bb/RubyVM/src/com/rho/RhoClassFactory.java +125 -0
  506. data/platform/bb/RubyVM/src/com/rho/RhoConf.java +403 -0
  507. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoEmptyLogger.java +0 -0
  508. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoEmptyProfiler.java +0 -0
  509. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoLogConf.java +0 -0
  510. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoLogFileSink.java +0 -0
  511. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoLogOutputSink.java +0 -0
  512. data/platform/bb/RubyVM/src/com/rho/RhoLogger.java +278 -0
  513. data/platform/bb/RubyVM/src/com/rho/RhoParamArray.java +33 -0
  514. data/platform/bb/RubyVM/src/com/rho/RhoParams.java +62 -0
  515. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoProfiler.java +0 -0
  516. data/platform/bb/RubyVM/src/com/rho/RhoRuby.java +257 -0
  517. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/RhoThread.java +0 -0
  518. data/platform/bb/RubyVM/src/com/rho/RhodesApp.java +307 -0
  519. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/SplashScreen.java +0 -0
  520. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/Sprintf.java +0 -0
  521. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/StringScanner.java +0 -0
  522. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/TestProfiler.java +0 -0
  523. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/TestRhoLog.java +0 -0
  524. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/ThreadQueue.java +0 -0
  525. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/TimeInterval.java +0 -0
  526. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/Tokenizer.java +0 -0
  527. data/platform/bb/RubyVM/src/com/rho/db/DBAdapter.java +1198 -0
  528. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/db/DBAttrManager.java +0 -0
  529. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/db/DBException.java +0 -0
  530. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/db/IDBCallback.java +0 -0
  531. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/db/IDBResult.java +0 -0
  532. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/db/IDBStorage.java +0 -0
  533. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/file/IFile.java +0 -0
  534. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/file/IFileAccess.java +0 -0
  535. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/file/IRAFile.java +0 -0
  536. data/platform/bb/RubyVM/src/com/rho/file/RandomAccessFile.java +240 -0
  537. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/file/SimpleFile.java +0 -0
  538. data/platform/bb/RubyVM/src/com/rho/net/AsyncHttp.java +386 -0
  539. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/net/IHttpConnection.java +0 -0
  540. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/net/INetworkAccess.java +0 -0
  541. data/platform/bb/RubyVM/src/com/rho/net/NetRequest.java +706 -0
  542. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/net/NetResponse.java +0 -0
  543. data/platform/bb/RubyVM/src/com/rho/net/RhoConnection.java +847 -0
  544. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/net/URI.java +0 -0
  545. data/platform/bb/RubyVM/src/com/rho/rjson/RJSONTokener.java +247 -0
  546. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/sync/ClientRegister.java +0 -0
  547. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/sync/ISyncProtocol.java +0 -0
  548. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/sync/ISyncStatusListener.java +0 -0
  549. data/platform/bb/RubyVM/src/com/rho/sync/JSONArrayIterator.java +62 -0
  550. data/platform/bb/RubyVM/src/com/rho/sync/JSONEntry.java +75 -0
  551. data/platform/bb/RubyVM/src/com/rho/sync/JSONStructIterator.java +74 -0
  552. data/platform/bb/RubyVM/src/com/rho/sync/SyncEngine.java +918 -0
  553. data/platform/bb/RubyVM/src/com/rho/sync/SyncNotify.java +596 -0
  554. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/rho/sync/SyncProtocol_3.java +0 -0
  555. data/platform/bb/RubyVM/src/com/rho/sync/SyncSource.java +960 -0
  556. data/platform/bb/RubyVM/src/com/rho/sync/SyncThread.java +825 -0
  557. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/ObjectSpace_Methods.java +0 -0
  558. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyArray_Methods.java +0 -0
  559. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyBignum_Methods.java +0 -0
  560. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyDir_Methods.java +0 -0
  561. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyENV_Methods.java +0 -0
  562. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyExceptionValue_Methods.java +0 -0
  563. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyFileTestModule_Methods.java +0 -0
  564. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyFile_Methods.java +0 -0
  565. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyFixnum_Methods.java +0 -0
  566. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyFloat_Methods.java +0 -0
  567. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyGC_Methods.java +0 -0
  568. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyHash_Methods.java +0 -0
  569. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyIO_Methods.java +0 -0
  570. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyInteger_Methods.java +0 -0
  571. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyMatchData_Methods.java +0 -0
  572. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyMethodValue_Methods.java +0 -0
  573. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyNumeric_Methods.java +0 -0
  574. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyObject_Methods.java +0 -0
  575. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyProc_Methods.java +0 -0
  576. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyRandom_Methods.java +0 -0
  577. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyRange_Methods.java +0 -0
  578. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyRegexp_Methods.java +0 -0
  579. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyStringIO_Methods.java +0 -0
  580. data/platform/bb/RubyVM/src/com/xruby/GeneratedMethods/RubyString_Methods.java +275 -0
  581. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyStruct_Methods.java +0 -0
  582. data/platform/bb/RubyVM/src/com/xruby/GeneratedMethods/RubySymbol_Methods.java +44 -0
  583. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyThreadGroup_Methods.java +0 -0
  584. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyThread_Methods.java +0 -0
  585. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyTime_Methods.java +0 -0
  586. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/GeneratedMethods/RubyTopSelf_Methods.java +0 -0
  587. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/ArrayPacker.java +0 -0
  588. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/AttrReader.java +0 -0
  589. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/AttrWriter.java +0 -0
  590. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/ErrnoModuleBuilder.java +0 -0
  591. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/IErrno.java +0 -0
  592. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/InputStreamExecutor.java +0 -0
  593. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/ObjectFactory.java +0 -0
  594. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/OutputStreamExecutor.java +0 -0
  595. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyArray.java +0 -0
  596. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyBignum.java +0 -0
  597. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyData.java +0 -0
  598. data/platform/bb/RubyVM/src/com/xruby/runtime/builtin/RubyDir.java +310 -0
  599. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyENV.java +0 -0
  600. data/platform/bb/RubyVM/src/com/xruby/runtime/builtin/RubyFile.java +318 -0
  601. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyFileTestModule.java +0 -0
  602. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyFixnum.java +0 -0
  603. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyFloat.java +0 -0
  604. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyGC.java +0 -0
  605. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyHash.java +0 -0
  606. data/platform/bb/RubyVM/src/com/xruby/runtime/builtin/RubyIO.java +398 -0
  607. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyIOExecutor.java +0 -0
  608. data/platform/bb/RubyVM/src/com/xruby/runtime/builtin/RubyIOFileExecutor.java +218 -0
  609. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyIOPipeSinkExecutor.java +0 -0
  610. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyIOPipeSourceExecutor.java +0 -0
  611. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyInteger.java +0 -0
  612. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyMatchData.java +0 -0
  613. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyMethodValue.java +0 -0
  614. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyMutex.java +0 -0
  615. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyNumeric.java +0 -0
  616. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyProc.java +0 -0
  617. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyRandom.java +0 -0
  618. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyRange.java +0 -0
  619. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyRegexp.java +0 -0
  620. data/platform/bb/RubyVM/src/com/xruby/runtime/builtin/RubyString.java +1521 -0
  621. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyStruct.java +0 -0
  622. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyThread.java +0 -0
  623. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyThreadGroup.java +0 -0
  624. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyTime.java +0 -0
  625. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyTopSelf.java +0 -0
  626. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/builtin/RubyTypesUtil.java +0 -0
  627. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/AtExitBlocks.java +0 -0
  628. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/ClassFactory.java +0 -0
  629. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/GlobalVariables.java +0 -0
  630. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/MethodBlockBase.java +0 -0
  631. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/MethodCache.java +0 -0
  632. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/ObjectSpace.java +0 -0
  633. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RhoSupport.java +367 -0
  634. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyAPI.java +0 -0
  635. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyBasic.java +0 -0
  636. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyBinding.java +0 -0
  637. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyBlock.java +0 -0
  638. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyClass.java +0 -0
  639. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyClass_Methods.java +0 -0
  640. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RubyConstant.java +31 -0
  641. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyException.java +0 -0
  642. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyExceptionValue.java +0 -0
  643. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyExceptionValueForThrow.java +0 -0
  644. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyID.java +0 -0
  645. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyIncludeClass.java +0 -0
  646. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyKernelModule.java +0 -0
  647. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyKernelModule_Methods.java +0 -0
  648. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyMarshalModule.java +0 -0
  649. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyMarshalModule_Methods.java +0 -0
  650. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyMathModule.java +0 -0
  651. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyMathModule_Methods.java +0 -0
  652. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyMethod.java +0 -0
  653. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyModule.java +0 -0
  654. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyModule_Methods.java +0 -0
  655. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyNoArgBlock.java +0 -0
  656. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyNoArgMethod.java +0 -0
  657. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyNoOrOneArgMethod.java +0 -0
  658. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyObject.java +0 -0
  659. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyOneArgBlock.java +0 -0
  660. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyOneArgMethod.java +0 -0
  661. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyOneOrTwoArgMethod.java +0 -0
  662. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyProgram.java +0 -0
  663. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RubyRuntime.java +526 -0
  664. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubySingletonClass.java +0 -0
  665. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubySpecialValue.java +0 -0
  666. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RubySymbol.java +309 -0
  667. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyTwoArgBlock.java +0 -0
  668. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyTwoArgMethod.java +0 -0
  669. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyValue.java +0 -0
  670. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyVarArgBlock.java +0 -0
  671. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/RubyVarArgMethod.java +0 -0
  672. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/DummyMethod.java +0 -0
  673. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyAllocMethod.java +0 -0
  674. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyLevelClass.java +0 -0
  675. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyLevelConstant.java +0 -0
  676. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyLevelMethod.java +0 -0
  677. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyLevelModule.java +0 -0
  678. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/RubyLevelObject.java +0 -0
  679. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/annotation/UndefMethod.java +0 -0
  680. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/CgMethodItem.java +0 -0
  681. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/DummyMethod.java +0 -0
  682. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/MethodFactory.java +0 -0
  683. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/MethodFactoryHelper.java +0 -0
  684. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/MethodType.java +0 -0
  685. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/NoArgRunMethodHelper.java +0 -0
  686. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/OneArgRunMethodHelper.java +0 -0
  687. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyClassBuilder.java +0 -0
  688. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyClassFactory.java +0 -0
  689. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyModuleBuilder.java +0 -0
  690. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyModuleFactory.java +0 -0
  691. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyObjectBuilder.java +0 -0
  692. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyObjectFactory.java +0 -0
  693. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RubyTypeFactory.java +0 -0
  694. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/RunMethodHelper.java +0 -0
  695. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/TwoArgRunMethodHelper.java +0 -0
  696. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/lang/util/VarArgRunMethodHelper.java +0 -0
  697. data/platform/{shared/rubyJVM → bb/RubyVM}/src/com/xruby/runtime/stdlib/RubyStringIO.java +0 -0
  698. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/CharConversionException.java +0 -0
  699. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/Closeable.java +0 -0
  700. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/DataInput.java +0 -0
  701. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/DataOutput.java +0 -0
  702. data/platform/bb/RubyVM/src/j2me/io/File.java +222 -0
  703. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/FileFilter.java +0 -0
  704. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/FileInputStream.java +0 -0
  705. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/FileNotFoundException.java +0 -0
  706. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/FileOutputStream.java +0 -0
  707. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/FilenameFilter.java +0 -0
  708. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/Flushable.java +0 -0
  709. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/InvalidClassException.java +0 -0
  710. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/InvalidObjectException.java +0 -0
  711. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/NotActiveException.java +0 -0
  712. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/NotSerializableException.java +0 -0
  713. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectInput.java +0 -0
  714. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectInputStream.java +0 -0
  715. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectInputValidation.java +0 -0
  716. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectOutput.java +0 -0
  717. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectOutputStream.java +0 -0
  718. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/ObjectStreamException.java +0 -0
  719. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/OptionalDataException.java +0 -0
  720. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/RandomAccessFile.java +0 -0
  721. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/Serializable.java +0 -0
  722. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/StreamCorruptedException.java +0 -0
  723. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/SyncFailedException.java +0 -0
  724. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/io/WriteAbortedException.java +0 -0
  725. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/ArrayMe.java +0 -0
  726. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/AssertMe.java +0 -0
  727. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/CalendarMe.java +0 -0
  728. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/CharSequence.java +0 -0
  729. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/CharacterDataLatin1.java +0 -0
  730. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/CharacterMe.java +0 -0
  731. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/CloneNotSupportedException.java +0 -0
  732. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Cloneable.java +0 -0
  733. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Comparable.java +0 -0
  734. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Convert.java +0 -0
  735. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/EnumConstantNotPresentException.java +0 -0
  736. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/IllegalStateException.java +0 -0
  737. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Iterable.java +0 -0
  738. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/MathEx.java +0 -0
  739. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/NoSuchFieldException.java +0 -0
  740. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/NoSuchMethodException.java +0 -0
  741. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Number.java +0 -0
  742. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/PrintStreamMe.java +0 -0
  743. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/Readable.java +0 -0
  744. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/SecurityException.java +0 -0
  745. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/StringBufferMe.java +0 -0
  746. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/StringMe.java +0 -0
  747. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/SystemMe.java +0 -0
  748. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/ThreadLocal.java +0 -0
  749. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/TimeZoneMe.java +0 -0
  750. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/TypeNotPresentException.java +0 -0
  751. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/lang/UnsupportedOperationException.java +0 -0
  752. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/math/HugeDigit.java +0 -0
  753. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/math/HugeInt.java +0 -0
  754. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/math/HugeIntHelper.java +0 -0
  755. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/Buffer.java +0 -0
  756. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/BufferUnderflowException.java +0 -0
  757. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/ByteBuffer.java +0 -0
  758. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/ByteOrder.java +0 -0
  759. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/CharBuffer.java +0 -0
  760. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/InvalidMarkException.java +0 -0
  761. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/channels/FileChannel.java +0 -0
  762. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/nio/channels/Pipe.java +0 -0
  763. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/text/ParsePosition.java +0 -0
  764. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/ArrayList.java +0 -0
  765. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Collection.java +0 -0
  766. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Collections.java +0 -0
  767. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Comparator.java +0 -0
  768. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/ConcurrentModificationException.java +0 -0
  769. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/DuplicateFormatFlagsException.java +0 -0
  770. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/EventListener.java +0 -0
  771. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/FormatFlagsConversionMismatchException.java +0 -0
  772. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Formattable.java +0 -0
  773. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Formatter.java +0 -0
  774. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/FormatterClosedException.java +0 -0
  775. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/HashMap.java +0 -0
  776. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/HashSet.java +0 -0
  777. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatCodePointException.java +0 -0
  778. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatConversionException.java +0 -0
  779. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatException.java +0 -0
  780. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatFlagsException.java +0 -0
  781. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatPrecisionException.java +0 -0
  782. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/IllegalFormatWidthException.java +0 -0
  783. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/InputMismatchException.java +0 -0
  784. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/InvalidPropertiesFormatException.java +0 -0
  785. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Iterator.java +0 -0
  786. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/LinkedHashMap.java +0 -0
  787. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/LinkedHashSet.java +0 -0
  788. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/LinkedList.java +0 -0
  789. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/List.java +0 -0
  790. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/ListIterator.java +0 -0
  791. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Locale.java +0 -0
  792. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Map.java +0 -0
  793. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/MissingFormatArgumentException.java +0 -0
  794. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/MissingFormatWidthException.java +0 -0
  795. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/MissingResourceException.java +0 -0
  796. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/NavigableMap.java +0 -0
  797. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/NavigableSet.java +0 -0
  798. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/NoSuchElementException.java +0 -0
  799. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Observable.java +0 -0
  800. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Observer.java +0 -0
  801. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Queue.java +0 -0
  802. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/RandomAccess.java +0 -0
  803. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/RandomMe.java +0 -0
  804. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/Set.java +0 -0
  805. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/SortedMap.java +0 -0
  806. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/SortedSet.java +0 -0
  807. data/platform/bb/RubyVM/src/j2me/util/StringParser.java +245 -0
  808. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/TooManyListenersException.java +0 -0
  809. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/UnknownFormatConversionException.java +0 -0
  810. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/UnknownFormatFlagsException.java +0 -0
  811. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/WeakHashMap.java +0 -0
  812. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/concurrent/ConcurrentHashMap.java +0 -0
  813. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/concurrent/ConcurrentMap.java +0 -0
  814. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/concurrent/atomic/AtomicLong.java +0 -0
  815. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/concurrent/locks/ReentrantLock.java +0 -0
  816. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/logging/Level.java +0 -0
  817. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/logging/LogRecord.java +0 -0
  818. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/logging/Logger.java +0 -0
  819. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/zip/ZipEntry.java +0 -0
  820. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2me/util/zip/ZipFile.java +0 -0
  821. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2mex/realtime/MemoryArea.java +0 -0
  822. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2mex/realtime/NoHeapRealtimeThread.java +0 -0
  823. data/platform/{shared/rubyJVM → bb/RubyVM}/src/j2mex/realtime/RealtimeThread.java +0 -0
  824. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/Javolution.java +0 -0
  825. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/JavolutionError.java +0 -0
  826. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/Allocator.java +0 -0
  827. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/AllocatorContext.java +0 -0
  828. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ArrayFactory.java +0 -0
  829. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ConcurrentContext.java +0 -0
  830. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ConcurrentException.java +0 -0
  831. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ConcurrentThread.java +0 -0
  832. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/Context.java +0 -0
  833. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/HeapContext.java +0 -0
  834. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ImmortalContext.java +0 -0
  835. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/LocalContext.java +0 -0
  836. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/LogContext.java +0 -0
  837. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/ObjectFactory.java +0 -0
  838. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/PersistentContext.java +0 -0
  839. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/SecurityContext.java +0 -0
  840. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/context/StackContext.java +0 -0
  841. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/AppendableWriter.java +0 -0
  842. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/CharSequenceReader.java +0 -0
  843. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/UTF8ByteBufferReader.java +0 -0
  844. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/UTF8ByteBufferWriter.java +0 -0
  845. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/UTF8StreamReader.java +0 -0
  846. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/io/UTF8StreamWriter.java +0 -0
  847. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/ClassInitializer.java +0 -0
  848. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Configurable.java +0 -0
  849. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Enum.java +0 -0
  850. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Immutable.java +0 -0
  851. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/MathLib.java +0 -0
  852. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Realtime.java +0 -0
  853. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Reference.java +0 -0
  854. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Reflection.java +0 -0
  855. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/Reusable.java +0 -0
  856. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/lang/ValueType.java +0 -0
  857. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/Appendable.java +0 -0
  858. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/CharArray.java +0 -0
  859. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/CharSet.java +0 -0
  860. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/Text.java +0 -0
  861. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/TextBuilder.java +0 -0
  862. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/TextFormat.java +0 -0
  863. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/text/TypeFormat.java +0 -0
  864. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastCollection.java +0 -0
  865. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastComparator.java +0 -0
  866. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastIterator.java +0 -0
  867. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastList.java +0 -0
  868. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastMap.java +0 -0
  869. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/FastSet.java +0 -0
  870. data/platform/bb/RubyVM/src/javolution/util/FastTable.java +975 -0
  871. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/Index.java +0 -0
  872. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/LocalMap.java +0 -0
  873. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/ReentrantLock.java +0 -0
  874. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/StandardLog.java +0 -0
  875. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/doc-files/list-add.png +0 -0
  876. data/platform/{shared/rubyJVM → bb/RubyVM}/src/javolution/util/doc-files/map-put.png +0 -0
  877. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/io/GlobFilenameFilter.java +0 -0
  878. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/io/RegexFilenameFilter.java +0 -0
  879. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/GenericPatternCache.java +0 -0
  880. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/GlobCompiler.java +0 -0
  881. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/MalformedCachePatternException.java +0 -0
  882. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/PatternCache.java +0 -0
  883. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/PatternCacheLRU.java +0 -0
  884. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/PatternMatchingEngineFactory.java +0 -0
  885. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/perl/MalformedPerl5PatternException.java +0 -0
  886. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/perl/ParsedSubstitutionEntry.java +0 -0
  887. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/perl/Perl5Util.java +0 -0
  888. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/CharStringPointer.java +0 -0
  889. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/MalformedPatternException.java +0 -0
  890. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/MatchResult.java +0 -0
  891. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/OpCode.java +0 -0
  892. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Pattern.java +0 -0
  893. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/PatternCompiler.java +0 -0
  894. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/PatternCompilerOptions.java +0 -0
  895. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/PatternMatcher.java +0 -0
  896. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/PatternMatcherInput.java +0 -0
  897. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/PatternMatchingEngine.java +0 -0
  898. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5Compiler.java +0 -0
  899. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5MatchResult.java +0 -0
  900. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5Matcher.java +0 -0
  901. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5Pattern.java +0 -0
  902. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5Repetition.java +0 -0
  903. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Perl5Substitution.java +0 -0
  904. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/StringSubstitution.java +0 -0
  905. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Substitution.java +0 -0
  906. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/text/regex/Util.java +0 -0
  907. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/util/Cache.java +0 -0
  908. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/util/CacheLRU.java +0 -0
  909. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/util/GenericCache.java +0 -0
  910. data/platform/{shared/rubyJVM → bb/RubyVM}/src/org/apache/oro/util/GenericCacheEntry.java +0 -0
  911. data/platform/bb/RubyVM/src/org/json/me/RhoJSONArray.java +871 -0
  912. data/platform/bb/RubyVM/src/org/json/me/RhoJSONException.java +27 -0
  913. data/platform/bb/RubyVM/src/org/json/me/RhoJSONObject.java +1290 -0
  914. data/platform/bb/RubyVM/src/org/json/me/RhoJSONString.java +18 -0
  915. data/platform/bb/RubyVM/src/org/json/me/RhoJSONTokener.java +460 -0
  916. data/platform/bb/build/RubyVM_build.files +412 -411
  917. data/platform/bb/build/bb.rake +240 -90
  918. data/platform/bb/rhodes/platform/6.0/com/rho/BrowserAdapter5.java +155 -0
  919. data/platform/bb/rhodes/platform/6.0/com/rho/RhoMainScreen.java +36 -0
  920. data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +5 -0
  921. data/platform/bb/rhodes/src/com/rho/file/Jsr75RAFileImpl.java +2 -2
  922. data/platform/bb/rhodes/src/com/rho/net/BaseSocket.java +6 -0
  923. data/platform/bb/rhodes/src/com/rho/net/NetworkAccess.java +1 -1
  924. data/platform/bb/rhodes/src/com/rho/net/SSLSocket.java +15 -0
  925. data/platform/bb/rhodes/src/com/rho/net/TCPSocket.java +15 -0
  926. data/platform/bb/rhodes/src/com/rho/rubyext/GeoLocation.java +2 -2
  927. data/platform/bb/rhodes/src/com/rho/rubyext/WebView.java +8 -3
  928. data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +39 -9
  929. data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +40 -42
  930. data/platform/bb/rhodes/src/rhomobile/RingtoneManager.java +2 -10
  931. data/platform/bb/rhodes/src/rhomobile/mapview/GoogleMapField.java +10 -10
  932. data/platform/iphone/Classes/AppManager/AppManager.m +9 -2
  933. data/platform/iphone/Classes/Camera/PickImageDelegate.m +6 -4
  934. data/platform/iphone/Classes/DateTimePicker.m +2 -0
  935. data/platform/iphone/Classes/DateTimePickerDelegate.m +19 -7
  936. data/platform/iphone/Classes/GeoLocation/LocationController.m +4 -0
  937. data/platform/iphone/Classes/MapView/MapViewController.h +1 -1
  938. data/platform/iphone/Classes/MapView/MapViewController.m +4 -1
  939. data/platform/iphone/Classes/NativeBar.m +7 -1
  940. data/platform/iphone/Classes/NavBar.m +4 -1
  941. data/platform/iphone/Classes/Phonebook/phonebook.m +5 -0
  942. data/platform/iphone/Classes/RhoAlert.h +1 -1
  943. data/platform/iphone/Classes/RhoAlert.m +8 -0
  944. data/platform/iphone/Classes/RhoMainView.h +0 -1
  945. data/platform/iphone/Classes/RhoNativeViewManager.mm +224 -0
  946. data/platform/iphone/Classes/RhoNativeViewManagerOC.h +45 -0
  947. data/platform/iphone/Classes/Rhodes.h +4 -1
  948. data/platform/iphone/Classes/Rhodes.m +157 -55
  949. data/platform/iphone/Classes/Signature/SignatureDelegate.h +29 -0
  950. data/platform/iphone/Classes/Signature/SignatureDelegate.m +98 -0
  951. data/platform/iphone/Classes/Signature/SignatureView.h +31 -0
  952. data/platform/iphone/Classes/Signature/SignatureView.m +216 -0
  953. data/platform/iphone/Classes/Signature/SignatureViewController.h +25 -0
  954. data/platform/iphone/Classes/Signature/SignatureViewController.m +163 -0
  955. data/platform/iphone/Classes/SimpleMainView.h +11 -1
  956. data/platform/iphone/Classes/SimpleMainView.m +243 -57
  957. data/platform/iphone/Classes/TabbedMainView.h +2 -0
  958. data/platform/iphone/Classes/TabbedMainView.m +9 -10
  959. data/platform/iphone/Classes/WebView.m +38 -24
  960. data/platform/iphone/Classes/rho/net/NetRequestImpl.m +11 -1
  961. data/platform/iphone/Entitlements.plist +6 -0
  962. data/platform/iphone/Info.plist +1 -1
  963. data/platform/iphone/RhoLib/RhoLib.xcodeproj/project.pbxproj +20 -16
  964. data/platform/iphone/rbuild/iphone.rake +138 -134
  965. data/platform/iphone/rhorubylib/rhorubylib.xcodeproj/project.pbxproj +19 -7
  966. data/platform/iphone/rhorunner.xcodeproj/project.pbxproj +65 -23
  967. data/platform/shared/SyncClient/RhoError.h +29 -0
  968. data/platform/shared/SyncClient/SyncClient.cpp +860 -0
  969. data/platform/shared/SyncClient/SyncClient.h +76 -0
  970. data/platform/shared/common/IRhoClassFactory.h +1 -3
  971. data/platform/shared/common/PosixThreadImpl.cpp +30 -12
  972. data/platform/shared/common/PosixThreadImpl.h +1 -0
  973. data/platform/shared/common/RhoAppAdapter.h +34 -0
  974. data/platform/shared/common/RhoConf.cpp +6 -5
  975. data/platform/shared/common/RhoConf.h +2 -1
  976. data/platform/shared/common/RhoFile.cpp +22 -3
  977. data/platform/shared/common/RhoFile.h +1 -1
  978. data/platform/shared/common/RhoNativeViewManager.h +43 -0
  979. data/platform/shared/common/RhoPort.h +16 -0
  980. data/platform/shared/common/RhoStd.h +9 -2
  981. data/platform/shared/common/RhoThread.h +2 -2
  982. data/platform/shared/common/RhodesApp.cpp +193 -111
  983. data/platform/shared/common/RhodesApp.h +28 -27
  984. data/platform/shared/common/RhodesAppBase.cpp +130 -0
  985. data/platform/shared/common/RhodesAppBase.h +64 -0
  986. data/platform/shared/common/SplashScreen.cpp +1 -1
  987. data/platform/shared/common/ThreadQueue.cpp +3 -3
  988. data/platform/shared/common/ThreadQueue.h +7 -7
  989. data/platform/shared/common/Tokenizer.h +2 -1
  990. data/platform/shared/common/iphone/RhoClassFactory.cpp +22 -0
  991. data/platform/shared/common/iphone/RhoClassfactory.h +29 -0
  992. data/platform/shared/common/iphone/RhoFileImpl.m +46 -0
  993. data/platform/shared/common/iphone/RhoThreadImpl.m +24 -0
  994. data/platform/shared/common/rhoparams.cpp +188 -0
  995. data/platform/shared/common/rhoparams.h +35 -42
  996. data/platform/shared/curl/lib/url.c +1 -1
  997. data/platform/shared/db/DBAdapter.cpp +68 -22
  998. data/platform/shared/db/DBAdapter.h +36 -5
  999. data/platform/shared/db/DBAttrManager.cpp +4 -0
  1000. data/platform/shared/db/DBAttrManager.h +2 -1
  1001. data/platform/shared/db/DBResult.cpp +2 -2
  1002. data/platform/shared/db/DBResult.h +25 -5
  1003. data/{res/build-tools → platform/shared/db/res}/db/syncdb.schema +0 -0
  1004. data/{res/build-tools → platform/shared/db/res}/db/syncdb.triggers +0 -0
  1005. data/platform/shared/json/JSONIterator.cpp +4 -2
  1006. data/platform/shared/json/RJSONTokener.c +16 -13
  1007. data/platform/shared/logging/RhoLog.cpp +1 -1
  1008. data/platform/shared/logging/RhoLogConf.cpp +12 -0
  1009. data/platform/shared/net/AsyncHttp.cpp +62 -63
  1010. data/platform/shared/net/AsyncHttp.h +26 -17
  1011. data/platform/shared/net/CURLNetRequest.cpp +248 -156
  1012. data/platform/shared/net/CURLNetRequest.h +42 -16
  1013. data/platform/shared/net/HttpServer.cpp +58 -84
  1014. data/platform/shared/net/HttpServer.h +6 -5
  1015. data/platform/shared/net/URI.cpp +39 -0
  1016. data/platform/shared/net/URI.h +3 -0
  1017. data/platform/{iphone/Classes/rho/net → shared/net/iphone}/sslimpl.cpp +0 -0
  1018. data/platform/{iphone/Classes/rho/net → shared/net/iphone}/sslimpl.h +0 -0
  1019. data/platform/shared/net/ssl.cpp +1 -1
  1020. data/platform/shared/ruby/ext/alert/alert.i +1 -1
  1021. data/platform/shared/ruby/ext/alert/alert_wrap.c +8 -8
  1022. data/platform/shared/ruby/ext/asynchttp/asynchttp.i +10 -17
  1023. data/platform/shared/ruby/ext/asynchttp/asynchttp_wrap.c +20 -340
  1024. data/platform/shared/ruby/ext/mapview/mapview.i +1 -1
  1025. data/platform/shared/ruby/ext/mapview/mapview_wrap.c +8 -8
  1026. data/platform/shared/ruby/ext/nativebar/nativebar.i +1 -1
  1027. data/platform/shared/ruby/ext/nativebar/nativebar_wrap.c +8 -8
  1028. data/platform/shared/ruby/ext/navbar/navbar.i +1 -1
  1029. data/platform/shared/ruby/ext/navbar/navbar_wrap.c +8 -8
  1030. data/platform/shared/ruby/ext/rho/rhoruby.c +29 -9
  1031. data/platform/shared/ruby/ext/rho/rhoruby.h +45 -7
  1032. data/platform/shared/ruby/ext/rhoconf/rhoconf.i +9 -2
  1033. data/platform/shared/ruby/ext/rhoconf/rhoconf_wrap.c +431 -122
  1034. data/platform/shared/ruby/ext/signature/signature.i +8 -0
  1035. data/platform/shared/ruby/ext/signature/signature_wrap.c +2184 -0
  1036. data/platform/shared/ruby/ext/sqlite3_api/sqlite3_api_wrap.c +32 -26
  1037. data/platform/shared/ruby/ext/syncengine/syncengine.i +8 -10
  1038. data/platform/shared/ruby/ext/syncengine/syncengine_wrap.c +449 -208
  1039. data/platform/shared/ruby/ext/webview/webview.i +1 -1
  1040. data/platform/shared/ruby/ext/webview/webview_wrap.c +11 -11
  1041. data/platform/shared/ruby/file.c +19 -11
  1042. data/platform/shared/ruby/linux/ruby/config.h +8 -8
  1043. data/platform/shared/ruby/strftime.c +9 -1
  1044. data/platform/shared/ruby/wince/io_wce.c +69 -29
  1045. data/platform/shared/ruby/wince/sys/stat.c +1 -1
  1046. data/platform/shared/ruby/wince/sys/timeb.c +1 -0
  1047. data/platform/shared/ruby/wince/wince.h +1 -0
  1048. data/platform/shared/rubyext/GeoLocation.cpp +27 -11
  1049. data/platform/shared/rubyext/GeoLocation.h +8 -2
  1050. data/platform/shared/rubyext/RhoAppAdapter.cpp +41 -0
  1051. data/platform/shared/rubyext/System.cpp +1 -18
  1052. data/platform/shared/rubyext/WebView.h +3 -1
  1053. data/platform/shared/sync/ClientRegister.cpp +2 -3
  1054. data/platform/shared/sync/ClientRegister.h +0 -2
  1055. data/platform/shared/sync/SyncEngine.cpp +136 -65
  1056. data/platform/shared/sync/SyncEngine.h +9 -4
  1057. data/platform/shared/sync/SyncNotify.cpp +123 -180
  1058. data/platform/shared/sync/SyncNotify.h +34 -24
  1059. data/platform/shared/sync/SyncSource.cpp +36 -33
  1060. data/platform/shared/sync/SyncSource.h +9 -3
  1061. data/platform/shared/sync/SyncThread.cpp +116 -38
  1062. data/platform/shared/sync/SyncThread.h +26 -30
  1063. data/platform/shared/test/test_helper.cpp +50 -0
  1064. data/platform/shared/test/test_helper.h +2 -0
  1065. data/platform/shared/xruby/src/com/xruby/compiler/codedom/AsciiValueExpression.java +54 -48
  1066. data/platform/shared/xruby/src/com/xruby/compiler/codegen/ClassGeneratorForRubyProgram.java +95 -95
  1067. data/platform/shared/xruby/src/com/xruby/compiler/codegen/RubyCompilerImpl.java +1 -1
  1068. data/platform/shared/xruby/src/com/xruby/compiler/codegen/RubyIDClassGenerator.java +102 -100
  1069. data/platform/wm/RhoLib/RhoLib.vcproj +10 -10
  1070. data/platform/wm/build/build_inf.js +1 -1
  1071. data/platform/wm/build/wm.rake +73 -14
  1072. data/platform/wm/rhodes/Alert.cpp +1 -1
  1073. data/platform/wm/rhodes/MainWindow.cpp +23 -4
  1074. data/platform/wm/rhodes/MainWindow.h +3 -1
  1075. data/platform/wm/rhodes/Rhodes.cpp +6 -5
  1076. data/platform/wm/rhodes/Vibrate.cpp +1 -1
  1077. data/platform/wm/rhodes/camera/Camera.cpp +2 -2
  1078. data/platform/wm/rhodes/phonebook/phonebook.cpp +2 -0
  1079. data/platform/wm/rhodes/rho/common/RhoClassFactory.cpp +2 -7
  1080. data/platform/wm/rhodes/rho/common/RhoClassFactory.h +0 -6
  1081. data/platform/wm/rhodes/rho/common/RhoThreadImpl.h +1 -0
  1082. data/platform/wm/rhodes/rho/net/NetRequest.cpp +1 -1
  1083. data/platform/wm/rhodes/rho/net/NetRequest.h +1 -0
  1084. data/platform/wm/rhodes/rho/net/NetRequestImpl.cpp +8 -3
  1085. data/platform/wm/rhodes/rho/net/NetRequestImpl.h +1 -0
  1086. data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +13 -10
  1087. data/platform/wm/rhodes/rho/rubyext/WebView.cpp +11 -1
  1088. data/platform/wm/rhodes/rhodes.vcproj +26 -9
  1089. data/platform/wm/rhodes/signature/Signature.cpp +28 -0
  1090. data/platform/wm/rhodes/signature/Signature.h +3 -0
  1091. data/platform/wm/rhodes/stdafx.h +5 -0
  1092. data/platform/wm/rubylib/rubylib.vcproj +11 -3
  1093. data/platform/wm/syncengine/syncengine.vcproj +1 -1
  1094. data/platform/wm/tcmalloc/tcmalloc.vcproj +1 -0
  1095. data/rakefile.rb +189 -110
  1096. data/res/build-tools/xruby-0.3.3.jar +0 -0
  1097. data/res/generators/rhogen.rb +9 -9
  1098. data/res/generators/templates/application/app/Settings/home.erb +15 -18
  1099. data/res/generators/templates/application/app/Settings/index.erb +26 -42
  1100. data/res/generators/templates/application/app/Settings/login.erb +19 -23
  1101. data/res/generators/templates/application/app/Settings/reset.erb +12 -13
  1102. data/res/generators/templates/application/app/Settings/wait.erb +2 -2
  1103. data/res/generators/templates/application/app/application.rb +6 -2
  1104. data/res/generators/templates/application/app/helpers/application_helper.rb +39 -21
  1105. data/res/generators/templates/application/app/index.erb +21 -18
  1106. data/res/generators/templates/application/app/layout.erb +38 -21
  1107. data/res/generators/templates/application/build.yml +2 -1
  1108. data/res/generators/templates/application/public/css/android.css +122 -88
  1109. data/res/generators/templates/application/public/css/iphone.css +161 -133
  1110. data/res/generators/templates/application/public/css/windows_mobile.css +126 -116
  1111. data/res/generators/templates/application/public/images/iphone/jqtouch/backButton.png +0 -0
  1112. data/res/generators/templates/application/public/images/iphone/jqtouch/blueButton.png +0 -0
  1113. data/res/generators/templates/application/public/images/iphone/jqtouch/cancel.png +0 -0
  1114. data/res/generators/templates/application/public/images/iphone/jqtouch/chevron.png +0 -0
  1115. data/res/generators/templates/application/public/images/iphone/jqtouch/grayButton.png +0 -0
  1116. data/res/generators/templates/application/public/images/iphone/jqtouch/listArrowSel.png +0 -0
  1117. data/res/generators/templates/application/public/images/iphone/jqtouch/listGroup.png +0 -0
  1118. data/res/generators/templates/application/public/images/iphone/jqtouch/loading.gif +0 -0
  1119. data/res/generators/templates/application/public/images/iphone/jqtouch/on_off.png +0 -0
  1120. data/res/generators/templates/application/public/images/iphone/jqtouch/pinstripes.png +0 -0
  1121. data/res/generators/templates/application/public/images/iphone/jqtouch/selection.png +0 -0
  1122. data/res/generators/templates/application/public/images/iphone/jqtouch/thumb.png +0 -0
  1123. data/res/generators/templates/application/public/images/iphone/jqtouch/toggle.png +0 -0
  1124. data/res/generators/templates/application/public/images/iphone/jqtouch/toggleOn.png +0 -0
  1125. data/res/generators/templates/application/public/images/iphone/jqtouch/toolButton.png +0 -0
  1126. data/res/generators/templates/application/public/images/iphone/jqtouch/toolbar.png +0 -0
  1127. data/res/generators/templates/application/public/images/iphone/jqtouch/whiteButton.png +0 -0
  1128. data/res/generators/templates/application/public/jqtouch/jqtouch.css +378 -0
  1129. data/res/generators/templates/application/public/jqtouch/jqtouch.js +741 -0
  1130. data/res/generators/templates/application/public/jqtouch/jqtouch.transitions.js +60 -0
  1131. data/res/generators/templates/application/public/jqtouch/jquery.1.3.2.min.js +19 -0
  1132. data/res/generators/templates/application/rhoconfig.txt +6 -0
  1133. data/res/generators/templates/model/controller.rb +1 -2
  1134. data/res/generators/templates/model/edit.erb +22 -18
  1135. data/res/generators/templates/model/index.erb +25 -25
  1136. data/res/generators/templates/model/model.rb +4 -1
  1137. data/res/generators/templates/model/new.erb +20 -17
  1138. data/res/generators/templates/model/show.erb +16 -12
  1139. data/res/generators/templates/spec/app/mspec.rb +4 -1
  1140. data/res/generators/templates/spec/app/spec_runner.rb +4 -6
  1141. data/rhobuild.yml.example +13 -7
  1142. data/rhodes.gemspec +3 -2
  1143. data/spec/framework_spec/app/SpecRunner/controller.rb +0 -2
  1144. data/spec/framework_spec/app/mspec.rb +4 -1
  1145. data/spec/framework_spec/app/spec/core/dir/mkdir_spec.rb +3 -2
  1146. data/spec/framework_spec/app/spec/core/dir/path_spec.rb +1 -1
  1147. data/spec/framework_spec/app/spec/core/dir/shared/delete.rb +4 -2
  1148. data/spec/framework_spec/app/spec/core/file/basename_spec.rb +10 -10
  1149. data/spec/framework_spec/app/spec/core/file/constants/constants_spec.rb +2 -0
  1150. data/spec/framework_spec/app/spec/core/file/inspect_spec.rb +5 -3
  1151. data/spec/framework_spec/app/spec/core/file/path_spec.rb +1 -1
  1152. data/spec/framework_spec/app/spec/core/file/shared/fnmatch.rb +5 -5
  1153. data/spec/framework_spec/app/spec/core/file/shared/stat.rb +2 -2
  1154. data/spec/framework_spec/app/spec/core/file/split_spec.rb +2 -1
  1155. data/spec/framework_spec/app/spec/core/math/atanh_spec.rb +8 -6
  1156. data/spec/framework_spec/app/spec/shared/file/readable.rb +2 -1
  1157. data/spec/framework_spec/app/spec_runner.rb +50 -30
  1158. data/spec/framework_spec/build.yml +7 -4
  1159. data/spec/perfomance_spec/Rakefile +27 -0
  1160. data/spec/perfomance_spec/app/Perftest/controller.rb +92 -0
  1161. data/spec/perfomance_spec/app/Perftest/index.erb +21 -0
  1162. data/spec/perfomance_spec/app/Perftest/perftest.rb +4 -0
  1163. data/spec/perfomance_spec/app/application.rb +4 -0
  1164. data/spec/perfomance_spec/app/index.erb +0 -0
  1165. data/spec/perfomance_spec/app/layout.erb +25 -0
  1166. data/spec/perfomance_spec/build.yml +22 -0
  1167. data/spec/perfomance_spec/icon/icon.ico +0 -0
  1168. data/spec/perfomance_spec/icon/icon.png +0 -0
  1169. data/spec/perfomance_spec/public/css/android.css +287 -0
  1170. data/spec/perfomance_spec/public/css/blackberry.css +114 -0
  1171. data/spec/perfomance_spec/public/css/iphone.css +382 -0
  1172. data/{res/generators/templates/application → spec/perfomance_spec}/public/css/webkit.css +0 -0
  1173. data/spec/perfomance_spec/public/css/windows_mobile.css +212 -0
  1174. data/spec/perfomance_spec/public/pinstripes.png +0 -0
  1175. data/spec/perfomance_spec/rhoconfig.txt +34 -0
  1176. data/spec/phone_spec/app/Account/account.rb +7 -0
  1177. data/spec/phone_spec/app/Account_s/account_s.rb +50 -0
  1178. data/spec/phone_spec/app/Barcode/Barcode_UPC_01.png +0 -0
  1179. data/spec/phone_spec/app/Barcode/Barcode_UPC_02.jpg +0 -0
  1180. data/spec/{framework_spec → phone_spec}/app/BlobTest/blob_test.rb +0 -0
  1181. data/spec/{framework_spec → phone_spec}/app/BlobTest/test.png +0 -0
  1182. data/spec/{framework_spec → phone_spec}/app/BlobTest/test2.png +0 -0
  1183. data/spec/{framework_spec → phone_spec}/app/Case/case.rb +0 -0
  1184. data/spec/phone_spec/app/Case_s/case_s.rb +25 -0
  1185. data/spec/phone_spec/app/Customer/customer.rb +7 -0
  1186. data/spec/phone_spec/app/Customer_s/customer_s.rb +21 -0
  1187. data/spec/phone_spec/app/Data/big_test.json +1 -0
  1188. data/spec/phone_spec/app/Data/reqTest.rb +5 -0
  1189. data/spec/phone_spec/app/Data/test1.xml +6 -0
  1190. data/spec/phone_spec/app/Data/test_log.txt +1 -0
  1191. data/spec/phone_spec/app/Product/product.rb +29 -0
  1192. data/spec/phone_spec/app/Product_s/product_s.rb +22 -0
  1193. data/spec/phone_spec/app/Spec/asynchttp_spec.rb +131 -38
  1194. data/spec/phone_spec/app/Spec/barcode_spec.rb +19 -0
  1195. data/spec/phone_spec/app/Spec/blobsync_spec.rb +154 -0
  1196. data/spec/{framework_spec/app/spec → phone_spec/app/Spec}/bsearch_spec.rb +0 -0
  1197. data/spec/phone_spec/app/Spec/bulksync_spec.rb +74 -0
  1198. data/spec/phone_spec/app/Spec/contacts_spec.rb +23 -25
  1199. data/spec/phone_spec/app/Spec/crypt_spec.rb +14 -0
  1200. data/spec/phone_spec/app/Spec/date_spec.rb +17 -0
  1201. data/spec/{framework_spec/app/spec → phone_spec/app/Spec}/fixtures/client_info.txt +0 -0
  1202. data/spec/phone_spec/app/Spec/fixtures/object_values.txt +90 -0
  1203. data/spec/phone_spec/app/Spec/json_spec.rb +79 -42
  1204. data/spec/phone_spec/app/Spec/mapview_spec.rb +10 -12
  1205. data/spec/phone_spec/app/Spec/nativebar_spec.rb +5 -7
  1206. data/spec/phone_spec/app/Spec/navbar_spec.rb +6 -9
  1207. data/spec/phone_spec/app/Spec/pagination/fixtures/object_values.txt +91 -0
  1208. data/spec/phone_spec/app/Spec/rho_controller_spec.rb +156 -0
  1209. data/spec/phone_spec/app/Spec/rho_spec.rb +483 -0
  1210. data/spec/phone_spec/app/Spec/rhofile_spec.rb +52 -18
  1211. data/spec/phone_spec/app/Spec/rhom_object_spec.rb +835 -0
  1212. data/spec/phone_spec/app/Spec/syncengine_spec.rb +287 -0
  1213. data/spec/phone_spec/app/Spec/xml_spec.rb +88 -24
  1214. data/spec/phone_spec/app/Spec/xruby_spec.rb +61 -4
  1215. data/spec/phone_spec/app/SpecRunner/controller.rb +22 -0
  1216. data/spec/phone_spec/app/SpecRunner/index.erb +17 -0
  1217. data/spec/phone_spec/app/index.erb +1 -1
  1218. data/spec/phone_spec/app/spec_runner.rb +41 -0
  1219. data/spec/phone_spec/build.yml +16 -6
  1220. data/spec/phone_spec/rhoconfig.txt +2 -1
  1221. data/spec/phone_spec/server.rb +5 -0
  1222. metadata +944 -696
  1223. data/platform/android/Rhodes/jni/include/rhodes/SystemInfoImpl.h +0 -26
  1224. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_Rhodes.h +0 -131
  1225. data/platform/android/Rhodes/jni/src/syncengine.cpp +0 -13
  1226. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesInstance.java +0 -40
  1227. data/platform/iphone/Classes/RhoFileImpl.m +0 -40
  1228. data/platform/iphone/Classes/rho/common/RhoClassFactory.cpp +0 -26
  1229. data/platform/iphone/Classes/rho/common/RhoClassFactory.h +0 -34
  1230. data/platform/iphone/Classes/rho/common/SystemInfoImpl.h +0 -20
  1231. data/platform/shared/common/ISystemInfo.h +0 -16
  1232. data/platform/shared/common/rhoparams.c +0 -105
  1233. data/platform/shared/rubyJVM/src/com/rho/Convert.java +0 -1989
  1234. data/platform/shared/rubyJVM/src/com/rho/IRhoRubyHelper.java +0 -34
  1235. data/platform/shared/rubyJVM/src/com/rho/RhoClassFactory.java +0 -122
  1236. data/platform/shared/rubyJVM/src/com/rho/RhoConf.java +0 -370
  1237. data/platform/shared/rubyJVM/src/com/rho/RhoLogger.java +0 -275
  1238. data/platform/shared/rubyJVM/src/com/rho/RhoRuby.java +0 -333
  1239. data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +0 -308
  1240. data/platform/shared/rubyJVM/src/com/rho/db/DBAdapter.java +0 -1189
  1241. data/platform/shared/rubyJVM/src/com/rho/file/RandomAccessFile.java +0 -229
  1242. data/platform/shared/rubyJVM/src/com/rho/net/AsyncHttp.java +0 -401
  1243. data/platform/shared/rubyJVM/src/com/rho/net/NetRequest.java +0 -692
  1244. data/platform/shared/rubyJVM/src/com/rho/net/RhoConnection.java +0 -847
  1245. data/platform/shared/rubyJVM/src/com/rho/rjson/RJSONTokener.java +0 -247
  1246. data/platform/shared/rubyJVM/src/com/rho/sync/JSONArrayIterator.java +0 -62
  1247. data/platform/shared/rubyJVM/src/com/rho/sync/JSONEntry.java +0 -75
  1248. data/platform/shared/rubyJVM/src/com/rho/sync/JSONStructIterator.java +0 -74
  1249. data/platform/shared/rubyJVM/src/com/rho/sync/SyncEngine.java +0 -846
  1250. data/platform/shared/rubyJVM/src/com/rho/sync/SyncNotify.java +0 -664
  1251. data/platform/shared/rubyJVM/src/com/rho/sync/SyncSource.java +0 -954
  1252. data/platform/shared/rubyJVM/src/com/rho/sync/SyncThread.java +0 -822
  1253. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubyString_Methods.java +0 -264
  1254. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubySymbol_Methods.java +0 -37
  1255. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyDir.java +0 -307
  1256. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyFile.java +0 -312
  1257. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyIO.java +0 -395
  1258. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyIOFileExecutor.java +0 -218
  1259. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyString.java +0 -1462
  1260. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RhoSupport.java +0 -364
  1261. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubyConstant.java +0 -26
  1262. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubyRuntime.java +0 -482
  1263. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubySymbol.java +0 -303
  1264. data/platform/shared/rubyJVM/src/j2me/io/File.java +0 -222
  1265. data/platform/shared/rubyJVM/src/j2me/util/StringParser.java +0 -236
  1266. data/platform/shared/rubyJVM/src/javolution/context/package.html +0 -123
  1267. data/platform/shared/rubyJVM/src/javolution/io/package.html +0 -5
  1268. data/platform/shared/rubyJVM/src/javolution/lang/package.html +0 -4
  1269. data/platform/shared/rubyJVM/src/javolution/text/package.html +0 -56
  1270. data/platform/shared/rubyJVM/src/javolution/util/FastTable.java +0 -975
  1271. data/platform/shared/rubyJVM/src/javolution/util/package.html +0 -244
  1272. data/platform/shared/rubyJVM/src/org/json/me/JSONArray.java +0 -871
  1273. data/platform/shared/rubyJVM/src/org/json/me/JSONException.java +0 -27
  1274. data/platform/shared/rubyJVM/src/org/json/me/JSONObject.java +0 -1290
  1275. data/platform/shared/rubyJVM/src/org/json/me/JSONString.java +0 -18
  1276. data/platform/shared/rubyJVM/src/org/json/me/JSONTokener.java +0 -460
  1277. data/platform/shared/rubyext/RhoRuby.cpp +0 -31
  1278. data/platform/shared/rubyext/RhoRuby.h +0 -32
  1279. data/platform/wm/rhodes/rho/common/SystemInfoImpl.h +0 -21
  1280. data/res/generators/templates/spec/app/fileutils.rb +0 -1592
  1281. data/res/generators/templates/spec/app/mspec/guards/endian.rb +0 -44
  1282. data/spec/framework_spec/app/Account/account.rb +0 -7
  1283. data/spec/framework_spec/app/BulkTest/bulk_test.rb +0 -9
  1284. data/spec/framework_spec/app/Customer/customer.rb +0 -6
  1285. data/spec/framework_spec/app/Product/controller.rb +0 -62
  1286. data/spec/framework_spec/app/Product/product.rb +0 -9
  1287. data/spec/framework_spec/app/fileutils.rb +0 -1592
  1288. data/spec/framework_spec/app/mspec/expectations/expectations.rb +0 -17
  1289. data/spec/framework_spec/app/mspec/expectations/should.rb +0 -25
  1290. data/spec/framework_spec/app/mspec/expectations.rb +0 -2
  1291. data/spec/framework_spec/app/mspec/fileutils.rb +0 -1589
  1292. data/spec/framework_spec/app/mspec/guards/background.rb +0 -21
  1293. data/spec/framework_spec/app/mspec/guards/bug.rb +0 -24
  1294. data/spec/framework_spec/app/mspec/guards/compliance.rb +0 -37
  1295. data/spec/framework_spec/app/mspec/guards/conflict.rb +0 -18
  1296. data/spec/framework_spec/app/mspec/guards/extensions.rb +0 -20
  1297. data/spec/framework_spec/app/mspec/guards/guard.rb +0 -165
  1298. data/spec/framework_spec/app/mspec/guards/noncompliance.rb +0 -20
  1299. data/spec/framework_spec/app/mspec/guards/platform.rb +0 -43
  1300. data/spec/framework_spec/app/mspec/guards/quarantine.rb +0 -17
  1301. data/spec/framework_spec/app/mspec/guards/runner.rb +0 -34
  1302. data/spec/framework_spec/app/mspec/guards/superuser.rb +0 -17
  1303. data/spec/framework_spec/app/mspec/guards/support.rb +0 -20
  1304. data/spec/framework_spec/app/mspec/guards/tty.rb +0 -20
  1305. data/spec/framework_spec/app/mspec/guards/version.rb +0 -38
  1306. data/spec/framework_spec/app/mspec/guards.rb +0 -16
  1307. data/spec/framework_spec/app/mspec/helpers/argv.rb +0 -43
  1308. data/spec/framework_spec/app/mspec/helpers/bignum.rb +0 -5
  1309. data/spec/framework_spec/app/mspec/helpers/const_lookup.rb +0 -9
  1310. data/spec/framework_spec/app/mspec/helpers/ducktype.rb +0 -33
  1311. data/spec/framework_spec/app/mspec/helpers/enumerator_class.rb +0 -9
  1312. data/spec/framework_spec/app/mspec/helpers/environment.rb +0 -32
  1313. data/spec/framework_spec/app/mspec/helpers/fixture.rb +0 -20
  1314. data/spec/framework_spec/app/mspec/helpers/flunk.rb +0 -5
  1315. data/spec/framework_spec/app/mspec/helpers/fs.rb +0 -58
  1316. data/spec/framework_spec/app/mspec/helpers/hash.rb +0 -27
  1317. data/spec/framework_spec/app/mspec/helpers/infinity.rb +0 -5
  1318. data/spec/framework_spec/app/mspec/helpers/io.rb +0 -17
  1319. data/spec/framework_spec/app/mspec/helpers/language_version.rb +0 -20
  1320. data/spec/framework_spec/app/mspec/helpers/metaclass.rb +0 -7
  1321. data/spec/framework_spec/app/mspec/helpers/mock_to_path.rb +0 -7
  1322. data/spec/framework_spec/app/mspec/helpers/nan.rb +0 -5
  1323. data/spec/framework_spec/app/mspec/helpers/ruby_exe.rb +0 -123
  1324. data/spec/framework_spec/app/mspec/helpers/scratch.rb +0 -17
  1325. data/spec/framework_spec/app/mspec/helpers/tmp.rb +0 -32
  1326. data/spec/framework_spec/app/mspec/helpers.rb +0 -19
  1327. data/spec/framework_spec/app/mspec/matchers/base.rb +0 -95
  1328. data/spec/framework_spec/app/mspec/matchers/be_an_instance_of.rb +0 -26
  1329. data/spec/framework_spec/app/mspec/matchers/be_ancestor_of.rb +0 -24
  1330. data/spec/framework_spec/app/mspec/matchers/be_close.rb +0 -27
  1331. data/spec/framework_spec/app/mspec/matchers/be_empty.rb +0 -20
  1332. data/spec/framework_spec/app/mspec/matchers/be_false.rb +0 -20
  1333. data/spec/framework_spec/app/mspec/matchers/be_kind_of.rb +0 -24
  1334. data/spec/framework_spec/app/mspec/matchers/be_nil.rb +0 -20
  1335. data/spec/framework_spec/app/mspec/matchers/be_true.rb +0 -20
  1336. data/spec/framework_spec/app/mspec/matchers/complain.rb +0 -56
  1337. data/spec/framework_spec/app/mspec/matchers/eql.rb +0 -26
  1338. data/spec/framework_spec/app/mspec/matchers/equal.rb +0 -26
  1339. data/spec/framework_spec/app/mspec/matchers/equal_element.rb +0 -78
  1340. data/spec/framework_spec/app/mspec/matchers/equal_utf16.rb +0 -34
  1341. data/spec/framework_spec/app/mspec/matchers/have_constant.rb +0 -30
  1342. data/spec/framework_spec/app/mspec/matchers/have_instance_method.rb +0 -24
  1343. data/spec/framework_spec/app/mspec/matchers/have_method.rb +0 -24
  1344. data/spec/framework_spec/app/mspec/matchers/have_private_instance_method.rb +0 -24
  1345. data/spec/framework_spec/app/mspec/matchers/have_public_instance_method.rb +0 -24
  1346. data/spec/framework_spec/app/mspec/matchers/include.rb +0 -32
  1347. data/spec/framework_spec/app/mspec/matchers/match_yaml.rb +0 -47
  1348. data/spec/framework_spec/app/mspec/matchers/method.rb +0 -14
  1349. data/spec/framework_spec/app/mspec/matchers/output.rb +0 -67
  1350. data/spec/framework_spec/app/mspec/matchers/output_to_fd.rb +0 -71
  1351. data/spec/framework_spec/app/mspec/matchers/raise_error.rb +0 -49
  1352. data/spec/framework_spec/app/mspec/matchers/respond_to.rb +0 -24
  1353. data/spec/framework_spec/app/mspec/matchers/stringsymboladapter.rb +0 -8
  1354. data/spec/framework_spec/app/mspec/matchers.rb +0 -25
  1355. data/spec/framework_spec/app/mspec/mocks/mock.rb +0 -159
  1356. data/spec/framework_spec/app/mspec/mocks/object.rb +0 -24
  1357. data/spec/framework_spec/app/mspec/mocks/proxy.rb +0 -151
  1358. data/spec/framework_spec/app/mspec/mocks.rb +0 -3
  1359. data/spec/framework_spec/app/mspec/pp.rb +0 -893
  1360. data/spec/framework_spec/app/mspec/runner/actions/debug.rb +0 -17
  1361. data/spec/framework_spec/app/mspec/runner/actions/filter.rb +0 -40
  1362. data/spec/framework_spec/app/mspec/runner/actions/gdb.rb +0 -17
  1363. data/spec/framework_spec/app/mspec/runner/actions/tag.rb +0 -133
  1364. data/spec/framework_spec/app/mspec/runner/actions/taglist.rb +0 -56
  1365. data/spec/framework_spec/app/mspec/runner/actions/tagpurge.rb +0 -56
  1366. data/spec/framework_spec/app/mspec/runner/actions/tally.rb +0 -116
  1367. data/spec/framework_spec/app/mspec/runner/actions/timer.rb +0 -22
  1368. data/spec/framework_spec/app/mspec/runner/actions.rb +0 -8
  1369. data/spec/framework_spec/app/mspec/runner/context.rb +0 -188
  1370. data/spec/framework_spec/app/mspec/runner/example.rb +0 -34
  1371. data/spec/framework_spec/app/mspec/runner/exception.rb +0 -43
  1372. data/spec/framework_spec/app/mspec/runner/filters/match.rb +0 -22
  1373. data/spec/framework_spec/app/mspec/runner/filters/profile.rb +0 -54
  1374. data/spec/framework_spec/app/mspec/runner/filters/regexp.rb +0 -7
  1375. data/spec/framework_spec/app/mspec/runner/filters/tag.rb +0 -29
  1376. data/spec/framework_spec/app/mspec/runner/filters.rb +0 -4
  1377. data/spec/framework_spec/app/mspec/runner/formatters/describe.rb +0 -24
  1378. data/spec/framework_spec/app/mspec/runner/formatters/dotted.rb +0 -98
  1379. data/spec/framework_spec/app/mspec/runner/formatters/file.rb +0 -19
  1380. data/spec/framework_spec/app/mspec/runner/formatters/html.rb +0 -81
  1381. data/spec/framework_spec/app/mspec/runner/formatters/method.rb +0 -93
  1382. data/spec/framework_spec/app/mspec/runner/formatters/specdoc.rb +0 -41
  1383. data/spec/framework_spec/app/mspec/runner/formatters/spinner.rb +0 -99
  1384. data/spec/framework_spec/app/mspec/runner/formatters/summary.rb +0 -11
  1385. data/spec/framework_spec/app/mspec/runner/formatters/unit.rb +0 -21
  1386. data/spec/framework_spec/app/mspec/runner/formatters/yaml.rb +0 -44
  1387. data/spec/framework_spec/app/mspec/runner/formatters.rb +0 -10
  1388. data/spec/framework_spec/app/mspec/runner/mspec.rb +0 -361
  1389. data/spec/framework_spec/app/mspec/runner/object.rb +0 -24
  1390. data/spec/framework_spec/app/mspec/runner/shared.rb +0 -12
  1391. data/spec/framework_spec/app/mspec/runner/tag.rb +0 -32
  1392. data/spec/framework_spec/app/mspec/runner.rb +0 -15
  1393. data/spec/framework_spec/app/mspec/utils/name_map.rb +0 -129
  1394. data/spec/framework_spec/app/mspec/utils/options.rb +0 -441
  1395. data/spec/framework_spec/app/mspec/utils/ruby_name.rb +0 -8
  1396. data/spec/framework_spec/app/mspec/utils/script.rb +0 -220
  1397. data/spec/framework_spec/app/mspec/utils/version.rb +0 -53
  1398. data/spec/framework_spec/app/mspec/version.rb +0 -5
  1399. data/spec/framework_spec/app/spec/blobsync_spec.rb +0 -155
  1400. data/spec/framework_spec/app/spec/bulksync_spec.rb +0 -65
  1401. data/spec/framework_spec/app/spec/fixtures/object_values.txt +0 -90
  1402. data/spec/framework_spec/app/spec/pagination/fixtures/object_values.txt +0 -91
  1403. data/spec/framework_spec/app/spec/rho_controller_spec.rb +0 -143
  1404. data/spec/framework_spec/app/spec/rho_spec.rb +0 -69
  1405. data/spec/framework_spec/app/spec/rhoerror_spec.rb +0 -40
  1406. data/spec/framework_spec/app/spec/rhom_db_adapter_spec.rb +0 -27
  1407. data/spec/framework_spec/app/spec/rhom_object_spec.rb +0 -660
  1408. data/spec/framework_spec/app/spec/rhom_spec.rb +0 -60
  1409. data/spec/framework_spec/app/spec/rhoruby_spec.rb +0 -31
  1410. data/spec/framework_spec/app/spec/syncengine_spec.rb +0 -190
  1411. data/spec/phone_spec/app/Spec/controller.rb +0 -69
  1412. data/spec/phone_spec/app/Spec/index.erb +0 -17
  1413. data/spec/phone_spec/app/Spec/spec_runner.rb +0 -22
@@ -0,0 +1,3957 @@
1
+ /*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org)
2
+ You can redistribute this library and/or modify it under the terms of the
3
+ GNU Lesser General Public License as published by the Free Software
4
+ Foundation; either version 2.1 of the License, or (at your option) any later
5
+ version.*/
6
+ #include <config.h>
7
+ #include <stdlib.h>
8
+ #include <limits.h>
9
+ #include <string.h>
10
+ #include <time.h>
11
+ #include "qrcode.h"
12
+ #include "qrdec.h"
13
+ #include "bch15_5.h"
14
+ #include "rs.h"
15
+ #include "isaac.h"
16
+ #include "util.h"
17
+ #include "binarize.h"
18
+ #include "image.h"
19
+ #include "error.h"
20
+ #include "svg.h"
21
+
22
+ typedef int qr_line[3];
23
+
24
+ typedef struct qr_finder_cluster qr_finder_cluster;
25
+ typedef struct qr_finder_edge_pt qr_finder_edge_pt;
26
+ typedef struct qr_finder_center qr_finder_center;
27
+
28
+ typedef struct qr_aff qr_aff;
29
+ typedef struct qr_hom qr_hom;
30
+
31
+ typedef struct qr_finder qr_finder;
32
+
33
+ typedef struct qr_hom_cell qr_hom_cell;
34
+ typedef struct qr_sampling_grid qr_sampling_grid;
35
+ typedef struct qr_pack_buf qr_pack_buf;
36
+
37
+ /*The number of bits in an int.
38
+ Note the cast to (int): this prevents this value from "promoting" whole
39
+ expressions to an (unsigned) size_t.*/
40
+ #define QR_INT_BITS ((int)sizeof(int)*CHAR_BIT)
41
+ #define QR_INT_LOGBITS (QR_ILOG(QR_INT_BITS))
42
+
43
+ /*A 14 bit resolution for a homography ensures that the ideal module size for a
44
+ version 40 code differs from that of a version 39 code by at least 2.*/
45
+ #define QR_HOM_BITS (14)
46
+
47
+ /*The number of bits of sub-module precision to use when searching for
48
+ alignment patterns.
49
+ Two bits allows an alignment pattern to be found even if the modules have
50
+ been eroded by up to 50% (due to blurring, etc.).
51
+ This must be at least one, since it affects the dynamic range of the
52
+ transforms, and we sample at half-module resolution to compute a bounding
53
+ quadrilateral for the code.*/
54
+ #define QR_ALIGN_SUBPREC (2)
55
+
56
+
57
+ /* collection of finder lines */
58
+ typedef struct qr_finder_lines {
59
+ qr_finder_line *lines;
60
+ int nlines, clines;
61
+ } qr_finder_lines;
62
+
63
+
64
+ struct qr_reader {
65
+ /*The GF(256) representation used in Reed-Solomon decoding.*/
66
+ rs_gf256 gf;
67
+ /*The random number generator used by RANSAC.*/
68
+ isaac_ctx isaac;
69
+ /* current finder state, horizontal and vertical lines */
70
+ qr_finder_lines finder_lines[2];
71
+ };
72
+
73
+
74
+ /*Initializes a client reader handle.*/
75
+ static void qr_reader_init (qr_reader *reader)
76
+ {
77
+ /*time_t now;
78
+ now=time(NULL);
79
+ isaac_init(&_reader->isaac,&now,sizeof(now));*/
80
+ isaac_init(&reader->isaac, NULL, 0);
81
+ rs_gf256_init(&reader->gf, QR_PPOLY);
82
+ }
83
+
84
+ /*Allocates a client reader handle.*/
85
+ qr_reader *_zbar_qr_create (void)
86
+ {
87
+ qr_reader *reader = (qr_reader*)calloc(1, sizeof(*reader));
88
+ qr_reader_init(reader);
89
+ return(reader);
90
+ }
91
+
92
+ /*Frees a client reader handle.*/
93
+ void _zbar_qr_destroy (qr_reader *reader)
94
+ {
95
+ zprintf(1, "max finder lines = %dx%d\n",
96
+ reader->finder_lines[0].clines,
97
+ reader->finder_lines[1].clines);
98
+ if(reader->finder_lines[0].lines)
99
+ free(reader->finder_lines[0].lines);
100
+ if(reader->finder_lines[1].lines)
101
+ free(reader->finder_lines[1].lines);
102
+ free(reader);
103
+ }
104
+
105
+ /* reset finder state between scans */
106
+ void _zbar_qr_reset (qr_reader *reader)
107
+ {
108
+ reader->finder_lines[0].nlines = 0;
109
+ reader->finder_lines[1].nlines = 0;
110
+ }
111
+
112
+
113
+ /*A cluster of lines crossing a finder pattern (all in the same direction).*/
114
+ struct qr_finder_cluster{
115
+ /*Pointers to the lines crossing the pattern.*/
116
+ qr_finder_line **lines;
117
+ /*The number of lines in the cluster.*/
118
+ int nlines;
119
+ };
120
+
121
+
122
+ /*A point on the edge of a finder pattern.
123
+ These are obtained from the endpoints of the lines crossing this particular
124
+ pattern.*/
125
+ struct qr_finder_edge_pt{
126
+ /*The location of the edge point.*/
127
+ qr_point pos;
128
+ /*A label classifying which edge this belongs to:
129
+ 0: negative u edge (left)
130
+ 1: positive u edge (right)
131
+ 2: negative v edge (top)
132
+ 3: positive v edge (bottom)*/
133
+ int edge;
134
+ /*The (signed) perpendicular distance of the edge point from a line parallel
135
+ to the edge passing through the finder center, in (u,v) coordinates.
136
+ This is also re-used by RANSAC to store inlier flags.*/
137
+ int extent;
138
+ };
139
+
140
+
141
+ /*The center of a finder pattern obtained from the crossing of one or more
142
+ clusters of horizontal finder lines with one or more clusters of vertical
143
+ finder lines.*/
144
+ struct qr_finder_center{
145
+ /*The estimated location of the finder center.*/
146
+ qr_point pos;
147
+ /*The list of edge points from the crossing lines.*/
148
+ qr_finder_edge_pt *edge_pts;
149
+ /*The number of edge points from the crossing lines.*/
150
+ int nedge_pts;
151
+ };
152
+
153
+
154
+ static int qr_finder_vline_cmp(const void *_a,const void *_b){
155
+ const qr_finder_line *a;
156
+ const qr_finder_line *b;
157
+ a=(const qr_finder_line *)_a;
158
+ b=(const qr_finder_line *)_b;
159
+ return ((a->pos[0]>b->pos[0])-(a->pos[0]<b->pos[0])<<1)+
160
+ (a->pos[1]>b->pos[1])-(a->pos[1]<b->pos[1]);
161
+ }
162
+
163
+ /*Clusters adjacent lines into groups that are large enough to be crossing a
164
+ finder pattern (relative to their length).
165
+ _clusters: The buffer in which to store the clusters found.
166
+ _neighbors: The buffer used to store the lists of lines in each cluster.
167
+ _lines: The list of lines to cluster.
168
+ Horizontal lines must be sorted in ascending order by Y
169
+ coordinate, with ties broken by X coordinate.
170
+ Vertical lines must be sorted in ascending order by X coordinate,
171
+ with ties broken by Y coordinate.
172
+ _nlines: The number of lines in the set of lines to cluster.
173
+ _v: 0 for horizontal lines, or 1 for vertical lines.
174
+ Return: The number of clusters.*/
175
+ static int qr_finder_cluster_lines(qr_finder_cluster *_clusters,
176
+ qr_finder_line **_neighbors,qr_finder_line *_lines,int _nlines,int _v){
177
+ unsigned char *mark;
178
+ qr_finder_line **neighbors;
179
+ int nneighbors;
180
+ int nclusters;
181
+ int i;
182
+ /*TODO: Kalman filters!*/
183
+ mark=(unsigned char *)calloc(_nlines,sizeof(*mark));
184
+ neighbors=_neighbors;
185
+ nclusters=0;
186
+ for(i=0;i<_nlines-1;i++)if(!mark[i]){
187
+ int len;
188
+ int j;
189
+ nneighbors=1;
190
+ neighbors[0]=_lines+i;
191
+ len=_lines[i].len;
192
+ for(j=i+1;j<_nlines;j++)if(!mark[j]){
193
+ const qr_finder_line *a;
194
+ const qr_finder_line *b;
195
+ int thresh;
196
+ a=neighbors[nneighbors-1];
197
+ b=_lines+j;
198
+ /*The clustering threshold is proportional to the size of the lines,
199
+ since minor noise in large areas can interrupt patterns more easily
200
+ at high resolutions.*/
201
+ thresh=a->len+7>>2;
202
+ if(abs(a->pos[1-_v]-b->pos[1-_v])>thresh)break;
203
+ if(abs(a->pos[_v]-b->pos[_v])>thresh)continue;
204
+ if(abs(a->pos[_v]+a->len-b->pos[_v]-b->len)>thresh)continue;
205
+ if(a->boffs>0&&b->boffs>0&&
206
+ abs(a->pos[_v]-a->boffs-b->pos[_v]+b->boffs)>thresh){
207
+ continue;
208
+ }
209
+ if(a->eoffs>0&&b->eoffs>0&&
210
+ abs(a->pos[_v]+a->len+a->eoffs-b->pos[_v]-b->len-b->eoffs)>thresh){
211
+ continue;
212
+ }
213
+ neighbors[nneighbors++]=_lines+j;
214
+ len+=b->len;
215
+ }
216
+ /*We require at least three lines to form a cluster, which eliminates a
217
+ large number of false positives, saving considerable decoding time.
218
+ This should still be sufficient for 1-pixel codes with no noise.*/
219
+ if(nneighbors<3)continue;
220
+ /*The expected number of lines crossing a finder pattern is equal to their
221
+ average length.
222
+ We accept the cluster if size is at least 1/3 their average length (this
223
+ is a very small threshold, but was needed for some test images).*/
224
+ len=((len<<1)+nneighbors)/(nneighbors<<1);
225
+ if(nneighbors*(5<<QR_FINDER_SUBPREC)>=len){
226
+ _clusters[nclusters].lines=neighbors;
227
+ _clusters[nclusters].nlines=nneighbors;
228
+ for(j=0;j<nneighbors;j++)mark[neighbors[j]-_lines]=1;
229
+ neighbors+=nneighbors;
230
+ nclusters++;
231
+ }
232
+ }
233
+ free(mark);
234
+ return nclusters;
235
+ }
236
+
237
+ /*Adds the coordinates of the edge points from the lines contained in the
238
+ given list of clusters to the list of edge points for a finder center.
239
+ Only the edge point position is initialized.
240
+ The edge label and extent are set by qr_finder_edge_pts_aff_classify()
241
+ or qr_finder_edge_pts_hom_classify().
242
+ _edge_pts: The buffer in which to store the edge points.
243
+ _nedge_pts: The current number of edge points in the buffer.
244
+ _neighbors: The list of lines in the cluster.
245
+ _nneighbors: The number of lines in the list of lines in the cluster.
246
+ _v: 0 for horizontal lines and 1 for vertical lines.
247
+ Return: The new total number of edge points.*/
248
+ static int qr_finder_edge_pts_fill(qr_finder_edge_pt *_edge_pts,int _nedge_pts,
249
+ qr_finder_cluster **_neighbors,int _nneighbors,int _v){
250
+ int i;
251
+ for(i=0;i<_nneighbors;i++){
252
+ qr_finder_cluster *c;
253
+ int j;
254
+ c=_neighbors[i];
255
+ for(j=0;j<c->nlines;j++){
256
+ qr_finder_line *l;
257
+ l=c->lines[j];
258
+ if(l->boffs>0){
259
+ _edge_pts[_nedge_pts].pos[0]=l->pos[0];
260
+ _edge_pts[_nedge_pts].pos[1]=l->pos[1];
261
+ _edge_pts[_nedge_pts].pos[_v]-=l->boffs;
262
+ _nedge_pts++;
263
+ }
264
+ if(l->eoffs>0){
265
+ _edge_pts[_nedge_pts].pos[0]=l->pos[0];
266
+ _edge_pts[_nedge_pts].pos[1]=l->pos[1];
267
+ _edge_pts[_nedge_pts].pos[_v]+=l->len+l->eoffs;
268
+ _nedge_pts++;
269
+ }
270
+ }
271
+ }
272
+ return _nedge_pts;
273
+ }
274
+
275
+ static int qr_finder_center_cmp(const void *_a,const void *_b){
276
+ const qr_finder_center *a;
277
+ const qr_finder_center *b;
278
+ a=(const qr_finder_center *)_a;
279
+ b=(const qr_finder_center *)_b;
280
+ return ((b->nedge_pts>a->nedge_pts)-(b->nedge_pts<a->nedge_pts)<<2)+
281
+ ((a->pos[1]>b->pos[1])-(a->pos[1]<b->pos[1])<<1)+
282
+ (a->pos[0]>b->pos[0])-(a->pos[0]<b->pos[0]);
283
+ }
284
+
285
+ /*Determine if a horizontal line crosses a vertical line.
286
+ _hline: The horizontal line.
287
+ _vline: The vertical line.
288
+ Return: A non-zero value if the lines cross, or zero if they do not.*/
289
+ static int qr_finder_lines_are_crossing(const qr_finder_line *_hline,
290
+ const qr_finder_line *_vline){
291
+ return
292
+ _hline->pos[0]<=_vline->pos[0]&&_vline->pos[0]<_hline->pos[0]+_hline->len&&
293
+ _vline->pos[1]<=_hline->pos[1]&&_hline->pos[1]<_vline->pos[1]+_vline->len;
294
+ }
295
+
296
+ /*Finds horizontal clusters that cross corresponding vertical clusters,
297
+ presumably corresponding to a finder center.
298
+ _center: The buffer in which to store putative finder centers.
299
+ _edge_pts: The buffer to use for the edge point lists for each finder
300
+ center.
301
+ _hclusters: The clusters of horizontal lines crossing finder patterns.
302
+ _nhclusters: The number of horizontal line clusters.
303
+ _vclusters: The clusters of vertical lines crossing finder patterns.
304
+ _nvclusters: The number of vertical line clusters.
305
+ Return: The number of putative finder centers.*/
306
+ static int qr_finder_find_crossings(qr_finder_center *_centers,
307
+ qr_finder_edge_pt *_edge_pts,qr_finder_cluster *_hclusters,int _nhclusters,
308
+ qr_finder_cluster *_vclusters,int _nvclusters){
309
+ qr_finder_cluster **hneighbors;
310
+ qr_finder_cluster **vneighbors;
311
+ unsigned char *hmark;
312
+ unsigned char *vmark;
313
+ int ncenters;
314
+ int i;
315
+ int j;
316
+ hneighbors=(qr_finder_cluster **)malloc(_nhclusters*sizeof(*hneighbors));
317
+ vneighbors=(qr_finder_cluster **)malloc(_nvclusters*sizeof(*vneighbors));
318
+ hmark=(unsigned char *)calloc(_nhclusters,sizeof(*hmark));
319
+ vmark=(unsigned char *)calloc(_nvclusters,sizeof(*vmark));
320
+ ncenters=0;
321
+ /*TODO: This may need some re-working.
322
+ We should be finding groups of clusters such that _all_ horizontal lines in
323
+ _all_ horizontal clusters in the group cross _all_ vertical lines in _all_
324
+ vertical clusters in the group.
325
+ This is equivalent to finding the maximum bipartite clique in the
326
+ connectivity graph, which requires linear progamming to solve efficiently.
327
+ In principle, that is easy to do, but a realistic implementation without
328
+ floating point is a lot of work (and computationally expensive).
329
+ Right now we are relying on a sufficient border around the finder patterns
330
+ to prevent false positives.*/
331
+ for(i=0;i<_nhclusters;i++)if(!hmark[i]){
332
+ qr_finder_line *a;
333
+ qr_finder_line *b;
334
+ int nvneighbors;
335
+ int nedge_pts;
336
+ int y;
337
+ a=_hclusters[i].lines[_hclusters[i].nlines>>1];
338
+ y=nvneighbors=0;
339
+ for(j=0;j<_nvclusters;j++)if(!vmark[j]){
340
+ b=_vclusters[j].lines[_vclusters[j].nlines>>1];
341
+ if(qr_finder_lines_are_crossing(a,b)){
342
+ vmark[j]=1;
343
+ y+=(b->pos[1]<<1)+b->len;
344
+ if(b->boffs>0&&b->eoffs>0)y+=b->eoffs-b->boffs;
345
+ vneighbors[nvneighbors++]=_vclusters+j;
346
+ }
347
+ }
348
+ if(nvneighbors>0){
349
+ qr_finder_center *c;
350
+ int nhneighbors;
351
+ int x;
352
+ x=(a->pos[0]<<1)+a->len;
353
+ if(a->boffs>0&&a->eoffs>0)x+=a->eoffs-a->boffs;
354
+ hneighbors[0]=_hclusters+i;
355
+ nhneighbors=1;
356
+ j=nvneighbors>>1;
357
+ b=vneighbors[j]->lines[vneighbors[j]->nlines>>1];
358
+ for(j=i+1;j<_nhclusters;j++)if(!hmark[j]){
359
+ a=_hclusters[j].lines[_hclusters[j].nlines>>1];
360
+ if(qr_finder_lines_are_crossing(a,b)){
361
+ hmark[j]=1;
362
+ x+=(a->pos[0]<<1)+a->len;
363
+ if(a->boffs>0&&a->eoffs>0)x+=a->eoffs-a->boffs;
364
+ hneighbors[nhneighbors++]=_hclusters+j;
365
+ }
366
+ }
367
+ c=_centers+ncenters++;
368
+ c->pos[0]=(x+nhneighbors)/(nhneighbors<<1);
369
+ c->pos[1]=(y+nvneighbors)/(nvneighbors<<1);
370
+ c->edge_pts=_edge_pts;
371
+ nedge_pts=qr_finder_edge_pts_fill(_edge_pts,0,
372
+ hneighbors,nhneighbors,0);
373
+ nedge_pts=qr_finder_edge_pts_fill(_edge_pts,nedge_pts,
374
+ vneighbors,nvneighbors,1);
375
+ c->nedge_pts=nedge_pts;
376
+ _edge_pts+=nedge_pts;
377
+ }
378
+ }
379
+ free(vmark);
380
+ free(hmark);
381
+ free(vneighbors);
382
+ free(hneighbors);
383
+ /*Sort the centers by decreasing numbers of edge points.*/
384
+ qsort(_centers,ncenters,sizeof(*_centers),qr_finder_center_cmp);
385
+ return ncenters;
386
+ }
387
+
388
+ /*Locates a set of putative finder centers in the image.
389
+ First we search for horizontal and vertical lines that have
390
+ (dark:light:dark:light:dark) runs with size ratios of roughly (1:1:3:1:1).
391
+ Then we cluster them into groups such that each subsequent pair of endpoints
392
+ is close to the line before it in the cluster.
393
+ This will locate many line clusters that don't cross a finder pattern, but
394
+ qr_finder_find_crossings() will filter most of them out.
395
+ Where horizontal and vertical clusters cross, a prospective finder center is
396
+ returned.
397
+ _centers: Returns a pointer to a freshly-allocated list of finder centers.
398
+ This must be freed by the caller.
399
+ _edge_pts: Returns a pointer to a freshly-allocated list of edge points
400
+ around those centers.
401
+ This must be freed by the caller.
402
+ _img: The binary image to search.
403
+ _width: The width of the image.
404
+ _height: The height of the image.
405
+ Return: The number of putative finder centers located.*/
406
+ static int qr_finder_centers_locate(qr_finder_center **_centers,
407
+ qr_finder_edge_pt **_edge_pts, qr_reader *reader,
408
+ int _width,int _height){
409
+ qr_finder_line *hlines = reader->finder_lines[0].lines;
410
+ int nhlines = reader->finder_lines[0].nlines;
411
+ qr_finder_line *vlines = reader->finder_lines[1].lines;
412
+ int nvlines = reader->finder_lines[1].nlines;
413
+
414
+ qr_finder_line **hneighbors;
415
+ qr_finder_cluster *hclusters;
416
+ int nhclusters;
417
+ qr_finder_line **vneighbors;
418
+ qr_finder_cluster *vclusters;
419
+ int nvclusters;
420
+ int ncenters;
421
+
422
+ /*Cluster the detected lines.*/
423
+ hneighbors=(qr_finder_line **)malloc(nhlines*sizeof(*hneighbors));
424
+ /*We require more than one line per cluster, so there are at most nhlines/2.*/
425
+ hclusters=(qr_finder_cluster *)malloc((nhlines>>1)*sizeof(*hclusters));
426
+ nhclusters=qr_finder_cluster_lines(hclusters,hneighbors,hlines,nhlines,0);
427
+ /*We need vertical lines to be sorted by X coordinate, with ties broken by Y
428
+ coordinate, for clustering purposes.
429
+ We scan the image in the opposite order for cache efficiency, so sort the
430
+ lines we found here.*/
431
+ qsort(vlines,nvlines,sizeof(*vlines),qr_finder_vline_cmp);
432
+ vneighbors=(qr_finder_line **)malloc(nvlines*sizeof(*vneighbors));
433
+ /*We require more than one line per cluster, so there are at most nvlines/2.*/
434
+ vclusters=(qr_finder_cluster *)malloc((nvlines>>1)*sizeof(*vclusters));
435
+ nvclusters=qr_finder_cluster_lines(vclusters,vneighbors,vlines,nvlines,1);
436
+ /*Find line crossings among the clusters.*/
437
+ if(nhclusters>=3&&nvclusters>=3){
438
+ qr_finder_edge_pt *edge_pts;
439
+ qr_finder_center *centers;
440
+ int nedge_pts;
441
+ int i;
442
+ nedge_pts=0;
443
+ for(i=0;i<nhclusters;i++)nedge_pts+=hclusters[i].nlines;
444
+ for(i=0;i<nvclusters;i++)nedge_pts+=vclusters[i].nlines;
445
+ nedge_pts<<=1;
446
+ edge_pts=(qr_finder_edge_pt *)malloc(nedge_pts*sizeof(*edge_pts));
447
+ centers=(qr_finder_center *)malloc(
448
+ QR_MINI(nhclusters,nvclusters)*sizeof(*centers));
449
+ ncenters=qr_finder_find_crossings(centers,edge_pts,
450
+ hclusters,nhclusters,vclusters,nvclusters);
451
+ *_centers=centers;
452
+ *_edge_pts=edge_pts;
453
+ }
454
+ else ncenters=0;
455
+ free(vclusters);
456
+ free(vneighbors);
457
+ free(hclusters);
458
+ free(hneighbors);
459
+ return ncenters;
460
+ }
461
+
462
+
463
+
464
+ static void qr_point_translate(qr_point _point,int _dx,int _dy){
465
+ _point[0]+=_dx;
466
+ _point[1]+=_dy;
467
+ }
468
+
469
+ static unsigned qr_point_distance2(const qr_point _p1,const qr_point _p2){
470
+ return (_p1[0]-_p2[0])*(_p1[0]-_p2[0])+(_p1[1]-_p2[1])*(_p1[1]-_p2[1]);
471
+ }
472
+
473
+ /*Returns the cross product of the three points, which is positive if they are
474
+ in CCW order (in a right-handed coordinate system), and 0 if they're
475
+ colinear.*/
476
+ static int qr_point_ccw(const qr_point _p0,
477
+ const qr_point _p1,const qr_point _p2){
478
+ return (_p1[0]-_p0[0])*(_p2[1]-_p0[1])-(_p1[1]-_p0[1])*(_p2[0]-_p0[0]);
479
+ }
480
+
481
+
482
+
483
+ /*Evaluates a line equation at a point.
484
+ _line: The line to evaluate.
485
+ _x: The X coordinate of the point.
486
+ _y: The y coordinate of the point.
487
+ Return: The value of the line equation _line[0]*_x+_line[1]*_y+_line[2].*/
488
+ static int qr_line_eval(qr_line _line,int _x,int _y){
489
+ return _line[0]*_x+_line[1]*_y+_line[2];
490
+ }
491
+
492
+ /*Computes a line passing through the given point using the specified second
493
+ order statistics.
494
+ Given a line defined by the equation
495
+ A*x+B*y+C = 0 ,
496
+ the least squares fit to n points (x_i,y_i) must satisfy the two equations
497
+ A^2 + (Syy - Sxx)/Sxy*A*B - B^2 = 0 ,
498
+ C = -(xbar*A+ybar*B) ,
499
+ where
500
+ xbar = sum(x_i)/n ,
501
+ ybar = sum(y_i)/n ,
502
+ Sxx = sum((x_i-xbar)**2) ,
503
+ Sxy = sum((x_i-xbar)*(y_i-ybar)) ,
504
+ Syy = sum((y_i-ybar)**2) .
505
+ The quadratic can be solved for the ratio (A/B) or (B/A):
506
+ A/B = (Syy + sqrt((Sxx-Syy)**2 + 4*Sxy**2) - Sxx)/(-2*Sxy) ,
507
+ B/A = (Sxx + sqrt((Sxx-Syy)**2 + 4*Sxy**2) - Syy)/(-2*Sxy) .
508
+ We pick the one that leads to the larger ratio to avoid destructive
509
+ cancellation (and e.g., 0/0 for horizontal or vertical lines).
510
+ The above solutions correspond to the actual minimum.
511
+ The other solution of the quadratic corresponds to a saddle point of the
512
+ least squares objective function.
513
+ _l: Returns the fitted line values A, B, and C.
514
+ _x0: The X coordinate of the point the line is supposed to pass through.
515
+ _y0: The Y coordinate of the point the line is supposed to pass through.
516
+ _sxx: The sum Sxx.
517
+ _sxy: The sum Sxy.
518
+ _syy: The sum Syy.
519
+ _res: The maximum number of bits occupied by the product of any two of
520
+ _l[0] or _l[1].
521
+ Smaller numbers give less angular resolution, but allow more overhead
522
+ room for computations.*/
523
+ static void qr_line_fit(qr_line _l,int _x0,int _y0,
524
+ int _sxx,int _sxy,int _syy,int _res){
525
+ int dshift;
526
+ int dround;
527
+ int u;
528
+ int v;
529
+ int w;
530
+ u=abs(_sxx-_syy);
531
+ v=-_sxy<<1;
532
+ w=qr_ihypot(u,v);
533
+ /*Computations in later stages can easily overflow with moderate sizes, so we
534
+ compute a shift factor to scale things down into a managable range.
535
+ We ensure that the product of any two of _l[0] and _l[1] fits within _res
536
+ bits, which allows computation of line intersections without overflow.*/
537
+ dshift=QR_MAXI(0,QR_MAXI(qr_ilog(u),qr_ilog(abs(v)))+1-(_res+1>>1));
538
+ dround=(1<<dshift)>>1;
539
+ if(_sxx>_syy){
540
+ _l[0]=v+dround>>dshift;
541
+ _l[1]=u+w+dround>>dshift;
542
+ }
543
+ else{
544
+ _l[0]=u+w+dround>>dshift;
545
+ _l[1]=v+dround>>dshift;
546
+ }
547
+ _l[2]=-(_x0*_l[0]+_y0*_l[1]);
548
+ }
549
+
550
+ /*Perform a least-squares line fit to a list of points.
551
+ At least two points are required.*/
552
+ static void qr_line_fit_points(qr_line _l,qr_point *_p,int _np,int _res){
553
+ int sx;
554
+ int sy;
555
+ int xmin;
556
+ int xmax;
557
+ int ymin;
558
+ int ymax;
559
+ int xbar;
560
+ int ybar;
561
+ int dx;
562
+ int dy;
563
+ int sxx;
564
+ int sxy;
565
+ int syy;
566
+ int sshift;
567
+ int sround;
568
+ int i;
569
+ sx=sy=0;
570
+ ymax=xmax=INT_MIN;
571
+ ymin=xmin=INT_MAX;
572
+ for(i=0;i<_np;i++){
573
+ sx+=_p[i][0];
574
+ xmin=QR_MINI(xmin,_p[i][0]);
575
+ xmax=QR_MAXI(xmax,_p[i][0]);
576
+ sy+=_p[i][1];
577
+ ymin=QR_MINI(ymin,_p[i][1]);
578
+ ymax=QR_MAXI(ymax,_p[i][1]);
579
+ }
580
+ xbar=(sx+(_np>>1))/_np;
581
+ ybar=(sy+(_np>>1))/_np;
582
+ sshift=QR_MAXI(0,qr_ilog(_np*QR_MAXI(QR_MAXI(xmax-xbar,xbar-xmin),
583
+ QR_MAXI(ymax-ybar,ybar-ymin)))-(QR_INT_BITS-1>>1));
584
+ sround=(1<<sshift)>>1;
585
+ sxx=sxy=syy=0;
586
+ for(i=0;i<_np;i++){
587
+ dx=_p[i][0]-xbar+sround>>sshift;
588
+ dy=_p[i][1]-ybar+sround>>sshift;
589
+ sxx+=dx*dx;
590
+ sxy+=dx*dy;
591
+ syy+=dy*dy;
592
+ }
593
+ qr_line_fit(_l,xbar,ybar,sxx,sxy,syy,_res);
594
+ }
595
+
596
+ static void qr_line_orient(qr_line _l,int _x,int _y){
597
+ if(qr_line_eval(_l,_x,_y)<0){
598
+ _l[0]=-_l[0];
599
+ _l[1]=-_l[1];
600
+ _l[2]=-_l[2];
601
+ }
602
+ }
603
+
604
+ static int qr_line_isect(qr_point _p,const qr_line _l0,const qr_line _l1){
605
+ int d;
606
+ int x;
607
+ int y;
608
+ d=_l0[0]*_l1[1]-_l0[1]*_l1[0];
609
+ if(d==0)return -1;
610
+ x=_l0[1]*_l1[2]-_l1[1]*_l0[2];
611
+ y=_l1[0]*_l0[2]-_l0[0]*_l1[2];
612
+ if(d<0){
613
+ x=-x;
614
+ y=-y;
615
+ d=-d;
616
+ }
617
+ _p[0]=QR_DIVROUND(x,d);
618
+ _p[1]=QR_DIVROUND(y,d);
619
+ return 0;
620
+ }
621
+
622
+
623
+
624
+ /*An affine homography.
625
+ This maps from the image (at subpel resolution) to a square domain with
626
+ power-of-two sides (of res bits) and back.*/
627
+ struct qr_aff{
628
+ int fwd[2][2];
629
+ int inv[2][2];
630
+ int x0;
631
+ int y0;
632
+ int res;
633
+ };
634
+
635
+
636
+ static void qr_aff_init(qr_aff *_aff,
637
+ const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res){
638
+ int det;
639
+ int dx1;
640
+ int dy1;
641
+ int dx2;
642
+ int dy2;
643
+ /*det is ensured to be positive by our caller.*/
644
+ det=qr_point_ccw(_p0,_p1,_p2);
645
+ dx1=_p1[0]-_p0[0];
646
+ dx2=_p2[0]-_p0[0];
647
+ dy1=_p1[1]-_p0[1];
648
+ dy2=_p2[1]-_p0[1];
649
+ _aff->fwd[0][0]=dx1;
650
+ _aff->fwd[0][1]=dx2;
651
+ _aff->fwd[1][0]=dy1;
652
+ _aff->fwd[1][1]=dy2;
653
+ _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det);
654
+ _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det);
655
+ _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det);
656
+ _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det);
657
+ _aff->x0=_p0[0];
658
+ _aff->y0=_p0[1];
659
+ _aff->res=_res;
660
+ }
661
+
662
+ /*Map from the image (at subpel resolution) into the square domain.*/
663
+ static void qr_aff_unproject(qr_point _q,const qr_aff *_aff,
664
+ int _x,int _y){
665
+ _q[0]=_aff->inv[0][0]*(_x-_aff->x0)+_aff->inv[0][1]*(_y-_aff->y0);
666
+ _q[1]=_aff->inv[1][0]*(_x-_aff->x0)+_aff->inv[1][1]*(_y-_aff->y0);
667
+ }
668
+
669
+ /*Map from the square domain into the image (at subpel resolution).*/
670
+ static void qr_aff_project(qr_point _p,const qr_aff *_aff,
671
+ int _u,int _v){
672
+ _p[0]=(_aff->fwd[0][0]*_u+_aff->fwd[0][1]*_v+(1<<_aff->res-1)>>_aff->res)
673
+ +_aff->x0;
674
+ _p[1]=(_aff->fwd[1][0]*_u+_aff->fwd[1][1]*_v+(1<<_aff->res-1)>>_aff->res)
675
+ +_aff->y0;
676
+ }
677
+
678
+
679
+
680
+ /*A full homography.
681
+ Like the affine homography, this maps from the image (at subpel resolution)
682
+ to a square domain with power-of-two sides (of res bits) and back.*/
683
+ struct qr_hom{
684
+ int fwd[3][2];
685
+ int inv[3][2];
686
+ int fwd22;
687
+ int inv22;
688
+ int x0;
689
+ int y0;
690
+ int res;
691
+ };
692
+
693
+
694
+ static void qr_hom_init(qr_hom *_hom,int _x0,int _y0,
695
+ int _x1,int _y1,int _x2,int _y2,int _x3,int _y3,int _res){
696
+ int dx10;
697
+ int dx20;
698
+ int dx30;
699
+ int dx31;
700
+ int dx32;
701
+ int dy10;
702
+ int dy20;
703
+ int dy30;
704
+ int dy31;
705
+ int dy32;
706
+ int a20;
707
+ int a21;
708
+ int a22;
709
+ int b0;
710
+ int b1;
711
+ int b2;
712
+ int s1;
713
+ int s2;
714
+ int r1;
715
+ int r2;
716
+ dx10=_x1-_x0;
717
+ dx20=_x2-_x0;
718
+ dx30=_x3-_x0;
719
+ dx31=_x3-_x1;
720
+ dx32=_x3-_x2;
721
+ dy10=_y1-_y0;
722
+ dy20=_y2-_y0;
723
+ dy30=_y3-_y0;
724
+ dy31=_y3-_y1;
725
+ dy32=_y3-_y2;
726
+ a20=dx32*dy10-dx10*dy32;
727
+ a21=dx20*dy31-dx31*dy20;
728
+ a22=dx32*dy31-dx31*dy32;
729
+ /*Figure out if we need to downscale anything.*/
730
+ b0=qr_ilog(QR_MAXI(abs(dx10),abs(dy10)))+qr_ilog(abs(a20+a22));
731
+ b1=qr_ilog(QR_MAXI(abs(dx20),abs(dy20)))+qr_ilog(abs(a21+a22));
732
+ b2=qr_ilog(QR_MAXI(QR_MAXI(abs(a20),abs(a21)),abs(a22)));
733
+ s1=QR_MAXI(0,_res+QR_MAXI(QR_MAXI(b0,b1),b2)-(QR_INT_BITS-2));
734
+ r1=(1<<s1)>>1;
735
+ /*Compute the final coefficients of the forward transform.
736
+ The 32x32->64 bit multiplies are really needed for accuracy with large
737
+ versions.*/
738
+ _hom->fwd[0][0]=QR_FIXMUL(dx10,a20+a22,r1,s1);
739
+ _hom->fwd[0][1]=QR_FIXMUL(dx20,a21+a22,r1,s1);
740
+ _hom->x0=_x0;
741
+ _hom->fwd[1][0]=QR_FIXMUL(dy10,a20+a22,r1,s1);
742
+ _hom->fwd[1][1]=QR_FIXMUL(dy20,a21+a22,r1,s1);
743
+ _hom->y0=_y0;
744
+ _hom->fwd[2][0]=a20+r1>>s1;
745
+ _hom->fwd[2][1]=a21+r1>>s1;
746
+ _hom->fwd22=s1>_res?a22+(r1>>_res)>>s1-_res:a22<<_res-s1;
747
+ /*Now compute the inverse transform.*/
748
+ b0=qr_ilog(QR_MAXI(QR_MAXI(abs(dx10),abs(dx20)),abs(dx30)))+
749
+ qr_ilog(QR_MAXI(abs(_hom->fwd[0][0]),abs(_hom->fwd[1][0])));
750
+ b1=qr_ilog(QR_MAXI(QR_MAXI(abs(dy10),abs(dy20)),abs(dy30)))+
751
+ qr_ilog(QR_MAXI(abs(_hom->fwd[0][1]),abs(_hom->fwd[1][1])));
752
+ b2=qr_ilog(abs(a22))-s1;
753
+ s2=QR_MAXI(0,QR_MAXI(b0,b1)+b2-(QR_INT_BITS-3));
754
+ r2=(1<<s2)>>1;
755
+ s1+=s2;
756
+ r1<<=s2;
757
+ /*The 32x32->64 bit multiplies are really needed for accuracy with large
758
+ versions.*/
759
+ _hom->inv[0][0]=QR_FIXMUL(_hom->fwd[1][1],a22,r1,s1);
760
+ _hom->inv[0][1]=QR_FIXMUL(-_hom->fwd[0][1],a22,r1,s1);
761
+ _hom->inv[1][0]=QR_FIXMUL(-_hom->fwd[1][0],a22,r1,s1);
762
+ _hom->inv[1][1]=QR_FIXMUL(_hom->fwd[0][0],a22,r1,s1);
763
+ _hom->inv[2][0]=QR_FIXMUL(_hom->fwd[1][0],_hom->fwd[2][1],
764
+ -QR_EXTMUL(_hom->fwd[1][1],_hom->fwd[2][0],r2),s2);
765
+ _hom->inv[2][1]=QR_FIXMUL(_hom->fwd[0][1],_hom->fwd[2][0],
766
+ -QR_EXTMUL(_hom->fwd[0][0],_hom->fwd[2][1],r2),s2);
767
+ _hom->inv22=QR_FIXMUL(_hom->fwd[0][0],_hom->fwd[1][1],
768
+ -QR_EXTMUL(_hom->fwd[0][1],_hom->fwd[1][0],r2),s2);
769
+ _hom->res=_res;
770
+ }
771
+
772
+
773
+ /*Map from the image (at subpel resolution) into the square domain.
774
+ Returns a negative value if the point went to infinity.*/
775
+ static int qr_hom_unproject(qr_point _q,const qr_hom *_hom,int _x,int _y){
776
+ int x;
777
+ int y;
778
+ int w;
779
+ _x-=_hom->x0;
780
+ _y-=_hom->y0;
781
+ x=_hom->inv[0][0]*_x+_hom->inv[0][1]*_y;
782
+ y=_hom->inv[1][0]*_x+_hom->inv[1][1]*_y;
783
+ w=_hom->inv[2][0]*_x+_hom->inv[2][1]*_y
784
+ +_hom->inv22+(1<<_hom->res-1)>>_hom->res;
785
+ if(w==0){
786
+ _q[0]=x<0?INT_MIN:INT_MAX;
787
+ _q[1]=y<0?INT_MIN:INT_MAX;
788
+ return -1;
789
+ }
790
+ else{
791
+ if(w<0){
792
+ x=-x;
793
+ y=-y;
794
+ w=-w;
795
+ }
796
+ _q[0]=QR_DIVROUND(x,w);
797
+ _q[1]=QR_DIVROUND(y,w);
798
+ }
799
+ return 0;
800
+ }
801
+
802
+ /*Finish a partial projection, converting from homogeneous coordinates to the
803
+ normal 2-D representation.
804
+ In loops, we can avoid many multiplies by computing the homogeneous _x, _y,
805
+ and _w incrementally, but we cannot avoid the divisions, done here.*/
806
+ static void qr_hom_fproject(qr_point _p,const qr_hom *_hom,
807
+ int _x,int _y,int _w){
808
+ if(_w==0){
809
+ _p[0]=_x<0?INT_MIN:INT_MAX;
810
+ _p[1]=_y<0?INT_MIN:INT_MAX;
811
+ }
812
+ else{
813
+ if(_w<0){
814
+ _x=-_x;
815
+ _y=-_y;
816
+ _w=-_w;
817
+ }
818
+ _p[0]=QR_DIVROUND(_x,_w)+_hom->x0;
819
+ _p[1]=QR_DIVROUND(_y,_w)+_hom->y0;
820
+ }
821
+ }
822
+
823
+ #if defined(QR_DEBUG)
824
+ /*Map from the square domain into the image (at subpel resolution).
825
+ Currently only used directly by debug code.*/
826
+ static void qr_hom_project(qr_point _p,const qr_hom *_hom,
827
+ int _u,int _v){
828
+ qr_hom_fproject(_p,_hom,
829
+ _hom->fwd[0][0]*_u+_hom->fwd[0][1]*_v,
830
+ _hom->fwd[1][0]*_u+_hom->fwd[1][1]*_v,
831
+ _hom->fwd[2][0]*_u+_hom->fwd[2][1]*_v+_hom->fwd22);
832
+ }
833
+ #endif
834
+
835
+
836
+
837
+ /*All the information we've collected about a finder pattern in the current
838
+ configuration.*/
839
+ struct qr_finder{
840
+ /*The module size along each axis (in the square domain).*/
841
+ int size[2];
842
+ /*The version estimated from the module size along each axis.*/
843
+ int eversion[2];
844
+ /*The list of classified edge points for each edge.*/
845
+ qr_finder_edge_pt *edge_pts[4];
846
+ /*The number of edge points classified as belonging to each edge.*/
847
+ int nedge_pts[4];
848
+ /*The number of inliers found after running RANSAC on each edge.*/
849
+ int ninliers[4];
850
+ /*The center of the finder pattern (in the square domain).*/
851
+ qr_point o;
852
+ /*The finder center information from the original image.*/
853
+ qr_finder_center *c;
854
+ };
855
+
856
+
857
+ static int qr_cmp_edge_pt(const void *_a,const void *_b){
858
+ const qr_finder_edge_pt *a;
859
+ const qr_finder_edge_pt *b;
860
+ a=(const qr_finder_edge_pt *)_a;
861
+ b=(const qr_finder_edge_pt *)_b;
862
+ return ((a->edge>b->edge)-(a->edge<b->edge)<<1)+
863
+ (a->extent>b->extent)-(a->extent<b->extent);
864
+ }
865
+
866
+ /*Computes the index of the edge each edge point belongs to, and its (signed)
867
+ distance along the corresponding axis from the center of the finder pattern
868
+ (in the square domain).
869
+ The resulting list of edge points is sorted by edge index, with ties broken
870
+ by extent.*/
871
+ static void qr_finder_edge_pts_aff_classify(qr_finder *_f,const qr_aff *_aff){
872
+ qr_finder_center *c;
873
+ int i;
874
+ int e;
875
+ c=_f->c;
876
+ for(e=0;e<4;e++)_f->nedge_pts[e]=0;
877
+ for(i=0;i<c->nedge_pts;i++){
878
+ qr_point q;
879
+ int d;
880
+ qr_aff_unproject(q,_aff,c->edge_pts[i].pos[0],c->edge_pts[i].pos[1]);
881
+ qr_point_translate(q,-_f->o[0],-_f->o[1]);
882
+ d=abs(q[1])>abs(q[0]);
883
+ e=d<<1|(q[d]>=0);
884
+ _f->nedge_pts[e]++;
885
+ c->edge_pts[i].edge=e;
886
+ c->edge_pts[i].extent=q[d];
887
+ }
888
+ qsort(c->edge_pts,c->nedge_pts,sizeof(*c->edge_pts),qr_cmp_edge_pt);
889
+ _f->edge_pts[0]=c->edge_pts;
890
+ for(e=1;e<4;e++)_f->edge_pts[e]=_f->edge_pts[e-1]+_f->nedge_pts[e-1];
891
+ }
892
+
893
+ /*Computes the index of the edge each edge point belongs to, and its (signed)
894
+ distance along the corresponding axis from the center of the finder pattern
895
+ (in the square domain).
896
+ The resulting list of edge points is sorted by edge index, with ties broken
897
+ by extent.*/
898
+ static void qr_finder_edge_pts_hom_classify(qr_finder *_f,const qr_hom *_hom){
899
+ qr_finder_center *c;
900
+ int i;
901
+ int e;
902
+ c=_f->c;
903
+ for(e=0;e<4;e++)_f->nedge_pts[e]=0;
904
+ for(i=0;i<c->nedge_pts;i++){
905
+ qr_point q;
906
+ int d;
907
+ if(qr_hom_unproject(q,_hom,
908
+ c->edge_pts[i].pos[0],c->edge_pts[i].pos[1])>=0){
909
+ qr_point_translate(q,-_f->o[0],-_f->o[1]);
910
+ d=abs(q[1])>abs(q[0]);
911
+ e=d<<1|(q[d]>=0);
912
+ _f->nedge_pts[e]++;
913
+ c->edge_pts[i].edge=e;
914
+ c->edge_pts[i].extent=q[d];
915
+ }
916
+ else{
917
+ c->edge_pts[i].edge=4;
918
+ c->edge_pts[i].extent=q[0];
919
+ }
920
+ }
921
+ qsort(c->edge_pts,c->nedge_pts,sizeof(*c->edge_pts),qr_cmp_edge_pt);
922
+ _f->edge_pts[0]=c->edge_pts;
923
+ for(e=1;e<4;e++)_f->edge_pts[e]=_f->edge_pts[e-1]+_f->nedge_pts[e-1];
924
+ }
925
+
926
+ /*TODO: Perhaps these thresholds should be on the module size instead?
927
+ Unfortunately, I'd need real-world images of codes with larger versions to
928
+ see if these thresholds are still effective, but such versions aren't used
929
+ often.*/
930
+
931
+ /*The amount that the estimated version numbers are allowed to differ from the
932
+ real version number and still be considered valid.*/
933
+ #define QR_SMALL_VERSION_SLACK (1)
934
+ /*Since cell phone cameras can have severe radial distortion, the estimated
935
+ version for larger versions can be off by larger amounts.*/
936
+ #define QR_LARGE_VERSION_SLACK (3)
937
+
938
+ /*Estimates the size of a module after classifying the edge points.
939
+ _width: The distance between UL and UR in the square domain.
940
+ _height: The distance between UL and DL in the square domain.*/
941
+ static int qr_finder_estimate_module_size_and_version(qr_finder *_f,
942
+ int _width,int _height){
943
+ qr_point offs;
944
+ int sums[4];
945
+ int nsums[4];
946
+ int usize;
947
+ int nusize;
948
+ int vsize;
949
+ int nvsize;
950
+ int uversion;
951
+ int vversion;
952
+ int e;
953
+ offs[0]=offs[1]=0;
954
+ for(e=0;e<4;e++)if(_f->nedge_pts[e]>0){
955
+ qr_finder_edge_pt *edge_pts;
956
+ int sum;
957
+ int mean;
958
+ int n;
959
+ int i;
960
+ /*Average the samples for this edge, dropping the top and bottom 25%.*/
961
+ edge_pts=_f->edge_pts[e];
962
+ n=_f->nedge_pts[e];
963
+ sum=0;
964
+ for(i=(n>>2);i<n-(n>>2);i++)sum+=edge_pts[i].extent;
965
+ n=n-((n>>2)<<1);
966
+ mean=QR_DIVROUND(sum,n);
967
+ offs[e>>1]+=mean;
968
+ sums[e]=sum;
969
+ nsums[e]=n;
970
+ }
971
+ else nsums[e]=sums[e]=0;
972
+ /*If we have samples on both sides of an axis, refine our idea of where the
973
+ unprojected finder center is located.*/
974
+ if(_f->nedge_pts[0]>0&&_f->nedge_pts[1]>0){
975
+ _f->o[0]-=offs[0]>>1;
976
+ sums[0]-=offs[0]*nsums[0]>>1;
977
+ sums[1]-=offs[0]*nsums[1]>>1;
978
+ }
979
+ if(_f->nedge_pts[2]>0&&_f->nedge_pts[3]>0){
980
+ _f->o[1]-=offs[1]>>1;
981
+ sums[2]-=offs[1]*nsums[2]>>1;
982
+ sums[3]-=offs[1]*nsums[3]>>1;
983
+ }
984
+ /*We must have _some_ samples along each axis... if we don't, our transform
985
+ must be pretty severely distorting the original square (e.g., with
986
+ coordinates so large as to cause overflow).*/
987
+ nusize=nsums[0]+nsums[1];
988
+ if(nusize<=0)return -1;
989
+ /*The module size is 1/3 the average edge extent.*/
990
+ nusize*=3;
991
+ usize=sums[1]-sums[0];
992
+ usize=((usize<<1)+nusize)/(nusize<<1);
993
+ if(usize<=0)return -1;
994
+ /*Now estimate the version directly from the module size and the distance
995
+ between the finder patterns.
996
+ This is done independently using the extents along each axis.
997
+ If either falls significantly outside the valid range (1 to 40), reject the
998
+ configuration.*/
999
+ uversion=(_width-8*usize)/(usize<<2);
1000
+ if(uversion<1||uversion>40+QR_LARGE_VERSION_SLACK)return -1;
1001
+ /*Now do the same for the other axis.*/
1002
+ nvsize=nsums[2]+nsums[3];
1003
+ if(nvsize<=0)return -1;
1004
+ nvsize*=3;
1005
+ vsize=sums[3]-sums[2];
1006
+ vsize=((vsize<<1)+nvsize)/(nvsize<<1);
1007
+ if(vsize<=0)return -1;
1008
+ vversion=(_height-8*vsize)/(vsize<<2);
1009
+ if(vversion<1||vversion>40+QR_LARGE_VERSION_SLACK)return -1;
1010
+ /*If the estimated version using extents along one axis is significantly
1011
+ different than the estimated version along the other axis, then the axes
1012
+ have significantly different scalings (relative to the grid).
1013
+ This can happen, e.g., when we have multiple adjacent QR codes, and we've
1014
+ picked two finder patterns from one and the third finder pattern from
1015
+ another, e.g.:
1016
+ X---DL UL---X
1017
+ |.... |....
1018
+ X.... UR....
1019
+ Such a configuration might even pass any other geometric checks if we
1020
+ didn't reject it here.*/
1021
+ if(abs(uversion-vversion)>QR_LARGE_VERSION_SLACK)return -1;
1022
+ _f->size[0]=usize;
1023
+ _f->size[1]=vsize;
1024
+ /*We intentionally do not compute an average version from the sizes along
1025
+ both axes.
1026
+ In the presence of projective distortion, one of them will be much more
1027
+ accurate than the other.*/
1028
+ _f->eversion[0]=uversion;
1029
+ _f->eversion[1]=vversion;
1030
+ return 0;
1031
+ }
1032
+
1033
+ /*Eliminate outliers from the classified edge points with RANSAC.*/
1034
+ static void qr_finder_ransac(qr_finder *_f,const qr_aff *_hom,
1035
+ isaac_ctx *_isaac,int _e){
1036
+ qr_finder_edge_pt *edge_pts;
1037
+ int best_ninliers;
1038
+ int n;
1039
+ edge_pts=_f->edge_pts[_e];
1040
+ n=_f->nedge_pts[_e];
1041
+ best_ninliers=0;
1042
+ if(n>1){
1043
+ int max_iters;
1044
+ int i;
1045
+ int j;
1046
+ /*17 iterations is enough to guarantee an outlier-free sample with more
1047
+ than 99% probability given as many as 50% outliers.*/
1048
+ max_iters=17;
1049
+ for(i=0;i<max_iters;i++){
1050
+ qr_point q0;
1051
+ qr_point q1;
1052
+ int ninliers;
1053
+ int thresh;
1054
+ int p0i;
1055
+ int p1i;
1056
+ int *p0;
1057
+ int *p1;
1058
+ int j;
1059
+ /*Pick two random points on this edge.*/
1060
+ p0i=isaac_next_uint(_isaac,n);
1061
+ p1i=isaac_next_uint(_isaac,n-1);
1062
+ if(p1i>=p0i)p1i++;
1063
+ p0=edge_pts[p0i].pos;
1064
+ p1=edge_pts[p1i].pos;
1065
+ /*If the corresponding line is not within 45 degrees of the proper
1066
+ orientation in the square domain, reject it outright.
1067
+ This can happen, e.g., when highly skewed orientations cause points to
1068
+ be misclassified into the wrong edge.
1069
+ The irony is that using such points might produce a line which _does_
1070
+ pass the corresponding validity checks.*/
1071
+ qr_aff_unproject(q0,_hom,p0[0],p0[1]);
1072
+ qr_aff_unproject(q1,_hom,p1[0],p1[1]);
1073
+ qr_point_translate(q0,-_f->o[0],-_f->o[1]);
1074
+ qr_point_translate(q1,-_f->o[0],-_f->o[1]);
1075
+ if(abs(q0[_e>>1]-q1[_e>>1])>abs(q0[1-(_e>>1)]-q1[1-(_e>>1)]))continue;
1076
+ /*Identify the other edge points which are inliers.
1077
+ The squared distance should be distributed as a \Chi^2 distribution
1078
+ with one degree of freedom, which means for a 95% confidence the
1079
+ point should lie within a factor 3.8414588 ~= 4 times the expected
1080
+ variance of the point locations.
1081
+ We grossly approximate the standard deviation as 1 pixel in one
1082
+ direction, and 0.5 pixels in the other (because we average two
1083
+ coordinates).*/
1084
+ thresh=qr_isqrt(qr_point_distance2(p0,p1)<<2*QR_FINDER_SUBPREC+1);
1085
+ ninliers=0;
1086
+ for(j=0;j<n;j++){
1087
+ if(abs(qr_point_ccw(p0,p1,edge_pts[j].pos))<=thresh){
1088
+ edge_pts[j].extent|=1;
1089
+ ninliers++;
1090
+ }
1091
+ else edge_pts[j].extent&=~1;
1092
+ }
1093
+ if(ninliers>best_ninliers){
1094
+ for(j=0;j<n;j++)edge_pts[j].extent<<=1;
1095
+ best_ninliers=ninliers;
1096
+ /*The actual number of iterations required is
1097
+ log(1-\alpha)/log(1-r*r),
1098
+ where \alpha is the required probability of taking a sample with
1099
+ no outliers (e.g., 0.99) and r is the estimated ratio of inliers
1100
+ (e.g. ninliers/n).
1101
+ This is just a rough (but conservative) approximation, but it
1102
+ should be good enough to stop the iteration early when we find
1103
+ a good set of inliers.*/
1104
+ if(ninliers>n>>1)max_iters=(67*n-63*ninliers-1)/(n<<1);
1105
+ }
1106
+ }
1107
+ /*Now collect all the inliers at the beginning of the list.*/
1108
+ for(i=j=0;j<best_ninliers;i++)if(edge_pts[i].extent&2){
1109
+ if(j<i){
1110
+ qr_finder_edge_pt tmp;
1111
+ *&tmp=*(edge_pts+i);
1112
+ *(edge_pts+j)=*(edge_pts+i);
1113
+ *(edge_pts+i)=*&tmp;
1114
+ }
1115
+ j++;
1116
+ }
1117
+ }
1118
+ _f->ninliers[_e]=best_ninliers;
1119
+ }
1120
+
1121
+ /*Perform a least-squares line fit to an edge of a finder pattern using the
1122
+ inliers found by RANSAC.*/
1123
+ static int qr_line_fit_finder_edge(qr_line _l,
1124
+ const qr_finder *_f,int _e,int _res){
1125
+ qr_finder_edge_pt *edge_pts;
1126
+ qr_point *pts;
1127
+ int npts;
1128
+ int i;
1129
+ npts=_f->ninliers[_e];
1130
+ if(npts<2)return -1;
1131
+ /*We could write a custom version of qr_line_fit_points that accesses
1132
+ edge_pts directly, but this saves on code size and doesn't measurably slow
1133
+ things down.*/
1134
+ pts=(qr_point *)malloc(npts*sizeof(*pts));
1135
+ edge_pts=_f->edge_pts[_e];
1136
+ for(i=0;i<npts;i++){
1137
+ pts[i][0]=edge_pts[i].pos[0];
1138
+ pts[i][1]=edge_pts[i].pos[1];
1139
+ }
1140
+ qr_line_fit_points(_l,pts,npts,_res);
1141
+ /*Make sure the center of the finder pattern lies in the positive halfspace
1142
+ of the line.*/
1143
+ qr_line_orient(_l,_f->c->pos[0],_f->c->pos[1]);
1144
+ free(pts);
1145
+ return 0;
1146
+ }
1147
+
1148
+ /*Perform a least-squares line fit to a pair of common finder edges using the
1149
+ inliers found by RANSAC.
1150
+ Unlike a normal edge fit, we guarantee that this one succeeds by creating at
1151
+ least one point on each edge using the estimated module size if it has no
1152
+ inliers.*/
1153
+ static void qr_line_fit_finder_pair(qr_line _l,const qr_aff *_aff,
1154
+ const qr_finder *_f0,const qr_finder *_f1,int _e){
1155
+ qr_point *pts;
1156
+ int npts;
1157
+ qr_finder_edge_pt *edge_pts;
1158
+ qr_point q;
1159
+ int n0;
1160
+ int n1;
1161
+ int i;
1162
+ n0=_f0->ninliers[_e];
1163
+ n1=_f1->ninliers[_e];
1164
+ /*We could write a custom version of qr_line_fit_points that accesses
1165
+ edge_pts directly, but this saves on code size and doesn't measurably slow
1166
+ things down.*/
1167
+ npts=QR_MAXI(n0,1)+QR_MAXI(n1,1);
1168
+ pts=(qr_point *)malloc(npts*sizeof(*pts));
1169
+ if(n0>0){
1170
+ edge_pts=_f0->edge_pts[_e];
1171
+ for(i=0;i<n0;i++){
1172
+ pts[i][0]=edge_pts[i].pos[0];
1173
+ pts[i][1]=edge_pts[i].pos[1];
1174
+ }
1175
+ }
1176
+ else{
1177
+ q[0]=_f0->o[0];
1178
+ q[1]=_f0->o[1];
1179
+ q[_e>>1]+=_f0->size[_e>>1]*(2*(_e&1)-1);
1180
+ qr_aff_project(pts[0],_aff,q[0],q[1]);
1181
+ n0++;
1182
+ }
1183
+ if(n1>0){
1184
+ edge_pts=_f1->edge_pts[_e];
1185
+ for(i=0;i<n1;i++){
1186
+ pts[n0+i][0]=edge_pts[i].pos[0];
1187
+ pts[n0+i][1]=edge_pts[i].pos[1];
1188
+ }
1189
+ }
1190
+ else{
1191
+ q[0]=_f1->o[0];
1192
+ q[1]=_f1->o[1];
1193
+ q[_e>>1]+=_f1->size[_e>>1]*(2*(_e&1)-1);
1194
+ qr_aff_project(pts[n0],_aff,q[0],q[1]);
1195
+ n1++;
1196
+ }
1197
+ qr_line_fit_points(_l,pts,npts,_aff->res);
1198
+ /*Make sure at least one finder center lies in the positive halfspace.*/
1199
+ qr_line_orient(_l,_f0->c->pos[0],_f0->c->pos[1]);
1200
+ free(pts);
1201
+ }
1202
+
1203
+ static int qr_finder_quick_crossing_check(const unsigned char *_img,
1204
+ int _width,int _height,int _x0,int _y0,int _x1,int _y1,int _v){
1205
+ /*The points must be inside the image, and have a !_v:_v:!_v pattern.
1206
+ We don't scan the whole line initially, but quickly reject if the endpoints
1207
+ aren't !_v, or the midpoint isn't _v.
1208
+ If either end point is out of the image, or we don't encounter a _v pixel,
1209
+ we return a negative value, indicating the region should be considered
1210
+ empty.
1211
+ Otherwise, we return a positive value to indicate it is non-empty.*/
1212
+ if(_x0<0||_x0>=_width||_y0<0||_y0>=_height||
1213
+ _x1<0||_x1>=_width||_y1<0||_y1>=_height){
1214
+ return -1;
1215
+ }
1216
+ if(!_img[_y0*_width+_x0]!=_v||!_img[_y1*_width+_x1]!=_v)return 1;
1217
+ if(!_img[(_y0+_y1>>1)*_width+(_x0+_x1>>1)]==_v)return -1;
1218
+ return 0;
1219
+ }
1220
+
1221
+ /*Locate the midpoint of a _v segment along a !_v:_v:!_v line from (_x0,_y0) to
1222
+ (_x1,_y1).
1223
+ All coordinates, which are NOT in subpel resolution, must lie inside the
1224
+ image, and the endpoints are already assumed to have the value !_v.
1225
+ The returned value is in subpel resolution.*/
1226
+ static int qr_finder_locate_crossing(const unsigned char *_img,
1227
+ int _width,int _height,int _x0,int _y0,int _x1,int _y1,int _v,qr_point _p){
1228
+ qr_point x0;
1229
+ qr_point x1;
1230
+ qr_point dx;
1231
+ int step[2];
1232
+ int steep;
1233
+ int err;
1234
+ int derr;
1235
+ /*Use Bresenham's algorithm to trace along the line and find the exact
1236
+ transitions from !_v to _v and back.*/
1237
+ x0[0]=_x0;
1238
+ x0[1]=_y0;
1239
+ x1[0]=_x1;
1240
+ x1[1]=_y1;
1241
+ dx[0]=abs(_x1-_x0);
1242
+ dx[1]=abs(_y1-_y0);
1243
+ steep=dx[1]>dx[0];
1244
+ err=0;
1245
+ derr=dx[1-steep];
1246
+ step[0]=((_x0<_x1)<<1)-1;
1247
+ step[1]=((_y0<_y1)<<1)-1;
1248
+ /*Find the first crossing from !_v to _v.*/
1249
+ for(;;){
1250
+ /*If we make it all the way to the other side, there's no crossing.*/
1251
+ if(x0[steep]==x1[steep])return -1;
1252
+ x0[steep]+=step[steep];
1253
+ err+=derr;
1254
+ if(err<<1>dx[steep]){
1255
+ x0[1-steep]+=step[1-steep];
1256
+ err-=dx[steep];
1257
+ }
1258
+ if(!_img[x0[1]*_width+x0[0]]!=_v)break;
1259
+ }
1260
+ /*Find the last crossing from _v to !_v.*/
1261
+ err=0;
1262
+ for(;;){
1263
+ if(x0[steep]==x1[steep])break;
1264
+ x1[steep]-=step[steep];
1265
+ err+=derr;
1266
+ if(err<<1>dx[steep]){
1267
+ x1[1-steep]-=step[1-steep];
1268
+ err-=dx[steep];
1269
+ }
1270
+ if(!_img[x1[1]*_width+x1[0]]!=_v)break;
1271
+ }
1272
+ /*Return the midpoint of the _v segment.*/
1273
+ _p[0]=(x0[0]+x1[0]+1<<QR_FINDER_SUBPREC)>>1;
1274
+ _p[1]=(x0[1]+x1[1]+1<<QR_FINDER_SUBPREC)>>1;
1275
+ return 0;
1276
+ }
1277
+
1278
+ static int qr_aff_line_step(const qr_aff *_aff,qr_line _l,
1279
+ int _v,int _du,int *_dv){
1280
+ int shift;
1281
+ int round;
1282
+ int dv;
1283
+ int n;
1284
+ int d;
1285
+ n=_aff->fwd[0][_v]*_l[0]+_aff->fwd[1][_v]*_l[1];
1286
+ d=_aff->fwd[0][1-_v]*_l[0]+_aff->fwd[1][1-_v]*_l[1];
1287
+ if(d<0){
1288
+ n=-n;
1289
+ d=-d;
1290
+ }
1291
+ shift=QR_MAXI(0,qr_ilog(_du)+qr_ilog(abs(n))+3-QR_INT_BITS);
1292
+ round=(1<<shift)>>1;
1293
+ n=n+round>>shift;
1294
+ d=d+round>>shift;
1295
+ /*The line should not be outside 45 degrees of horizontal/vertical.
1296
+ TODO: We impose this restriction to help ensure the loop below terminates,
1297
+ but it should not technically be required.
1298
+ It also, however, ensures we avoid division by zero.*/
1299
+ if(abs(n)>=d)return -1;
1300
+ n=-_du*n;
1301
+ dv=QR_DIVROUND(n,d);
1302
+ if(abs(dv)>=_du)return -1;
1303
+ *_dv=dv;
1304
+ return 0;
1305
+ }
1306
+
1307
+ /*Computes the Hamming distance between two bit patterns (the number of bits
1308
+ that differ).
1309
+ May stop counting after _maxdiff differences.*/
1310
+ static int qr_hamming_dist(unsigned _y1,unsigned _y2,int _maxdiff){
1311
+ unsigned y;
1312
+ int ret;
1313
+ y=_y1^_y2;
1314
+ for(ret=0;ret<_maxdiff&&y;ret++)y&=y-1;
1315
+ return ret;
1316
+ }
1317
+
1318
+ /*Retrieve a bit (guaranteed to be 0 or 1) from the image, given coordinates in
1319
+ subpel resolution which have not been bounds checked.*/
1320
+ static int qr_img_get_bit(const unsigned char *_img,int _width,int _height,
1321
+ int _x,int _y){
1322
+ _x>>=QR_FINDER_SUBPREC;
1323
+ _y>>=QR_FINDER_SUBPREC;
1324
+ return _img[QR_CLAMPI(0,_y,_height-1)*_width+QR_CLAMPI(0,_x,_width-1)]!=0;
1325
+ }
1326
+
1327
+ #if defined(QR_DEBUG)
1328
+ #include "image.h"
1329
+
1330
+ static void qr_finder_dump_aff_undistorted(qr_finder *_ul,qr_finder *_ur,
1331
+ qr_finder *_dl,qr_aff *_aff,const unsigned char *_img,int _width,int _height){
1332
+ unsigned char *gimg;
1333
+ FILE *fout;
1334
+ int lpsz;
1335
+ int pixel_size;
1336
+ int dim;
1337
+ int min;
1338
+ int max;
1339
+ int u;
1340
+ int y;
1341
+ int i;
1342
+ int j;
1343
+ lpsz=qr_ilog(_ur->size[0]+_ur->size[1]+_dl->size[0]+_dl->size[1])-6;
1344
+ pixel_size=1<<lpsz;
1345
+ dim=(1<<_aff->res-lpsz)+128;
1346
+ gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
1347
+ for(i=0;i<dim;i++)for(j=0;j<dim;j++){
1348
+ qr_point p;
1349
+ qr_aff_project(p,_aff,(j-64)<<lpsz,(i-64)<<lpsz);
1350
+ gimg[i*dim+j]=_img[
1351
+ QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
1352
+ QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
1353
+ }
1354
+ {
1355
+ min=(_ur->o[0]-7*_ur->size[0]>>lpsz)+64;
1356
+ if(min<0)min=0;
1357
+ max=(_ur->o[0]+7*_ur->size[0]>>lpsz)+64;
1358
+ if(max>dim)max=dim;
1359
+ for(y=-7;y<=7;y++){
1360
+ i=(_ur->o[1]+y*_ur->size[1]>>lpsz)+64;
1361
+ if(i<0||i>=dim)continue;
1362
+ for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
1363
+ }
1364
+ min=(_ur->o[1]-7*_ur->size[1]>>lpsz)+64;
1365
+ if(min<0)min=0;
1366
+ max=(_ur->o[1]+7*_ur->size[1]>>lpsz)+64;
1367
+ if(max>dim)max=dim;
1368
+ for(u=-7;u<=7;u++){
1369
+ j=(_ur->o[0]+u*_ur->size[0]>>lpsz)+64;
1370
+ if(j<0||j>=dim)continue;
1371
+ for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
1372
+ }
1373
+ }
1374
+ {
1375
+ min=(_dl->o[0]-7*_dl->size[0]>>lpsz)+64;
1376
+ if(min<0)min=0;
1377
+ max=(_dl->o[0]+7*_dl->size[0]>>lpsz)+64;
1378
+ if(max>dim)max=dim;
1379
+ for(y=-7;y<=7;y++){
1380
+ i=(_dl->o[1]+y*_dl->size[1]>>lpsz)+64;
1381
+ if(i<0||i>=dim)continue;
1382
+ for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
1383
+ }
1384
+ min=(_dl->o[1]-7*_dl->size[1]>>lpsz)+64;
1385
+ if(min<0)min=0;
1386
+ max=(_dl->o[1]+7*_dl->size[1]>>lpsz)+64;
1387
+ if(max>dim)max=dim;
1388
+ for(u=-7;u<=7;u++){
1389
+ j=(_dl->o[0]+u*_dl->size[0]>>lpsz)+64;
1390
+ if(j<0||j>=dim)continue;
1391
+ for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
1392
+ }
1393
+ }
1394
+ fout=fopen("undistorted_aff.png","wb");
1395
+ image_write_png(gimg,dim,dim,fout);
1396
+ fclose(fout);
1397
+ free(gimg);
1398
+ }
1399
+
1400
+ static void qr_finder_dump_hom_undistorted(qr_finder *_ul,qr_finder *_ur,
1401
+ qr_finder *_dl,qr_hom *_hom,const unsigned char *_img,int _width,int _height){
1402
+ unsigned char *gimg;
1403
+ FILE *fout;
1404
+ int lpsz;
1405
+ int pixel_size;
1406
+ int dim;
1407
+ int min;
1408
+ int max;
1409
+ int u;
1410
+ int v;
1411
+ int i;
1412
+ int j;
1413
+ lpsz=qr_ilog(_ur->size[0]+_ur->size[1]+_dl->size[0]+_dl->size[1])-6;
1414
+ pixel_size=1<<lpsz;
1415
+ dim=(1<<_hom->res-lpsz)+256;
1416
+ gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
1417
+ for(i=0;i<dim;i++)for(j=0;j<dim;j++){
1418
+ qr_point p;
1419
+ qr_hom_project(p,_hom,(j-128)<<lpsz,(i-128)<<lpsz);
1420
+ gimg[i*dim+j]=_img[
1421
+ QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
1422
+ QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
1423
+ }
1424
+ {
1425
+ min=(_ur->o[0]-7*_ur->size[0]>>lpsz)+128;
1426
+ if(min<0)min=0;
1427
+ max=(_ur->o[0]+7*_ur->size[0]>>lpsz)+128;
1428
+ if(max>dim)max=dim;
1429
+ for(v=-7;v<=7;v++){
1430
+ i=(_ur->o[1]+v*_ur->size[1]>>lpsz)+128;
1431
+ if(i<0||i>=dim)continue;
1432
+ for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
1433
+ }
1434
+ min=(_ur->o[1]-7*_ur->size[1]>>lpsz)+128;
1435
+ if(min<0)min=0;
1436
+ max=(_ur->o[1]+7*_ur->size[1]>>lpsz)+128;
1437
+ if(max>dim)max=dim;
1438
+ for(u=-7;u<=7;u++){
1439
+ j=(_ur->o[0]+u*_ur->size[0]>>lpsz)+128;
1440
+ if(j<0||j>=dim)continue;
1441
+ for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
1442
+ }
1443
+ }
1444
+ {
1445
+ min=(_dl->o[0]-7*_dl->size[0]>>lpsz)+128;
1446
+ if(min<0)min=0;
1447
+ max=(_dl->o[0]+7*_dl->size[0]>>lpsz)+128;
1448
+ if(max>dim)max=dim;
1449
+ for(v=-7;v<=7;v++){
1450
+ i=(_dl->o[1]+v*_dl->size[1]>>lpsz)+128;
1451
+ if(i<0||i>=dim)continue;
1452
+ for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
1453
+ }
1454
+ min=(_dl->o[1]-7*_dl->size[1]>>lpsz)+128;
1455
+ if(min<0)min=0;
1456
+ max=(_dl->o[1]+7*_dl->size[1]>>lpsz)+128;
1457
+ if(max>dim)max=dim;
1458
+ for(u=-7;u<=7;u++){
1459
+ j=(_dl->o[0]+u*_dl->size[0]>>lpsz)+128;
1460
+ if(j<0||j>=dim)continue;
1461
+ for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
1462
+ }
1463
+ }
1464
+ fout=fopen("undistorted_hom.png","wb");
1465
+ image_write_png(gimg,dim,dim,fout);
1466
+ fclose(fout);
1467
+ free(gimg);
1468
+ }
1469
+ #endif
1470
+
1471
+
1472
+
1473
+ /*A homography from one region of the grid back to the image.
1474
+ Unlike a qr_hom, this does not include an inverse transform and maps directly
1475
+ from the grid points, not a square with power-of-two sides.*/
1476
+ struct qr_hom_cell{
1477
+ int fwd[3][3];
1478
+ int x0;
1479
+ int y0;
1480
+ int u0;
1481
+ int v0;
1482
+ };
1483
+
1484
+
1485
+ static void qr_hom_cell_init(qr_hom_cell *_cell,int _u0,int _v0,
1486
+ int _u1,int _v1,int _u2,int _v2,int _u3,int _v3,int _x0,int _y0,
1487
+ int _x1,int _y1,int _x2,int _y2,int _x3,int _y3){
1488
+ int du10;
1489
+ int du20;
1490
+ int du30;
1491
+ int du31;
1492
+ int du32;
1493
+ int dv10;
1494
+ int dv20;
1495
+ int dv30;
1496
+ int dv31;
1497
+ int dv32;
1498
+ int dx10;
1499
+ int dx20;
1500
+ int dx30;
1501
+ int dx31;
1502
+ int dx32;
1503
+ int dy10;
1504
+ int dy20;
1505
+ int dy30;
1506
+ int dy31;
1507
+ int dy32;
1508
+ int a00;
1509
+ int a01;
1510
+ int a02;
1511
+ int a10;
1512
+ int a11;
1513
+ int a12;
1514
+ int a20;
1515
+ int a21;
1516
+ int a22;
1517
+ int i00;
1518
+ int i01;
1519
+ int i10;
1520
+ int i11;
1521
+ int i20;
1522
+ int i21;
1523
+ int i22;
1524
+ int b0;
1525
+ int b1;
1526
+ int b2;
1527
+ int shift;
1528
+ int round;
1529
+ int x;
1530
+ int y;
1531
+ int w;
1532
+ /*First, correct for the arrangement of the source points.
1533
+ We take advantage of the fact that we know the source points have a very
1534
+ limited dynamic range (so there will never be overflow) and a small amount
1535
+ of projective distortion.*/
1536
+ du10=_u1-_u0;
1537
+ du20=_u2-_u0;
1538
+ du30=_u3-_u0;
1539
+ du31=_u3-_u1;
1540
+ du32=_u3-_u2;
1541
+ dv10=_v1-_v0;
1542
+ dv20=_v2-_v0;
1543
+ dv30=_v3-_v0;
1544
+ dv31=_v3-_v1;
1545
+ dv32=_v3-_v2;
1546
+ /*Compute the coefficients of the forward transform from the unit square to
1547
+ the source point configuration.*/
1548
+ a20=du32*dv10-du10*dv32;
1549
+ a21=du20*dv31-du31*dv20;
1550
+ if(a20||a21)a22=du32*dv31-du31*dv32;
1551
+ /*If the source grid points aren't in a non-affine arrangement, there's no
1552
+ reason to scale everything by du32*dv31-du31*dv32.
1553
+ Not doing so allows a much larger dynamic range, and is the only way we can
1554
+ initialize a base cell that covers the whole grid.*/
1555
+ else a22=1;
1556
+ a00=du10*(a20+a22);
1557
+ a01=du20*(a21+a22);
1558
+ a10=dv10*(a20+a22);
1559
+ a11=dv20*(a21+a22);
1560
+ /*Now compute the inverse transform.*/
1561
+ i00=a11*a22;
1562
+ i01=-a01*a22;
1563
+ i10=-a10*a22;
1564
+ i11=a00*a22;
1565
+ i20=a10*a21-a11*a20;
1566
+ i21=a01*a20-a00*a21;
1567
+ i22=a00*a11-a01*a10;
1568
+ /*Invert the coefficients.
1569
+ Since i22 is the largest, we divide it by all the others.
1570
+ The quotient is often exact (e.g., when the source points contain no
1571
+ projective distortion), and is never zero.
1572
+ Hence we can use zero to signal "infinity" when the divisor is zero.*/
1573
+ if(i00)i00=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i00)),i00);
1574
+ if(i01)i01=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i01)),i01);
1575
+ if(i10)i10=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i10)),i10);
1576
+ if(i11)i11=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i11)),i11);
1577
+ if(i20)i20=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i20)),i20);
1578
+ if(i21)i21=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i21)),i21);
1579
+ /*Now compute the map from the unit square into the image.*/
1580
+ dx10=_x1-_x0;
1581
+ dx20=_x2-_x0;
1582
+ dx30=_x3-_x0;
1583
+ dx31=_x3-_x1;
1584
+ dx32=_x3-_x2;
1585
+ dy10=_y1-_y0;
1586
+ dy20=_y2-_y0;
1587
+ dy30=_y3-_y0;
1588
+ dy31=_y3-_y1;
1589
+ dy32=_y3-_y2;
1590
+ a20=dx32*dy10-dx10*dy32;
1591
+ a21=dx20*dy31-dx31*dy20;
1592
+ a22=dx32*dy31-dx31*dy32;
1593
+ /*Figure out if we need to downscale anything.*/
1594
+ b0=qr_ilog(QR_MAXI(abs(dx10),abs(dy10)))+qr_ilog(abs(a20+a22));
1595
+ b1=qr_ilog(QR_MAXI(abs(dx20),abs(dy20)))+qr_ilog(abs(a21+a22));
1596
+ b2=qr_ilog(QR_MAXI(QR_MAXI(abs(a20),abs(a21)),abs(a22)));
1597
+ shift=QR_MAXI(0,QR_MAXI(QR_MAXI(b0,b1),b2)-(QR_INT_BITS-3-QR_ALIGN_SUBPREC));
1598
+ round=(1<<shift)>>1;
1599
+ /*Compute the final coefficients of the forward transform.*/
1600
+ a00=QR_FIXMUL(dx10,a20+a22,round,shift);
1601
+ a01=QR_FIXMUL(dx20,a21+a22,round,shift);
1602
+ a10=QR_FIXMUL(dy10,a20+a22,round,shift);
1603
+ a11=QR_FIXMUL(dy20,a21+a22,round,shift);
1604
+ /*And compose the two transforms.
1605
+ Since we inverted the coefficients above, we divide by them here instead
1606
+ of multiplying.
1607
+ This lets us take advantage of the full dynamic range.
1608
+ Note a zero divisor is really "infinity", and thus the quotient should also
1609
+ be zero.*/
1610
+ _cell->fwd[0][0]=(i00?QR_DIVROUND(a00,i00):0)+(i10?QR_DIVROUND(a01,i10):0);
1611
+ _cell->fwd[0][1]=(i01?QR_DIVROUND(a00,i01):0)+(i11?QR_DIVROUND(a01,i11):0);
1612
+ _cell->fwd[1][0]=(i00?QR_DIVROUND(a10,i00):0)+(i10?QR_DIVROUND(a11,i10):0);
1613
+ _cell->fwd[1][1]=(i01?QR_DIVROUND(a10,i01):0)+(i11?QR_DIVROUND(a11,i11):0);
1614
+ _cell->fwd[2][0]=(i00?QR_DIVROUND(a20,i00):0)+(i10?QR_DIVROUND(a21,i10):0)
1615
+ +(i20?QR_DIVROUND(a22,i20):0)+round>>shift;
1616
+ _cell->fwd[2][1]=(i01?QR_DIVROUND(a20,i01):0)+(i11?QR_DIVROUND(a21,i11):0)
1617
+ +(i21?QR_DIVROUND(a22,i21):0)+round>>shift;
1618
+ _cell->fwd[2][2]=a22+round>>shift;
1619
+ /*Mathematically, a02 and a12 are exactly zero.
1620
+ However, that concentrates all of the rounding error in the (_u3,_v3)
1621
+ corner; we compute offsets which distribute it over the whole range.*/
1622
+ x=_cell->fwd[0][0]*du10+_cell->fwd[0][1]*dv10;
1623
+ y=_cell->fwd[1][0]*du10+_cell->fwd[1][1]*dv10;
1624
+ w=_cell->fwd[2][0]*du10+_cell->fwd[2][1]*dv10+_cell->fwd[2][2];
1625
+ a02=dx10*w-x;
1626
+ a12=dy10*w-y;
1627
+ x=_cell->fwd[0][0]*du20+_cell->fwd[0][1]*dv20;
1628
+ y=_cell->fwd[1][0]*du20+_cell->fwd[1][1]*dv20;
1629
+ w=_cell->fwd[2][0]*du20+_cell->fwd[2][1]*dv20+_cell->fwd[2][2];
1630
+ a02+=dx20*w-x;
1631
+ a12+=dy20*w-y;
1632
+ x=_cell->fwd[0][0]*du30+_cell->fwd[0][1]*dv30;
1633
+ y=_cell->fwd[1][0]*du30+_cell->fwd[1][1]*dv30;
1634
+ w=_cell->fwd[2][0]*du30+_cell->fwd[2][1]*dv30+_cell->fwd[2][2];
1635
+ a02+=dx30*w-x;
1636
+ a12+=dy30*w-y;
1637
+ _cell->fwd[0][2]=a02+2>>2;
1638
+ _cell->fwd[1][2]=a12+2>>2;
1639
+ _cell->x0=_x0;
1640
+ _cell->y0=_y0;
1641
+ _cell->u0=_u0;
1642
+ _cell->v0=_v0;
1643
+ }
1644
+
1645
+ /*Finish a partial projection, converting from homogeneous coordinates to the
1646
+ normal 2-D representation.
1647
+ In loops, we can avoid many multiplies by computing the homogeneous _x, _y,
1648
+ and _w incrementally, but we cannot avoid the divisions, done here.*/
1649
+ static void qr_hom_cell_fproject(qr_point _p,const qr_hom_cell *_cell,
1650
+ int _x,int _y,int _w){
1651
+ if(_w==0){
1652
+ _p[0]=_x<0?INT_MIN:INT_MAX;
1653
+ _p[1]=_y<0?INT_MIN:INT_MAX;
1654
+ }
1655
+ else{
1656
+ if(_w<0){
1657
+ _x=-_x;
1658
+ _y=-_y;
1659
+ _w=-_w;
1660
+ }
1661
+ _p[0]=QR_DIVROUND(_x,_w)+_cell->x0;
1662
+ _p[1]=QR_DIVROUND(_y,_w)+_cell->y0;
1663
+ }
1664
+ }
1665
+
1666
+ static void qr_hom_cell_project(qr_point _p,const qr_hom_cell *_cell,
1667
+ int _u,int _v,int _res){
1668
+ _u-=_cell->u0<<_res;
1669
+ _v-=_cell->v0<<_res;
1670
+ qr_hom_cell_fproject(_p,_cell,
1671
+ _cell->fwd[0][0]*_u+_cell->fwd[0][1]*_v+(_cell->fwd[0][2]<<_res),
1672
+ _cell->fwd[1][0]*_u+_cell->fwd[1][1]*_v+(_cell->fwd[1][2]<<_res),
1673
+ _cell->fwd[2][0]*_u+_cell->fwd[2][1]*_v+(_cell->fwd[2][2]<<_res));
1674
+ }
1675
+
1676
+
1677
+
1678
+ /*Retrieves the bits corresponding to the alignment pattern template centered
1679
+ at the given location in the original image (at subpel precision).*/
1680
+ static unsigned qr_alignment_pattern_fetch(qr_point _p[5][5],int _x0,int _y0,
1681
+ const unsigned char *_img,int _width,int _height){
1682
+ unsigned v;
1683
+ int i;
1684
+ int j;
1685
+ int k;
1686
+ int dx;
1687
+ int dy;
1688
+ dx=_x0-_p[2][2][0];
1689
+ dy=_y0-_p[2][2][1];
1690
+ v=0;
1691
+ for(k=i=0;i<5;i++)for(j=0;j<5;j++,k++){
1692
+ v|=qr_img_get_bit(_img,_width,_height,_p[i][j][0]+dx,_p[i][j][1]+dy)<<k;
1693
+ }
1694
+ return v;
1695
+ }
1696
+
1697
+ /*Searches for an alignment pattern near the given location.*/
1698
+ static int qr_alignment_pattern_search(qr_point _p,const qr_hom_cell *_cell,
1699
+ int _u,int _v,int _r,const unsigned char *_img,int _width,int _height){
1700
+ qr_point c[4];
1701
+ int nc[4];
1702
+ qr_point p[5][5];
1703
+ qr_point pc;
1704
+ unsigned best_match;
1705
+ int best_dist;
1706
+ int bestx;
1707
+ int besty;
1708
+ unsigned match;
1709
+ int dist;
1710
+ int u;
1711
+ int v;
1712
+ int x0;
1713
+ int y0;
1714
+ int w0;
1715
+ int x;
1716
+ int y;
1717
+ int w;
1718
+ int dxdu;
1719
+ int dydu;
1720
+ int dwdu;
1721
+ int dxdv;
1722
+ int dydv;
1723
+ int dwdv;
1724
+ int dx;
1725
+ int dy;
1726
+ int i;
1727
+ int j;
1728
+ /*Build up a basic template using _cell to control shape and scale.
1729
+ We project the points in the template back to the image just once, since if
1730
+ the alignment pattern has moved, we don't really know why.
1731
+ If it's because of radial distortion, or the code wasn't flat, or something
1732
+ else, there's no reason to expect that a re-projection around each
1733
+ subsequent search point would be any closer to the actual shape than our
1734
+ first projection.
1735
+ Therefore we simply slide this template around, as is.*/
1736
+ u=(_u-2)-_cell->u0;
1737
+ v=(_v-2)-_cell->v0;
1738
+ x0=_cell->fwd[0][0]*u+_cell->fwd[0][1]*v+_cell->fwd[0][2];
1739
+ y0=_cell->fwd[1][0]*u+_cell->fwd[1][1]*v+_cell->fwd[1][2];
1740
+ w0=_cell->fwd[2][0]*u+_cell->fwd[2][1]*v+_cell->fwd[2][2];
1741
+ dxdu=_cell->fwd[0][0];
1742
+ dydu=_cell->fwd[1][0];
1743
+ dwdu=_cell->fwd[2][0];
1744
+ dxdv=_cell->fwd[0][1];
1745
+ dydv=_cell->fwd[1][1];
1746
+ dwdv=_cell->fwd[2][1];
1747
+ for(i=0;i<5;i++){
1748
+ x=x0;
1749
+ y=y0;
1750
+ w=w0;
1751
+ for(j=0;j<5;j++){
1752
+ qr_hom_cell_fproject(p[i][j],_cell,x,y,w);
1753
+ x+=dxdu;
1754
+ y+=dydu;
1755
+ w+=dwdu;
1756
+ }
1757
+ x0+=dxdv;
1758
+ y0+=dydv;
1759
+ w0+=dwdv;
1760
+ }
1761
+ bestx=p[2][2][0];
1762
+ besty=p[2][2][1];
1763
+ best_match=qr_alignment_pattern_fetch(p,bestx,besty,_img,_width,_height);
1764
+ best_dist=qr_hamming_dist(best_match,0x1F8D63F,25);
1765
+ if(best_dist>0){
1766
+ u=_u-_cell->u0;
1767
+ v=_v-_cell->v0;
1768
+ x=_cell->fwd[0][0]*u+_cell->fwd[0][1]*v+_cell->fwd[0][2]<<QR_ALIGN_SUBPREC;
1769
+ y=_cell->fwd[1][0]*u+_cell->fwd[1][1]*v+_cell->fwd[1][2]<<QR_ALIGN_SUBPREC;
1770
+ w=_cell->fwd[2][0]*u+_cell->fwd[2][1]*v+_cell->fwd[2][2]<<QR_ALIGN_SUBPREC;
1771
+ /*Search an area at most _r modules around the target location, in
1772
+ concentric squares..*/
1773
+ for(i=1;i<_r<<QR_ALIGN_SUBPREC;i++){
1774
+ int side_len;
1775
+ side_len=(i<<1)-1;
1776
+ x-=dxdu+dxdv;
1777
+ y-=dydu+dydv;
1778
+ w-=dwdu+dwdv;
1779
+ for(j=0;j<4*side_len;j++){
1780
+ int dir;
1781
+ qr_hom_cell_fproject(pc,_cell,x,y,w);
1782
+ match=qr_alignment_pattern_fetch(p,pc[0],pc[1],_img,_width,_height);
1783
+ dist=qr_hamming_dist(match,0x1F8D63F,best_dist+1);
1784
+ if(dist<best_dist){
1785
+ best_match=match;
1786
+ best_dist=dist;
1787
+ bestx=pc[0];
1788
+ besty=pc[1];
1789
+ }
1790
+ if(j<2*side_len){
1791
+ dir=j>=side_len;
1792
+ x+=_cell->fwd[0][dir];
1793
+ y+=_cell->fwd[1][dir];
1794
+ w+=_cell->fwd[2][dir];
1795
+ }
1796
+ else{
1797
+ dir=j>=3*side_len;
1798
+ x-=_cell->fwd[0][dir];
1799
+ y-=_cell->fwd[1][dir];
1800
+ w-=_cell->fwd[2][dir];
1801
+ }
1802
+ if(!best_dist)break;
1803
+ }
1804
+ if(!best_dist)break;
1805
+ }
1806
+ }
1807
+ /*If the best result we got was sufficiently bad, reject the match.
1808
+ If we're wrong and we include it, we can grossly distort the nearby
1809
+ region, whereas using the initial starting point should at least be
1810
+ consistent with the geometry we already have.*/
1811
+ if(best_dist>6){
1812
+ _p[0]=p[2][2][0];
1813
+ _p[1]=p[2][2][1];
1814
+ return -1;
1815
+ }
1816
+ /*Now try to get a more accurate location of the pattern center.*/
1817
+ dx=bestx-p[2][2][0];
1818
+ dy=besty-p[2][2][1];
1819
+ memset(nc,0,sizeof(nc));
1820
+ memset(c,0,sizeof(c));
1821
+ /*We consider 8 lines across the finder pattern in turn.
1822
+ If we actually found a symmetric pattern along that line, search for its
1823
+ exact center in the image.
1824
+ There are plenty more lines we could use if these don't work, but if we've
1825
+ found anything remotely close to an alignment pattern, we should be able
1826
+ to use most of these.*/
1827
+ for(i=0;i<8;i++){
1828
+ static const unsigned MASK_TESTS[8][2]={
1829
+ {0x1040041,0x1000001},{0x0041040,0x0001000},
1830
+ {0x0110110,0x0100010},{0x0011100,0x0001000},
1831
+ {0x0420084,0x0400004},{0x0021080,0x0001000},
1832
+ {0x0006C00,0x0004400},{0x0003800,0x0001000},
1833
+ };
1834
+ static const unsigned char MASK_COORDS[8][2]={
1835
+ {0,0},{1,1},{4,0},{3,1},{2,0},{2,1},{0,2},{1,2}
1836
+ };
1837
+ if((best_match&MASK_TESTS[i][0])==MASK_TESTS[i][1]){
1838
+ int x0;
1839
+ int y0;
1840
+ int x1;
1841
+ int y1;
1842
+ x0=p[MASK_COORDS[i][1]][MASK_COORDS[i][0]][0]+dx>>QR_FINDER_SUBPREC;
1843
+ if(x0<0||x0>=_width)continue;
1844
+ y0=p[MASK_COORDS[i][1]][MASK_COORDS[i][0]][1]+dy>>QR_FINDER_SUBPREC;
1845
+ if(y0<0||y0>=_height)continue;
1846
+ x1=p[4-MASK_COORDS[i][1]][4-MASK_COORDS[i][0]][0]+dx>>QR_FINDER_SUBPREC;
1847
+ if(x1<0||x1>=_width)continue;
1848
+ y1=p[4-MASK_COORDS[i][1]][4-MASK_COORDS[i][0]][1]+dy>>QR_FINDER_SUBPREC;
1849
+ if(y1<0||y1>=_height)continue;
1850
+ if(!qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,i&1,pc)){
1851
+ int w;
1852
+ int cx;
1853
+ int cy;
1854
+ cx=pc[0]-bestx;
1855
+ cy=pc[1]-besty;
1856
+ if(i&1){
1857
+ /*Weight crossings around the center dot more highly, as they are
1858
+ generally more reliable.*/
1859
+ w=3;
1860
+ cx+=cx<<1;
1861
+ cy+=cy<<1;
1862
+ }
1863
+ else w=1;
1864
+ nc[i>>1]+=w;
1865
+ c[i>>1][0]+=cx;
1866
+ c[i>>1][1]+=cy;
1867
+ }
1868
+ }
1869
+ }
1870
+ /*Sum offsets from lines in orthogonal directions.*/
1871
+ for(i=0;i<2;i++){
1872
+ int a;
1873
+ int b;
1874
+ a=nc[i<<1];
1875
+ b=nc[i<<1|1];
1876
+ if(a&&b){
1877
+ int w;
1878
+ w=QR_MAXI(a,b);
1879
+ c[i<<1][0]=QR_DIVROUND(w*(b*c[i<<1][0]+a*c[i<<1|1][0]),a*b);
1880
+ c[i<<1][1]=QR_DIVROUND(w*(b*c[i<<1][1]+a*c[i<<1|1][1]),a*b);
1881
+ nc[i<<1]=w<<1;
1882
+ }
1883
+ else{
1884
+ c[i<<1][0]+=c[i<<1|1][0];
1885
+ c[i<<1][1]+=c[i<<1|1][1];
1886
+ nc[i<<1]+=b;
1887
+ }
1888
+ }
1889
+ /*Average offsets from pairs of orthogonal lines.*/
1890
+ c[0][0]+=c[2][0];
1891
+ c[0][1]+=c[2][1];
1892
+ nc[0]+=nc[2];
1893
+ /*If we actually found any such lines, apply the adjustment.*/
1894
+ if(nc[0]){
1895
+ dx=QR_DIVROUND(c[0][0],nc[0]);
1896
+ dy=QR_DIVROUND(c[0][1],nc[0]);
1897
+ /*But only if it doesn't make things worse.*/
1898
+ match=qr_alignment_pattern_fetch(p,bestx+dx,besty+dy,_img,_width,_height);
1899
+ dist=qr_hamming_dist(match,0x1F8D63F,best_dist+1);
1900
+ if(dist<=best_dist){
1901
+ bestx+=dx;
1902
+ besty+=dy;
1903
+ }
1904
+ }
1905
+ _p[0]=bestx;
1906
+ _p[1]=besty;
1907
+ return 0;
1908
+ }
1909
+
1910
+ static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur,
1911
+ qr_finder *_dl,qr_point _p[4],const qr_aff *_aff,isaac_ctx *_isaac,
1912
+ const unsigned char *_img,int _width,int _height){
1913
+ qr_point *b;
1914
+ int nb;
1915
+ int cb;
1916
+ qr_point *r;
1917
+ int nr;
1918
+ int cr;
1919
+ qr_line l[4];
1920
+ qr_point q;
1921
+ qr_point p;
1922
+ int ox;
1923
+ int oy;
1924
+ int ru;
1925
+ int rv;
1926
+ int dru;
1927
+ int drv;
1928
+ int bu;
1929
+ int bv;
1930
+ int dbu;
1931
+ int dbv;
1932
+ int rx;
1933
+ int ry;
1934
+ int drxi;
1935
+ int dryi;
1936
+ int drxj;
1937
+ int dryj;
1938
+ int rdone;
1939
+ int nrempty;
1940
+ int rlastfit;
1941
+ int bx;
1942
+ int by;
1943
+ int dbxi;
1944
+ int dbyi;
1945
+ int dbxj;
1946
+ int dbyj;
1947
+ int bdone;
1948
+ int nbempty;
1949
+ int blastfit;
1950
+ int shift;
1951
+ int round;
1952
+ int version4;
1953
+ int brx;
1954
+ int bry;
1955
+ int i;
1956
+ /*We attempt to correct large-scale perspective distortion by fitting lines
1957
+ to the edge of the code area.
1958
+ We could also look for an alignment pattern now, but that wouldn't work for
1959
+ version 1 codes, which have no alignment pattern.
1960
+ Even if the code is supposed to have one, there's go guarantee we'd find it
1961
+ intact.*/
1962
+ /*Fitting lines is easy for the edges on which we have two finder patterns.
1963
+ After the fit, UL is guaranteed to be on the proper side, but if either of
1964
+ the other two finder patterns aren't, something is wrong.*/
1965
+ qr_finder_ransac(_ul,_aff,_isaac,0);
1966
+ qr_finder_ransac(_dl,_aff,_isaac,0);
1967
+ qr_line_fit_finder_pair(l[0],_aff,_ul,_dl,0);
1968
+ if(qr_line_eval(l[0],_dl->c->pos[0],_dl->c->pos[1])<0||
1969
+ qr_line_eval(l[0],_ur->c->pos[0],_ur->c->pos[1])<0){
1970
+ return -1;
1971
+ }
1972
+ qr_finder_ransac(_ul,_aff,_isaac,2);
1973
+ qr_finder_ransac(_ur,_aff,_isaac,2);
1974
+ qr_line_fit_finder_pair(l[2],_aff,_ul,_ur,2);
1975
+ if(qr_line_eval(l[2],_dl->c->pos[0],_dl->c->pos[1])<0||
1976
+ qr_line_eval(l[2],_ur->c->pos[0],_ur->c->pos[1])<0){
1977
+ return -1;
1978
+ }
1979
+ /*The edges which only have one finder pattern are more difficult.
1980
+ We start by fitting a line to the edge of the one finder pattern we do
1981
+ have.
1982
+ This can fail due to an insufficient number of sample points, and even if
1983
+ it succeeds can be fairly inaccurate, because all of the points are
1984
+ clustered in one corner of the QR code.
1985
+ If it fails, we just use an axis-aligned line in the affine coordinate
1986
+ system.
1987
+ Then we walk along the edge of the entire code, looking for
1988
+ light:dark:light patterns perpendicular to the edge.
1989
+ Wherever we find one, we take the center of the dark portion as an
1990
+ additional sample point.
1991
+ At the end, we re-fit the line using all such sample points found.*/
1992
+ drv=_ur->size[1]>>1;
1993
+ qr_finder_ransac(_ur,_aff,_isaac,1);
1994
+ if(qr_line_fit_finder_edge(l[1],_ur,1,_aff->res)>=0){
1995
+ if(qr_line_eval(l[1],_ul->c->pos[0],_ul->c->pos[1])<0||
1996
+ qr_line_eval(l[1],_dl->c->pos[0],_dl->c->pos[1])<0){
1997
+ return -1;
1998
+ }
1999
+ /*Figure out the change in ru for a given change in rv when stepping along
2000
+ the fitted line.*/
2001
+ if(qr_aff_line_step(_aff,l[1],1,drv,&dru)<0)return -1;
2002
+ }
2003
+ else dru=0;
2004
+ ru=_ur->o[0]+3*_ur->size[0]-2*dru;
2005
+ rv=_ur->o[1]-2*drv;
2006
+ dbu=_dl->size[0]>>1;
2007
+ qr_finder_ransac(_dl,_aff,_isaac,3);
2008
+ if(qr_line_fit_finder_edge(l[3],_dl,3,_aff->res)>=0){
2009
+ if(qr_line_eval(l[3],_ul->c->pos[0],_ul->c->pos[1])<0||
2010
+ qr_line_eval(l[3],_ur->c->pos[0],_ur->c->pos[1])<0){
2011
+ return -1;
2012
+ }
2013
+ /*Figure out the change in bv for a given change in bu when stepping along
2014
+ the fitted line.*/
2015
+ if(qr_aff_line_step(_aff,l[3],0,dbu,&dbv)<0)return -1;
2016
+ }
2017
+ else dbv=0;
2018
+ bu=_dl->o[0]-2*dbu;
2019
+ bv=_dl->o[1]+3*_dl->size[1]-2*dbv;
2020
+ /*Set up the initial point lists.*/
2021
+ nr=rlastfit=_ur->ninliers[1];
2022
+ cr=nr+(_dl->o[1]-rv+drv-1)/drv;
2023
+ r=(qr_point *)malloc(cr*sizeof(*r));
2024
+ for(i=0;i<_ur->ninliers[1];i++){
2025
+ memcpy(r[i],_ur->edge_pts[1][i].pos,sizeof(r[i]));
2026
+ }
2027
+ nb=blastfit=_dl->ninliers[3];
2028
+ cb=nb+(_ur->o[0]-bu+dbu-1)/dbu;
2029
+ b=(qr_point *)malloc(cb*sizeof(*b));
2030
+ for(i=0;i<_dl->ninliers[3];i++){
2031
+ memcpy(b[i],_dl->edge_pts[3][i].pos,sizeof(b[i]));
2032
+ }
2033
+ /*Set up the step parameters for the affine projection.*/
2034
+ ox=(_aff->x0<<_aff->res)+(1<<_aff->res-1);
2035
+ oy=(_aff->y0<<_aff->res)+(1<<_aff->res-1);
2036
+ rx=_aff->fwd[0][0]*ru+_aff->fwd[0][1]*rv+ox;
2037
+ ry=_aff->fwd[1][0]*ru+_aff->fwd[1][1]*rv+oy;
2038
+ drxi=_aff->fwd[0][0]*dru+_aff->fwd[0][1]*drv;
2039
+ dryi=_aff->fwd[1][0]*dru+_aff->fwd[1][1]*drv;
2040
+ drxj=_aff->fwd[0][0]*_ur->size[0];
2041
+ dryj=_aff->fwd[1][0]*_ur->size[0];
2042
+ bx=_aff->fwd[0][0]*bu+_aff->fwd[0][1]*bv+ox;
2043
+ by=_aff->fwd[1][0]*bu+_aff->fwd[1][1]*bv+oy;
2044
+ dbxi=_aff->fwd[0][0]*dbu+_aff->fwd[0][1]*dbv;
2045
+ dbyi=_aff->fwd[1][0]*dbu+_aff->fwd[1][1]*dbv;
2046
+ dbxj=_aff->fwd[0][1]*_dl->size[1];
2047
+ dbyj=_aff->fwd[1][1]*_dl->size[1];
2048
+ /*Now step along the lines, looking for new sample points.*/
2049
+ nrempty=nbempty=0;
2050
+ for(;;){
2051
+ int ret;
2052
+ int x0;
2053
+ int y0;
2054
+ int x1;
2055
+ int y1;
2056
+ /*If we take too many steps without encountering a non-zero pixel, assume
2057
+ we have wandered off the edge and stop looking before we hit the other
2058
+ side of the quiet region.
2059
+ Otherwise, stop when the lines cross (if they do so inside the affine
2060
+ region) or come close to crossing (outside the affine region).
2061
+ TODO: We don't have any way of detecting when we've wandered into the
2062
+ code interior; we could stop if the outside sample ever shows up dark,
2063
+ but this could happen because of noise in the quiet region, too.*/
2064
+ rdone=rv>=QR_MINI(bv,_dl->o[1]+bv>>1)||nrempty>14;
2065
+ bdone=bu>=QR_MINI(ru,_ur->o[0]+ru>>1)||nbempty>14;
2066
+ if(!rdone&&(bdone||rv<bu)){
2067
+ x0=rx+drxj>>_aff->res+QR_FINDER_SUBPREC;
2068
+ y0=ry+dryj>>_aff->res+QR_FINDER_SUBPREC;
2069
+ x1=rx-drxj>>_aff->res+QR_FINDER_SUBPREC;
2070
+ y1=ry-dryj>>_aff->res+QR_FINDER_SUBPREC;
2071
+ if(nr>=cr){
2072
+ cr=cr<<1|1;
2073
+ r=(qr_point *)realloc(r,cr*sizeof(*r));
2074
+ }
2075
+ ret=qr_finder_quick_crossing_check(_img,_width,_height,x0,y0,x1,y1,1);
2076
+ if(!ret){
2077
+ ret=qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,1,r[nr]);
2078
+ }
2079
+ if(ret>=0){
2080
+ if(!ret){
2081
+ qr_aff_unproject(q,_aff,r[nr][0],r[nr][1]);
2082
+ /*Move the current point halfway towards the crossing.
2083
+ We don't move the whole way to give us some robustness to noise.*/
2084
+ ru=ru+q[0]>>1;
2085
+ /*But ensure that rv monotonically increases.*/
2086
+ if(q[1]+drv>rv)rv=rv+q[1]>>1;
2087
+ rx=_aff->fwd[0][0]*ru+_aff->fwd[0][1]*rv+ox;
2088
+ ry=_aff->fwd[1][0]*ru+_aff->fwd[1][1]*rv+oy;
2089
+ nr++;
2090
+ /*Re-fit the line to update the step direction periodically.*/
2091
+ if(nr>QR_MAXI(1,rlastfit+(rlastfit>>2))){
2092
+ qr_line_fit_points(l[1],r,nr,_aff->res);
2093
+ if(qr_aff_line_step(_aff,l[1],1,drv,&dru)>=0){
2094
+ drxi=_aff->fwd[0][0]*dru+_aff->fwd[0][1]*drv;
2095
+ dryi=_aff->fwd[1][0]*dru+_aff->fwd[1][1]*drv;
2096
+ }
2097
+ rlastfit=nr;
2098
+ }
2099
+ }
2100
+ else nrempty=0;
2101
+ }
2102
+ else nrempty++;
2103
+ ru+=dru;
2104
+ /*Our final defense: if we overflow, stop.*/
2105
+ if(rv+drv>rv)rv+=drv;
2106
+ else nrempty=INT_MAX;
2107
+ rx+=drxi;
2108
+ ry+=dryi;
2109
+ }
2110
+ else if(!bdone){
2111
+ x0=bx+dbxj>>_aff->res+QR_FINDER_SUBPREC;
2112
+ y0=by+dbyj>>_aff->res+QR_FINDER_SUBPREC;
2113
+ x1=bx-dbxj>>_aff->res+QR_FINDER_SUBPREC;
2114
+ y1=by-dbyj>>_aff->res+QR_FINDER_SUBPREC;
2115
+ if(nb>=cb){
2116
+ cb=cb<<1|1;
2117
+ b=(qr_point *)realloc(b,cb*sizeof(*b));
2118
+ }
2119
+ ret=qr_finder_quick_crossing_check(_img,_width,_height,x0,y0,x1,y1,1);
2120
+ if(!ret){
2121
+ ret=qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,1,b[nb]);
2122
+ }
2123
+ if(ret>=0){
2124
+ if(!ret){
2125
+ qr_aff_unproject(q,_aff,b[nb][0],b[nb][1]);
2126
+ /*Move the current point halfway towards the crossing.
2127
+ We don't move the whole way to give us some robustness to noise.*/
2128
+ /*But ensure that bu monotonically increases.*/
2129
+ if(q[0]+dbu>bu)bu=bu+q[0]>>1;
2130
+ bv=bv+q[1]>>1;
2131
+ bx=_aff->fwd[0][0]*bu+_aff->fwd[0][1]*bv+ox;
2132
+ by=_aff->fwd[1][0]*bu+_aff->fwd[1][1]*bv+oy;
2133
+ nb++;
2134
+ /*Re-fit the line to update the step direction periodically.*/
2135
+ if(nb>QR_MAXI(1,blastfit+(blastfit>>2))){
2136
+ qr_line_fit_points(l[3],b,nb,_aff->res);
2137
+ if(qr_aff_line_step(_aff,l[3],0,dbu,&dbv)>=0){
2138
+ dbxi=_aff->fwd[0][0]*dbu+_aff->fwd[0][1]*dbv;
2139
+ dbyi=_aff->fwd[1][0]*dbu+_aff->fwd[1][1]*dbv;
2140
+ }
2141
+ blastfit=nb;
2142
+ }
2143
+ }
2144
+ nbempty=0;
2145
+ }
2146
+ else nbempty++;
2147
+ /*Our final defense: if we overflow, stop.*/
2148
+ if(bu+dbu>bu)bu+=dbu;
2149
+ else nbempty=INT_MAX;
2150
+ bv+=dbv;
2151
+ bx+=dbxi;
2152
+ by+=dbyi;
2153
+ }
2154
+ else break;
2155
+ }
2156
+ /*Fit the new lines.
2157
+ If we _still_ don't have enough sample points, then just use an
2158
+ axis-aligned line from the affine coordinate system (e.g., one parallel
2159
+ to the opposite edge in the image).*/
2160
+ if(nr>1)qr_line_fit_points(l[1],r,nr,_aff->res);
2161
+ else{
2162
+ qr_aff_project(p,_aff,_ur->o[0]+3*_ur->size[0],_ur->o[1]);
2163
+ shift=QR_MAXI(0,
2164
+ qr_ilog(QR_MAXI(abs(_aff->fwd[0][1]),abs(_aff->fwd[1][1])))
2165
+ -(_aff->res+1>>1));
2166
+ round=(1<<shift)>>1;
2167
+ l[1][0]=_aff->fwd[1][1]+round>>shift;
2168
+ l[1][1]=-_aff->fwd[0][1]+round>>shift;
2169
+ l[1][2]=-(l[1][0]*p[0]+l[1][1]*p[1]);
2170
+ }
2171
+ free(r);
2172
+ if(nb>1)qr_line_fit_points(l[3],b,nb,_aff->res);
2173
+ else{
2174
+ qr_aff_project(p,_aff,_dl->o[0],_dl->o[1]+3*_dl->size[1]);
2175
+ shift=QR_MAXI(0,
2176
+ qr_ilog(QR_MAXI(abs(_aff->fwd[0][1]),abs(_aff->fwd[1][1])))
2177
+ -(_aff->res+1>>1));
2178
+ round=(1<<shift)>>1;
2179
+ l[3][0]=_aff->fwd[1][0]+round>>shift;
2180
+ l[3][1]=-_aff->fwd[0][0]+round>>shift;
2181
+ l[3][2]=-(l[1][0]*p[0]+l[1][1]*p[1]);
2182
+ }
2183
+ free(b);
2184
+ for(i=0;i<4;i++){
2185
+ if(qr_line_isect(_p[i],l[i&1],l[2+(i>>1)])<0)return -1;
2186
+ /*It's plausible for points to be somewhat outside the image, but too far
2187
+ and too much of the pattern will be gone for it to be decodable.*/
2188
+ if(_p[i][0]<-_width<<QR_FINDER_SUBPREC||
2189
+ _p[i][0]>=_width<<QR_FINDER_SUBPREC+1||
2190
+ _p[i][1]<-_height<<QR_FINDER_SUBPREC||
2191
+ _p[i][1]>=_height<<QR_FINDER_SUBPREC+1){
2192
+ return -1;
2193
+ }
2194
+ }
2195
+ /*By default, use the edge intersection point for the bottom-right corner.*/
2196
+ brx=_p[3][0];
2197
+ bry=_p[3][1];
2198
+ /*However, if our average version estimate is greater than 1, NOW we try to
2199
+ search for an alignment pattern.
2200
+ We get a much better success rate by doing this after our initial attempt
2201
+ to promote the transform to a homography than before.
2202
+ You might also think it would be more reliable to use the interior finder
2203
+ pattern edges, since the outer ones may be obscured or damaged, and it
2204
+ would save us a reprojection below, since they would form a nice square
2205
+ with the location of the alignment pattern, but this turns out to be a bad
2206
+ idea.
2207
+ Non-linear distortion is usually maximal on the outside edge, and thus
2208
+ estimating the grid position from points on the interior means we might
2209
+ get mis-aligned by the time we reach the edge.*/
2210
+ version4=_ul->eversion[0]+_ul->eversion[1]+_ur->eversion[0]+_dl->eversion[1];
2211
+ if(version4>4){
2212
+ qr_hom_cell cell;
2213
+ qr_point p3;
2214
+ int dim;
2215
+ dim=17+version4;
2216
+ qr_hom_cell_init(&cell,0,0,dim-1,0,0,dim-1,dim-1,dim-1,
2217
+ _p[0][0],_p[0][1],_p[1][0],_p[1][1],
2218
+ _p[2][0],_p[2][1],_p[3][0],_p[3][1]);
2219
+ if(qr_alignment_pattern_search(p3,&cell,dim-7,dim-7,4,
2220
+ _img,_width,_height)>=0){
2221
+ int c21;
2222
+ int dx21;
2223
+ int dy21;
2224
+ int mask;
2225
+ int w;
2226
+ /*There's no real need to update the bounding box corner, and in fact we
2227
+ actively perform worse if we do.
2228
+ Clearly it was good enough for us to find this alignment pattern, so
2229
+ it should be good enough to use for grid initialization.
2230
+ The point of doing the search was to get more accurate version
2231
+ estimates and a better chance of decoding the version and format info.
2232
+ This is particularly important for small versions that have no encoded
2233
+ version info, since any mismatch in version renders the code
2234
+ undecodable.*/
2235
+ /*We do, however, need four points in a square to initialize our
2236
+ homography, so project the point from the alignment center to the
2237
+ corner of the code area.*/
2238
+ c21=_p[2][0]*_p[1][1]-_p[2][1]*_p[1][0];
2239
+ dx21=_p[2][0]-_p[1][0];
2240
+ dy21=_p[2][1]-_p[1][1];
2241
+ w=(dim-7)*c21
2242
+ +(dim-13)*(_p[0][0]*dy21-_p[0][1]*dx21)+6*(p3[0]*dy21-p3[1]*dx21);
2243
+ mask=QR_SIGNMASK(w);
2244
+ w=abs(w);
2245
+ brx=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][0],p3[0]*dy21,
2246
+ QR_EXTMUL((dim-13)*p3[0],c21-_p[0][1]*dx21,
2247
+ QR_EXTMUL(6*_p[0][0],c21-p3[1]*dx21,0)))+mask^mask,w);
2248
+ bry=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][1],-p3[1]*dx21,
2249
+ QR_EXTMUL((dim-13)*p3[1],c21+_p[0][0]*dy21,
2250
+ QR_EXTMUL(6*_p[0][1],c21+p3[0]*dy21,0)))+mask^mask,w);
2251
+ }
2252
+ }
2253
+ /*Now we have four points that map to a square: initialize the projection.*/
2254
+ qr_hom_init(_hom,_p[0][0],_p[0][1],_p[1][0],_p[1][1],
2255
+ _p[2][0],_p[2][1],brx,bry,QR_HOM_BITS);
2256
+ return 0;
2257
+ }
2258
+
2259
+
2260
+
2261
+ /*The BCH(18,6,3) codes are only used for version information, which must lie
2262
+ between 7 and 40 (inclusive).*/
2263
+ static const unsigned BCH18_6_CODES[34]={
2264
+ 0x07C94,
2265
+ 0x085BC,0x09A99,0x0A4D3,0x0BBF6,0x0C762,0x0D847,0x0E60D,0x0F928,
2266
+ 0x10B78,0x1145D,0x12A17,0x13532,0x149A6,0x15683,0x168C9,0x177EC,
2267
+ 0x18EC4,0x191E1,0x1AFAB,0x1B08E,0x1CC1A,0x1D33F,0x1ED75,0x1F250,
2268
+ 0x209D5,0x216F0,0x228BA,0x2379F,0x24B0B,0x2542E,0x26A64,0x27541,
2269
+ 0x28C69
2270
+ };
2271
+
2272
+ /*Corrects a BCH(18,6,3) code word.
2273
+ _y: Contains the code word to be checked on input, and the corrected value on
2274
+ output.
2275
+ Return: The number of errors.
2276
+ If more than 3 errors are detected, returns a negative value and
2277
+ performs no correction.*/
2278
+ static int bch18_6_correct(unsigned *_y){
2279
+ unsigned x;
2280
+ unsigned y;
2281
+ int nerrs;
2282
+ y=*_y;
2283
+ /*Check the easy case first: see if the data bits were uncorrupted.*/
2284
+ x=y>>12;
2285
+ if(x>=7&&x<=40){
2286
+ nerrs=qr_hamming_dist(y,BCH18_6_CODES[x-7],4);
2287
+ if(nerrs<4){
2288
+ *_y=BCH18_6_CODES[x-7];
2289
+ return nerrs;
2290
+ }
2291
+ }
2292
+ /*Exhaustive search is faster than field operations in GF(19).*/
2293
+ for(x=0;x<34;x++)if(x+7!=y>>12){
2294
+ nerrs=qr_hamming_dist(y,BCH18_6_CODES[x],4);
2295
+ if(nerrs<4){
2296
+ *_y=BCH18_6_CODES[x];
2297
+ return nerrs;
2298
+ }
2299
+ }
2300
+ return -1;
2301
+ }
2302
+
2303
+ #if 0
2304
+ static unsigned bch18_6_encode(unsigned _x){
2305
+ return (-(_x&1)&0x01F25)^(-(_x>>1&1)&0x0216F)^(-(_x>>2&1)&0x042DE)^
2306
+ (-(_x>>3&1)&0x085BC)^(-(_x>>4&1)&0x10B78)^(-(_x>>5&1)&0x209D5);
2307
+ }
2308
+ #endif
2309
+
2310
+ /*Reads the version bits near a finder module and decodes the version number.*/
2311
+ static int qr_finder_version_decode(qr_finder *_f,const qr_hom *_hom,
2312
+ const unsigned char *_img,int _width,int _height,int _dir){
2313
+ qr_point q;
2314
+ unsigned v;
2315
+ int x0;
2316
+ int y0;
2317
+ int w0;
2318
+ int dxi;
2319
+ int dyi;
2320
+ int dwi;
2321
+ int dxj;
2322
+ int dyj;
2323
+ int dwj;
2324
+ int ret;
2325
+ int i;
2326
+ int j;
2327
+ int k;
2328
+ v=0;
2329
+ q[_dir]=_f->o[_dir]-7*_f->size[_dir];
2330
+ q[1-_dir]=_f->o[1-_dir]-3*_f->size[1-_dir];
2331
+ x0=_hom->fwd[0][0]*q[0]+_hom->fwd[0][1]*q[1];
2332
+ y0=_hom->fwd[1][0]*q[0]+_hom->fwd[1][1]*q[1];
2333
+ w0=_hom->fwd[2][0]*q[0]+_hom->fwd[2][1]*q[1]+_hom->fwd22;
2334
+ dxi=_hom->fwd[0][1-_dir]*_f->size[1-_dir];
2335
+ dyi=_hom->fwd[1][1-_dir]*_f->size[1-_dir];
2336
+ dwi=_hom->fwd[2][1-_dir]*_f->size[1-_dir];
2337
+ dxj=_hom->fwd[0][_dir]*_f->size[_dir];
2338
+ dyj=_hom->fwd[1][_dir]*_f->size[_dir];
2339
+ dwj=_hom->fwd[2][_dir]*_f->size[_dir];
2340
+ for(k=i=0;i<6;i++){
2341
+ int x;
2342
+ int y;
2343
+ int w;
2344
+ x=x0;
2345
+ y=y0;
2346
+ w=w0;
2347
+ for(j=0;j<3;j++,k++){
2348
+ qr_point p;
2349
+ qr_hom_fproject(p,_hom,x,y,w);
2350
+ v|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
2351
+ x+=dxj;
2352
+ y+=dyj;
2353
+ w+=dwj;
2354
+ }
2355
+ x0+=dxi;
2356
+ y0+=dyi;
2357
+ w0+=dwi;
2358
+ }
2359
+ ret=bch18_6_correct(&v);
2360
+ /*TODO: I'd certainly hope the order the version bits is accessed in is
2361
+ well-defined, but I seem to have images for two different codes with the
2362
+ same version using two different orders?
2363
+ Maybe the other one is a model 1 code?
2364
+ Even if I parse the version here, I can't decode the rest of the code.
2365
+ If this is really needed, we should just re-order the bits.*/
2366
+ #if 0
2367
+ if(ret<0){
2368
+ /*17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2369
+ 0 3 6 9 12 15 1 4 7 10 13 16 2 5 8 11 14 17
2370
+ 17 13 9 5 1 -3 10 6 2 -2 -6-10 3 -1 -5 -9-13-17*/
2371
+ v=0;
2372
+ for(k=i=0;i<3;i++){
2373
+ p[_dir]=_f->o[_dir]+_f->size[_dir]*(-5-i);
2374
+ for(j=0;j<6;j++,k++){
2375
+ qr_point q;
2376
+ p[1-_dir]=_f->o[1-_dir]+_f->size[1-_dir]*(2-j);
2377
+ qr_hom_project(q,_hom,p[0],p[1]);
2378
+ v|=qr_img_get_bit(_img,_width,_height,q[0],q[1])<<k;
2379
+ }
2380
+ }
2381
+ ret=bch18_6_correct(&v);
2382
+ }
2383
+ #endif
2384
+ return ret>=0?(int)(v>>12):ret;
2385
+ }
2386
+
2387
+ /*Reads the format info bits near the finder modules and decodes them.*/
2388
+ static int qr_finder_fmt_info_decode(qr_finder *_ul,qr_finder *_ur,
2389
+ qr_finder *_dl,const qr_hom *_hom,
2390
+ const unsigned char *_img,int _width,int _height){
2391
+ qr_point p;
2392
+ unsigned lo[2];
2393
+ unsigned hi[2];
2394
+ int u;
2395
+ int v;
2396
+ int x;
2397
+ int y;
2398
+ int w;
2399
+ int dx;
2400
+ int dy;
2401
+ int dw;
2402
+ int fmt_info[4];
2403
+ int count[4];
2404
+ int nerrs[4];
2405
+ int nfmt_info;
2406
+ int besti;
2407
+ int imax;
2408
+ int di;
2409
+ int i;
2410
+ int k;
2411
+ /*Read the bits around the UL corner.*/
2412
+ lo[0]=0;
2413
+ u=_ul->o[0]+5*_ul->size[0];
2414
+ v=_ul->o[1]-3*_ul->size[1];
2415
+ x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
2416
+ y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
2417
+ w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
2418
+ dx=_hom->fwd[0][1]*_ul->size[1];
2419
+ dy=_hom->fwd[1][1]*_ul->size[1];
2420
+ dw=_hom->fwd[2][1]*_ul->size[1];
2421
+ for(k=i=0;;i++){
2422
+ /*Skip the timing pattern row.*/
2423
+ if(i!=6){
2424
+ qr_hom_fproject(p,_hom,x,y,w);
2425
+ lo[0]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k++;
2426
+ /*Don't advance q in the last iteration... we'll start the next loop from
2427
+ the current position.*/
2428
+ if(i>=8)break;
2429
+ }
2430
+ x+=dx;
2431
+ y+=dy;
2432
+ w+=dw;
2433
+ }
2434
+ hi[0]=0;
2435
+ dx=-_hom->fwd[0][0]*_ul->size[0];
2436
+ dy=-_hom->fwd[1][0]*_ul->size[0];
2437
+ dw=-_hom->fwd[2][0]*_ul->size[0];
2438
+ while(i-->0){
2439
+ x+=dx;
2440
+ y+=dy;
2441
+ w+=dw;
2442
+ /*Skip the timing pattern column.*/
2443
+ if(i!=6){
2444
+ qr_hom_fproject(p,_hom,x,y,w);
2445
+ hi[0]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k++;
2446
+ }
2447
+ }
2448
+ /*Read the bits next to the UR corner.*/
2449
+ lo[1]=0;
2450
+ u=_ur->o[0]+3*_ur->size[0];
2451
+ v=_ur->o[1]+5*_ur->size[1];
2452
+ x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
2453
+ y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
2454
+ w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
2455
+ dx=-_hom->fwd[0][0]*_ur->size[0];
2456
+ dy=-_hom->fwd[1][0]*_ur->size[0];
2457
+ dw=-_hom->fwd[2][0]*_ur->size[0];
2458
+ for(k=0;k<8;k++){
2459
+ qr_hom_fproject(p,_hom,x,y,w);
2460
+ lo[1]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
2461
+ x+=dx;
2462
+ y+=dy;
2463
+ w+=dw;
2464
+ }
2465
+ /*Read the bits next to the DL corner.*/
2466
+ hi[1]=0;
2467
+ u=_dl->o[0]+5*_dl->size[0];
2468
+ v=_dl->o[1]-3*_dl->size[1];
2469
+ x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
2470
+ y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
2471
+ w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
2472
+ dx=_hom->fwd[0][1]*_dl->size[1];
2473
+ dy=_hom->fwd[1][1]*_dl->size[1];
2474
+ dw=_hom->fwd[2][1]*_dl->size[1];
2475
+ for(k=8;k<15;k++){
2476
+ qr_hom_fproject(p,_hom,x,y,w);
2477
+ hi[1]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
2478
+ x+=dx;
2479
+ y+=dy;
2480
+ w+=dw;
2481
+ }
2482
+ /*For the 8th bit we have 3 samples... use the majority value.
2483
+ TODO: The DL bit appears to be wrong as much as right? Guess it's not
2484
+ really a third copy after all, but doesn't appear to be used for data.
2485
+ i=((lo[0]>>7&1)+(lo[1]>>7&1)+(hi[1]>>7&1)>>1)<<7;
2486
+ lo[0]=lo[0]&~0x80|i;
2487
+ lo[1]=lo[1]&~0x80|i;
2488
+ hi[1]&=~0x80;*/
2489
+ /*For the remaining bits we have two samples... try them in all
2490
+ combinations and pick the most popular valid code, breaking ties using
2491
+ the number of bit errors.*/
2492
+ imax=2<<(hi[0]!=hi[1]);
2493
+ di=1+(lo[0]==lo[1]);
2494
+ nfmt_info=0;
2495
+ for(i=0;i<imax;i+=di){
2496
+ unsigned v;
2497
+ int ret;
2498
+ int j;
2499
+ v=(lo[i&1]|hi[i>>1])^0x5412;
2500
+ ret=bch15_5_correct(&v);
2501
+ v>>=10;
2502
+ if(ret<0)ret=4;
2503
+ for(j=0;;j++){
2504
+ if(j>=nfmt_info){
2505
+ fmt_info[j]=v;
2506
+ count[j]=1;
2507
+ nerrs[j]=ret;
2508
+ nfmt_info++;
2509
+ break;
2510
+ }
2511
+ if(fmt_info[j]==(int)v){
2512
+ count[j]++;
2513
+ if(ret<nerrs[j])nerrs[j]=ret;
2514
+ break;
2515
+ }
2516
+ }
2517
+ }
2518
+ besti=0;
2519
+ for(i=1;i<nfmt_info;i++){
2520
+ if(nerrs[besti]>3&&nerrs[i]<=3||
2521
+ count[i]>count[besti]||count[i]==count[besti]&&nerrs[i]<nerrs[besti]){
2522
+ besti=i;
2523
+ }
2524
+ }
2525
+ return nerrs[besti]<4?fmt_info[besti]:-1;
2526
+ }
2527
+
2528
+
2529
+
2530
+ /*The grid used to sample the image bits.
2531
+ The grid is divided into separate cells bounded by finder patterns and/or
2532
+ alignment patterns, and a separate map back to the original image is
2533
+ constructed for each cell.
2534
+ All of these structural elements, as well as the timing patterns, version
2535
+ info, and format info, are marked in fpmask so they can easily be skipped
2536
+ during decode.*/
2537
+ struct qr_sampling_grid{
2538
+ qr_hom_cell *cells[6];
2539
+ unsigned *fpmask;
2540
+ int cell_limits[6];
2541
+ int ncells;
2542
+ };
2543
+
2544
+
2545
+ /*Mark a given region as belonging to the function pattern.*/
2546
+ static void qr_sampling_grid_fp_mask_rect(qr_sampling_grid *_grid,int _dim,
2547
+ int _u,int _v,int _w,int _h){
2548
+ int i;
2549
+ int j;
2550
+ int stride;
2551
+ stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
2552
+ /*Note that we store bits column-wise, since that's how they're read out of
2553
+ the grid.*/
2554
+ for(j=_u;j<_u+_w;j++)for(i=_v;i<_v+_h;i++){
2555
+ _grid->fpmask[j*stride+(i>>QR_INT_LOGBITS)]|=1<<(i&QR_INT_BITS-1);
2556
+ }
2557
+ }
2558
+
2559
+ /*Determine if a given grid location is inside the function pattern.*/
2560
+ static int qr_sampling_grid_is_in_fp(const qr_sampling_grid *_grid,int _dim,
2561
+ int _u,int _v){
2562
+ return _grid->fpmask[_u*(_dim+QR_INT_BITS-1>>QR_INT_LOGBITS)
2563
+ +(_v>>QR_INT_LOGBITS)]>>(_v&QR_INT_BITS-1)&1;
2564
+ }
2565
+
2566
+ /*The spacing between alignment patterns after the second for versions >= 7.
2567
+ We could compact this more, but the code to access it would eliminate the
2568
+ gains.*/
2569
+ static const unsigned char QR_ALIGNMENT_SPACING[34]={
2570
+ 16,18,20,22,24,26,28,
2571
+ 20,22,24,24,26,28,28,
2572
+ 22,24,24,26,26,28,28,
2573
+ 24,24,26,26,26,28,28,
2574
+ 24,26,26,26,28,28
2575
+ };
2576
+
2577
+ static inline void qr_svg_points(const char *cls,
2578
+ qr_point *p,
2579
+ int n)
2580
+ {
2581
+ int i;
2582
+ svg_path_start(cls, 1, 0, 0);
2583
+ for(i = 0; i < n; i++, p++)
2584
+ svg_path_moveto(SVG_ABS, p[0][0], p[0][1]);
2585
+ svg_path_end();
2586
+ }
2587
+
2588
+ /*Initialize the sampling grid for each region of the code.
2589
+ _version: The (decoded) version number.
2590
+ _ul_pos: The location of the UL finder pattern.
2591
+ _ur_pos: The location of the UR finder pattern.
2592
+ _dl_pos: The location of the DL finder pattern.
2593
+ _p: On input, contains estimated positions of the four corner modules.
2594
+ On output, contains a bounding quadrilateral for the code.
2595
+ _img: The binary input image.
2596
+ _width: The width of the input image.
2597
+ _height: The height of the input image.
2598
+ Return: 0 on success, or a negative value on error.*/
2599
+ static void qr_sampling_grid_init(qr_sampling_grid *_grid,int _version,
2600
+ const qr_point _ul_pos,const qr_point _ur_pos,const qr_point _dl_pos,
2601
+ qr_point _p[4],const unsigned char *_img,int _width,int _height){
2602
+ qr_hom_cell base_cell;
2603
+ int align_pos[7];
2604
+ int dim;
2605
+ int nalign;
2606
+ int i;
2607
+ dim=17+(_version<<2);
2608
+ nalign=(_version/7)+2;
2609
+ /*Create a base cell to bootstrap the alignment pattern search.*/
2610
+ qr_hom_cell_init(&base_cell,0,0,dim-1,0,0,dim-1,dim-1,dim-1,
2611
+ _p[0][0],_p[0][1],_p[1][0],_p[1][1],_p[2][0],_p[2][1],_p[3][0],_p[3][1]);
2612
+ /*Allocate the array of cells.*/
2613
+ _grid->ncells=nalign-1;
2614
+ _grid->cells[0]=(qr_hom_cell *)malloc(
2615
+ (nalign-1)*(nalign-1)*sizeof(*_grid->cells[0]));
2616
+ for(i=1;i<_grid->ncells;i++)_grid->cells[i]=_grid->cells[i-1]+_grid->ncells;
2617
+ /*Initialize the function pattern mask.*/
2618
+ _grid->fpmask=(unsigned *)calloc(dim,
2619
+ (dim+QR_INT_BITS-1>>QR_INT_LOGBITS)*sizeof(*_grid->fpmask));
2620
+ /*Mask out the finder patterns (and separators and format info bits).*/
2621
+ qr_sampling_grid_fp_mask_rect(_grid,dim,0,0,9,9);
2622
+ qr_sampling_grid_fp_mask_rect(_grid,dim,0,dim-8,9,8);
2623
+ qr_sampling_grid_fp_mask_rect(_grid,dim,dim-8,0,8,9);
2624
+ /*Mask out the version number bits.*/
2625
+ if(_version>6){
2626
+ qr_sampling_grid_fp_mask_rect(_grid,dim,0,dim-11,6,3);
2627
+ qr_sampling_grid_fp_mask_rect(_grid,dim,dim-11,0,3,6);
2628
+ }
2629
+ /*Mask out the timing patterns.*/
2630
+ qr_sampling_grid_fp_mask_rect(_grid,dim,9,6,dim-17,1);
2631
+ qr_sampling_grid_fp_mask_rect(_grid,dim,6,9,1,dim-17);
2632
+ /*If we have no alignment patterns (e.g., this is a version 1 code), just use
2633
+ the base cell and hope it's good enough.*/
2634
+ if(_version<2)memcpy(_grid->cells[0],&base_cell,sizeof(base_cell));
2635
+ else{
2636
+ qr_point *q;
2637
+ qr_point *p;
2638
+ int j;
2639
+ int k;
2640
+ q=(qr_point *)malloc(nalign*nalign*sizeof(*q));
2641
+ p=(qr_point *)malloc(nalign*nalign*sizeof(*p));
2642
+ /*Initialize the alignment pattern position list.*/
2643
+ align_pos[0]=6;
2644
+ align_pos[nalign-1]=dim-7;
2645
+ if(_version>6){
2646
+ int d;
2647
+ d=QR_ALIGNMENT_SPACING[_version-7];
2648
+ for(i=nalign-1;i-->1;)align_pos[i]=align_pos[i+1]-d;
2649
+ }
2650
+ /*Three of the corners use a finder pattern instead of a separate
2651
+ alignment pattern.*/
2652
+ q[0][0]=3;
2653
+ q[0][1]=3;
2654
+ p[0][0]=_ul_pos[0];
2655
+ p[0][1]=_ul_pos[1];
2656
+ q[nalign-1][0]=dim-4;
2657
+ q[nalign-1][1]=3;
2658
+ p[nalign-1][0]=_ur_pos[0];
2659
+ p[nalign-1][1]=_ur_pos[1];
2660
+ q[(nalign-1)*nalign][0]=3;
2661
+ q[(nalign-1)*nalign][1]=dim-4;
2662
+ p[(nalign-1)*nalign][0]=_dl_pos[0];
2663
+ p[(nalign-1)*nalign][1]=_dl_pos[1];
2664
+ /*Scan for alignment patterns using a diagonal sweep.*/
2665
+ for(k=1;k<2*nalign-1;k++){
2666
+ int jmin;
2667
+ int jmax;
2668
+ jmax=QR_MINI(k,nalign-1)-(k==nalign-1);
2669
+ jmin=QR_MAXI(0,k-(nalign-1))+(k==nalign-1);
2670
+ for(j=jmin;j<=jmax;j++){
2671
+ qr_hom_cell *cell;
2672
+ int u;
2673
+ int v;
2674
+ int k;
2675
+ i=jmax-(j-jmin);
2676
+ k=i*nalign+j;
2677
+ u=align_pos[j];
2678
+ v=align_pos[i];
2679
+ q[k][0]=u;
2680
+ q[k][1]=v;
2681
+ /*Mask out the alignment pattern.*/
2682
+ qr_sampling_grid_fp_mask_rect(_grid,dim,u-2,v-2,5,5);
2683
+ /*Pick a cell to use to govern the alignment pattern search.*/
2684
+ if(i>1&&j>1){
2685
+ qr_point p0;
2686
+ qr_point p1;
2687
+ qr_point p2;
2688
+ /*Each predictor is basically a straight-line extrapolation from two
2689
+ neighboring alignment patterns (except possibly near the opposing
2690
+ finder patterns).*/
2691
+ qr_hom_cell_project(p0,_grid->cells[i-2]+j-1,u,v,0);
2692
+ qr_hom_cell_project(p1,_grid->cells[i-2]+j-2,u,v,0);
2693
+ qr_hom_cell_project(p2,_grid->cells[i-1]+j-2,u,v,0);
2694
+ /*Take the median of the predictions as the search center.*/
2695
+ QR_SORT2I(p0[0],p1[0]);
2696
+ QR_SORT2I(p0[1],p1[1]);
2697
+ QR_SORT2I(p1[0],p2[0]);
2698
+ QR_SORT2I(p1[1],p2[1]);
2699
+ QR_SORT2I(p0[0],p1[0]);
2700
+ QR_SORT2I(p0[1],p1[1]);
2701
+ /*We need a cell that has the target point at a known (u,v) location.
2702
+ Since our cells don't have inverses, just construct one from our
2703
+ neighboring points.*/
2704
+ cell=_grid->cells[i-1]+j-1;
2705
+ qr_hom_cell_init(cell,
2706
+ q[k-nalign-1][0],q[k-nalign-1][1],q[k-nalign][0],q[k-nalign][1],
2707
+ q[k-1][0],q[k-1][1],q[k][0],q[k][1],
2708
+ p[k-nalign-1][0],p[k-nalign-1][1],p[k-nalign][0],p[k-nalign][1],
2709
+ p[k-1][0],p[k-1][1],p1[0],p1[1]);
2710
+ }
2711
+ else if(i>1&&j>0)cell=_grid->cells[i-2]+j-1;
2712
+ else if(i>0&&j>1)cell=_grid->cells[i-1]+j-2;
2713
+ else cell=&base_cell;
2714
+ /*Use a very small search radius.
2715
+ A large displacement here usually means a false positive (e.g., when
2716
+ the real alignment pattern is damaged or missing), which can
2717
+ severely distort the projection.*/
2718
+ qr_alignment_pattern_search(p[k],cell,u,v,2,_img,_width,_height);
2719
+ if(i>0&&j>0){
2720
+ qr_hom_cell_init(_grid->cells[i-1]+j-1,
2721
+ q[k-nalign-1][0],q[k-nalign-1][1],q[k-nalign][0],q[k-nalign][1],
2722
+ q[k-1][0],q[k-1][1],q[k][0],q[k][1],
2723
+ p[k-nalign-1][0],p[k-nalign-1][1],p[k-nalign][0],p[k-nalign][1],
2724
+ p[k-1][0],p[k-1][1],p[k][0],p[k][1]);
2725
+ }
2726
+ }
2727
+ }
2728
+ qr_svg_points("align", p, nalign * nalign);
2729
+ free(q);
2730
+ free(p);
2731
+ }
2732
+ /*Set the limits over which each cell is used.*/
2733
+ memcpy(_grid->cell_limits,align_pos+1,
2734
+ (_grid->ncells-1)*sizeof(*_grid->cell_limits));
2735
+ _grid->cell_limits[_grid->ncells-1]=dim;
2736
+ /*Produce a bounding square for the code (to mark finder centers with).
2737
+ Because of non-linear distortion, this might not actually bound the code,
2738
+ but it should be good enough.
2739
+ I don't think it's worth computing a convex hull or anything silly like
2740
+ that.*/
2741
+ qr_hom_cell_project(_p[0],_grid->cells[0]+0,-1,-1,1);
2742
+ qr_hom_cell_project(_p[1],_grid->cells[0]+_grid->ncells-1,(dim<<1)-1,-1,1);
2743
+ qr_hom_cell_project(_p[2],_grid->cells[_grid->ncells-1]+0,-1,(dim<<1)-1,1);
2744
+ qr_hom_cell_project(_p[3],_grid->cells[_grid->ncells-1]+_grid->ncells-1,
2745
+ (dim<<1)-1,(dim<<1)-1,1);
2746
+ /*Clamp the points somewhere near the image (this is really just in case a
2747
+ corner is near the plane at infinity).*/
2748
+ for(i=0;i<4;i++){
2749
+ _p[i][0]=QR_CLAMPI(-_width<<QR_FINDER_SUBPREC,_p[i][0],
2750
+ _width<<QR_FINDER_SUBPREC+1);
2751
+ _p[i][1]=QR_CLAMPI(-_height<<QR_FINDER_SUBPREC,_p[i][1],
2752
+ _height<<QR_FINDER_SUBPREC+1);
2753
+ }
2754
+ /*TODO: Make fine adjustments using the timing patterns.
2755
+ Possible strategy: scan the timing pattern at QR_ALIGN_SUBPREC (or finer)
2756
+ resolution, use dynamic programming to match midpoints between
2757
+ transitions to the ideal grid locations.*/
2758
+ }
2759
+
2760
+ static void qr_sampling_grid_clear(qr_sampling_grid *_grid){
2761
+ free(_grid->fpmask);
2762
+ free(_grid->cells[0]);
2763
+ }
2764
+
2765
+
2766
+
2767
+ #if defined(QR_DEBUG)
2768
+ static void qr_sampling_grid_dump(qr_sampling_grid *_grid,int _version,
2769
+ const unsigned char *_img,int _width,int _height){
2770
+ unsigned char *gimg;
2771
+ FILE *fout;
2772
+ int dim;
2773
+ int u;
2774
+ int v;
2775
+ int x;
2776
+ int y;
2777
+ int w;
2778
+ int i;
2779
+ int j;
2780
+ int r;
2781
+ int s;
2782
+ dim=17+(_version<<2)+8<<QR_ALIGN_SUBPREC;
2783
+ gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
2784
+ for(i=0;i<dim;i++)for(j=0;j<dim;j++){
2785
+ qr_hom_cell *cell;
2786
+ if(i>=(4<<QR_ALIGN_SUBPREC)&&i<=dim-(5<<QR_ALIGN_SUBPREC)&&
2787
+ j>=(4<<QR_ALIGN_SUBPREC)&&j<=dim-(5<<QR_ALIGN_SUBPREC)&&
2788
+ ((!(i&(1<<QR_ALIGN_SUBPREC)-1))^(!(j&(1<<QR_ALIGN_SUBPREC)-1)))){
2789
+ gimg[i*dim+j]=0x7F;
2790
+ }
2791
+ else{
2792
+ qr_point p;
2793
+ u=(j>>QR_ALIGN_SUBPREC)-4;
2794
+ v=(i>>QR_ALIGN_SUBPREC)-4;
2795
+ for(r=0;r<_grid->ncells-1;r++)if(u<_grid->cell_limits[r])break;
2796
+ for(s=0;s<_grid->ncells-1;s++)if(v<_grid->cell_limits[s])break;
2797
+ cell=_grid->cells[s]+r;
2798
+ u=j-(cell->u0+4<<QR_ALIGN_SUBPREC);
2799
+ v=i-(cell->v0+4<<QR_ALIGN_SUBPREC);
2800
+ x=cell->fwd[0][0]*u+cell->fwd[0][1]*v+(cell->fwd[0][2]<<QR_ALIGN_SUBPREC);
2801
+ y=cell->fwd[1][0]*u+cell->fwd[1][1]*v+(cell->fwd[1][2]<<QR_ALIGN_SUBPREC);
2802
+ w=cell->fwd[2][0]*u+cell->fwd[2][1]*v+(cell->fwd[2][2]<<QR_ALIGN_SUBPREC);
2803
+ qr_hom_cell_fproject(p,cell,x,y,w);
2804
+ gimg[i*dim+j]=_img[
2805
+ QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
2806
+ QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
2807
+ }
2808
+ }
2809
+ for(v=0;v<17+(_version<<2);v++)for(u=0;u<17+(_version<<2);u++){
2810
+ if(qr_sampling_grid_is_in_fp(_grid,17+(_version<<2),u,v)){
2811
+ j=u+4<<QR_ALIGN_SUBPREC;
2812
+ i=v+4<<QR_ALIGN_SUBPREC;
2813
+ gimg[(i-1)*dim+j-1]=0x7F;
2814
+ gimg[(i-1)*dim+j]=0x7F;
2815
+ gimg[(i-1)*dim+j+1]=0x7F;
2816
+ gimg[i*dim+j-1]=0x7F;
2817
+ gimg[i*dim+j+1]=0x7F;
2818
+ gimg[(i+1)*dim+j-1]=0x7F;
2819
+ gimg[(i+1)*dim+j]=0x7F;
2820
+ gimg[(i+1)*dim+j+1]=0x7F;
2821
+ }
2822
+ }
2823
+ fout=fopen("grid.png","wb");
2824
+ image_write_png(gimg,dim,dim,fout);
2825
+ fclose(fout);
2826
+ free(gimg);
2827
+ }
2828
+ #endif
2829
+
2830
+ /*Generate the data mask corresponding to the given mask pattern.*/
2831
+ static void qr_data_mask_fill(unsigned *_mask,int _dim,int _pattern){
2832
+ int stride;
2833
+ int i;
2834
+ int j;
2835
+ stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
2836
+ /*Note that we store bits column-wise, since that's how they're read out of
2837
+ the grid.*/
2838
+ switch(_pattern){
2839
+ /*10101010 i+j+1&1
2840
+ 01010101
2841
+ 10101010
2842
+ 01010101*/
2843
+ case 0:{
2844
+ int m;
2845
+ m=0x55;
2846
+ for(j=0;j<_dim;j++){
2847
+ memset(_mask+j*stride,m,stride*sizeof(*_mask));
2848
+ m^=0xFF;
2849
+ }
2850
+ }break;
2851
+ /*11111111 i+1&1
2852
+ 00000000
2853
+ 11111111
2854
+ 00000000*/
2855
+ case 1:memset(_mask,0x55,_dim*stride*sizeof(*_mask));break;
2856
+ /*10010010 (j+1)%3&1
2857
+ 10010010
2858
+ 10010010
2859
+ 10010010*/
2860
+ case 2:{
2861
+ unsigned m;
2862
+ m=0xFF;
2863
+ for(j=0;j<_dim;j++){
2864
+ memset(_mask+j*stride,m&0xFF,stride*sizeof(*_mask));
2865
+ m=m<<8|m>>16;
2866
+ }
2867
+ }break;
2868
+ /*10010010 (i+j+1)%3&1
2869
+ 00100100
2870
+ 01001001
2871
+ 10010010*/
2872
+ case 3:{
2873
+ unsigned mi;
2874
+ unsigned mj;
2875
+ mj=0;
2876
+ for(i=0;i<(QR_INT_BITS+2)/3;i++)mj|=1<<3*i;
2877
+ for(j=0;j<_dim;j++){
2878
+ mi=mj;
2879
+ for(i=0;i<stride;i++){
2880
+ _mask[j*stride+i]=mi;
2881
+ mi=mi>>QR_INT_BITS%3|mi<<3-QR_INT_BITS%3;
2882
+ }
2883
+ mj=mj>>1|mj<<2;
2884
+ }
2885
+ }break;
2886
+ /*11100011 (i>>1)+(j/3)+1&1
2887
+ 11100011
2888
+ 00011100
2889
+ 00011100*/
2890
+ case 4:{
2891
+ unsigned m;
2892
+ m=7;
2893
+ for(j=0;j<_dim;j++){
2894
+ memset(_mask+j*stride,(0xCC^-(m&1))&0xFF,stride*sizeof(*_mask));
2895
+ m=m>>1|m<<5;
2896
+ }
2897
+ }break;
2898
+ /*11111111 !((i*j)%6)
2899
+ 10000010
2900
+ 10010010
2901
+ 10101010*/
2902
+ case 5:{
2903
+ for(j=0;j<_dim;j++){
2904
+ unsigned m;
2905
+ m=0;
2906
+ for(i=0;i<6;i++)m|=!((i*j)%6)<<i;
2907
+ for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
2908
+ for(i=0;i<stride;i++){
2909
+ _mask[j*stride+i]=m;
2910
+ m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
2911
+ }
2912
+ }
2913
+ }break;
2914
+ /*11111111 (i*j)%3+i*j+1&1
2915
+ 11100011
2916
+ 11011011
2917
+ 10101010*/
2918
+ case 6:{
2919
+ for(j=0;j<_dim;j++){
2920
+ unsigned m;
2921
+ m=0;
2922
+ for(i=0;i<6;i++)m|=((i*j)%3+i*j+1&1)<<i;
2923
+ for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
2924
+ for(i=0;i<stride;i++){
2925
+ _mask[j*stride+i]=m;
2926
+ m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
2927
+ }
2928
+ }
2929
+ }break;
2930
+ /*10101010 (i*j)%3+i+j+1&1
2931
+ 00011100
2932
+ 10001110
2933
+ 01010101*/
2934
+ default:{
2935
+ for(j=0;j<_dim;j++){
2936
+ unsigned m;
2937
+ m=0;
2938
+ for(i=0;i<6;i++)m|=((i*j)%3+i+j+1&1)<<i;
2939
+ for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
2940
+ for(i=0;i<stride;i++){
2941
+ _mask[j*stride+i]=m;
2942
+ m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
2943
+ }
2944
+ }
2945
+ }break;
2946
+ }
2947
+ }
2948
+
2949
+ static void qr_sampling_grid_sample(const qr_sampling_grid *_grid,
2950
+ unsigned *_data_bits,int _dim,int _fmt_info,
2951
+ const unsigned char *_img,int _width,int _height){
2952
+ int stride;
2953
+ int u0;
2954
+ int u1;
2955
+ int j;
2956
+ /*We initialize the buffer with the data mask and XOR bits into it as we read
2957
+ them out of the image instead of unmasking in a separate step.*/
2958
+ qr_data_mask_fill(_data_bits,_dim,_fmt_info&7);
2959
+ stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
2960
+ u0=0;
2961
+ svg_path_start("sampling-grid", 1, 0, 0);
2962
+ /*We read data cell-by-cell to avoid having to constantly change which
2963
+ projection we're using as we read each bit.
2964
+ This (and the position-dependent data mask) is the reason we buffer the
2965
+ bits we read instead of converting them directly to codewords here.
2966
+ Note that bits are stored column-wise, since that's how we'll scan them.*/
2967
+ for(j=0;j<_grid->ncells;j++){
2968
+ int i;
2969
+ int v0;
2970
+ int v1;
2971
+ u1=_grid->cell_limits[j];
2972
+ v0=0;
2973
+ for(i=0;i<_grid->ncells;i++){
2974
+ qr_hom_cell *cell;
2975
+ int x0;
2976
+ int y0;
2977
+ int w0;
2978
+ int u;
2979
+ int du;
2980
+ int dv;
2981
+ v1=_grid->cell_limits[i];
2982
+ cell=_grid->cells[i]+j;
2983
+ du=u0-cell->u0;
2984
+ dv=v0-cell->v0;
2985
+ x0=cell->fwd[0][0]*du+cell->fwd[0][1]*dv+cell->fwd[0][2];
2986
+ y0=cell->fwd[1][0]*du+cell->fwd[1][1]*dv+cell->fwd[1][2];
2987
+ w0=cell->fwd[2][0]*du+cell->fwd[2][1]*dv+cell->fwd[2][2];
2988
+ for(u=u0;u<u1;u++){
2989
+ int x;
2990
+ int y;
2991
+ int w;
2992
+ int v;
2993
+ x=x0;
2994
+ y=y0;
2995
+ w=w0;
2996
+ for(v=v0;v<v1;v++){
2997
+ /*Skip doing all the divisions and bounds checks if the bit is in the
2998
+ function pattern.*/
2999
+ if(!qr_sampling_grid_is_in_fp(_grid,_dim,u,v)){
3000
+ qr_point p;
3001
+ qr_hom_cell_fproject(p,cell,x,y,w);
3002
+ _data_bits[u*stride+(v>>QR_INT_LOGBITS)]^=
3003
+ qr_img_get_bit(_img,_width,_height,p[0],p[1])<<(v&QR_INT_BITS-1);
3004
+ svg_path_moveto(SVG_ABS, p[0], p[1]);
3005
+ }
3006
+ x+=cell->fwd[0][1];
3007
+ y+=cell->fwd[1][1];
3008
+ w+=cell->fwd[2][1];
3009
+ }
3010
+ x0+=cell->fwd[0][0];
3011
+ y0+=cell->fwd[1][0];
3012
+ w0+=cell->fwd[2][0];
3013
+ }
3014
+ v0=v1;
3015
+ }
3016
+ u0=u1;
3017
+ }
3018
+ svg_path_end();
3019
+ }
3020
+
3021
+ /*Arranges the sample bits read by qr_sampling_grid_sample() into bytes and
3022
+ groups those bytes into Reed-Solomon blocks.
3023
+ The individual block pointers are destroyed by this routine.*/
3024
+ static void qr_samples_unpack(unsigned char **_blocks,int _nblocks,
3025
+ int _nshort_data,int _nshort_blocks,const unsigned *_data_bits,
3026
+ const unsigned *_fp_mask,int _dim){
3027
+ unsigned bits;
3028
+ int biti;
3029
+ int stride;
3030
+ int blocki;
3031
+ int blockj;
3032
+ int i;
3033
+ int j;
3034
+ stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
3035
+ /*If _all_ the blocks are short, don't skip anything (see below).*/
3036
+ if(_nshort_blocks>=_nblocks)_nshort_blocks=0;
3037
+ /*Scan columns in pairs from right to left.*/
3038
+ bits=0;
3039
+ for(blocki=blockj=biti=0,j=_dim-1;j>0;j-=2){
3040
+ unsigned data1;
3041
+ unsigned data2;
3042
+ unsigned fp_mask1;
3043
+ unsigned fp_mask2;
3044
+ int nbits;
3045
+ int l;
3046
+ /*Scan up a pair of columns.*/
3047
+ nbits=(_dim-1&QR_INT_BITS-1)+1;
3048
+ l=j*stride;
3049
+ for(i=stride;i-->0;){
3050
+ data1=_data_bits[l+i];
3051
+ fp_mask1=_fp_mask[l+i];
3052
+ data2=_data_bits[l+i-stride];
3053
+ fp_mask2=_fp_mask[l+i-stride];
3054
+ while(nbits-->0){
3055
+ /*Pull a bit from the right column.*/
3056
+ if(!(fp_mask1>>nbits&1)){
3057
+ bits=bits<<1|data1>>nbits&1;
3058
+ biti++;
3059
+ }
3060
+ /*Pull a bit from the left column.*/
3061
+ if(!(fp_mask2>>nbits&1)){
3062
+ bits=bits<<1|data2>>nbits&1;
3063
+ biti++;
3064
+ }
3065
+ /*If we finished a byte, drop it in a block.*/
3066
+ if(biti>=8){
3067
+ biti-=8;
3068
+ *_blocks[blocki++]++=(unsigned char)(bits>>biti);
3069
+ /*For whatever reason, the long blocks are at the _end_ of the list,
3070
+ instead of the beginning.
3071
+ Even worse, the extra bytes they get come at the end of the data
3072
+ bytes, before the parity bytes.
3073
+ Hence the logic here: when we've filled up the data portion of the
3074
+ short blocks, skip directly to the long blocks for the next byte.
3075
+ It's also the reason we increment _blocks[blocki] on each store,
3076
+ instead of just indexing with blockj (after this iteration the
3077
+ number of bytes in each block differs).*/
3078
+ if(blocki>=_nblocks)blocki=++blockj==_nshort_data?_nshort_blocks:0;
3079
+ }
3080
+ }
3081
+ nbits=QR_INT_BITS;
3082
+ }
3083
+ j-=2;
3084
+ /*Skip the column with the vertical timing pattern.*/
3085
+ if(j==6)j--;
3086
+ /*Scan down a pair of columns.*/
3087
+ l=j*stride;
3088
+ for(i=0;i<stride;i++){
3089
+ data1=_data_bits[l+i];
3090
+ fp_mask1=_fp_mask[l+i];
3091
+ data2=_data_bits[l+i-stride];
3092
+ fp_mask2=_fp_mask[l+i-stride];
3093
+ nbits=QR_MINI(_dim-(i<<QR_INT_LOGBITS),QR_INT_BITS);
3094
+ while(nbits-->0){
3095
+ /*Pull a bit from the right column.*/
3096
+ if(!(fp_mask1&1)){
3097
+ bits=bits<<1|data1&1;
3098
+ biti++;
3099
+ }
3100
+ data1>>=1;
3101
+ fp_mask1>>=1;
3102
+ /*Pull a bit from the left column.*/
3103
+ if(!(fp_mask2&1)){
3104
+ bits=bits<<1|data2&1;
3105
+ biti++;
3106
+ }
3107
+ data2>>=1;
3108
+ fp_mask2>>=1;
3109
+ /*If we finished a byte, drop it in a block.*/
3110
+ if(biti>=8){
3111
+ biti-=8;
3112
+ *_blocks[blocki++]++=(unsigned char)(bits>>biti);
3113
+ /*See comments on the "up" loop for the reason behind this mess.*/
3114
+ if(blocki>=_nblocks)blocki=++blockj==_nshort_data?_nshort_blocks:0;
3115
+ }
3116
+ }
3117
+ }
3118
+ }
3119
+ }
3120
+
3121
+
3122
+ /*Bit reading code blatantly stolen^W^Wadapted from libogg/libtheora (because
3123
+ I've already debugged it and I know it works).
3124
+ Portions (C) Xiph.Org Foundation 1994-2008, BSD-style license.*/
3125
+ struct qr_pack_buf{
3126
+ const unsigned char *buf;
3127
+ int endbyte;
3128
+ int endbit;
3129
+ int storage;
3130
+ };
3131
+
3132
+
3133
+ static void qr_pack_buf_init(qr_pack_buf *_b,
3134
+ const unsigned char *_data,int _ndata){
3135
+ _b->buf=_data;
3136
+ _b->storage=_ndata;
3137
+ _b->endbyte=_b->endbit=0;
3138
+ }
3139
+
3140
+ /*Assumes 0<=_bits<=16.*/
3141
+ static int qr_pack_buf_read(qr_pack_buf *_b,int _bits){
3142
+ const unsigned char *p;
3143
+ unsigned ret;
3144
+ int m;
3145
+ int d;
3146
+ m=16-_bits;
3147
+ _bits+=_b->endbit;
3148
+ d=_b->storage-_b->endbyte;
3149
+ if(d<=2){
3150
+ /*Not the main path.*/
3151
+ if(d*8<_bits){
3152
+ _b->endbyte+=_bits>>3;
3153
+ _b->endbit=_bits&7;
3154
+ return -1;
3155
+ }
3156
+ /*Special case to avoid reading p[0] below, which might be past the end of
3157
+ the buffer; also skips some useless accounting.*/
3158
+ else if(!_bits)return 0;
3159
+ }
3160
+ p=_b->buf+_b->endbyte;
3161
+ ret=p[0]<<8+_b->endbit;
3162
+ if(_bits>8){
3163
+ ret|=p[1]<<_b->endbit;
3164
+ if(_bits>16)ret|=p[2]>>8-_b->endbit;
3165
+ }
3166
+ _b->endbyte+=_bits>>3;
3167
+ _b->endbit=_bits&7;
3168
+ return (ret&0xFFFF)>>m;
3169
+ }
3170
+
3171
+ static int qr_pack_buf_avail(const qr_pack_buf *_b){
3172
+ return (_b->storage-_b->endbyte<<3)-_b->endbit;
3173
+ }
3174
+
3175
+
3176
+ /*The characters available in QR_MODE_ALNUM.*/
3177
+ static const unsigned char QR_ALNUM_TABLE[45]={
3178
+ '0','1','2','3','4','5','6','7','8','9',
3179
+ 'A','B','C','D','E','F','G','H','I','J',
3180
+ 'K','L','M','N','O','P','Q','R','S','T',
3181
+ 'U','V','W','X','Y','Z',' ','$','%','*',
3182
+ '+','-','.','/',':'
3183
+ };
3184
+
3185
+ static int qr_code_data_parse(qr_code_data *_qrdata,int _version,
3186
+ const unsigned char *_data,int _ndata){
3187
+ qr_pack_buf qpb;
3188
+ int centries;
3189
+ int len_bits_idx;
3190
+ /*Entries are stored directly in the struct during parsing.
3191
+ Caller cleans up any allocated data on failure.*/
3192
+ _qrdata->entries=NULL;
3193
+ _qrdata->nentries=0;
3194
+ _qrdata->sa_size=0;
3195
+ centries=0;
3196
+ /*The versions are divided into 3 ranges that each use a different number of
3197
+ bits for length fields.*/
3198
+ len_bits_idx=(_version>9)+(_version>26);
3199
+ qr_pack_buf_init(&qpb,_data,_ndata);
3200
+ /*While we have enough bits to read a mode...*/
3201
+ while(qr_pack_buf_avail(&qpb)>=4){
3202
+ qr_code_data_entry *entry;
3203
+ int mode;
3204
+ mode=qr_pack_buf_read(&qpb,4);
3205
+ /*Mode 0 is a terminator.*/
3206
+ if(!mode)break;
3207
+ if(_qrdata->nentries>=centries){
3208
+ centries=centries<<1|1;
3209
+ _qrdata->entries=(qr_code_data_entry *)realloc(_qrdata->entries,
3210
+ centries*sizeof(*_qrdata->entries));
3211
+ }
3212
+ entry=_qrdata->entries+_qrdata->nentries++;
3213
+ /*Set the mode to an invalid value until we allocate a buffer for it.
3214
+ This ensures we don't try to free it on clean-up until then.*/
3215
+ entry->mode=-1;
3216
+ switch(mode){
3217
+ /*The number of bits used to encode the character count for each version
3218
+ range and each data mode.*/
3219
+ static const unsigned char LEN_BITS[3][4]={
3220
+ {10, 9, 8, 8},
3221
+ {12,11,16,10},
3222
+ {14,13,16,12}
3223
+ };
3224
+ case QR_MODE_NUM:{
3225
+ unsigned char *buf;
3226
+ unsigned bits;
3227
+ int len;
3228
+ int count;
3229
+ int rem;
3230
+ len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][0]);
3231
+ if(len<0)return -1;
3232
+ /*Check to see if there are enough bits left now, so we don't have to
3233
+ in the decode loop.*/
3234
+ count=len/3;
3235
+ rem=len%3;
3236
+ if(qr_pack_buf_avail(&qpb)<10*count+7*(rem>>1&1)+4*(rem&1))return -1;
3237
+ entry->mode=mode;
3238
+ entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
3239
+ entry->payload.data.len=len;
3240
+ /*Read groups of 3 digits encoded in 10 bits.*/
3241
+ while(count-->0){
3242
+ bits=qr_pack_buf_read(&qpb,10);
3243
+ if(bits>=1000)return -1;
3244
+ *buf++=(unsigned char)('0'+bits/100);
3245
+ bits%=100;
3246
+ *buf++=(unsigned char)('0'+bits/10);
3247
+ *buf++=(unsigned char)('0'+bits%10);
3248
+ }
3249
+ /*Read the last two digits encoded in 7 bits.*/
3250
+ if(rem>1){
3251
+ bits=qr_pack_buf_read(&qpb,7);
3252
+ if(bits>=100)return -1;
3253
+ *buf++=(unsigned char)('0'+bits/10);
3254
+ *buf++=(unsigned char)('0'+bits%10);
3255
+ }
3256
+ /*Or the last one digit encoded in 4 bits.*/
3257
+ else if(rem){
3258
+ bits=qr_pack_buf_read(&qpb,4);
3259
+ if(bits>=10)return -1;
3260
+ *buf++=(unsigned char)('0'+bits);
3261
+ }
3262
+ }break;
3263
+ case QR_MODE_ALNUM:{
3264
+ unsigned char *buf;
3265
+ unsigned bits;
3266
+ int len;
3267
+ int count;
3268
+ int rem;
3269
+ len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][1]);
3270
+ if(len<0)return -1;
3271
+ /*Check to see if there are enough bits left now, so we don't have to
3272
+ in the decode loop.*/
3273
+ count=len>>1;
3274
+ rem=len&1;
3275
+ if(qr_pack_buf_avail(&qpb)<11*count+6*rem)return -1;
3276
+ entry->mode=mode;
3277
+ entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
3278
+ entry->payload.data.len=len;
3279
+ /*Read groups of two characters encoded in 11 bits.*/
3280
+ while(count-->0){
3281
+ bits=qr_pack_buf_read(&qpb,11);
3282
+ if(bits>=2025)return -1;
3283
+ *buf++=QR_ALNUM_TABLE[bits/45];
3284
+ *buf++=QR_ALNUM_TABLE[bits%45];
3285
+ len-=2;
3286
+ }
3287
+ /*Read the last character encoded in 6 bits.*/
3288
+ if(rem){
3289
+ bits=qr_pack_buf_read(&qpb,6);
3290
+ if(bits>=45)return -1;
3291
+ *buf++=QR_ALNUM_TABLE[bits];
3292
+ }
3293
+ }break;
3294
+ /*Structured-append header.*/
3295
+ case QR_MODE_STRUCT:{
3296
+ int bits;
3297
+ entry->mode=mode;
3298
+ bits=qr_pack_buf_read(&qpb,16);
3299
+ if(bits<0)return -1;
3300
+ /*We also save a copy of the data in _qrdata for easy reference when
3301
+ grouping structured-append codes.
3302
+ If for some reason the code has multiple S-A headers, last one wins
3303
+ (TODO: should we return an error instead?).*/
3304
+ _qrdata->sa_index=entry->payload.sa.sa_index=
3305
+ (unsigned char)(bits>>12&0xF);
3306
+ _qrdata->sa_size=entry->payload.sa.sa_size=
3307
+ (unsigned char)((bits>>8&0xF)+1);
3308
+ _qrdata->sa_parity=entry->payload.sa.sa_parity=
3309
+ (unsigned char)(bits&0xFF);
3310
+ }break;
3311
+ case QR_MODE_BYTE:{
3312
+ unsigned char *buf;
3313
+ int len;
3314
+ len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][2]);
3315
+ if(len<0)return -1;
3316
+ /*Check to see if there are enough bits left now, so we don't have to
3317
+ in the decode loop.*/
3318
+ if(qr_pack_buf_avail(&qpb)<len<<3)return -1;
3319
+ entry->mode=mode;
3320
+ entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
3321
+ entry->payload.data.len=len;
3322
+ while(len-->0)*buf++=(unsigned char)qr_pack_buf_read(&qpb,8);
3323
+ }break;
3324
+ /*FNC1 first position marker.*/
3325
+ case QR_MODE_FNC1_1ST:entry->mode=mode;break;
3326
+ /*Extended Channel Interpretation data.*/
3327
+ case QR_MODE_ECI:{
3328
+ unsigned val;
3329
+ int bits;
3330
+ /*ECI uses a variable-width encoding similar to UTF-8*/
3331
+ bits=qr_pack_buf_read(&qpb,8);
3332
+ if(bits<0)return -1;
3333
+ /*One byte:*/
3334
+ if(!(bits&0x80))val=bits;
3335
+ /*Two bytes:*/
3336
+ else if(!(bits&0x40)){
3337
+ val=bits&0x3F<<8;
3338
+ bits=qr_pack_buf_read(&qpb,8);
3339
+ if(bits<0)return -1;
3340
+ val|=bits;
3341
+ }
3342
+ /*Three bytes:*/
3343
+ else if(!(bits&0x20)){
3344
+ val=bits&0x1F<<16;
3345
+ bits=qr_pack_buf_read(&qpb,16);
3346
+ if(bits<0)return -1;
3347
+ val|=bits;
3348
+ /*Valid ECI values are 0...999999.*/
3349
+ if(val>=1000000)return -1;
3350
+ }
3351
+ /*Invalid lead byte.*/
3352
+ else return -1;
3353
+ entry->mode=mode;
3354
+ entry->payload.eci=val;
3355
+ }break;
3356
+ case QR_MODE_KANJI:{
3357
+ unsigned char *buf;
3358
+ unsigned bits;
3359
+ int len;
3360
+ len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][3]);
3361
+ if(len<0)return -1;
3362
+ /*Check to see if there are enough bits left now, so we don't have to
3363
+ in the decode loop.*/
3364
+ if(qr_pack_buf_avail(&qpb)<13*len)return -1;
3365
+ entry->mode=mode;
3366
+ entry->payload.data.buf=buf=(unsigned char *)malloc(2*len*sizeof(*buf));
3367
+ entry->payload.data.len=2*len;
3368
+ /*Decode 2-byte SJIS characters encoded in 13 bits.*/
3369
+ while(len-->0){
3370
+ bits=qr_pack_buf_read(&qpb,13);
3371
+ bits=(bits/0xC0<<8|bits%0xC0)+0x8140;
3372
+ if(bits>=0xA000)bits+=0x4000;
3373
+ /*Are values 0xXX7F, 0xXXFD...0xXXFF always invalid?
3374
+ Should we reject them here?*/
3375
+ *buf++=(unsigned char)(bits>>8);
3376
+ *buf++=(unsigned char)(bits&0xFF);
3377
+ }
3378
+ }break;
3379
+ /*FNC1 second position marker.*/
3380
+ case QR_MODE_FNC1_2ND:entry->mode=mode;break;
3381
+ /*Unknown mode number:*/
3382
+ default:{
3383
+ /*Unfortunately, because we have to understand the format of a mode to
3384
+ know how many bits it occupies, we can't skip unknown modes.
3385
+ Therefore we have to fail.*/
3386
+ return -1;
3387
+ }break;
3388
+ }
3389
+ }
3390
+ /*TODO: If there was a S-A header, we should compute the parity of this
3391
+ code; how are non-data modes handled (ECI, FNC1)?*/
3392
+ _qrdata->self_parity=0;
3393
+ /*Success.*/
3394
+ _qrdata->entries=(qr_code_data_entry *)realloc(_qrdata->entries,
3395
+ _qrdata->nentries*sizeof(*_qrdata->entries));
3396
+ return 0;
3397
+ }
3398
+
3399
+ static void qr_code_data_clear(qr_code_data *_qrdata){
3400
+ int i;
3401
+ for(i=0;i<_qrdata->nentries;i++){
3402
+ if(QR_MODE_HAS_DATA(_qrdata->entries[i].mode)){
3403
+ free(_qrdata->entries[i].payload.data.buf);
3404
+ }
3405
+ }
3406
+ free(_qrdata->entries);
3407
+ }
3408
+
3409
+
3410
+ void qr_code_data_list_init(qr_code_data_list *_qrlist){
3411
+ _qrlist->qrdata=NULL;
3412
+ _qrlist->nqrdata=_qrlist->cqrdata=0;
3413
+ }
3414
+
3415
+ void qr_code_data_list_clear(qr_code_data_list *_qrlist){
3416
+ int i;
3417
+ for(i=0;i<_qrlist->nqrdata;i++)qr_code_data_clear(_qrlist->qrdata+i);
3418
+ free(_qrlist->qrdata);
3419
+ qr_code_data_list_init(_qrlist);
3420
+ }
3421
+
3422
+ static void qr_code_data_list_add(qr_code_data_list *_qrlist,
3423
+ qr_code_data *_qrdata){
3424
+ if(_qrlist->nqrdata>=_qrlist->cqrdata){
3425
+ _qrlist->cqrdata=_qrlist->cqrdata<<1|1;
3426
+ _qrlist->qrdata=(qr_code_data *)realloc(_qrlist->qrdata,
3427
+ _qrlist->cqrdata*sizeof(*_qrlist->qrdata));
3428
+ }
3429
+ memcpy(_qrlist->qrdata+_qrlist->nqrdata++,_qrdata,sizeof(*_qrdata));
3430
+ }
3431
+
3432
+ #if 0
3433
+ static const unsigned short QR_NCODEWORDS[40]={
3434
+ 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
3435
+ 404, 466, 532, 581, 655, 733, 815, 901, 991,1085,
3436
+ 1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,
3437
+ 2323,2465,2611,2761,2876,3034,3196,3362,3532,3706
3438
+ };
3439
+ #endif
3440
+
3441
+ /*The total number of codewords in a QR code.*/
3442
+ static int qr_code_ncodewords(unsigned _version){
3443
+ unsigned nalign;
3444
+ /*This is 24-27 instructions on ARM in thumb mode, or a 26-32 byte savings
3445
+ over just using a table (not counting the instructions that would be
3446
+ needed to do the table lookup).*/
3447
+ if(_version==1)return 26;
3448
+ nalign=(_version/7)+2;
3449
+ return (_version<<4)*(_version+8)
3450
+ -(5*nalign)*(5*nalign-2)+36*(_version<7)+83>>3;
3451
+ }
3452
+
3453
+ #if 0
3454
+ /*The number of parity bytes per Reed-Solomon block for each version and error
3455
+ correction level.*/
3456
+ static const unsigned char QR_RS_NPAR[40][4]={
3457
+ { 7,10,13,17},{10,16,22,28},{15,26,18,22},{20,18,26,16},
3458
+ {26,24,18,22},{18,16,24,28},{20,18,18,26},{24,22,22,26},
3459
+ {30,22,20,24},{18,26,24,28},{20,30,28,24},{24,22,26,28},
3460
+ {26,22,24,22},{30,24,20,24},{22,24,30,24},{24,28,24,30},
3461
+ {28,28,28,28},{30,26,28,28},{28,26,26,26},{28,26,30,28},
3462
+ {28,26,28,30},{28,28,30,24},{30,28,30,30},{30,28,30,30},
3463
+ {26,28,30,30},{28,28,28,30},{30,28,30,30},{30,28,30,30},
3464
+ {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30},
3465
+ {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30},
3466
+ {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30}
3467
+ };
3468
+ #endif
3469
+
3470
+ /*Bulk data for the number of parity bytes per Reed-Solomon block.*/
3471
+ static const unsigned char QR_RS_NPAR_VALS[71]={
3472
+ /*[ 0]*/ 7,10,13,17,
3473
+ /*[ 4]*/10,16,22, 28,26,26, 26,22, 24,22,22, 26,24,18,22,
3474
+ /*[19]*/15,26,18, 22,24, 30,24,20,24,
3475
+ /*[28]*/18,16,24, 28, 28, 28,28,30,24,
3476
+ /*[37]*/20,18, 18,26, 24,28,24, 30,26,28, 28, 26,28,30, 30,22,20,24,
3477
+ /*[55]*/20,18,26,16,
3478
+ /*[59]*/20,30,28, 24,22,26, 28,26, 30,28,30,30
3479
+ };
3480
+
3481
+ /*An offset into QR_RS_NPAR_DATA for each version that gives the number of
3482
+ parity bytes per Reed-Solomon block for each error correction level.*/
3483
+ static const unsigned char QR_RS_NPAR_OFFS[40]={
3484
+ 0, 4,19,55,15,28,37,12,51,39,
3485
+ 59,62,10,24,22,41,31,44, 7,65,
3486
+ 47,33,67,67,48,32,67,67,67,67,
3487
+ 67,67,67,67,67,67,67,67,67,67
3488
+ };
3489
+
3490
+ /*The number of Reed-Solomon blocks for each version and error correction
3491
+ level.*/
3492
+ static const unsigned char QR_RS_NBLOCKS[40][4]={
3493
+ { 1, 1, 1, 1},{ 1, 1, 1, 1},{ 1, 1, 2, 2},{ 1, 2, 2, 4},
3494
+ { 1, 2, 4, 4},{ 2, 4, 4, 4},{ 2, 4, 6, 5},{ 2, 4, 6, 6},
3495
+ { 2, 5, 8, 8},{ 4, 5, 8, 8},{ 4, 5, 8,11},{ 4, 8,10,11},
3496
+ { 4, 9,12,16},{ 4, 9,16,16},{ 6,10,12,18},{ 6,10,17,16},
3497
+ { 6,11,16,19},{ 6,13,18,21},{ 7,14,21,25},{ 8,16,20,25},
3498
+ { 8,17,23,25},{ 9,17,23,34},{ 9,18,25,30},{10,20,27,32},
3499
+ {12,21,29,35},{12,23,34,37},{12,25,34,40},{13,26,35,42},
3500
+ {14,28,38,45},{15,29,40,48},{16,31,43,51},{17,33,45,54},
3501
+ {18,35,48,57},{19,37,51,60},{19,38,53,63},{20,40,56,66},
3502
+ {21,43,59,70},{22,45,62,74},{24,47,65,77},{25,49,68,81}
3503
+ };
3504
+
3505
+ /*Attempts to fully decode a QR code.
3506
+ _qrdata: Returns the parsed code data.
3507
+ _gf: Used for Reed-Solomon error correction.
3508
+ _ul_pos: The location of the UL finder pattern.
3509
+ _ur_pos: The location of the UR finder pattern.
3510
+ _dl_pos: The location of the DL finder pattern.
3511
+ _version: The (decoded) version number.
3512
+ _fmt_info: The decoded format info.
3513
+ _img: The binary input image.
3514
+ _width: The width of the input image.
3515
+ _height: The height of the input image.
3516
+ Return: 0 on success, or a negative value on error.*/
3517
+ static int qr_code_decode(qr_code_data *_qrdata,const rs_gf256 *_gf,
3518
+ const qr_point _ul_pos,const qr_point _ur_pos,const qr_point _dl_pos,
3519
+ int _version,int _fmt_info,
3520
+ const unsigned char *_img,int _width,int _height){
3521
+ qr_sampling_grid grid;
3522
+ unsigned *data_bits;
3523
+ unsigned char **blocks;
3524
+ unsigned char *block_data;
3525
+ int nblocks;
3526
+ int nshort_blocks;
3527
+ int ncodewords;
3528
+ int block_sz;
3529
+ int ecc_level;
3530
+ int ndata;
3531
+ int npar;
3532
+ int dim;
3533
+ int ret;
3534
+ int i;
3535
+ /*Read the bits out of the image.*/
3536
+ qr_sampling_grid_init(&grid,_version,_ul_pos,_ur_pos,_dl_pos,_qrdata->bbox,
3537
+ _img,_width,_height);
3538
+ #if defined(QR_DEBUG)
3539
+ qr_sampling_grid_dump(&grid,_version,_img,_width,_height);
3540
+ #endif
3541
+ dim=17+(_version<<2);
3542
+ data_bits=(unsigned *)malloc(
3543
+ dim*(dim+QR_INT_BITS-1>>QR_INT_LOGBITS)*sizeof(*data_bits));
3544
+ qr_sampling_grid_sample(&grid,data_bits,dim,_fmt_info,_img,_width,_height);
3545
+ /*Group those bits into Reed-Solomon codewords.*/
3546
+ ecc_level=(_fmt_info>>3)^1;
3547
+ nblocks=QR_RS_NBLOCKS[_version-1][ecc_level];
3548
+ npar=*(QR_RS_NPAR_VALS+QR_RS_NPAR_OFFS[_version-1]+ecc_level);
3549
+ ncodewords=qr_code_ncodewords(_version);
3550
+ block_sz=ncodewords/nblocks;
3551
+ nshort_blocks=nblocks-(ncodewords%nblocks);
3552
+ blocks=(unsigned char **)malloc(nblocks*sizeof(*blocks));
3553
+ block_data=(unsigned char *)malloc(ncodewords*sizeof(*block_data));
3554
+ blocks[0]=block_data;
3555
+ for(i=1;i<nblocks;i++)blocks[i]=blocks[i-1]+block_sz+(i>nshort_blocks);
3556
+ qr_samples_unpack(blocks,nblocks,block_sz-npar,nshort_blocks,
3557
+ data_bits,grid.fpmask,dim);
3558
+ qr_sampling_grid_clear(&grid);
3559
+ free(blocks);
3560
+ free(data_bits);
3561
+ /*Perform the error correction.*/
3562
+ ndata=0;
3563
+ ncodewords=0;
3564
+ ret=0;
3565
+ for(i=0;i<nblocks;i++){
3566
+ int block_szi;
3567
+ int ndatai;
3568
+ block_szi=block_sz+(i>=nshort_blocks);
3569
+ if(rs_correct(_gf,QR_M0,block_data+ncodewords,block_szi,npar,NULL,0)<0){
3570
+ ret=-1;
3571
+ break;
3572
+ }
3573
+ ndatai=block_szi-npar;
3574
+ memmove(block_data+ndata,block_data+ncodewords,ndatai*sizeof(*block_data));
3575
+ ncodewords+=block_szi;
3576
+ ndata+=ndatai;
3577
+ }
3578
+ /*Parse the corrected bitstream.*/
3579
+ if(ret>=0){
3580
+ ret=qr_code_data_parse(_qrdata,_version,block_data,ndata);
3581
+ /*We could return any partially decoded data, but then we'd have to have
3582
+ API support for that; a mode ignoring ECC errors might also be useful.*/
3583
+ if(ret<0)qr_code_data_clear(_qrdata);
3584
+ _qrdata->version=_version;
3585
+ _qrdata->ecc_level=ecc_level;
3586
+ }
3587
+ free(block_data);
3588
+ return ret;
3589
+ }
3590
+
3591
+ /*Searches for an arrangement of these three finder centers that yields a valid
3592
+ configuration.
3593
+ _c: On input, the three finder centers to consider in any order.
3594
+ Return: The detected version number, or a negative value on error.*/
3595
+ static int qr_reader_try_configuration(qr_reader *_reader,
3596
+ qr_code_data *_qrdata,const unsigned char *_img,int _width,int _height,
3597
+ qr_finder_center *_c[3]){
3598
+ int ci[7];
3599
+ unsigned maxd;
3600
+ int ccw;
3601
+ int i0;
3602
+ int i;
3603
+ /*Sort the points in counter-clockwise order.*/
3604
+ ccw=qr_point_ccw(_c[0]->pos,_c[1]->pos,_c[2]->pos);
3605
+ /*Colinear points can't be the corners of a quadrilateral.*/
3606
+ if(!ccw)return -1;
3607
+ /*Include a few extra copies of the cyclical list to avoid mods.*/
3608
+ ci[6]=ci[3]=ci[0]=0;
3609
+ ci[4]=ci[1]=1+(ccw<0);
3610
+ ci[5]=ci[2]=2-(ccw<0);
3611
+ /*Assume the points farthest from each other are the opposite corners, and
3612
+ find the top-left point.*/
3613
+ maxd=qr_point_distance2(_c[1]->pos,_c[2]->pos);
3614
+ i0=0;
3615
+ for(i=1;i<3;i++){
3616
+ unsigned d;
3617
+ d=qr_point_distance2(_c[ci[i+1]]->pos,_c[ci[i+2]]->pos);
3618
+ if(d>maxd){
3619
+ i0=i;
3620
+ maxd=d;
3621
+ }
3622
+ }
3623
+ /*However, try all three possible orderings, just to be sure (a severely
3624
+ skewed projection could move opposite corners closer than adjacent).*/
3625
+ for(i=i0;i<i0+3;i++){
3626
+ qr_aff aff;
3627
+ qr_hom hom;
3628
+ qr_finder ul;
3629
+ qr_finder ur;
3630
+ qr_finder dl;
3631
+ int res;
3632
+ int ur_version;
3633
+ int dl_version;
3634
+ int fmt_info;
3635
+ ul.c=_c[ci[i]];
3636
+ ur.c=_c[ci[i+1]];
3637
+ dl.c=_c[ci[i+2]];
3638
+ /*Estimate the module size and version number from the two opposite corners.
3639
+ The module size is not constant in the image, so we compute an affine
3640
+ projection from the three points we have to a square domain, and
3641
+ estimate it there.
3642
+ Although it should be the same along both axes, we keep separate
3643
+ estimates to account for any remaining projective distortion.*/
3644
+ res=QR_INT_BITS-2-QR_FINDER_SUBPREC-qr_ilog(QR_MAXI(_width,_height)-1);
3645
+ qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res);
3646
+ qr_aff_unproject(ur.o,&aff,ur.c->pos[0],ur.c->pos[1]);
3647
+ qr_finder_edge_pts_aff_classify(&ur,&aff);
3648
+ if(qr_finder_estimate_module_size_and_version(&ur,1<<res,1<<res)<0)continue;
3649
+ qr_aff_unproject(dl.o,&aff,dl.c->pos[0],dl.c->pos[1]);
3650
+ qr_finder_edge_pts_aff_classify(&dl,&aff);
3651
+ if(qr_finder_estimate_module_size_and_version(&dl,1<<res,1<<res)<0)continue;
3652
+ /*If the estimated versions are significantly different, reject the
3653
+ configuration.*/
3654
+ if(abs(ur.eversion[1]-dl.eversion[0])>QR_LARGE_VERSION_SLACK)continue;
3655
+ qr_aff_unproject(ul.o,&aff,ul.c->pos[0],ul.c->pos[1]);
3656
+ qr_finder_edge_pts_aff_classify(&ul,&aff);
3657
+ if(qr_finder_estimate_module_size_and_version(&ul,1<<res,1<<res)<0||
3658
+ abs(ul.eversion[1]-ur.eversion[1])>QR_LARGE_VERSION_SLACK||
3659
+ abs(ul.eversion[0]-dl.eversion[0])>QR_LARGE_VERSION_SLACK){
3660
+ continue;
3661
+ }
3662
+ #if defined(QR_DEBUG)
3663
+ qr_finder_dump_aff_undistorted(&ul,&ur,&dl,&aff,_img,_width,_height);
3664
+ #endif
3665
+ /*If we made it this far, upgrade the affine homography to a full
3666
+ homography.*/
3667
+ if(qr_hom_fit(&hom,&ul,&ur,&dl,_qrdata->bbox,&aff,
3668
+ &_reader->isaac,_img,_width,_height)<0){
3669
+ continue;
3670
+ }
3671
+ qr_hom_unproject(ul.o,&hom,ul.c->pos[0],ul.c->pos[1]);
3672
+ qr_hom_unproject(ur.o,&hom,ur.c->pos[0],ur.c->pos[1]);
3673
+ qr_hom_unproject(dl.o,&hom,dl.c->pos[0],dl.c->pos[1]);
3674
+ qr_finder_edge_pts_hom_classify(&ur,&hom);
3675
+ if(qr_finder_estimate_module_size_and_version(&ur,
3676
+ ur.o[0]-ul.o[0],ur.o[0]-ul.o[0])<0){
3677
+ continue;
3678
+ }
3679
+ qr_finder_edge_pts_hom_classify(&dl,&hom);
3680
+ if(qr_finder_estimate_module_size_and_version(&dl,
3681
+ dl.o[1]-ul.o[1],dl.o[1]-ul.o[1])<0){
3682
+ continue;
3683
+ }
3684
+ #if defined(QR_DEBUG)
3685
+ qr_finder_dump_hom_undistorted(&ul,&ur,&dl,&hom,_img,_width,_height);
3686
+ #endif
3687
+ /*If we have a small version (less than 7), there's no encoded version
3688
+ information.
3689
+ If the estimated version on the two corners matches and is sufficiently
3690
+ small, we assume this is the case.*/
3691
+ if(ur.eversion[1]==dl.eversion[0]&&ur.eversion[1]<7){
3692
+ /*We used to do a whole bunch of extra geometric checks for small
3693
+ versions, because with just an affine correction, it was fairly easy
3694
+ to estimate two consistent module sizes given a random configuration.
3695
+ However, now that we're estimating a full homography, these appear to
3696
+ be unnecessary.*/
3697
+ #if 0
3698
+ static const signed char LINE_TESTS[12][6]={
3699
+ /*DL left, UL > 0, UR > 0*/
3700
+ {2,0,0, 1,1, 1},
3701
+ /*DL right, UL > 0, UR < 0*/
3702
+ {2,1,0, 1,1,-1},
3703
+ /*UR top, UL > 0, DL > 0*/
3704
+ {1,2,0, 1,2, 1},
3705
+ /*UR bottom, UL > 0, DL < 0*/
3706
+ {1,3,0, 1,2,-1},
3707
+ /*UR left, DL < 0, UL < 0*/
3708
+ {1,0,2,-1,0,-1},
3709
+ /*UR right, DL > 0, UL > 0*/
3710
+ {1,1,2, 1,0, 1},
3711
+ /*DL top, UR < 0, UL < 0*/
3712
+ {2,2,1,-1,0,-1},
3713
+ /*DL bottom, UR > 0, UL > 0*/
3714
+ {2,3,1, 1,0, 1},
3715
+ /*UL left, DL > 0, UR > 0*/
3716
+ {0,0,2, 1,1, 1},
3717
+ /*UL right, DL > 0, UR < 0*/
3718
+ {0,1,2, 1,1,-1},
3719
+ /*UL top, UR > 0, DL > 0*/
3720
+ {0,2,1, 1,2, 1},
3721
+ /*UL bottom, UR > 0, DL < 0*/
3722
+ {0,3,1, 1,2,-1}
3723
+ };
3724
+ qr_finder *f[3];
3725
+ int j;
3726
+ /*Start by decoding the format information.
3727
+ This is cheap, but unlikely to reject invalid configurations.
3728
+ 56.25% of all bitstrings are valid, and we mix and match several pieces
3729
+ until we find a valid combination, so our real chances of finding a
3730
+ valid codeword in random bits are even higher.*/
3731
+ fmt_info=qr_finder_fmt_info_decode(&ul,&ur,&dl,&aff,_img,_width,_height);
3732
+ if(fmt_info<0)continue;
3733
+ /*Now we fit lines to the edges of each finder pattern and check to make
3734
+ sure the centers of the other finder patterns lie on the proper side.*/
3735
+ f[0]=&ul;
3736
+ f[1]=&ur;
3737
+ f[2]=&dl;
3738
+ for(j=0;j<12;j++){
3739
+ const signed char *t;
3740
+ qr_line l0;
3741
+ int *p;
3742
+ t=LINE_TESTS[j];
3743
+ qr_finder_ransac(f[t[0]],&aff,&_reader->isaac,t[1]);
3744
+ /*We may not have enough points to fit a line accurately here.
3745
+ If not, we just skip the test.*/
3746
+ if(qr_line_fit_finder_edge(l0,f[t[0]],t[1],res)<0)continue;
3747
+ p=f[t[2]]->c->pos;
3748
+ if(qr_line_eval(l0,p[0],p[1])*t[3]<0)break;
3749
+ p=f[t[4]]->c->pos;
3750
+ if(qr_line_eval(l0,p[0],p[1])*t[5]<0)break;
3751
+ }
3752
+ if(j<12)continue;
3753
+ /*All tests passed.*/
3754
+ #endif
3755
+ ur_version=ur.eversion[1];
3756
+ }
3757
+ else{
3758
+ /*If the estimated versions are significantly different, reject the
3759
+ configuration.*/
3760
+ if(abs(ur.eversion[1]-dl.eversion[0])>QR_LARGE_VERSION_SLACK)continue;
3761
+ /*Otherwise we try to read the actual version data from the image.
3762
+ If the real version is not sufficiently close to our estimated version,
3763
+ then we assume there was an unrecoverable decoding error (so many bit
3764
+ errors we were within 3 errors of another valid code), and throw that
3765
+ value away.
3766
+ If no decoded version could be sufficiently close, we don't even try.*/
3767
+ if(ur.eversion[1]>=7-QR_LARGE_VERSION_SLACK){
3768
+ ur_version=qr_finder_version_decode(&ur,&hom,_img,_width,_height,0);
3769
+ if(abs(ur_version-ur.eversion[1])>QR_LARGE_VERSION_SLACK)ur_version=-1;
3770
+ }
3771
+ else ur_version=-1;
3772
+ if(dl.eversion[0]>=7-QR_LARGE_VERSION_SLACK){
3773
+ dl_version=qr_finder_version_decode(&dl,&hom,_img,_width,_height,1);
3774
+ if(abs(dl_version-dl.eversion[0])>QR_LARGE_VERSION_SLACK)dl_version=-1;
3775
+ }
3776
+ else dl_version=-1;
3777
+ /*If we got at least one valid version, or we got two and they match,
3778
+ then we found a valid configuration.*/
3779
+ if(ur_version>=0){
3780
+ if(dl_version>=0&&dl_version!=ur_version)continue;
3781
+ }
3782
+ else if(dl_version<0)continue;
3783
+ else ur_version=dl_version;
3784
+ }
3785
+ qr_finder_edge_pts_hom_classify(&ul,&hom);
3786
+ if(qr_finder_estimate_module_size_and_version(&ul,
3787
+ ur.o[0]-dl.o[0],dl.o[1]-ul.o[1])<0||
3788
+ abs(ul.eversion[1]-ur.eversion[1])>QR_SMALL_VERSION_SLACK||
3789
+ abs(ul.eversion[0]-dl.eversion[0])>QR_SMALL_VERSION_SLACK){
3790
+ continue;
3791
+ }
3792
+ fmt_info=qr_finder_fmt_info_decode(&ul,&ur,&dl,&hom,_img,_width,_height);
3793
+ if(fmt_info<0)continue;
3794
+ if(qr_code_decode(_qrdata,&_reader->gf,ul.c->pos,ur.c->pos,dl.c->pos,
3795
+ ur_version,fmt_info,_img,_width,_height)<0){
3796
+ /*TODO: Maybe somebody flipped the code?
3797
+ We'd still get a valid version, and probably valid (but incorrect)
3798
+ format info.
3799
+ After we've come this far, it should be a simple matter to check.*/
3800
+ continue;
3801
+ }
3802
+ return ur_version;
3803
+ }
3804
+ return -1;
3805
+ }
3806
+
3807
+ void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist,
3808
+ qr_finder_center *_centers,int _ncenters,
3809
+ const unsigned char *_img,int _width,int _height){
3810
+ /*The number of centers should be small, so an O(n^3) exhaustive search of
3811
+ which ones go together should be reasonable.*/
3812
+ unsigned char *mark;
3813
+ int i;
3814
+ int j;
3815
+ int k;
3816
+ mark=(unsigned char *)calloc(_ncenters,sizeof(*mark));
3817
+ for(i=0;i<_ncenters;i++){
3818
+ /*TODO: We might be able to accelerate this step significantly by
3819
+ considering the remaining finder centers in a more intelligent order,
3820
+ based on the first finder center we just chose.*/
3821
+ for(j=i+1;!mark[i]&&j<_ncenters;j++){
3822
+ for(k=j+1;!mark[j]&&k<_ncenters;k++)if(!mark[k]){
3823
+ qr_finder_center *c[3];
3824
+ qr_code_data qrdata;
3825
+ int version;
3826
+ c[0]=_centers+i;
3827
+ c[1]=_centers+j;
3828
+ c[2]=_centers+k;
3829
+ version=qr_reader_try_configuration(_reader,&qrdata,
3830
+ _img,_width,_height,c);
3831
+ if(version>=0){
3832
+ int ninside;
3833
+ int l;
3834
+ /*Add the data to the list.*/
3835
+ qr_code_data_list_add(_qrlist,&qrdata);
3836
+ /*Convert the bounding box we're returning to the user to normal
3837
+ image coordinates.*/
3838
+ for(l=0;l<4;l++){
3839
+ _qrlist->qrdata[_qrlist->nqrdata-1].bbox[l][0]>>=QR_FINDER_SUBPREC;
3840
+ _qrlist->qrdata[_qrlist->nqrdata-1].bbox[l][1]>>=QR_FINDER_SUBPREC;
3841
+ }
3842
+ /*Mark these centers as used.*/
3843
+ mark[i]=mark[j]=mark[k]=1;
3844
+ /*Find any other finder centers located inside this code.*/
3845
+ for(l=ninside=0;l<_ncenters;l++)if(!mark[l]){
3846
+ if(qr_point_ccw(qrdata.bbox[0],qrdata.bbox[1],_centers[l].pos)>=0&&
3847
+ qr_point_ccw(qrdata.bbox[1],qrdata.bbox[3],_centers[l].pos)>=0&&
3848
+ qr_point_ccw(qrdata.bbox[3],qrdata.bbox[2],_centers[l].pos)>=0&&
3849
+ qr_point_ccw(qrdata.bbox[2],qrdata.bbox[0],_centers[l].pos)>=0){
3850
+ mark[l]=2;
3851
+ ninside++;
3852
+ }
3853
+ }
3854
+ if(ninside>=3){
3855
+ /*We might have a "Double QR": a code inside a code.
3856
+ Copy the relevant centers to a new array and do a search confined
3857
+ to that subset.*/
3858
+ qr_finder_center *inside;
3859
+ inside=(qr_finder_center *)malloc(ninside*sizeof(*inside));
3860
+ for(l=ninside=0;l<_ncenters;l++){
3861
+ if(mark[l]==2)*&inside[ninside++]=*&_centers[l];
3862
+ }
3863
+ qr_reader_match_centers(_reader,_qrlist,inside,ninside,
3864
+ _img,_width,_height);
3865
+ free(inside);
3866
+ }
3867
+ /*Mark _all_ such centers used: codes cannot partially overlap.*/
3868
+ for(l=0;l<_ncenters;l++)if(mark[l]==2)mark[l]=1;
3869
+ }
3870
+ }
3871
+ }
3872
+ }
3873
+ free(mark);
3874
+ }
3875
+
3876
+ int _zbar_qr_found_line (qr_reader *reader,
3877
+ int dir,
3878
+ const qr_finder_line *line)
3879
+ {
3880
+ /* minimally intrusive brute force version */
3881
+ qr_finder_lines *lines = &reader->finder_lines[dir];
3882
+
3883
+ if(lines->nlines >= lines->clines) {
3884
+ lines->clines *= 2;
3885
+ lines->lines = realloc(lines->lines,
3886
+ ++lines->clines * sizeof(*lines->lines));
3887
+ }
3888
+
3889
+ memcpy(lines->lines + lines->nlines++, line, sizeof(*line));
3890
+
3891
+ return(0);
3892
+ }
3893
+
3894
+ static inline void qr_svg_centers (const qr_finder_center *centers,
3895
+ int ncenters)
3896
+ {
3897
+ int i, j;
3898
+ svg_path_start("centers", 1, 0, 0);
3899
+ for(i = 0; i < ncenters; i++)
3900
+ svg_path_moveto(SVG_ABS, centers[i].pos[0], centers[i].pos[1]);
3901
+ svg_path_end();
3902
+
3903
+ svg_path_start("edge-pts", 1, 0, 0);
3904
+ for(i = 0; i < ncenters; i++) {
3905
+ const qr_finder_center *cen = centers + i;
3906
+ for(j = 0; j < cen->nedge_pts; j++)
3907
+ svg_path_moveto(SVG_ABS,
3908
+ cen->edge_pts[j].pos[0], cen->edge_pts[j].pos[1]);
3909
+ }
3910
+ svg_path_end();
3911
+ }
3912
+
3913
+ int _zbar_qr_decode (qr_reader *reader,
3914
+ zbar_image_scanner_t *iscn,
3915
+ zbar_image_t *img)
3916
+ {
3917
+ int nqrdata = 0, ncenters;
3918
+ qr_finder_edge_pt *edge_pts = NULL;
3919
+ qr_finder_center *centers = NULL;
3920
+
3921
+ if(reader->finder_lines[0].nlines < 9 ||
3922
+ reader->finder_lines[1].nlines < 9)
3923
+ return(0);
3924
+
3925
+ svg_group_start("finder", 0, 1. / (1 << QR_FINDER_SUBPREC), 0, 0, 0);
3926
+
3927
+ ncenters = qr_finder_centers_locate(&centers, &edge_pts, reader, 0, 0);
3928
+
3929
+ zprintf(14, "%dx%d finders, %d centers:\n",
3930
+ reader->finder_lines[0].nlines,
3931
+ reader->finder_lines[1].nlines,
3932
+ ncenters);
3933
+ qr_svg_centers(centers, ncenters);
3934
+
3935
+ if(ncenters >= 3) {
3936
+ void *bin = qr_binarize(img->data, img->width, img->height);
3937
+
3938
+ qr_code_data_list qrlist;
3939
+ qr_code_data_list_init(&qrlist);
3940
+
3941
+ qr_reader_match_centers(reader, &qrlist, centers, ncenters,
3942
+ bin, img->width, img->height);
3943
+
3944
+ if(qrlist.nqrdata > 0)
3945
+ nqrdata = qr_code_data_list_extract_text(&qrlist, iscn, img);
3946
+
3947
+ qr_code_data_list_clear(&qrlist);
3948
+ free(bin);
3949
+ }
3950
+ svg_group_end();
3951
+
3952
+ if(centers)
3953
+ free(centers);
3954
+ if(edge_pts)
3955
+ free(edge_pts);
3956
+ return(nqrdata);
3957
+ }