Browse Source

Merge branch 'gq' of ssh://git.9026.com:2212/roobe/miao into gq

gq 8 năm trước cách đây
mục cha
commit
b6a74ffc0e
100 tập tin đã thay đổi với 31486 bổ sung82 xóa
  1. BIN
      .vs/miaomiao/v14/.suo
  2. BIN
      miaomiao/bin/Android/Debug/android-debug-unaligned.apk
  3. BIN
      miaomiao/bin/Android/Debug/android-debug.apk
  4. 88 77
      miaomiao/config.xml
  5. 46 4
      miaomiao/package.json
  6. 10 0
      miaomiao/plugins/android.json
  7. 0 0
      miaomiao/plugins/cordova-hot-code-push-plugin/.npmInstalled
  8. 21 0
      miaomiao/plugins/cordova-plugin-jcore/LICENSE
  9. 32 0
      miaomiao/plugins/cordova-plugin-jcore/README.md
  10. BIN
      miaomiao/plugins/cordova-plugin-jcore/doc/sdk_model.png
  11. 104 0
      miaomiao/plugins/cordova-plugin-jcore/package.json
  12. 32 0
      miaomiao/plugins/cordova-plugin-jcore/plugin.xml
  13. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/arm64-v8a/libjcore113.so
  14. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/armeabi-v7a/libjcore113.so
  15. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/armeabi/libjcore113.so
  16. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/jcore-android_v1.1.3.jar
  17. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/mips/libjcore113.so
  18. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/mips64/libjcore113.so
  19. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/x86/libjcore113.so
  20. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/android/x86_64/libjcore113.so
  21. BIN
      miaomiao/plugins/cordova-plugin-jcore/src/ios/jcore-ios-1.1.3.a
  22. 5 0
      miaomiao/plugins/cordova-plugin-jcore/www/jcore.js
  23. 31 1
      miaomiao/plugins/fetch.json
  24. 3 0
      miaomiao/plugins/ios.json
  25. 448 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/CHANGELOG.md
  26. 22 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/LICENSE.txt
  27. 241 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/README.md
  28. 52 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/hooks/windows/check-arch.js
  29. 50 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/package.json
  30. 114 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/plugin.xml
  31. 83 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/spec/helper/cordova.js
  32. 78 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/spec/index.spec.js
  33. 1 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/README.md
  34. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/barcodescanner-release-2.1.5.aar
  35. 24 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/barcodescanner.gradle
  36. 325 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java
  37. 703 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/LICENSE
  38. 213 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/index.js
  39. 220 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/.cproject
  40. 2 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/.settings/com.qnx.tools.ide.core.prefs
  41. 2 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/device/.gitignore
  42. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/device/libBarcodeScanner.so
  43. 19 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/autolink.h
  44. 43 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/config.h
  45. 42 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/features.h
  46. 39 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/forwards.h
  47. 10 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/json.h
  48. 196 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/reader.h
  49. 1069 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/value.h
  50. 174 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/writer.h
  51. 125 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_batchallocator.h
  52. 448 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_internalarray.inl
  53. 607 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_internalmap.inl
  54. 892 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_reader.cpp
  55. 1726 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_value.cpp
  56. 292 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_valueiterator.inl
  57. 829 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_writer.cpp
  58. 320 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/plugin.cpp
  59. 70 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/plugin.h
  60. 222 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/tokenizer.cpp
  61. 55 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/tokenizer.h
  62. 2 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/simulator/.gitignore
  63. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/simulator/libBarcodeScanner.so
  64. 104 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/Logger.cpp
  65. 49 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/Logger.hpp
  66. 105 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_js.cpp
  67. 41 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_js.hpp
  68. 709 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_ndk.cpp
  69. 55 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_ndk.hpp
  70. 147 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/qrcode.js
  71. 24 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/browser/BarcodeScannerProxy.js
  72. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/beep.caf
  73. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch.png
  74. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch@2x.png
  75. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch@3x.png
  76. 1183 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.mm
  77. 185 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/scannerOverlay.xib
  78. 11982 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/zxing-all-in-one.cpp
  79. 5007 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/zxing-all-in-one.h
  80. 723 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/BarcodeScannerProxy.js
  81. 89 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/assets/plugin-barcodeScanner.css
  82. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/ANY/ZXing.winmd
  83. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/ARM/ZXing.winmd
  84. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/x64/ZXing.winmd
  85. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/x86/ZXing.winmd
  86. 39 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/Properties/AssemblyInfo.cs
  87. 173 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/Reader.cs
  88. 137 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/WinRTBarcodeReader.csproj
  89. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/ZXing.winmd
  90. 117 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScanner.cs
  91. 103 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerTask.cs
  92. 46 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerUI.xaml
  93. 182 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerUI.xaml.cs
  94. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/assets/cancel.png
  95. BIN
      miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/lib/zxing.wp8.0.dll
  96. 156 0
      miaomiao/plugins/phonegap-plugin-barcodescanner/www/barcodescanner.js
  97. BIN
      miaomiao/resources/android/icon/drawable-hdpi-icon.png
  98. BIN
      miaomiao/resources/android/icon/drawable-ldpi-icon.png
  99. BIN
      miaomiao/resources/android/icon/drawable-mdpi-icon.png
  100. BIN
      miaomiao/resources/android/icon/drawable-xhdpi-icon.png

BIN
.vs/miaomiao/v14/.suo


BIN
miaomiao/bin/Android/Debug/android-debug-unaligned.apk


BIN
miaomiao/bin/Android/Debug/android-debug.apk


+ 88 - 77
miaomiao/config.xml

xqd xqd
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<?xml version="1.0" encoding="utf-8"?>
 <widget id="com.ionicframework.ionictabs121641" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
   <name>瞄瞄</name>
   <description>
@@ -7,88 +7,99 @@
   <author email="you@example.com" href="http://example.com.com/">
       Your Name Here
     </author>
-  <content src="index.html"/>
-  <access origin="*"/>
-  <preference name="webviewbounce" value="false"/>
-  <preference name="UIWebViewBounce" value="false"/>
-  <preference name="DisallowOverscroll" value="true"/>
-  <preference name="android-minSdkVersion" value="16"/>
-  <preference name="BackupWebStorage" value="none"/>
-  <preference name="KeepRunning" value="True"/>
-  <preference name="ShowTitle" value="True"/>
-  <preference name="InAppBrowserStorageEnabled" value="True"/>
-  <preference name="SuppressesIncrementalRendering" value="True"/>
-  <preference name="windows-target-version" value="10.0"/>
-  <preference name="SplashScreen" value="screen"/>
-  <preference name="SplashScreenDelay" value="3000"/>
+  <content src="index.html" />
+  <access origin="*" />
+  <preference name="webviewbounce" value="false" />
+  <preference name="UIWebViewBounce" value="false" />
+  <preference name="DisallowOverscroll" value="true" />
+  <preference name="android-minSdkVersion" value="16" />
+  <preference name="BackupWebStorage" value="none" />
+  <preference name="KeepRunning" value="True" />
+  <preference name="ShowTitle" value="True" />
+  <preference name="InAppBrowserStorageEnabled" value="True" />
+  <preference name="SuppressesIncrementalRendering" value="True" />
+  <preference name="windows-target-version" value="10.0" />
+  <preference name="SplashScreen" value="screen" />
+  <preference name="SplashScreenDelay" value="3000" />
   <feature name="StatusBar">
-    <param name="ios-package" onload="true" value="CDVStatusBar"/>
+    <param name="ios-package" onload="true" value="CDVStatusBar" />
   </feature>
   <platform name="ios">
-    <icon height="57" src="resources/ios/icon/icon.png" width="57"/>
-    <icon height="114" src="resources/ios/icon/icon@2x.png" width="114"/>
-    <icon height="40" src="resources/ios/icon/icon-40.png" width="40"/>
-    <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80"/>
-    <icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120"/>
-    <icon height="50" src="resources/ios/icon/icon-50.png" width="50"/>
-    <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100"/>
-    <icon height="60" src="resources/ios/icon/icon-60.png" width="60"/>
-    <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120"/>
-    <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180"/>
-    <icon height="72" src="resources/ios/icon/icon-72.png" width="72"/>
-    <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144"/>
-    <icon height="76" src="resources/ios/icon/icon-76.png" width="76"/>
-    <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152"/>
-    <icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167"/>
-    <icon height="29" src="resources/ios/icon/icon-small.png" width="29"/>
-    <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58"/>
-    <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87"/>
-    <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640"/>
-    <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750"/>
-    <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242"/>
-    <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208"/>
-    <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048"/>
-    <splash height="2048" src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732"/>
-    <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024"/>
-    <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536"/>
-    <splash height="2732" src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048"/>
-    <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768"/>
-    <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640"/>
-    <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320"/>
+    <icon height="57" src="resources/ios/icon/icon.png" width="57" />
+    <icon height="114" src="resources/ios/icon/icon@2x.png" width="114" />
+    <icon height="40" src="resources/ios/icon/icon-40.png" width="40" />
+    <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80" />
+    <icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120" />
+    <icon height="50" src="resources/ios/icon/icon-50.png" width="50" />
+    <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100" />
+    <icon height="60" src="resources/ios/icon/icon-60.png" width="60" />
+    <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120" />
+    <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180" />
+    <icon height="72" src="resources/ios/icon/icon-72.png" width="72" />
+    <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144" />
+    <icon height="76" src="resources/ios/icon/icon-76.png" width="76" />
+    <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152" />
+    <icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167" />
+    <icon height="29" src="resources/ios/icon/icon-small.png" width="29" />
+    <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58" />
+    <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87" />
+    <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" />
+    <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750" />
+    <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242" />
+    <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208" />
+    <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" />
+    <splash height="2048" src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732" />
+    <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" />
+    <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" />
+    <splash height="2732" src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048" />
+    <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768" />
+    <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640" />
+    <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320" />
   </platform>
   <platform name="android">
-    <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
-    <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
-    <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
-    <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
-    <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
-    <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
-    <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/>
-    <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/>
-    <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/>
-    <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/>
-    <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/>
-    <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/>
-    <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
-    <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
-    <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
-    <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
-    <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
-    <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
+    <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
+    <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
+    <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />
+    <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" />
+    <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" />
+    <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" />
+    <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
+    <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
+    <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
+    <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" />
+    <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" />
+    <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" />
+    <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" />
+    <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" />
+    <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" />
+    <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" />
+    <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" />
+    <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
   </platform>
-  <plugin name="cordova-plugin-device" spec="~1.1.1"/>
-  <plugin name="cordova-plugin-console" spec="~1.0.2"/>
-  <plugin name="cordova-plugin-whitelist" spec="~1.2.1"/>
-  <plugin name="cordova-plugin-statusbar" spec="~2.1.0"/>
-  <plugin name="ionic-plugin-keyboard" spec="~1.0.9"/>
-  <plugin name="cordova-plugin-file-transfer" version="1.6.2"/>
-  <plugin name="cordova-plugin-file" version="4.3.2"/>
-  <plugin name="cordova-plugin-camera" version="2.4.0"/>
-  <plugin name="cordova-plugin-actionsheet" version="2.3.3"/>
-  <plugin name="cordova-plugin-media-capture" version="1.4.3"/>
-  <plugin name="cordova-plugin-compat" version="1.1.0"/>
-  <plugin name="cordova-plugin-splashscreen" version="4.0.3"/>
   <chcp>
-    <config-file url="http://i.9026.com/miaomiao/chcp.json"/>
+    <config-file url="http://i.9026.com/miaomiao/chcp.json" />
   </chcp>
+  <plugin name="cordova-hot-code-push-plugin" spec="~1.5.3" />
+  <plugin name="cordova-plugin-actionsheet" spec="2.3.3" />
+  <plugin name="cordova-plugin-camera" spec="2.4.0" />
+  <plugin name="cordova-plugin-compat" spec="1.1.0" />
+  <plugin name="cordova-plugin-console" spec="~1.0.2" />
+  <plugin name="cordova-plugin-device" spec="~1.1.1" />
+  <plugin name="cordova-plugin-file" spec="4.3.2" />
+  <plugin name="cordova-plugin-file-transfer" spec="1.6.2" />
+  <plugin name="cordova-plugin-media-capture" spec="1.4.3" />
+  <plugin name="cordova-plugin-splashscreen" spec="4.0.3" />
+  <plugin name="cordova-plugin-statusbar" spec="~2.1.0" />
+  <plugin name="cordova-plugin-whitelist" spec="~1.2.1" />
+  <plugin name="ionic-plugin-keyboard" spec="~1.0.9" />
+  <plugin name="jpush-phonegap-plugin" version="2.2.7" src="https://github.com/jpush/jpush-phonegap-plugin.git">
+    <variable name="API_KEY" value="041b70b4c7eee686870a32cd" />
+  </plugin>
+  <plugin name="cordova-plugin-jcore" version="1.1.5" />
+  <plugin name="phonegap-plugin-barcodescanner" version="6.0.8" src="https://github.com/phonegap/phonegap-plugin-barcodescanner.git">
+    <variable name="CAMERA_USAGE_DESCRIPTION" value="请摄像头对准条码" />
+  </plugin>
+  <plugin name="jpush-phonegap-plugin" version="3.2.2" src="https://github.com/jpush/jpush-phonegap-plugin.git">
+    <variable name="APP_KEY" value="041b70b4c7eee686870a32cd" />
+  </plugin>
 </widget>

+ 46 - 4
miaomiao/package.json

xqd xqd
@@ -3,11 +3,26 @@
   "version": "1.1.1",
   "description": "An Ionic project",
   "dependencies": {
+    "cordova-ios": "^4.4.0",
+    "cordova-plugin-actionsheet": "2.3.3",
+    "cordova-plugin-camera": "2.4.0",
+    "cordova-plugin-compat": "1.1.0",
+    "cordova-plugin-console": "~1.0.2",
+    "cordova-plugin-device": "~1.1.1",
+    "cordova-plugin-file": "4.3.2",
+    "cordova-plugin-file-transfer": "1.6.2",
+    "cordova-plugin-jcore": "^1.1.5",
+    "cordova-plugin-media-capture": "1.4.3",
+    "cordova-plugin-splashscreen": "4.0.3",
+    "cordova-plugin-statusbar": "~2.1.0",
+    "cordova-plugin-whitelist": "~1.2.1",
     "gulp": "^3.5.6",
-    "gulp-sass": "^2.0.4",
     "gulp-concat": "^2.2.0",
     "gulp-minify-css": "^0.3.0",
-    "gulp-rename": "^1.2.0"
+    "gulp-rename": "^1.2.0",
+    "gulp-sass": "^2.0.4",
+    "ionic-plugin-keyboard": "~1.0.9",
+    "jpush-phonegap-plugin": "^3.2.1"
   },
   "devDependencies": {
     "@ionic/cli-plugin-ionic1": "1.1.2",
@@ -24,7 +39,34 @@
     "ionic-plugin-keyboard",
     "cordova-plugin-file-transfer@1.6.2",
     "cordova-plugin-camera@2.4.0",
-    "cordova-hot-code-push-plugin"
+    "cordova-hot-code-push-plugin",
+    "jpush-phonegap-plugin@^3.2.1",
+    "jpush-phonegap-plugin@^3.0.1"
+  ],
+  "cordovaPlatforms": [
+    {
+      "platform": "ios",
+      "version": "3.9.0",
+      "locator": "ios@3.9.0"
+    }
   ],
-  "cordovaPlatforms": []
+  "cordova": {
+    "plugins": {
+      "cordova-plugin-actionsheet": {},
+      "cordova-plugin-camera": {},
+      "cordova-plugin-compat": {},
+      "cordova-plugin-console": {},
+      "cordova-plugin-device": {},
+      "cordova-plugin-file": {},
+      "cordova-plugin-file-transfer": {},
+      "cordova-plugin-media-capture": {},
+      "cordova-plugin-splashscreen": {},
+      "cordova-plugin-statusbar": {},
+      "cordova-plugin-whitelist": {},
+      "ionic-plugin-keyboard": {},
+      "jpush-phonegap-plugin": {
+        "APP_KEY": "041b70b4c7eee686870a32cd"
+      }
+    }
+  }
 }

+ 10 - 0
miaomiao/plugins/android.json

xqd xqd
@@ -31,6 +31,9 @@
         "cordova-plugin-file-transfer": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },
+        "cordova-plugin-jcore": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
         "cordova-plugin-media-capture": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },
@@ -45,6 +48,13 @@
         },
         "ionic-plugin-keyboard": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
+        "jpush-phonegap-plugin": {
+            "APP_KEY": "041b70b4c7eee686870a32cd",
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
+        "phonegap-plugin-barcodescanner": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         }
     },
     "dependent_plugins": {}

+ 0 - 0
miaomiao/plugins/cordova-hot-code-push-plugin/.npmInstalled


+ 21 - 0
miaomiao/plugins/cordova-plugin-jcore/LICENSE

xqd
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 极光开发者
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 32 - 0
miaomiao/plugins/cordova-plugin-jcore/README.md

xqd
@@ -0,0 +1,32 @@
+# Cordova Plugin JCore
+[![QQ Group](https://img.shields.io/badge/QQ%20Group-413602425-red.svg)]()
+[![release](https://img.shields.io/badge/release-1.1.5-blue.svg)](https://github.com/jpush/jpush-phonegap-plugin/releases)
+[![platforms](https://img.shields.io/badge/platforms-iOS%7CAndroid-lightgrey.svg)](https://github.com/jpush/jpush-phonegap-plugin)
+[![weibo](https://img.shields.io/badge/weibo-JPush-blue.svg)](http://weibo.com/jpush?refer_flag=1001030101_&is_all=1)
+
+极光各种开发者服务的核心依赖 JCore SDK 的 Cordova 插件。
+
+极光开发者服务及对应的 Cordova 插件如下:
+
+- 极光推送(JPush)- [jpush-phonegap-plugin](https://github.com/jpush/jpush-phonegap-plugin)
+- 极光 IM(JMessage)- [jmessage-phonegap-plugin](https://github.com/jpush/jmessage-phonegap-plugin)
+- 极光统计(JAnalytics)- [cordova-plugn-janalytics](https://github.com/wilhantian/cordova-plugin-janalytics)
+- 极光短信验证码(JSMS)- [cordova-plugin-jsms](https://github.com/jpush/cordova-plugin-jsms)
+
+## 什么是 JCore
+
+**模块化的极光开发者SDK**
+
+极光开发者服务 SDK 采用了模块化的使用模式,即一个核心(JCore)+ N 种服务(JPush,JMessage...)的使用方式,方便开发者使用某一项服务或多项服务,极大的优化了多模块同时使用时功能模块重复的问题。如下图:
+
+![](doc/sdk_model.png)
+
+## Install
+cordova-plugin-jcore 作为其他极光 Cordova 插件的依赖,在安装其他插件时会自动安装。
+
+## Support
+<!-- - [极光社区](http://community.jiguang.cn/) -->
+- QQ 交流群:413602425
+
+## License
+MIT © [JiGuang](/license)

BIN
miaomiao/plugins/cordova-plugin-jcore/doc/sdk_model.png


+ 104 - 0
miaomiao/plugins/cordova-plugin-jcore/package.json

xqd
@@ -0,0 +1,104 @@
+{
+  "_args": [
+    [
+      {
+        "raw": "cordova-plugin-jcore",
+        "scope": null,
+        "escapedName": "cordova-plugin-jcore",
+        "name": "cordova-plugin-jcore",
+        "rawSpec": "",
+        "spec": "latest",
+        "type": "tag"
+      },
+      "/Users/Mike/Vagrant/wwwroot/miaomiao/miaomiao/node_modules"
+    ]
+  ],
+  "_cnpm_publish_time": 1498100030220,
+  "_from": "cordova-plugin-jcore@latest",
+  "_hasShrinkwrap": false,
+  "_id": "cordova-plugin-jcore@1.1.5",
+  "_inCache": true,
+  "_location": "/cordova-plugin-jcore",
+  "_nodeVersion": "7.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/cordova-plugin-jcore-1.1.5.tgz_1498100029816_0.8400004613213241"
+  },
+  "_npmUser": {
+    "name": "jpush",
+    "email": "support@jpush.cn"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "raw": "cordova-plugin-jcore",
+    "scope": null,
+    "escapedName": "cordova-plugin-jcore",
+    "name": "cordova-plugin-jcore",
+    "rawSpec": "",
+    "spec": "latest",
+    "type": "tag"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://registry.npm.taobao.org/cordova-plugin-jcore/download/cordova-plugin-jcore-1.1.5.tgz",
+  "_shasum": "9170a59f2f9288a7236f1e7aff949bef900bee3b",
+  "_shrinkwrap": null,
+  "_spec": "cordova-plugin-jcore",
+  "_where": "/Users/Mike/Vagrant/wwwroot/miaomiao/miaomiao/node_modules",
+  "author": {
+    "name": "wilhantian, jpush"
+  },
+  "bugs": {
+    "url": "https://github.com/jpush/cordova-plugin-jcore/issues"
+  },
+  "cordova": {
+    "id": "cordova-plugin-jcore",
+    "platforms": [
+      "android",
+      "ios"
+    ]
+  },
+  "dependencies": {},
+  "description": "jcore for cordova plugin",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "9170a59f2f9288a7236f1e7aff949bef900bee3b",
+    "size": 6655966,
+    "noattachment": false,
+    "tarball": "http://registry.npm.taobao.org/cordova-plugin-jcore/download/cordova-plugin-jcore-1.1.5.tgz"
+  },
+  "gitHead": "bfa1c4c32c6594bae58c2ef8e64368884b5a5848",
+  "homepage": "https://github.com/jpush/cordova-plugin-jcore#readme",
+  "keywords": [
+    "jcore",
+    "jpush",
+    "ecosystem:cordova",
+    "cordova-android",
+    "cordova-ios"
+  ],
+  "license": "MIT License",
+  "maintainers": [
+    {
+      "name": "jpush",
+      "email": "support@jpush.cn"
+    },
+    {
+      "name": "wilhantian",
+      "email": "wilhan.tian@gmail.com"
+    }
+  ],
+  "name": "cordova-plugin-jcore",
+  "optionalDependencies": {},
+  "publish_time": 1498100030220,
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jpush/cordova-plugin-jcore.git"
+  },
+  "scripts": {},
+  "version": "1.1.5"
+}

+ 32 - 0
miaomiao/plugins/cordova-plugin-jcore/plugin.xml

xqd
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+     xmlns:android="http://schemas.android.com/apk/res/android"
+     id="cordova-plugin-jcore"
+     version="1.1.5">
+
+    <name>JCore</name>
+    <description>Cordova plugin for jcore</description>
+    <author>WilhanTian, JiGuang</author>
+    <keywords>jcore,jpush</keywords>
+    <license>MIT License</license>
+
+    <engines>
+        <engine name="cordova" version=">=3.0.0"/>
+    </engines>
+
+    <platform name="android">
+        <source-file src="src/android/arm64-v8a/libjcore113.so" target-dir="libs/arm64-v8a"/>
+        <source-file src="src/android/armeabi/libjcore113.so" target-dir="libs/armeabi"/>
+        <source-file src="src/android/armeabi-v7a/libjcore113.so" target-dir="libs/armeabi-v7a"/>
+        <source-file src="src/android/mips/libjcore113.so" target-dir="libs/mips"/>
+        <source-file src="src/android/mips64/libjcore113.so" target-dir="libs/mips64"/>
+        <source-file src="src/android/x86/libjcore113.so" target-dir="libs/x86"/>
+        <source-file src="src/android/x86_64/libjcore113.so" target-dir="libs/x86_64"/>
+
+        <source-file src="src/android/jcore-android_v1.1.3.jar" target-dir="libs"/>
+    </platform>
+
+    <platform name="ios">
+        <source-file src="src/ios/jcore-ios-1.1.3.a" framework="true" />
+    </platform>
+</plugin>

BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/arm64-v8a/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/armeabi-v7a/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/armeabi/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/jcore-android_v1.1.3.jar


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/mips/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/mips64/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/x86/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/android/x86_64/libjcore113.so


BIN
miaomiao/plugins/cordova-plugin-jcore/src/ios/jcore-ios-1.1.3.a


+ 5 - 0
miaomiao/plugins/cordova-plugin-jcore/www/jcore.js

xqd
@@ -0,0 +1,5 @@
+var exec = require('cordova/exec')
+
+exports.coolMethod = function (arg0, success, error) {
+  exec(success, error, 'jcore', 'coolMethod', [arg0])
+}

+ 31 - 1
miaomiao/plugins/fetch.json

xqd
@@ -98,9 +98,39 @@
     "cordova-hot-code-push-plugin": {
         "source": {
             "type": "registry",
-            "id": "cordova-hot-code-push-plugin"
+            "id": "cordova-hot-code-push-plugin@~1.5.3"
         },
         "is_top_level": true,
         "variables": {}
+    },
+    "cordova-plugin-jcore": {
+        "source": {
+            "type": "registry",
+            "id": "cordova-plugin-jcore"
+        },
+        "is_top_level": false,
+        "variables": {}
+    },
+    "jpush-phonegap-plugin": {
+        "source": {
+            "type": "git",
+            "url": "https://github.com/jpush/jpush-phonegap-plugin.git",
+            "subdir": "."
+        },
+        "is_top_level": true,
+        "variables": {
+            "API_KEY": "041b70b4c7eee686870a32cd"
+        }
+    },
+    "phonegap-plugin-barcodescanner": {
+        "source": {
+            "type": "git",
+            "url": "https://github.com/phonegap/phonegap-plugin-barcodescanner.git",
+            "subdir": "."
+        },
+        "is_top_level": true,
+        "variables": {
+            "CAMERA_USAGE_DESCRIPTION": "请摄像头对准条码"
+        }
     }
 }

+ 3 - 0
miaomiao/plugins/ios.json

xqd
@@ -33,6 +33,9 @@
         "cordova-plugin-file-transfer": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },
+        "cordova-plugin-jcore": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
         "cordova-plugin-media-capture": {
             "CAMERA_USAGE_DESCRIPTION": " ",
             "MICROPHONE_USAGE_DESCRIPTION": " ",

+ 448 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/CHANGELOG.md

xqd
@@ -0,0 +1,448 @@
+# Change Log
+
+## [v6.0.8](https://github.com/* remote origin
+  Fetch URL: https://github.com//tree/v6.0.8) (2017-07-18)
+[Full Changelog](https://github.com/* remote origin
+  Fetch URL: https://github.com//compare/v6.0.7...v6.0.8)
+
+- 6.0.8 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/b3e99476b768df3fb4da50ff3bca4aea6f863710)
+- :bookmark: Bumping plugin version to 6.0.8 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/7cf0c179ca40c8fefaec4016ac2d759ae728cd7a)
+- :bug: Issue #364: UPC_A codes now scans with extra 0 at the start [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/f311beeb945f80ac8790391f8238bd57d9fa0cd9)
+- Merge pull request #505 from renanbandeira/patch-1 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/919a626daf6df124c79c792863b352ca0a87044d)
+- Updates README.md with new saveHistory prop [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/e63ab0db5e278d9565b50ab1f5140dd75ecd1742)
+- reverts 523501d [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/7b3c22aeb9cf0683937ae43cc30ccbff1dfbd83c)
+- Gets saveHistory from preference defined in config [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/523501d8d7199928093c8dbebf67d9358476cc77)
+- Adds saveHistory flag [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/132359c564750651a9b10a01caf4b8dc30862556)
+- Updating CHANGELOG [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/20727f81f2add352433c0649a9e5e3e5093467ac)
+
+## [v6.0.7](https://github.com/* remote origin
+  Fetch URL: https://github.com//tree/v6.0.7) (2017-07-12)
+[Full Changelog](https://github.com/* remote origin
+  Fetch URL: https://github.com//compare/v6.0.6...v6.0.7)
+
+- 6.0.7 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/78dbf1cccb30935b832dc659eb377541edc52786)
+- :bookmark: Bumping plugin version to 6.0.7 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/d0a2b4c52169553a86fc3fb5e00c0caa489d097d)
+- :wrench: update pluginpub version [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/fc7e3be16f3b1c811e5013f028bed934ebd7c9c1)
+- :apple: Issue #238: ios callbacks not called [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/e33e64ef462d00a95a0c6f3258a087f61f0e15da)
+- Merge pull request #431 from phonegap/ios-fix-426 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/c65ba2f987838331eaa8a569b739515cad7a91e0)
+- :apple: Issue #340: iOS WebThreadLock crash on barcodeScanFailed [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/217d673644b6df96b175ce78ffa9cd8aee24135b)
+- Merge pull request #472 from jcesarmobile/beep-fix [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/8091c92f5e1e68e50f22fd171754a77740a76859)
+- :memo: Issue #470: PDF417 vs PDF_417, which one is valid [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/7ed5b212d25f2c0918e7ac0353cc3d59d8094a4c)
+- :fire: Removing these tests [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/54a28dd8871b81db810aed7df0a9909d71937b8b)
+- :wrench: Issue #473: Travis fails [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/68a2c5d9064bf927df0c5a862009d5b9812785b7)
+- :white_check_mark: Issue #473: Travis fails [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/2e335b82b7bd3ad9b7efc2c87adcb441c0d88bda)
+- Issue #330: Add a LICENSE file [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/a2f59f7adba728006c40dec431ecedf1c229f6e6)
+- :memo: Issue #471: README.md fix [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/cce5f050b8861dd05e6e8e0a03fc4b301ed3788f)
+- Fix beep [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/3cf20a6eb3397f3a2bb61a044c02f1e4810b5810)
+- Merge pull request #429 from jcesarmobile/pgb-usage-description [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/b5a135c6788e1a9ecb9f06a087931701f0b7a321)
+- Camera cannot focus due to wrong aspect ratio since plugin 6.0.5 #392 [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/04e0b3dadfe9aad8ec90e1d9480efe149f7e64f1)
+- [ios] re-add support for formats option [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/75ab7396d0e86b78188369d5f27a5c4fea602921)
+- Document usage description for phonegap build [view commit](http://github.com/* remote origin
+  Fetch URL: https://github.com//commit/01a9f77961be74581fe25786c17e351026f1bbb5)
+
+# Change Log
+
+[6.0.5](https://github.com/phonegap/phonegap-plugin-barcodescanner/tree/6.0.5) (2016-12-22)
+[Full Changelog](https://github.com/phonegap/phonegap-plugin-barcodescanner/compare/6.0.4...6.0.5)
+
+- Flashlight default value #385, Turning off found plain text #259, Remove Result Prompt #234, Custom Result Messages #219 [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fee66a7d1b4c3bca845beb3fa8c99365b4c15ce2)
+- Flipping orientation on Android crashes app [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/72ae2c75d3d66df24c124a6da9c26e48f7ad36a0)
+- Focus improvements [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52a23b0f42d454d6a9f2e29a693b5e984c0bb13f)
+- Crash on iOS on low memory devices [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6e3718c2db03fda3d8ea439a9471b3a08e121f21)
+- Disable Animation [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f9960f9b81aef35bd85ecba856c63058bc109ac1)
+- Flashlight option [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a7ed6890d4e5e2cb386c8754aca081fad559ba1a)
+- Merge pull request #343 from cepm-nate/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/77622ca92f5607a8d22131f62f2dea720857a5ed)
+- Merge pull request #334 from lucatorella/patch-1 [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10f94bc81aff5329291272a4922837e04569a339)
+- Merge pull request #346 from kunder-lab/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1cdbf871c9d290630e4535e8ed9db0804b413f74)
+- Catch Class not registered exception in case of missing Media Player [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d43964f06c8eb57fc168d7b19027462e957ba23d)
+- Adds promise scan .done particularly to handle "No cameras" error [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/68b6fd14a95f34b32ea2bb651f9715ff880e4ade)
+- Merge pull request #358 from vladimir-kotikov/explicit_intent [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/75cffc3282f09f6973d078d8ce9b306bff210bd5)
+- Use explicit intent to launch scan activity [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4c046898543dee838b259997a5ec360240e26354)
+- Merge pull request #338 from jlowe234/master [view commit](https://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7f4e4daf19951692873a490c845446cfa0fbda68)
+- 6.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/18f958796ee9587d5bc21e6229f40139dd4f0c8a)
+- Bumping plugin version to 6.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8728015c06d6d201cbd421621384cd19857f6720)
+- Update pluginpub [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ca4973214b3f99a135d3844d52f40a086022ddcb)
+- Merge pull request #303 from vladimir-kotikov/memory_consumption_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/631ab8fabe16266fb8ea6168d96250be11b8efd1)
+- Merge pull request #318 from vladimir-kotikov/surface3_crash [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4fffc8d187ddd7ee8df90ba285a5ae6eaac980fe)
+- Add contribution doc, issue and pull request templates [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/31d9badd9b9b3278a78650bcccd105a95a7b4c78)
+- Add editorconfig [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c33c2ab4d63f476bc63c3dd8a5b18f0301baf30f)
+- Setup CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1c2491db0f3e15322e543e87def64159cc4b3bb9)
+- Setup regression tests [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d6ee25e8f1ca3b2589c979a23f987afa60bb701)
+- Issue #270: OS 10 requires Camera permission reason [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/380a56a0b5236bf867bd11d10ceaa185351ea892)
+- Merge pull request #302 from jcesarmobile/add-permission-check [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7dd0e8404394b1bcb14fef49cf0301f5b32503c4)
+- Merge pull request #271 from EddyVerbruggen/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8004584a8f266fc4715ffc69fb7148a0a83724ae)
+- Merge pull request #307 from timkim/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d775cc7995c4ef6935c127a02d2d8164243bb795)
+- Avoid crash on Surface3 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1473daa0a8d2a4c9a0a7b5330be771acaf5a295a)
+- Merge pull request #314 from ben-8409/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2af63247c8f379bedbfb323734995b7420005367)
+- only set cdvMinSdkVersion if not set or smaller then 15. Fixes #275 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5513f5c99d9363582e5e77a77b0b6fd3ac8f85c9)
+- Merge pull request #183 from stigok/readme-update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/97a29911c49ad7aa4406ae99a9b74219212ee608)
+- Require camera [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5e58c0a1b8dabb301836440d6765f2423b3a9482)
+- [#277] - fix for crash on iOS switching cameras [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6c3d74dcbde681a464ba0abc29c5a3d084b09739)
+- Crash fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7841f6deba953121bc6d74bbf60d3380a466d73f)
+- Reduce memory consumption by using smaller video resolution [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/89a9c69f6d2ba2d0e3d5ae25d937d3772c48b67c)
+- iOS: Added permission ckeck and fail if it's not permited [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/59301afe045509f53d44c2f17bc7cd9927c357c1)
+- Updated version to 6.0.1 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3cf975bda01cdddd71b03d74ce31c97595ae98af)
+- Merge pull request #285 from daserge/visibilitychange [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9d4a96123030f71f2f85676c61a4bfb8b3846592)
+- [Windows] Handled visibilitychange to avoid camera freeze on minimize [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/005c30309d3c0b371c5fc4ceceb2ab8f7f2ffb40)
+- Merge pull request #284 from daserge/version-bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/11dd6b5ad2d3528df57a63f3b6ff093452e3bfb9)
+- Updated version to 6.0.0 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0f534db7e2dcee9348a2e707c7f47ebd0df48b8c)
+- https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/270 iOS 10 requires Camera permission reason [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2895b3b85506dd7dd91c93a741e1cc13acc59f09)
+- Merge pull request #263 from daserge/check-arch [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dd85e2530d9638ecac2774c2a00a7b9ec2a573b3)
+- Adds a windows pre compile/run hook to ensure an arch is specified [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49e33a85a08cfe0b1c5559d24d7f6f42a60334b5)
+- Merge pull request #269 from daserge/win8-deprecation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/865e1b678fd93b1f712084d65140f41f6ebc4a29)
+- Merge pull request #256 from daserge/cleanup-on-events [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d3344f2d0a0666357a2e9bc4230902227cdd039d)
+- Retargeted WinRTBarcodeReader component, deprecated windows8 platform support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eba7eb3a4cc9f558feed571ed589134fd3a7cfa4)
+- Merge pull request #170 from jcesarmobile/callback-with-blocks [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ae9f6e2a2e14aa0b16d86c039ea50ae1183f7bbe)
+- send callbacks on dismissViewControllerAnimated completion [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/21152cf42978623ae6c67488124fb6474342f9bc)
+- Merge pull request #266 from daserge/multiple-focus-3 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d92af72bd1ce76eb2f40b6fbb0a32292b4fa8817)
+- Merge pull request #267 from daserge/multiple-scan [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/78a53459d3c0b9abd6fa510571a422e279dfadde)
+- [Windows] Focus fails on multiple taps [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f18ed1a78c3b720ee88497b84734bcd77699ea2d)
+- Prevent multiple calls to scanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2aa5bdcda508bd4164326298da18638f955e0873)
+- [Windows] Cleanup camera on app suspension Save/restore scanning state on suspend/resume [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49489db0678e6e80a3b0744533d432681b9cfdb7)
+- Merge pull request #260 from Telerik-Verified-Plugins/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/55e693843e3a556ee9ba9f2dab13fd9ca652396f)
+- Stable plugin id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/363335c13b96f7f2c5a728d99a8be137b6601e34)
+- Stable plugin id - revert after PR [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/be3e490b95b99078740f473466b60cb0c7348796)
+- Stable plugin id for PR [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/73c32f4e62467694ecf725e5d9d307d3ed94a3e1)
+- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c0546f71e60991ff2dcbbde2d1e23443db5d19a7)
+- https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/40 https://github.com/phonegap/phonegap-plugin-barcodescanner/pull/171 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e9f1b1bfe18edfae2db087f91c9112b82909bd83)
+- Scanning crashes on Windows phone on device rotation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c3bcd87e1c66dc0fca7c04a2bbbd405ea9fbed2f)
+- Merge pull request #257 from daserge/multiple-focus-2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/45ec98fb46e4f5d18bbc5fb4d6627065cccac248)
+- Added missing CHECK_PLAYING_TIMEOUT Added a timeout before initial focus to prevent focusAsync hang on slow devices [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eb31d2e3416f64bb3312ed639f2fa046b4551414)
+- Merge pull request #250 from daserge/multipleFocus [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e65272ad4536bc49200d4ca8b23cd970d7a118db)
+- [Windows] Focus fails on multiple taps, this closes #249 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b836297ed5139d495bd0f0b4aeabaaa9734e4154)
+- Merge pull request #251 from daserge/close-button [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/128c80f63ae2aa490adbe0c27250598fdabdd722)
+- Merge pull request #253 from daserge/win10-CameraStreamState [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5161af4c7f92d7b0edc71230f6b43127502e3568)
+- Windows Mobile 10 - Close button does not work, this fixes #196 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/942d1ed199ec0ea7488bcf3d8ec0a9d6b711ec82)
+- [Windows10] Fix The request is invalid in the current state [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a3e4fd532fba820979046b85e573529742f3b62)
+- Merge pull request #252 from daserge/css-fixes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a3d4dfa18adeeb6ecb62a40ac0492d9825372458)
+- [Windows] CSS fixes - no-select, no-zoom, no-scroll [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5364553b1e00d4515dfc5293f4baae3629d8c48b)
+- Added a note about PGB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b20c04648b4cfcd1170e098c257e535cd6762f72)
+- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ce0cf94603c526a261cb80654be19652eae9d239)
+- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d4b22bb0094fc216a7837f61ddfabb91b4f3450d)
+- #221 updated version to 5.0.0 for release [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/27227e9d2b00174e816869bc6123071d470ade87)
+- stable plugin id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/762dea0958937ee2cc1b76831312733bb59a401f)
+- Merge pull request #217 from Telerik-Verified-Plugins/merge-phonegap-official [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bd6c295908a22a23d1a473f39db39956e6bc62bf)
+- Bump plugin version to 4.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0cda49bfe1229977d6bec855942c199d5357c7ee)
+- Fix iOS issues after merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/06f4a7d04bec902ffa2109b79602f3955175a17a)
+- Fixing Android after merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5641c8ea17d036f806fd2f15763ce16cc79ada3c)
+- Re-added old platform files we removed after forking Wildabeast [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/172f164b68d620699ac14bcf6468a21a65a57ada)
+- Merge remote-tracking branch 'upstream/master' into merge-phonegap-official [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6a7d7208b15000e004b894184860cc0f298b6e32)
+- fix Android M permission [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/29d3308b7d46a94fbda10945d3ecb78a7d6d1c08)
+- merge [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f0ad027425313f3edbfb9350ab81068ed4898894)
+- #28 Plugin renaming my app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/55b716ad8e6dd4bfad1921d2efa00eec45fd414b)
+- #28 Plugin renaming my app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1778bee6b028081ff4761c32748eca0c939b4368)
+- #10 Warnings on IOS 8.4 when using library [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/57babcc2beb1f6f2d45b738b126e4588b1b1643e)
+- #26 App crashes if the CordovaActivity is stopped during scanning - Moved `scan` to a background thread so it won't block the UI for about 50ms while initiating the scanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0bf407951f13759484a8fd2a77e6c3d1fb8ecc1)
+- Documented the new "orientation" feature for Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8dea274bb72d01039173c305cc4a276a9985a5c2)
+- This fixes a few issues in our fork: Image upside down on tablet #20 Android UI doesn't support Portrait and is small #4 Prebuilt Zebra Crossing (xzing) Library #3 Forcing landscape on camera android #17 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/25e00cd9e2d3a6789663ef9c0b9210f5ebf6776b)
+- Merge pull request #206 from sarangan12/Windows10Fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a5e289085e8a9a11b4863d7ddbdfcea58b22510)
+- Fix for the crash in Windows 10 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8e46fcb76d49c76f4598be195e489cd81fc29217)
+- #25 iOS app scans randomly UPC and other EAN formats when scanning EAN-13 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dde3c197026412811e719e016d2adad14330ad78)
+- #14 Cannot read code_128 barcodes in iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c0673038124e623e2c6f6558b87f75dd611d3171)
+- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b8ea34e5ac4b4e7b34b991e4e1065ef8619f776b)
+- Fixes Windows Mobile - Issue with Orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/383406708e265ef4eddea28a3c07163fc4787519)
+- Merge pull request #168 from MSOpenTech/escape_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d1dcfe0763cfdb24d0fc1f5c5811dcd05bfa74d8)
+- Fix plugin installation failure in VS2015 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4c0dcf4b27e9c6c4851f0b642a9436ab1c85bde9)
+- Merge pull request #135 from MSOpenTech/windows_refactor [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e22581cb56e9c6a147860ee6e6f4ce4991186493)
+- Refactor windows implementation in promise manner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0d01bde3a6ce1e499099d051d3fb54111537cf9c)
+- Merge pull request #134 from MSOpenTech/orientation_change [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/02c67a20d9f6c59388a1be8f71fa568358f984b2)
+- Add support for orientation change from #62 and #97 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/51216ff3dd0375a694eb4f9352bb78046ae47505)
+- Resolve merge conflicts and address feedback for #62 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cabb67e6425e23366ebed47b58ddbcd93c6925ee)
+- fixing issues for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d68cdce6f920c3db0bf7a1345f60a6fdabedde95)
+- Merge pull request #132 from MSOpenTech/windows_barcode_format_fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b5739fc692ab30e807feb7530d618ec7ba7ac8e)
+- Correct scan result to expose format name instead of format code. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/dc84cac7844d3fdf64d3bfbdf0765930bc0a6b9e)
+- Add information about windows 10 support to README [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b25d71061693f716658f0769c9be789b58b2b65e)
+- Removes intermediate winmd component from Win10 implementation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/521d427ed418d2288a1b31a11398b99f54fb1f5d)
+- Add Windows 10 Support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9c2da016e4ddbd973a596568c750b7bb48ea4409)
+- Merge pull request #131 from MSOpenTech/backbutton-fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9dec84ced0050f7f7221bb49d0fad4f39ccb819b)
+- Improve native look and feel for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/23b4343483104b21ce501f481e0001827f7f994b)
+- Merge pull request #128 from MSOpenTech/autofocus-fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4606ac6d2465e83742d436cf351902f2f09854b7)
+- Rework autofocus logic for windows. This fixes #41 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a905251130a5a956d28ed849bef69a3d6df6dee9)
+- Merge pull request #127 from timwindsor/barcodeEncodeBB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f4d5d5c638085169c10d54dde887b6203332a6ec)
+- Merge branch 'master' into barcodeEncodeBB [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d9f47951442cefe939a61d1f9c5ee72316d82863)
+- comments [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2219f194a6c4b5d87a1fb7d5bec2e60b91f41c07)
+- added data type check, and uri prepending for encode method [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1cf63768bf5b3e991b2b62d9f34f1f1283f92ef8)
+- error checking, data validation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d5e84c9f09480a0f5f2782e206c61b0cf92c8c37)
+- qrcode encode working [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2830a6d85c8be6f07aa503931c702e5f7444c879)
+- encode method or blackberry [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c662c85c9db8b43bc259e966a40203b74b8552f5)
+- Use maven reference to android-support-v4 library [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fb0a4f80092ab173366c98c6a1555bbed0ad864f)
+- bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/df1210276412c72d428d13d382141a200e811986)
+- fixes #162 button bar not working in ios8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1f51bb9561c92be3abf676dd56b82c86f207b204)
+- #15 Android M (6) compatibility [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/82bd97ef65b4b609a8d7a8be5a8068a5961b7cac)
+- #15 Android M (6) compatibility [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f028ec469a60031e31033fc2d44fd69358d95be0)
+- 4.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6b5f7fb7626f24b45fb643dcdd841e3fa0e5361f)
+- updated to version 4.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6452c9802f0e0a4b686e5b94f043cc23d2380acd)
+- Ignore linting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/64845f4cf4726f1b50610463daa703b7a3a7f649)
+- Removing custom strings [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/607efeb158f12e651e8555eec9abdd8d9480010a)
+- Merge pull request #78 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/940e98babdcc27e8dea6120a42412a3b8161e9ca)
+- Merge remote-tracking branch 'phonegap/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/28174b118447b86bdf4acebbc24913775db3fc7c)
+- revert obsolete workaround. Fixes delayed error. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b8f2fa5c4efcc72732ebadb8bb304cc46465e93e)
+- Parses result so it's consistent with other platforms. Removes obsolete, unused file. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0632e345a63b22e4a52b250cac427f9649ab9858)
+- #13 Cordova-iOS 4 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/de5700cc233cc845453bb98356e7b2cce67b6d92)
+- #11 PDF417 support on Android. Version bump. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/009175b0ac39f8eea71c928708af97226a636d44)
+- #11 PDF417 support on Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e413345fa765c61d46c8c5437eb08d754b9c4dd1)
+- updated version in plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/74f33d5d14107915c357753684e9276eb37a3f66)
+- 4.0.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/07322cb29310ad1f5b19f43472de8b86c558d19f)
+- Merge pull request #66 from olimortimer/patch-1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/346472ff22b94f94cef25dea9f6f7eb851974c43)
+- Merge pull request #52 from nlsdg/patch-1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/001a1be747183e5b727d367236ae477dc9b49613)
+- Fixed iPhone / iPod scanning issue [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c92bc8ac49e72a064093e83da4597aba2e68dab7)
+- Add BlackBerry namespace [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7175796244403b9b3de42ac5c1df2ca576606678)
+- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/49571fbb7b79742481c230daa7b146cc7b2d9e7c)
+- 4.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f72bc48f7508c84a52a2cbe9e31c31408063def9)
+- #48 fixed version in plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b7c4c6d8751005a0ac762d29f179244dbe68866)
+- 4.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b005d77852b22073c1b618ddec0d713453f5b69a)
+- Merge pull request #32 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7bbc73c82eb3dfb41c285103771d11451a1ae666)
+- Adds blackberry10 to package.json [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/0ecd01e1104b4a89efee38ec598f89a6a1b51cd8)
+- Merge pull request #1 from timwindsor/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/30196b3dfc2ef0f36c30253f6765cfbde283127b)
+- Completes merge of BB10 implementation into phonegap API [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52b5adb8d40e6116c20df2416cf1a78ec24f4b7e)
+- Unifying API for BlackBerry10 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/02c5ba86d5752df841359ba42df32db0b74ff10b)
+- Restore location of BlackBerry repo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8cf9df1c65d047d61b3dc6a59c30f1dbda4f7f54)
+- Restore location of iOS and Android repositories [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d801b7687dcb7b02ce7114e166d0cddf82adf12f)
+- Merge in BlackBerry 10 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6043674b179295489936ba81b8fd5ff1ff2fdfa8)
+- indentation fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cce09e379351065a303ad9af93dd463fc049da53)
+- stopRead error handling [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/66e572e3eb3f0febfa52b5ac2b334bfde11f2557)
+- Merges in BlackBerry 10 support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b320e1dfe3216937dc0bb77a4ba65d790169bf9)
+- Android 'encode' crashes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1feb36d34313077c2dd145c59d9009088542d347)
+- bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c484e0a754d67e2136ade27b9a3e4a4d115253e6)
+- Android 'encode' crashes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3632edc0cd0aa85b6a04d3f6671005a6215f6a82)
+- Ugh, AB build errors because of lint config [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/31a7ebfcc2159e5c5075668bba508e67bd00db30)
+- Ugh, AB build errors because of lint config [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c5cf295c7207ea3433f21b7319f1e29d538911a2)
+- V3.1.2 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/70ca00be45a675b1b1d6963ad6f72430e579788e)
+- Merge pull request #7 from mlaponder/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3d96f565e450f50fe0d36fb6d119c4e0d0268147)
+- Update version to 3.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/405c00b616a41dd6041c5daf359795dd7e4831a4)
+- 3.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b58323f54c72c0e93089d1e1fb81592a708309b4)
+- Merge pull request #6 from mlaponder/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9d12d19f9af5ae9379b8c11b658079e234b39d9d)
+- Fix incorrect uri for wp8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5f1fb8865264576b8be8b6bdce7a4e34d40ee8ce)
+- 3.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/78cc3fbcdf6f21e35614578409494d767193786b)
+- updated to version 3.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4647c48c2ee683437f36589a3ad27868698840e7)
+- Merge pull request #4 from komola/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/41c6e8c475b5028883478f22ed6694502e1b6b9d)
+- fixed issue with readme [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5fbee99fc7bf561f99f7fcbb90ad8b41669797a3)
+- added travis-ci support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/616a2700f60e3789505737330bc6446acc42c7c9)
+- fixed tests, made compatible with cordova-test-framework and paramedic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/652d50967a8754a623e3a9de04b8b9565b4aa06d)
+- Merge pull request #5 from stevengill/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b17891c002a04dc31c24e66ca5a50f31254d0e98)
+- updated ID to phonegap-plugin-barcodescanner, V3.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/50d3f0a23bb1313d128c00d9634f8ef6f4d7cc3d)
+- removed cordova.define from js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/729f2caddd96041dc671188cae95648927fcb860)
+- Merge pull request #1 from trongrg/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/262ef2b03b906043c05ca4f2283300eaa0fdff8c)
+- Updated src/android/com.google.zxing.client.android.captureactivity.jar [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fa13720cf7cf664f6cc7a6d5721038d4f0e92ad1)
+- Remove unnecessary retain calls [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5fce7a4d78c767e2e32e1d6173743c138e230406)
+- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/408adbf364c4336901d017d5176d27721271a439)
+- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f412fbc0db37cba9d96df3b6502715150794a70d)
+- [#4] Android UI doesn't support Portrait and is small - support for 320x240 screens [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6c120b984c2adb86cfd8c2cddc55cf2719e17731)
+- [#4] Android UI doesn't support Portrait and is small - portrait scanning of non-QR codes didn't work [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e197d222cd6b6c879eb0fed79316ee960674736f)
+- [#4] Android UI doesn't support Portrait and is small - support Android projects which have not set targetSDK (crashed without it) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f74da676341aaa9a9cfbcb23440408e35449fbd2)
+- [#4] Android UI doesn't support Portrait and is small [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a250540bec7b179820af584f3b714cc7920b1eda)
+- Restore MultiFormat Reader [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bd459f4b9c5aea7e7d20b7e7aaf7d61847ab48bb)
+- Merge pull request #1 from MSOpenTech/2.1-windows [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4e5af0ca1b782fe4c54f9f849495d5678edc95b8)
+- Include winmd source as subproject instead of prebuilt winmd [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/21083d4974e471e9233f66ed8b84f53df74b6eea)
+- Merge pull request #2 from MSOpenTech/2.0-wp8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/47aa58873097ad763c932c2fa2d7e0e0aa442ae5)
+- Check if the last n scans returned the same result  and only then accept the code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1d264dae30895a3edb07938c95c9902ef0ad69c3)
+- windows: fixes "class not registered" error [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/96284b34430dd8824c517a24eef8fd23046b6de2)
+- #616 Use single proxy for both windows8 and windows [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eabae9e10be2e21f8c5f917748bd769c9fe11b43)
+- #616 Adds support for windows platform [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/aa80367059e1a6c68a0947d56a7f6d63e896177b)
+- Windows Phone 8.0 improvements and bugfixes: [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0b2b27a77e02af5afec0cfd6c3566d1a3f65d62)
+- v2.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c74e37a40cbf5ecbec5be8f6677e3bf01f0920bf)
+- added support for adding config parameter which is passed to barcode scanner activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7773e4dae0afbe85ee50e3681df9ffbe7611a04e)
+- Restrict to EAN13 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f70288d7b27cbe96d134db68c5bf517f85ce8e92)
+- v2.1.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7b3302282215b4d41e1168cbef8af9a3abf122a6)
+- Played beep sound after scan succeeded. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b1bb4fa2fad9d27bf5d25b8aa2f7872c92ffcf2b)
+- iOS update encode method return format [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f04a2a0e4c8bc9c09d76a725ee771423e042837e)
+- Add QR code encoder implementation for IOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b10b8ae33fb672018fa9230079d8c6f096c4b13)
+- fixes #162 button bar not working in ios8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a1f216d4413596ca18251c3fe543f862acf972a5)
+- fixed size to int conversion and cordova 3.6 deprecation warnings for iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c2dcd871d25b480dfaf65b2eab878bc5a4775746)
+- Removed ARC code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/22a23b171a89322709bb1020fbdc02e90a079c21)
+- Version bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/30236cda293f6e4de564e3adfc7fb847e1dbc0ba)
+- Merge pull request #9 from galexandrov/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/35ad6da69b10f8107ad90491b4afb25ca9f5d971)
+- Remove unnecessary retain calls [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a44f7403649e7727b2b65a72585e631d703386e1)
+- up version to 2.0.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fb600c1710ff2f786a1c3a31cd135d69846817fe)
+- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/044de265661e17abb0aefcdf8230d9e357b6cfc0)
+- [#4] Android UI doesn't support Portrait and is small - support for tablets with default landscape orientation [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d0aa7d75ee35fc951d66b3b094deba00ef17db97)
+- [#4] Android UI doesn't support Portrait and is small - support for 320x240 screens [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7e60c7c1e830113b34673784ce0764ae450e7dfd)
+- Support browser. encode is NOT ready yet. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/116a3bb4e797b75292867900b626b8f2bae10fb9)
+- [#4] Android UI doesn't support Portrait and is small - portrait scanning of non-QR codes didn't work [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fe7746456defcb7f6d16ce4b023712c515bdb748)
+- [#4] Android UI doesn't support Portrait and is small - support Android projects which have not set targetSDK (crashed without it) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/20799f14ade1e2a1399428377fdea2f608c84b49)
+- [#4] Android UI doesn't support Portrait and is small [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b163ab694f1e49ae1667a2e4635f43a1bd6de74d)
+- Documented new features [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8b9d6a5835b5c1a7f487b9ba38a5cb4e4d323dd9)
+- Merge pull request #2 from EddyVerbruggen/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5f37fb12c6081809aa237b7896a5e7b26b32eeca)
+- Added option to select choose to show a 'flip camera' button (default: false) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9f194201327ed4cbe0eee21f67ed38496e2a5003)
+- Added option to select frontcamera via JS api [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/80a828516c1512964a85e0f2fdd44e09d206e418)
+- added repo + issue tags [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5268a02fd7f6c96aa2c2bc022ab777e89ae6cc23)
+- Upped version to 2.0.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c3090dcf5347c1cc10caaeff225bb2c0a0deeede)
+- [readme] fix encode example code [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a0978076fab0c5180d4c2989a4a3844a980fbe2)
+- Enabled ITF support [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/740aa3a33b55c5d51ae07dbb8bf40620bdd7b7b6)
+- Added support for front face camera.  Signed-off-by: Emil Marashliev <marashliev@gmail.com> [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a209c6d396a53c6304582f89f59300066ad56149)
+- Updated link to Cordova plugin spec to fix 404 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5a7aa5c29d98679513209247e5c65559cd2e275d)
+- Updated README links to the original iOS and Android repos to fix 404 errors [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a8c2a2609399cee2799c873863257b9ce870ac80)
+- avoid calling other apps activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/84af3e9f72bd12f172853f6c091b08eb556572cf)
+- [plugin.xml] updated description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f766ba2536b93cae56875060bf25af55cf80c178)
+- [plugin-xml] upped version to 1.2.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/552974245e156960bc48b991520f82d696d125b5)
+- Adds documentation for Windows Phone 8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/602dad12e506ec0f8601d144d1fde716d021814f)
+- Adds support for Windows phone 8.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b94b4f67c417d431094da193f2a40da7876b498b)
+- Adds documentation for Windows8. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/74f78db8ac7fb6b5aec25584a5a9518286a1de9d)
+- Adds Windows8 implementation (scan method only) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a7d7610ab8b2c0c94feecbaff854c564018ba9d)
+- [1.1.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2a2fc654bcc2a68598d04d417a84c5a64fe3fb24)
+- [js] plugin.xml asset backwards compat [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a6ed222163792190ce5b4b684b6ad746bfd7662d)
+- Compiled jar [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c93d7569c4fb88baa8a2546e5c278249f7961887)
+- Added a flip-camera button for Android - missing icon [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/332f12fe9c79a7a8210914f747ce8353368c1266)
+- Added a flip-camera button for Android - missing icon [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/48be871057bac642724de63c1c3707c99f9976ab)
+- Added a flip-camera button for Android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1a2b8c6126f9d61ff229bbee2f9f8109a78e806d)
+- Front camera scanning for iOS ([#108]) deserves a version bump [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/98f158aa4dde990c6d2bc89ff418039c77b6e15c)
+- Added support for front face camera.  Signed-off-by: Emil Marashliev <marashliev@gmail.com> [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d3c8ad2df92743bc8fd038ec37d89e0bce2053f9)
+- avoid calling other apps activity [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ef1155d09d53856b4d8dfd6326c734e05e702885)
+- [plugin.xml] updated description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cfa698d93773fa7d737fc1adf02d6a2e46538d09)
+- Change plugin.xml to use framework element [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/619f6984c3db640c14fa2505d06b659913018137)
+- Change barcode scanner to work similar to the iOS and Android versions. In plugin.xml added reference to ZXing.Net so it is refered as plugin is installed. Similar to other platforms' versions, there is a focus area - only this area is scanned for barcodes. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3a377ef883d0e5db138ed40f5e5f6838d1407f3a)
+- removed unused reference [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/05a5a17eceed4e377faa9674b2f3564ca37b422e)
+- [1.2.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/53ad095e86434adc7694b8a26bdf16d6c381238d)
+- ignore Intellij module files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1654970ac5b5b89c4e5008d71f93a755df71add0)
+- Updated Plugin, refactored some library parts, added description to read me [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/719f19d3f003a19313d29f81c8d668030980db7e)
+- added windows phone version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/039d1d0ea45d75902c748ba9f7f115a9b94887c7)
+- window.plugins is not defined anymore, replaced it with cordova.plugins [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7d831d83ed3967ce438551bed1b8a86ec2f7fb84)
+- Add missing iOS framework "QuartzCore" to plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ec4de624ae9f68a59557f21a1a5a4e18d3cfa425)
+- [plugin.xml] corrected supported cordova versions [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/24acf29896fa39578238a0269c9b1a3d643c6a3b)
+- delete plugin.xml.generate.php [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a310fda2d7d55e650a65b9d0327eff87356c0818)
+- Use <js-module> in favour of <asset> for the JS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8bf3cce0737f7435b979b55433c87657dab792a1)
+- [readme] fixed encode syntax typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2d8701634f4d761f3c3cc961d8eb337b44de79e5)
+- [android][0.7.2] remove busted menu items + fixes #11 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7880bf7b5c4a619acaff8e8b905e0710eb3f41b5)
+- [0.7.1] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/12a31b76b015d3218874437a37d9a78fe710b161)
+- [README] fix typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a2857ba5f8ed2a4ef7277fae8dc108239a2f15ee)
+- Merge branch 'ios_warnings' of https://github.com/agrieve/BarcodeScanner into agrive-ios_warnings [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f046f651ceb06e35a6867e3e3df0cbb2c58a0f13)
+- Use <js-module> in favour of <asset> for the JS. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6ad6dafc1169d62871663d013d49312df64acb2b)
+- Fix plugin for iOS on Cordova 3.0 by disabling ARC and using newer plugin signature. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/14d63e35ac9d1333f178cb3ae95a88b530d73538)
+- Fix some compile warnings on iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d901977064078efec335f3309c30bc8038372447)
+- [0.7.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7094cc6eda5ef8a225c550e463bc49907c36ac40)
+- Cordova 2.8 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fc3dcd56d1558415043aaa538c724426b6caa726)
+- minor [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/50a2f8bf5236e643635caf8cabba5e0d2df8ba69)
+- Merge remote-tracking branch 'upstream/master' [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8966e5207fdf506f5c94a9dee9f9e25b847aa5c7)
+- ident [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8fa142ca9d1d400ca91d651865b6eb5d9f79d204)
+- Encode object access fix. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6fd905a8e60a0341fc4a4453f594222eb7cd0b8d)
+- 3.0 fixed README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/32880fc1fa78dd0911a66c86895303d7479a2be5)
+- typo [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/903b02f142534057cb02d79772d874c37fdbd553)
+- Fix for https://issues.apache.org/jira/browse/CB-4379 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6fdac151eb089043c6147e6822e46ebea4604375)
+- Changes for crodova 3.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c84bf0e66d0ac14b44283261a2a3c9813e4750db)
+- PG 3.0 changes [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e728d331554837a3c905e569a579f290125d4717)
+- [readme] correct ios supported formats [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1242c551424e31270035929c024b4d7de55ae9ef)
+- [readme] plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3b1ad506b2a4e387405f62263ec3b5dd550775bc)
+- [0.6.0] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fab895ab3002da39e3fdaf0f11eee2a3f8ad4e9d)
+- app_name fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c5c60c88568b78898bd08a042b5e0087053cc9b1)
+- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5b01acb999fcc9f5316212a8887fcd29ebbf78a5)
+- minor refactoring ;-) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/db30964d5113d4ac4a63fe8997165d07e7bb9e20)
+- plugin spec. update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6e29489982aae3f761195647b18c8c1ccd2ff850)
+- Update to 4.3.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8c50a121e87425ffcf4c09f7c4a08669c7bb7a71)
+- [plugin.xml] update license tag [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e2cef45cb8b2a85f6979eee17dc96a6ec55d01e5)
+- [plugin.xml] license tag [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c24882311fc880f4881dc02bcb14f9816d1808cc)
+- Merge branch 'master' of https://github.com/Eccenux/BarcodeScanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5833a1fa9e5adcd1f823e86b76a28800af1980ae)
+- app_name fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9ed602fdacd4da7e8b083946089a4d04b51a46fd)
+- Update README.md [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/06b05fc6c98fae2b7c45502d6bd1ee315a339265)
+- minor refactoring ;-) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2f86c728e5953a35efe236e293a0eca48353be2a)
+- plugin spec. update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/01a74e4c6c198750dc9149c8e90bd363dc0670ff)
+- [0.5.4] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/18f2f7a9fe67ac42a1deafb11992050009df2ea2)
+- Update to 4.3.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cf2be813cb3fb28b61fd2fedf4803ed70d2d5c16)
+- Merge branch 'master' of github.com:wildabeast/BarcodeScanner [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10d66a4e67221957a8c5b02e7cd05b25539c4970)
+- [readme] reference plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/27d6d653fc51e6cb2eca1a7e610934d7f0a140a4)
+- [plugin-xml] added engines [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4efcc86a24144c40fd60e372f0a4a6d02ce8578a)
+- [plugin-xml] Add description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d38047b41fe4bed48b63249c1ce12b85f252089)
+- [readme] reference plugman not pluginstall [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/af21cd20f6c14bbd803e83f904573c9af9de225d)
+- [plugin-xml] added engines [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e38147f27f661137240b6ff673a08ca6e10c9c6d)
+- [0.5.3] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b45ce29fec8f2c062661670a5651684234545b12)
+- [spec] update specs to cordova.require/define [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/77d4a3dda27a10ec956c1e9e5f3281c76c54a25a)
+- [plugman] plugman don't like spec/config.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6f4e09be4f2e0fe17a3372bec5cb2309372395d7)
+- [plugin-xml] Add description [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b0747cadcef11fd1fd90fd94d0ffc8729e8256d3)
+- [0.5.3] upped version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3332885acd3072085dbbee8bc6389d83ff18dfcb)
+- [spec] update specs to cordova.require/define [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2331218b5a597d1c5888e66461a2d4bd7358a8ae)
+- [plugman] plugman don't like spec/config.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7ec3d477c208d7476eede4959f8675c6be1cc5f3)
+- [js] cordova.require instead of PhoneGap.require [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3ab188539c8529d4fa79497abb84f509d1411318)
+- [readme] formatting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/d9f9f2dc9bf5ede06df8b5d9f407456b8c938582)
+- [js] cordova.require instead of PhoneGap.require [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ea1586b0ffbf9a6774bcedab1f988c4f3d8c7fcf)
+- [readme] formatting [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/10f8e6b1164da3e108f3e8e52ca8953e7980c0c4)
+- [spec] FIXED IT [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6cf71f0a3ea1bbfa06806ba1d447a96321eec02f)
+- [spec] 2.5.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6d95b33987c1ee5d903ee51dd1ea496d8d786ae5)
+- [spec] removing a maybe bunk spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ec5e1dc843cf6f9c4090d597efc03a33a50373b0)
+- [spec] removing filsystem init [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/507c726215846a56c30cb85d309588166ab95ab9)
+- [spec] more specs [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/fceafa235a14a3f4d783c02e9529a1f96ecd64c3)
+- [spec] formatting for medic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/666387e132148cf332d5dd7cb3e379a735bca23d)
+- [spec] app id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/eb557c48279ebcc5147e474e73c4f374c1b9ec63)
+- [spec] Fixed spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/33b2e914a4420024fde9cb2206ac2f9e32bf7931)
+- [spec] app id, title [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/657ec4512268e56d5478bcc93c8a018da026dd32)
+- [spec] fixing spec app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/52ce70de60d6ad83b05e9639777cf8fa1f9126cd)
+- [spec] add barcodescanner.js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/ab95b1342d0ccabcd006f5691c39875c54c68c19)
+- [spec] Initial version of spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7e7c39dda69bd64359a8963b3cb5aa679b6047c9)
+- Do not copy the scanned barcode to the clipboard. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5c46e8d93f0b711963e88248f71a7be6babe6b75)
+- readme fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3bc65ebbaa3f0e7f96948b7a3484b9e4e9b3ea7b)
+- Update for Cordova/PhoneGap 2.0 plugins (http://simonmacdonald.blogspot.ca/2012/08/so-you-wanna-write-phonegap-200-android.html) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5d6f0d52f9e495aa34f9d6fec9c77743b2ea6c9a)
+- fix for a java ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f26cde76f54f3377d2e385c9fa97ebc65886d50c)
+- full paths for android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/5d452348dabed181cb3a8b970d94c9deead44be3)
+- fully qualified paths [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4d8646e26d9ac7008b6b1ba75c24de40960b6ef8)
+- Merge pull request #3 from filmaj/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b1f643f6f48c0dd7909c1e45da3807b35b2769f5)
+- fix for a java ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9c533da17ed0554394fee2aa98f79b4caf56a574)
+- full paths for android [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f568cc6d3e63837ecaa057b666d1913cad2b0e43)
+- fully qualified paths [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/215e077510b26981007500af27e503cc3f6211ae)
+- [spec] FIXED IT [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cc0f7d82a1723616033be2b25ad554fc614b1fe6)
+- [spec] 2.5.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f94c6129ae6c336660a240458b3371a1c501dfa9)
+- [spec] removing a maybe bunk spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/4579d40dc05964521f1e97026810d439e8e7be58)
+- [spec] removing filsystem init [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/40849d52d645ac5bda784ce44de2b18bb1cfac61)
+- [spec] more specs [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/2f7d652587b234362cc86c5205fce9ac10814c13)
+- [spec] formatting for medic [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c1d0b47929171a45df1bbe9ff095e128d4e7c74e)
+- [spec] app id [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/381ee1c6ace4ff2919ea0d33cf770700f5e70c2f)
+- [spec] Fixed spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/560cecc5b83c2257215398a9bee5ec12fdfea0b3)
+- [spec] app id, title [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/a0373c766fb8d9fca0c01a9b5dd1c0bd3c1161a7)
+- [spec] fixing spec app [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f9e3d0cffa88a09941aed82f515edeccd8773ad7)
+- [spec] add barcodescanner.js [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/604ebdf14485736b7d543812017812a40cada2b6)
+- [spec] Initial version of spec [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7c47973f78d6caad4b3c92709d0d82d59a4fb163)
+- update BarcodeScanner plugin for 2.5.0+ [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1661cc4387e1e4110f88b4ef561453030d795182)
+- Merge pull request #14 from jwark/do_not_copy_to_clipboard [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/15b5cb9442e1c43ce306fb91f8e2d07e42dd1244)
+- update BarcodeScanner plugin for 2.5.0+ [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/58e773af70c59d04012d51ded8ba408037142f95)
+- Do not copy the scanned barcode to the clipboard. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1d8ee5ca8d2e2878b82e4db95d7465c15c6fa5f4)
+- Merge pull request #7 from JaysonRaymond/master [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3c73e21796118c3a97ba944e67d6a06c80ca08b4)
+- [iOS][2.3.0] add plugin to config.xml for 2.3.0+ + upped version to 0.3.0 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/bb3812c0cb7b525065101c251b211e320d76c45a)
+- readme fix [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c7158af58ee9aeb0e325ae733c4bbfd1db51e563)
+- Update for Cordova/PhoneGap 2.0 plugins (http://simonmacdonald.blogspot.ca/2012/08/so-you-wanna-write-phonegap-200-android.html) [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3f166162a05c79782cbcf162154f16b94efa2609)
+- [0.2.2] updated version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/029cb4de7d30953811690dba6939b88d9a9ceca7)
+- [ios] Fixes AVCaptureSession leak, thanks @markus-olsson [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/1e2535ad010e94ee0319f727e0f444035b02742d)
+- [android] syntax error, missing else [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/695f524777f9b0ea49dcfe3e980a5053da2e3e4a)
+- [0.2.1][ios] lock scanner to portrait [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/084594d86c7cafb98f0985101629fa910141fa6a)
+- [0.2.0] updated version [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/87ffa13f2c5e63e7388ef37bacf9b02ead8fc0d9)
+- [ios] lock scanner orientation to portrait [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/413b0236978186d5c2e3b2675c72997867bcee6a)
+- [0.1.2] version update [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/566c1f166a27108c995fd77d5fa20454c7311196)
+- [ios] Integrated shazron's iOS6 orientation updates [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e0f7b9a33e647b9763934c09259be01edba88d5c)
+- [version] updated to 0.1.1 [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/f1fb499e42f31e06d1805dcdf40bd3edcb0fd384)
+- [android] Removed app_name string resource [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/b145a21012f1b997e0060f8d1c0e6fd25add1cca)
+- [readme] corrected supported types for iOS [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/7119054ce63bffdb3bfb77d97aec12307536d795)
+- [readme] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9211290b7656697f7b7a87a05b77286d1f85b2c8)
+- [readme] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/89ed3727372815966fd83b2b925b51d22a18b001)
+- [0.1.0] version updated [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/3e3093969f0544ede202e6646a655da6fb22f1ac)
+- [android] Added translated resource files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/47a8bdd29c277e69ab1750b94b3c4ac5c01ba19b)
+- [android] Modified zxing client to access resources from main package [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/9cff772bfc4f404337830a974a9593883cb81d23)
+- [android][plugin-xml] Added resource files [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/e3505aea3a65a967e7bb710f77f94d05fc556409)
+- [android] Added Zxing Library project [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/8421719edb1f7005b3a2a46a24c62d2d69479d7a)
+- [gitignore] [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/c432f127c593791aedc3008a83f7a1a818568700)
+- [readme] license [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/274b122932517ccea144d5e279c38beb4ad991aa)
+- [plugin-xml] fixed up plugin.xml [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/097548504dd6c192e26256e582882e6b5f12daec)
+- [ios] removed CORDOVA_FRAMEWORK ref [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/cb2e830ee5223076c9f126d80e07ef614ca3cff1)
+- Initial commit. Zeppelin rules. [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/92197289049bfd4aab63b6467dddb93449a8a7ef)
+- Initial commit [view commit](http://github.com/phonegap/phonegap-plugin-barcodescanner/commit/6de30878ff7ada1b43a01d1037dcee6e419a8050)

+ 22 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/LICENSE.txt

xqd
@@ -0,0 +1,22 @@
+Copyright 2010 Matt Kane
+Copyright 2011 IBM Corporation
+Copyright 2012-2017 Adobe Systems
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 241 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/README.md

xqd
@@ -0,0 +1,241 @@
+# PhoneGap Plugin BarcodeScanner
+================================
+
+[![Build Status](https://travis-ci.org/phonegap/phonegap-plugin-barcodescanner.svg)](https://travis-ci.org/phonegap/phonegap-plugin-barcodescanner)
+
+Cross-platform BarcodeScanner for Cordova / PhoneGap.
+
+Follows the [Cordova Plugin spec](https://cordova.apache.org/docs/en/latest/plugin_ref/spec.html), so that it works with [Plugman](https://github.com/apache/cordova-plugman).
+
+## Installation
+
+
+This requires phonegap 5.0+ ( current stable v3.0.0 )
+
+    phonegap plugin add phonegap-plugin-barcodescanner
+
+Older versions of phonegap can still install via the __deprecated__ id ( stale v2.0.1 )
+
+    phonegap plugin add com.phonegap.plugins.barcodescanner
+
+It is also possible to install via repo url directly ( unstable )
+
+    phonegap plugin add https://github.com/phonegap/phonegap-plugin-barcodescanner.git
+
+### Supported Platforms
+
+- Android
+- iOS
+- Windows (Windows/Windows Phone 8.1 and Windows 10)
+- Windows Phone 8
+- BlackBerry 10
+- Browser
+
+Note: the Android source for this project includes an Android Library Project.
+plugman currently doesn't support Library Project refs, so its been
+prebuilt as a jar library. Any updates to the Library Project should be
+committed with an updated jar.
+
+Note: Windows 10 applications can not be build for `AnyCPU` architecture, which is default for Windows platform. If you want to build/run Windows 10 app, you should specify target architecture explicitly, for example (Cordova CLI):
+
+```
+cordova run windows -- --archs=x86
+```
+
+Note: Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` in the info.plist.
+
+`NSCameraUsageDescription` describes the reason that the app accesses the user’s camera.
+When the system prompts the user to allow access, this string is displayed as part of the dialog box.
+
+To add this entry you can pass the following variable on plugin install.
+
+```
+cordova plugin add phonegap-plugin-barcodescanner --variable CAMERA_USAGE_DESCRIPTION="To scan barcodes"
+```
+
+If you are using Phonegap Build you can add this to your config.xml
+```
+<gap:config-file platform="ios" parent="NSCameraUsageDescription" overwrite="true">
+   <string>We are using the Camera for something..</string>
+</gap:config-file>
+```
+
+### PhoneGap Build
+If you're using [PhoneGap Build](https://build.phonegap.com/) please make sure you specify `gradle` as your Android build tool in `config.xml`: `<preference name="android-build-tool" value="gradle" />`.
+
+## Using the plugin ##
+The plugin creates the object `cordova.plugins.barcodeScanner` with the method `scan(success, fail)`.
+
+The following barcode types are currently supported:
+### Android
+
+* QR_CODE
+* DATA_MATRIX
+* UPC_E
+* UPC_A
+* EAN_8
+* EAN_13
+* CODE_128
+* CODE_39
+* CODE_93
+* CODABAR
+* ITF
+* RSS14
+* RSS_EXPANDED
+
+Not by default, but supported if you pass in the "formats" option:
+* PDF_417
+* AZTEC
+
+### iOS
+
+* QR_CODE
+* DATA_MATRIX
+* UPC_E
+* UPC_A
+* EAN_8
+* EAN_13
+* CODE_128
+* CODE_39
+* ITF
+
+### Windows
+
+* UPC_A
+* UPC_E
+* EAN_8
+* EAN_13
+* CODE_39
+* CODE_93
+* CODE_128
+* ITF
+* CODABAR
+* MSI
+* RSS14
+* QR_CODE
+* DATA_MATRIX
+* AZTEC
+* PDF_417
+
+### Windows Phone 8
+
+* UPC_A
+* UPC_E
+* EAN_8
+* EAN_13
+* CODE_39
+* CODE_93
+* CODE_128
+* ITF
+* CODABAR
+* MSI
+* RSS14
+* QR_CODE
+* DATA_MATRIX
+* AZTEC
+* PDF_417
+
+### BlackBerry 10
+* UPC_A
+* UPC_E
+* EAN_8
+* EAN_13
+* CODE_39
+* CODE_128
+* ITF
+* DATA_MATRIX
+* AZTEC
+
+`success` and `fail` are callback functions. Success is passed an object with data, type and cancelled properties. Data is the text representation of the barcode data, type is the type of barcode detected and cancelled is whether or not the user cancelled the scan.
+
+A full example could be:
+```js
+   cordova.plugins.barcodeScanner.scan(
+      function (result) {
+          alert("We got a barcode\n" +
+                "Result: " + result.text + "\n" +
+                "Format: " + result.format + "\n" +
+                "Cancelled: " + result.cancelled);
+      },
+      function (error) {
+          alert("Scanning failed: " + error);
+      },
+      {
+          preferFrontCamera : true, // iOS and Android
+          showFlipCameraButton : true, // iOS and Android
+          showTorchButton : true, // iOS and Android
+          torchOn: true, // Android, launch with the torch switched on (if available)
+          saveHistory: true // Android, save scan history (default false)
+          prompt : "Place a barcode inside the scan area", // Android
+          resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
+          formats : "QR_CODE,PDF_417", // default: all but PDF_417 and RSS_EXPANDED
+          orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
+          disableAnimations : true, // iOS
+          disableSuccessBeep: false // iOS
+      }
+   );
+```
+
+## Encoding a Barcode ##
+
+The plugin creates the object `cordova.plugins.barcodeScanner` with the method `encode(type, data, success, fail)`.
+
+Supported encoding types:
+
+* TEXT_TYPE
+* EMAIL_TYPE
+* PHONE_TYPE
+* SMS_TYPE
+
+```
+A full example could be:
+
+   cordova.plugins.barcodeScanner.encode(cordova.plugins.barcodeScanner.Encode.TEXT_TYPE, "http://www.nytimes.com", function(success) {
+            alert("encode success: " + success);
+          }, function(fail) {
+            alert("encoding failed: " + fail);
+          }
+        );
+```
+
+## Windows quirks ##
+
+* Windows implementation currently doesn't support encode functionality.
+
+* On Windows 10 desktop ensure that you have Windows Media Player and Media Feature pack installed.
+
+## Windows Phone 8 quirks ##
+Windows Phone 8 implementation currently doesn't support encode functionality.
+
+## BlackBerry 10 quirks
+BlackBerry 10 implementation currently doesn't support encode functionality.
+Cancelling a scan on BlackBerry 10 is done by touching the screen.
+
+## Thanks on Github ##
+
+So many -- check out the original [iOS](https://github.com/phonegap/phonegap-plugins/tree/DEPRECATED/iOS/BarcodeScanner),  [Android](https://github.com/phonegap/phonegap-plugins/tree/DEPRECATED/Android/BarcodeScanner) and
+[BlackBerry 10](https://github.com/blackberry/WebWorks-Community-APIs/tree/master/BB10-Cordova/BarcodeScanner) repos.
+
+## Licence ##
+
+The MIT License
+
+Copyright (c) 2010 Matt Kane
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 52 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/hooks/windows/check-arch.js

xqd
@@ -0,0 +1,52 @@
+module.exports = function(ctx) {
+    if (ctx.opts && ctx.opts.platforms && ctx.opts.platforms.indexOf('windows') > -1
+        && ctx.opts.options) {
+        var path = require('path');
+        var shell = ctx.requireCordovaModule('shelljs');
+        var nopt = ctx.requireCordovaModule('nopt');
+
+        // parse and validate args
+        var args = nopt({
+            'archs': [String],
+            'appx': String,
+            'phone': Boolean,
+            'win': Boolean,
+            'bundle': Boolean,
+            'packageCertificateKeyFile': String,
+            'packageThumbprint': String,
+            'publisherId': String,
+            'buildConfig': String
+        }, {}, ctx.opts.options.argv, 0);
+
+        // Check if --appx flag is passed so that we have a project build version override:  
+        var isWin10 = args.appx && args.appx.toLowerCase() === 'uap';
+
+        // Else check "windows-target-version" preference:
+        if (!isWin10) {
+            var configXml = shell.ls(path.join(ctx.opts.projectRoot, 'config.xml'))[0];
+
+            var reTargetVersion = /<preference\s+name="windows-target-version"\s+value="(.+)"\s*\/>/i;
+            var targetVersion = shell.grep(reTargetVersion, configXml);
+
+            var result = reTargetVersion.exec(targetVersion);
+            if (result !== null) {
+                var match = result[1];
+                isWin10 = parseInt(match.split('.'), 10) > 8;
+            }
+        }
+
+        // Non-AnyCPU arch is required for Windows 10 (UWP) projects only:
+        if (isWin10) {
+            var rawArchs = ctx.opts.options.archs || args.archs;
+            var archs = rawArchs ? rawArchs.split(' ') : [];
+
+            // Avoid "anycpu" arch:
+            if (archs.length === 0 || archs.some(function (item) {
+                return item.toLowerCase() === 'anycpu';
+            })) {
+                throw new Error('You must specify an architecture to include the proper ZXing library version.'
+                + '\nUse \'cordova run windows -- --arch="x64"\' or \'cordova run windows -- --arch="arm" --phone --device\' for example.');
+            }
+        }
+    }
+}

+ 50 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/package.json

xqd
@@ -0,0 +1,50 @@
+{
+  "name": "phonegap-plugin-barcodescanner",
+  "version": "6.0.8",
+  "description": "You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application.",
+  "cordova": {
+    "id": "phonegap-plugin-barcodescanner",
+    "platforms": [
+      "ios",
+      "android",
+      "windows",
+      "wp8",
+      "blackberry10",
+      "browser"
+    ]
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/phonegap/phonegap-plugin-barcodescanner.git"
+  },
+  "keywords": [
+    "ecosystem:cordova",
+    "ecosystem:phonegap",
+    "cordova-ios",
+    "cordova-android",
+    "cordova-windows",
+    "cordova-wp8",
+    "cordova-blackberry10",
+    "cordova-browser",
+    "cordova:plugin"
+  ],
+  "engines": [
+    {
+      "name": "cordova",
+      "version": ">=3.0.0"
+    }
+  ],
+  "author": "Adobe PhoneGap Team",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/phonegap/phonegap-plugin-barcodescanner/issues"
+  },
+  "homepage": "https://github.com/phonegap/phonegap-plugin-barcodescanner#readme",
+  "scripts": {
+    "test": "jasmine-node --color spec"
+  },
+  "devDependencies": {
+    "jasmine-node": "1.14.5",
+    "pluginpub": "^0.0.8"
+  }
+}

+ 114 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/plugin.xml

xqd
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:rim="http://www.blackberry.com/ns/widgets" id="phonegap-plugin-barcodescanner" version="6.0.8">
+  <name>BarcodeScanner</name>
+  <description>You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application.</description>
+  <license>MIT</license>
+  <repo>https://github.com/phonegap/phonegap-plugin-barcodescanner</repo>
+  <issue>https://github.com/phonegap/phonegap-plugin-barcodescanner/issues</issue>
+  <engines>
+    <engine name="cordova" version=">=3.0.0"/>
+  </engines>
+  <js-module src="www/barcodescanner.js" name="BarcodeScanner">
+    <clobbers target="cordova.plugins.barcodeScanner"/>
+  </js-module>
+  <platform name="ios">
+    <config-file target="config.xml" parent="/*">
+      <feature name="BarcodeScanner">
+        <param name="ios-package" value="CDVBarcodeScanner"/>
+      </feature>
+    </config-file>
+    <config-file target="*-Info.plist" parent="NSCameraUsageDescription">
+      <string>$CAMERA_USAGE_DESCRIPTION</string>
+    </config-file>
+    <preference name="CAMERA_USAGE_DESCRIPTION" default=" "/>
+    <resource-file src="src/ios/scannerOverlay.xib"/>
+    <resource-file src="src/ios/CDVBarcodeScanner.bundle"/>
+    <header-file src="src/ios/zxing-all-in-one.h"/>
+    <source-file src="src/ios/CDVBarcodeScanner.mm" compiler-flags="-fno-objc-arc"/>
+    <source-file src="src/ios/zxing-all-in-one.cpp"/>
+    <framework src="libiconv.dylib"/>
+    <framework src="AVFoundation.framework"/>
+    <framework src="AssetsLibrary.framework"/>
+    <framework src="CoreVideo.framework"/>
+    <framework src="QuartzCore.framework"/>
+    <framework src="CoreGraphics.framework"/>
+    <framework src="CoreImage.framework"/>
+    <framework src="AudioToolbox.framework"/>
+  </platform>
+  <platform name="android">
+    <source-file src="src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java" target-dir="src/com/phonegap/plugins/barcodescanner"/>
+    <config-file target="res/xml/config.xml" parent="/*">
+      <feature name="BarcodeScanner">
+        <param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner"/>
+      </feature>
+    </config-file>
+    <config-file target="AndroidManifest.xml" parent="/manifest/application">
+      <activity android:name="com.google.zxing.client.android.CaptureActivity" android:clearTaskOnLaunch="true" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden" android:exported="false"/>
+      <activity android:name="com.google.zxing.client.android.encode.EncodeActivity" android:label="Share"/>
+    </config-file>
+    <config-file target="AndroidManifest.xml" parent="/manifest">
+      <uses-permission android:name="android.permission.CAMERA"/>
+      <uses-permission android:name="android.permission.FLASHLIGHT"/>
+      <uses-feature android:name="android.hardware.camera" android:required="true"/>
+    </config-file>
+    <framework src="src/android/barcodescanner.gradle" custom="true" type="gradleReference"/>
+    <resource-file src="src/android/barcodescanner-release-2.1.5.aar" target="libs/barcodescanner.aar"/>
+    <dependency id="cordova-plugin-compat" version="^1.0.0"/>
+  </platform>
+  <platform name="windows">
+    <js-module src="src/windows/BarcodeScannerProxy.js" name="BarcodeScannerProxy">
+      <merges target=""/>
+    </js-module>
+    <config-file target="package.appxmanifest" parent="/Package/Capabilities">
+      <DeviceCapability Name="webcam"/>
+    </config-file>
+    <framework src="src/windows/lib.UW/x86/ZXing.winmd" target-dir="x86" arch="x86" custom="true" versions=">8.1"/>
+    <framework src="src/windows/lib.UW/x64/ZXing.winmd" target-dir="x64" arch="x64" custom="true" versions=">8.1"/>
+    <framework src="src/windows/lib.UW/ARM/ZXing.winmd" target-dir="ARM" arch="ARM" custom="true" versions=">8.1"/>
+    <framework src="src/windows/lib/WinRTBarcodeReader.csproj" custom="true" type="projectReference" versions="&lt;=8.1"/>
+    <asset src="src/windows/assets/plugin-barcodeScanner.css" target="css/plugin-barcodeScanner.css"/>
+    <hook src="hooks/windows/check-arch.js" type="before_compile"/>
+    <hook src="hooks/windows/check-arch.js" type="before_run"/>
+  </platform>
+  <platform name="wp8">
+    <config-file target="config.xml" parent="/*">
+      <feature name="BarcodeScanner">
+        <param name="wp-package" value="BarcodeScanner"/>
+      </feature>
+    </config-file>
+    <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
+      <Capability Name="ID_CAP_ISV_CAMERA"/>
+    </config-file>
+    <framework src="src/wp8/lib/zxing.wp8.0.dll" custom="true"/>
+    <asset src="src/wp8/assets/cancel.png" target="Images/appbar.cancel.png"/>
+    <source-file src="src/wp8/BarcodeScanner.cs"/>
+    <source-file src="src/wp8/BarcodeScannerTask.cs"/>
+    <source-file src="src/wp8/BarcodeScannerUI.xaml"/>
+    <source-file src="src/wp8/BarcodeScannerUI.xaml.cs"/>
+  </platform>
+  <platform name="browser">
+    <config-file target="config.xml" parent="/*">
+      <feature name="BarcodeScanner">
+        <param name="browser-package" value="BarcodeScanner"/>
+      </feature>
+    </config-file>
+    <js-module src="src/browser/BarcodeScannerProxy.js" name="BarcodeScannerProxy">
+      <runs/>
+    </js-module>
+  </platform>
+  <platform name="blackberry10">
+    <source-file src="src/blackberry10/index.js" target-dir="BarcodeScanner"/>
+    <source-file src="src/blackberry10/qrcode.js" target-dir="BarcodeScanner"/>
+    <lib-file src="src/blackberry10/native/device/libBarcodeScanner.so" arch="device"/>
+    <lib-file src="src/blackberry10/native/simulator/libBarcodeScanner.so" arch="simulator"/>
+    <config-file target="www/config.xml" parent="/widget">
+      <feature name="BarcodeScanner">
+        <param name="blackberry-package" value="phonegap-plugin-barcodescanner"/>
+      </feature>
+    </config-file>
+    <config-file target="www/config.xml" parent="/widget/rim:permissions">
+      <rim:permit>use_camera</rim:permit>
+    </config-file>
+    <dependency id="cordova-plugin-bb-app"/>
+  </platform>
+</plugin>

+ 83 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/spec/helper/cordova.js

xqd
@@ -0,0 +1,83 @@
+/* global cordova:true */
+
+/*!
+ * Module dependencies.
+ */
+
+/**
+ * cordova.js for node.
+ *
+ * Think of this as cordova-node, which would be simliar to cordova-android
+ * or cordova-browser. The purpose of this module is to enable testing
+ * of a plugin's JavaScript interface.
+ *
+ * When this module is first required, it will insert a global cordova
+ * instance, which can hijack cordova-specific commands within the pluin's
+ * implementation.
+ *
+ * Remember to require this module before the plugin that you want to test.
+ *
+ * Example:
+ *
+ *     var cordova = require('./helper/cordova'),
+ *         myPlugin = require('../www/myPlugin');
+ */
+
+module.exports = global.cordova = cordova = {
+
+    /**
+     * cordova.require Mock.
+     *
+     * Hijacks all cordova.requires. By default, it returns an empty function.
+     * You can define your own implementation of each required module before
+     * or after it has been required.
+     *
+     * See `cordova.required` to learn how to add your own module implemtnation.
+     */
+
+    require: function(moduleId) {
+        // define a default function if it doesn't exist
+        if (!cordova.required[moduleId]) {
+            cordova.required[moduleId] = function() {};
+        }
+        // create a new module mapping between the module Id and cordova.required.
+        return new ModuleMap(moduleId);
+    },
+
+    /**
+     * Cordova module implementations.
+     *
+     * A key-value hash, where the key is the module such as 'cordova/exec'
+     * and the value is the function or object returned.
+     *
+     * For example:
+     *
+     *     var exec = require('cordova/exec');
+     *
+     * Will map to:
+     *
+     *     cordova.required['cordova/exec'];
+     */
+
+    required: {
+        // populated at runtime
+    }
+};
+
+/**
+ * Module Mapper.
+ *
+ * Returns a function that when executed will lookup the implementation
+ * in cordova.required[id].
+ *
+ * @param {String} moduleId is the module name/path, such as 'cordova/exec'
+ * @return {Function}.
+ */
+
+function ModuleMap(moduleId) {
+    return function() {
+        // lookup and execute the module's mock implementation, passing
+        // in any parameters that were provided.
+        return cordova.required[moduleId].apply(this, arguments);
+    };
+}

+ 78 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/spec/index.spec.js

xqd
@@ -0,0 +1,78 @@
+/* globals require */
+
+/*!
+ * Module dependencies.
+ */
+
+var cordova = require('./helper/cordova'),
+    BarcodeScanner = require('../www/barcodescanner'),
+    execSpy,
+    execWin,
+    options;
+
+/*!
+ * Specification.
+ */
+
+describe('phonegap-plugin-barcodescanner', function () {
+    beforeEach(function () {
+        execWin = jasmine.createSpy();
+        execSpy = spyOn(cordova.required, 'cordova/exec').andCallFake(execWin);
+    });
+
+    describe('BarcodeScanner', function () {
+      it("BarcodeScanner plugin should exist", function() {
+          expect(BarcodeScanner).toBeDefined();
+          expect(typeof BarcodeScanner == 'object').toBe(true);
+      });
+
+      it("should contain a scan function", function() {
+          expect(BarcodeScanner.scan).toBeDefined();
+          expect(typeof BarcodeScanner.scan == 'function').toBe(true);
+      });
+
+      it("should contain an encode function", function() {
+          expect(BarcodeScanner.encode).toBeDefined();
+          expect(typeof BarcodeScanner.encode == 'function').toBe(true);
+      });
+
+      it("should contain three DestinationType constants", function() {
+          expect(BarcodeScanner.Encode.TEXT_TYPE).toBe("TEXT_TYPE");
+          expect(BarcodeScanner.Encode.EMAIL_TYPE).toBe("EMAIL_TYPE");
+          expect(BarcodeScanner.Encode.PHONE_TYPE).toBe("PHONE_TYPE");
+          expect(BarcodeScanner.Encode.SMS_TYPE).toBe("SMS_TYPE");
+      });
+    });
+
+    describe('BarcodeScanner instance', function () {
+        describe('cordova.exec', function () {
+            it('should call cordova.exec on next process tick', function (done) {
+                BarcodeScanner.scan(function() {}, function() {}, {});
+                setTimeout(function () {
+                    expect(execSpy).toHaveBeenCalledWith(
+                        jasmine.any(Function),
+                        jasmine.any(Function),
+                        'BarcodeScanner',
+                        'scan',
+                        jasmine.any(Object)
+                    );
+                    done();
+                }, 100);
+            });
+
+            it('should call cordova.exec on next process tick', function (done) {
+                BarcodeScanner.encode("", "",function() {}, function() {}, {});
+                setTimeout(function () {
+                    expect(execSpy).toHaveBeenCalledWith(
+                        jasmine.any(Function),
+                        jasmine.any(Function),
+                        'BarcodeScanner',
+                        'encode',
+                        jasmine.any(Object)
+                    );
+                    done();
+                }, 100);
+            });
+        });
+    });
+});

+ 1 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/README.md

xqd
@@ -0,0 +1 @@
+The Android .aar sources are [here](https://github.com/EddyVerbruggen/barcodescanner-lib-aar).

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/barcodescanner-release-2.1.5.aar


+ 24 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/barcodescanner.gradle

xqd
@@ -0,0 +1,24 @@
+def DEFAULT_MIN_SDK_VERSION = 15
+def minSdk = Math.max(DEFAULT_MIN_SDK_VERSION, cdvHelpers.getConfigPreference('android-minSdkVersion',0) as Integer);
+if (cdvMinSdkVersion == null || Integer.parseInt(cdvMinSdkVersion) < minSdk ) {
+    ext.cdvMinSdkVersion = minSdk;
+}
+
+repositories{
+    jcenter()
+    flatDir{
+        dirs 'libs'
+    }
+}
+
+dependencies {
+    compile 'com.android.support:support-v4:+'
+    compile(name:'barcodescanner', ext:'aar')
+}
+
+android {
+    packagingOptions {
+        exclude 'META-INF/NOTICE'
+        exclude 'META-INF/LICENSE'
+    }
+}

+ 325 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java

xqd
@@ -0,0 +1,325 @@
+/**
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) Matt Kane 2010
+ * Copyright (c) 2011, IBM Corporation
+ * Copyright (c) 2013, Maciej Nux Jaros
+ */
+package com.phonegap.plugins.barcodescanner;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.content.pm.PackageManager;
+
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.PermissionHelper;
+
+import com.google.zxing.client.android.CaptureActivity;
+import com.google.zxing.client.android.encode.EncodeActivity;
+import com.google.zxing.client.android.Intents;
+
+/**
+ * This calls out to the ZXing barcode reader and returns the result.
+ *
+ * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
+ */
+public class BarcodeScanner extends CordovaPlugin {
+    public static final int REQUEST_CODE = 0x0ba7c0de;
+
+    private static final String SCAN = "scan";
+    private static final String ENCODE = "encode";
+    private static final String CANCELLED = "cancelled";
+    private static final String FORMAT = "format";
+    private static final String TEXT = "text";
+    private static final String DATA = "data";
+    private static final String TYPE = "type";
+    private static final String PREFER_FRONTCAMERA = "preferFrontCamera";
+    private static final String ORIENTATION = "orientation";
+    private static final String SHOW_FLIP_CAMERA_BUTTON = "showFlipCameraButton";
+    private static final String RESULTDISPLAY_DURATION = "resultDisplayDuration";
+    private static final String SHOW_TORCH_BUTTON = "showTorchButton";
+    private static final String TORCH_ON = "torchOn";
+    private static final String SAVE_HISTORY = "saveHistory";
+    private static final String FORMATS = "formats";
+    private static final String PROMPT = "prompt";
+    private static final String TEXT_TYPE = "TEXT_TYPE";
+    private static final String EMAIL_TYPE = "EMAIL_TYPE";
+    private static final String PHONE_TYPE = "PHONE_TYPE";
+    private static final String SMS_TYPE = "SMS_TYPE";
+
+    private static final String LOG_TAG = "BarcodeScanner";
+
+    private String [] permissions = { Manifest.permission.CAMERA };
+
+    private JSONArray requestArgs;
+    private CallbackContext callbackContext;
+
+    /**
+     * Constructor.
+     */
+    public BarcodeScanner() {
+    }
+
+    /**
+     * Executes the request.
+     *
+     * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+     *     cordova.getThreadPool().execute(runnable);
+     *
+     * To run on the UI thread, use:
+     *     cordova.getActivity().runOnUiThread(runnable);
+     *
+     * @param action          The action to execute.
+     * @param args            The exec() arguments.
+     * @param callbackContext The callback context used when calling back into JavaScript.
+     * @return                Whether the action was valid.
+     *
+     * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
+     */
+    @Override
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
+        this.callbackContext = callbackContext;
+        this.requestArgs = args;
+
+        if (action.equals(ENCODE)) {
+            JSONObject obj = args.optJSONObject(0);
+            if (obj != null) {
+                String type = obj.optString(TYPE);
+                String data = obj.optString(DATA);
+
+                // If the type is null then force the type to text
+                if (type == null) {
+                    type = TEXT_TYPE;
+                }
+
+                if (data == null) {
+                    callbackContext.error("User did not specify data to encode");
+                    return true;
+                }
+
+                encode(type, data);
+            } else {
+                callbackContext.error("User did not specify data to encode");
+                return true;
+            }
+        } else if (action.equals(SCAN)) {
+
+            //android permission auto add
+            if(!hasPermisssion()) {
+              requestPermissions(0);
+            } else {
+              scan(args);
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Starts an intent to scan and decode a barcode.
+     */
+    public void scan(final JSONArray args) {
+
+        final CordovaPlugin that = this;
+
+        cordova.getThreadPool().execute(new Runnable() {
+            public void run() {
+
+                Intent intentScan = new Intent(that.cordova.getActivity().getBaseContext(), CaptureActivity.class);
+                intentScan.setAction(Intents.Scan.ACTION);
+                intentScan.addCategory(Intent.CATEGORY_DEFAULT);
+
+                // add config as intent extras
+                if (args.length() > 0) {
+
+                    JSONObject obj;
+                    JSONArray names;
+                    String key;
+                    Object value;
+
+                    for (int i = 0; i < args.length(); i++) {
+
+                        try {
+                            obj = args.getJSONObject(i);
+                        } catch (JSONException e) {
+                            Log.i("CordovaLog", e.getLocalizedMessage());
+                            continue;
+                        }
+
+                        names = obj.names();
+                        for (int j = 0; j < names.length(); j++) {
+                            try {
+                                key = names.getString(j);
+                                value = obj.get(key);
+
+                                if (value instanceof Integer) {
+                                    intentScan.putExtra(key, (Integer) value);
+                                } else if (value instanceof String) {
+                                    intentScan.putExtra(key, (String) value);
+                                }
+
+                            } catch (JSONException e) {
+                                Log.i("CordovaLog", e.getLocalizedMessage());
+                            }
+                        }
+
+                        intentScan.putExtra(Intents.Scan.CAMERA_ID, obj.optBoolean(PREFER_FRONTCAMERA, false) ? 1 : 0);
+                        intentScan.putExtra(Intents.Scan.SHOW_FLIP_CAMERA_BUTTON, obj.optBoolean(SHOW_FLIP_CAMERA_BUTTON, false));
+                        intentScan.putExtra(Intents.Scan.SHOW_TORCH_BUTTON, obj.optBoolean(SHOW_TORCH_BUTTON, false));
+                        intentScan.putExtra(Intents.Scan.TORCH_ON, obj.optBoolean(TORCH_ON, false));
+                        intentScan.putExtra(Intents.Scan.SAVE_HISTORY, obj.optBoolean(SAVE_HISTORY, false));
+                        if (obj.has(RESULTDISPLAY_DURATION)) {
+                            intentScan.putExtra(Intents.Scan.RESULT_DISPLAY_DURATION_MS, "" + obj.optLong(RESULTDISPLAY_DURATION));
+                        }
+                        if (obj.has(FORMATS)) {
+                            intentScan.putExtra(Intents.Scan.FORMATS, obj.optString(FORMATS));
+                        }
+                        if (obj.has(PROMPT)) {
+                            intentScan.putExtra(Intents.Scan.PROMPT_MESSAGE, obj.optString(PROMPT));
+                        }
+                        if (obj.has(ORIENTATION)) {
+                            intentScan.putExtra(Intents.Scan.ORIENTATION_LOCK, obj.optString(ORIENTATION));
+                        }
+                    }
+
+                }
+
+                // avoid calling other phonegap apps
+                intentScan.setPackage(that.cordova.getActivity().getApplicationContext().getPackageName());
+
+                that.cordova.startActivityForResult(that, intentScan, REQUEST_CODE);
+            }
+        });
+    }
+
+    /**
+     * Called when the barcode scanner intent completes.
+     *
+     * @param requestCode The request code originally supplied to startActivityForResult(),
+     *                       allowing you to identify who this result came from.
+     * @param resultCode  The integer result code returned by the child activity through its setResult().
+     * @param intent      An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+     */
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        if (requestCode == REQUEST_CODE && this.callbackContext != null) {
+            if (resultCode == Activity.RESULT_OK) {
+                JSONObject obj = new JSONObject();
+                try {
+                    obj.put(TEXT, intent.getStringExtra("SCAN_RESULT"));
+                    obj.put(FORMAT, intent.getStringExtra("SCAN_RESULT_FORMAT"));
+                    obj.put(CANCELLED, false);
+                } catch (JSONException e) {
+                    Log.d(LOG_TAG, "This should never happen");
+                }
+                //this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback);
+                this.callbackContext.success(obj);
+            } else if (resultCode == Activity.RESULT_CANCELED) {
+                JSONObject obj = new JSONObject();
+                try {
+                    obj.put(TEXT, "");
+                    obj.put(FORMAT, "");
+                    obj.put(CANCELLED, true);
+                } catch (JSONException e) {
+                    Log.d(LOG_TAG, "This should never happen");
+                }
+                //this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback);
+                this.callbackContext.success(obj);
+            } else {
+                //this.error(new PluginResult(PluginResult.Status.ERROR), this.callback);
+                this.callbackContext.error("Unexpected error");
+            }
+        }
+    }
+
+    /**
+     * Initiates a barcode encode.
+     *
+     * @param type Endoiding type.
+     * @param data The data to encode in the bar code.
+     */
+    public void encode(String type, String data) {
+        Intent intentEncode = new Intent(this.cordova.getActivity().getBaseContext(), EncodeActivity.class);
+        intentEncode.setAction(Intents.Encode.ACTION);
+        intentEncode.putExtra(Intents.Encode.TYPE, type);
+        intentEncode.putExtra(Intents.Encode.DATA, data);
+        // avoid calling other phonegap apps
+        intentEncode.setPackage(this.cordova.getActivity().getApplicationContext().getPackageName());
+
+        this.cordova.getActivity().startActivity(intentEncode);
+    }
+
+    /**
+     * check application's permissions
+     */
+   public boolean hasPermisssion() {
+       for(String p : permissions)
+       {
+           if(!PermissionHelper.hasPermission(this, p))
+           {
+               return false;
+           }
+       }
+       return true;
+   }
+
+    /**
+     * We override this so that we can access the permissions variable, which no longer exists in
+     * the parent class, since we can't initialize it reliably in the constructor!
+     *
+     * @param requestCode The code to get request action
+     */
+   public void requestPermissions(int requestCode)
+   {
+       PermissionHelper.requestPermissions(this, requestCode, permissions);
+   }
+
+   /**
+   * processes the result of permission request
+   *
+   * @param requestCode The code to get request action
+   * @param permissions The collection of permissions
+   * @param grantResults The result of grant
+   */
+  public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                         int[] grantResults) throws JSONException
+   {
+       PluginResult result;
+       for (int r : grantResults) {
+           if (r == PackageManager.PERMISSION_DENIED) {
+               Log.d(LOG_TAG, "Permission Denied!");
+               result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
+               this.callbackContext.sendPluginResult(result);
+               return;
+           }
+       }
+
+       switch(requestCode)
+       {
+           case 0:
+               scan(this.requestArgs);
+               break;
+       }
+   }
+
+    /**
+     * This plugin launches an external Activity when the camera is opened, so we
+     * need to implement the save/restore API in case the Activity gets killed
+     * by the OS while it's in the background.
+     */
+    public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
+        this.callbackContext = callbackContext;
+    }
+
+}

+ 703 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/LICENSE

xqd
@@ -0,0 +1,703 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+-------------------------------------------------------
+*JNEXT (v1.0.8.3)
+
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (the "License"); you may not use this file except in
+     compliance with the License. You may obtain a copy of the License at
+     http://www.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
+-------------------------------------------------------
+
+* Tokenizer
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+  you must not claim that you wrote the original software.
+  If you use this software in a product, an acknowledgment
+  in the product documentation would be appreciated but is
+  not required.
+
+2. Altered source versions must be plainly marked as such,
+  and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/

+ 213 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/index.js

xqd
@@ -0,0 +1,213 @@
+/*
+* Copyright 2013-2015 BlackBerry Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+var barcodescanner,
+	resultObjs = {},
+	readCallback,
+	_utils = require("../../lib/utils"),
+	_qr = require('plugin/BarcodeScanner/qrcode.js');
+
+const SMS_URI_ONE = "smsto:",
+	  SMS_URI_TWO = "sms:",
+	  EMAIL_URI = "mailto:",
+	  PHONE_URI = "tel:+1",
+	  SMS_TYPE = "SMS_TYPE",
+	  PHONE_TYPE = "PHONE_TYPE",
+	  EMAIL_TYPE = "EMAIL_TYPE",
+	  TEXT_TYPE = "TEXT_TYPE";
+
+module.exports = {
+
+	// methods to start and stop scanning
+	scan: function (success, fail, args, env) {
+		var result = new PluginResult(args, env);
+		resultObjs[result.callbackId] = result;
+		readCallback = result.callbackId;
+		var views = qnx.webplatform.getWebViews();
+		var handle = null;
+		var group = null;
+		var z = -1;
+		for (var i = 0; i < views.length; i++) {
+			if (views[i].visible && views[i].zOrder > z){
+				z = views[i].zOrder;
+				group = views[i].windowGroup;
+				handle = views[i].jsScreenWindowHandle;
+			}
+		}
+		if (handle !== null) {
+			var values = { group: group, handle: handle };
+			barcodescanner.getInstance().startRead(result.callbackId, values);
+			result.noResult(true);
+		} else {
+			result.error("Failed to find window handle", false);
+		}
+	},
+
+	/*
+	Method for barcode encoding. Returns base 64 image URI 
+	Currently only creates QRcodes
+	*/
+	encode: function (success, fail, args, env) {
+		
+		var result = new PluginResult(args, env);
+		values = decodeURIComponent(args[0]);
+		values = JSON.parse(values);
+		data = values["data"];
+		type = values["type"];
+	
+		if(data == "" || data == undefined){
+			result.error("Data to be encoded was not specified", false);
+			return;
+		}
+		if(type == "" || type == undefined){
+			type = TEXT_TYPE;
+		}
+
+		if(type == SMS_TYPE){
+			var check_one = data.substring(0,6).toLowerCase();
+			var check_two = data.substring(0,4).toLowerCase();
+			if(!(check_one == SMS_URI_ONE || check_two == SMS_URI_TWO)){
+				data = SMS_URI_ONE+data;
+			} 
+		}else if(type == EMAIL_TYPE){
+			var check = data.substring(0,7).toLowerCase();
+			if(check != EMAIL_URI){
+				data = EMAIL_URI+data;
+			} 
+		}else if(type == PHONE_TYPE){
+			var check = data.substring(0,4).toLowerCase();
+			if(check != PHONE_URI){
+				data = PHONE_URI+data;
+			} 
+		}
+
+		console.log("Type: "+type + " Data: " + data);
+
+		//Make QRcode using qrcode.js 
+		var bdiv = document.createElement('div');
+		var options = {
+	    	text: data,
+	   		width: 256,
+	    	height: 256,
+	    	colorDark : "#000000",
+	    	colorLight : "#ffffff",
+		};
+
+		var imageURI = _qr.makeQRcode(bdiv, options);
+
+		try{
+			result.ok(imageURI,false);
+		}catch(e){
+			result.error("Failed to encode barcode", false);
+		}
+	}
+};
+
+
+JNEXT.BarcodeScanner = function () {
+	var self = this,
+		hasInstance = false;
+
+	self.getId = function () {
+		return self.m_id;
+	};
+
+	self.init = function () {
+		if (!JNEXT.require("libBarcodeScanner")) {
+			return false;
+		}
+
+		self.m_id = JNEXT.createObject("libBarcodeScanner.BarcodeScannerJS");
+
+		if (self.m_id === "") {
+			return false;
+		}
+
+		JNEXT.registerEvents(self);
+	};
+
+	// ************************
+	// Enter your methods here
+	// ************************
+
+	// Fired by the Event framework (used by asynchronous callbacks)
+
+	self.onEvent = function (strData) {
+		var arData = strData.split(" "),
+			callbackId = arData[0],
+			receivedEvent = arData[1],
+			data = arData[2],
+			result = resultObjs[callbackId],
+			events = ["community.barcodescanner.codefound.native",
+					  "community.barcodescanner.errorfound.native",
+					  "community.barcodescanner.started.native",
+					  "community.barcodescanner.ended.native"];
+			
+		// Restructures results when codefound has spaces		  
+		if(arData.length > 3){
+			var i;
+			for(i=3; i<arData.length; i++) {
+				data += " " + arData[i];
+			}
+		}
+		
+		if (receivedEvent == "community.barcodescanner.codefound.native") {
+			if (result) {
+				var parsed = JSON.parse(data);
+				result.callbackOk(parsed, false);
+			}
+			this.stopRead(callbackId);
+
+		}
+		if (receivedEvent == "community.barcodescanner.started.native") {
+			console.log("Scanning started successfully");
+		}
+		if (receivedEvent == "community.barcodescanner.errorfound.native") {
+			if (result) {
+				result.callbackError(data, false);
+			}
+		}
+
+		if(receivedEvent == "community.barcodescanner.ended.native" || receivedEvent == "community.barcodescanner.errorfound.native") {
+			delete resultObjs[readCallback];
+			readCallback = null;
+		}
+
+	};
+
+	// Thread methods
+	self.startRead = function (callbackId, handle) {
+		return JNEXT.invoke(self.m_id, "startRead " + callbackId + " " + JSON.stringify(handle));
+	};
+	self.stopRead = function (callbackId) {
+		return JNEXT.invoke(self.m_id, "stopRead " + callbackId);
+	};
+
+	// ************************
+	// End of methods to edit
+	// ************************
+	self.m_id = "";
+
+	self.getInstance = function () {
+		if (!hasInstance) {
+			hasInstance = true;
+			self.init();
+		}
+		return self;
+	};
+
+};
+
+barcodescanner = new JNEXT.BarcodeScanner();

+ 220 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/.cproject

xqd
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" moduleId="org.eclipse.cdt.core.settings" name="device">
+				<externalSettings/>
+				<extensions>
+					<extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" errorParsers="com.qnx.tools.ide.qde.core.QDELinkerErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" name="device" parent="com.qnx.qcc.configuration.sharedLib.release" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">
+					<folderInfo id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567." name="/" resourcePath="">
+						<toolChain errorParsers="" id="com.qnx.qcc.toolChain.2215983" name="QNX QCC" superClass="com.qnx.qcc.toolChain">
+							<option id="com.qnx.qcc.option.cpu.315540759" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
+							<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1359109141" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+							<builder buildPath="${workspace_loc:/Template/Device-Release}" errorParsers="" id="com.qnx.nto.938326560" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/>
+							<tool command="qcc" commandLinePattern="${COMMAND}  ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} ${FLAGS}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="com.qnx.qcc.tool.compiler.242697771" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+								<option id="com.qnx.qcc.option.compiler.shared.553244928" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.optlevel.2070537906" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.2" valueType="enumerated"/>
+								<option id="com.qnx.qcc.option.compiler.includePath.1483355415" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/img"/>
+									<listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.security.9625963" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.defines.872099896" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.qccoptions.1015003128" name="QCC Options" superClass="com.qnx.qcc.option.compiler.qccoptions" valueType="stringList">
+									<listOptionValue builtIn="false" value="-frecord-gcc-switches"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.warningLevel.331428330" name="Warning Level (-w)" superClass="com.qnx.qcc.option.compiler.warningLevel" value="com.qnx.qcc.option.warningLevel.9" valueType="enumerated"/>
+								<inputType id="com.qnx.qcc.inputType.compiler.1443568066" superClass="com.qnx.qcc.inputType.compiler"/>
+							</tool>
+							<tool command="qcc" commandLinePattern="${COMMAND}  ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} ${FLAGS}" errorParsers="" id="com.qnx.qcc.tool.assembler.1996828008" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+								<option id="com.qnx.qcc.option.assembler.warningLevel.1519589523" name="Warning Level (-w)" superClass="com.qnx.qcc.option.assembler.warningLevel" value="com.qnx.qcc.option.warningLevel.9" valueType="enumerated"/>
+								<inputType id="com.qnx.qcc.inputType.assembler.116798417" superClass="com.qnx.qcc.inputType.assembler"/>
+							</tool>
+							<tool command="qcc" commandLinePattern="${COMMAND}  ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} ${FLAGS}" errorParsers="com.qnx.tools.ide.qde.core.QDELinkerErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="com.qnx.qcc.tool.linker.871546588" name="QCC Linker" superClass="com.qnx.qcc.tool.linker">
+								<option id="com.qnx.qcc.option.linker.shared.915102752" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraryPaths.1049529253" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/>
+								</option>
+								<option id="com.qnx.qcc.option.linker.security.1157664997" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraries.1316432206" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
+									<listOptionValue builtIn="false" value="camapi"/>
+									<listOptionValue builtIn="false" value="zxing"/>
+									<listOptionValue builtIn="false" value="img"/>
+									<listOptionValue builtIn="false" value="slog2"/>
+									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="screen"/>
+								</option>
+								<option id="com.qnx.qcc.option.linker.warningLevel.2067914469" name="Warning Level (-w)" superClass="com.qnx.qcc.option.linker.warningLevel" value="com.qnx.qcc.option.warningLevel.9" valueType="enumerated"/>
+								<inputType id="com.qnx.qcc.inputType.linker.1028572887" superClass="com.qnx.qcc.inputType.linker">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="com.qnx.qcc.tool.archiver.1781914947" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+		<cconfiguration id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" moduleId="org.eclipse.cdt.core.settings" name="simulator">
+				<externalSettings/>
+				<extensions>
+					<extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" name="simulator" parent="com.qnx.qcc.configuration.sharedLib.debug">
+					<folderInfo id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091." name="/" resourcePath="">
+						<toolChain id="com.qnx.qcc.toolChain.688026907" name="QNX QCC" superClass="com.qnx.qcc.toolChain">
+							<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.469207190" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+							<builder buildPath="${workspace_loc:/Template/Simulator-Debug}" id="com.qnx.nto.2029800497" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/>
+							<tool id="com.qnx.qcc.tool.compiler.1028279123" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+								<option id="com.qnx.qcc.option.compiler.shared.235893159" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.optlevel.1164238904" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
+								<option id="com.qnx.qcc.option.compile.debug.3716470" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.includePath.306305432" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/img"/>
+									<listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.security.1730007887" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.defines.1526896965" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.compiler.1881183122" superClass="com.qnx.qcc.inputType.compiler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.assembler.312168125" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+								<option id="com.qnx.qcc.option.assembler.debug.416544277" name="Debug (-g)" superClass="com.qnx.qcc.option.assembler.debug" value="true" valueType="boolean"/>
+								<inputType id="com.qnx.qcc.inputType.assembler.1722778407" superClass="com.qnx.qcc.inputType.assembler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.linker.2130364088" name="QCC Linker" superClass="com.qnx.qcc.tool.linker">
+								<option id="com.qnx.qcc.option.linker.debug.1332880614" name="Debug (-g)" superClass="com.qnx.qcc.option.linker.debug" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.shared.1633267255" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraryPaths.565794953" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/>
+								</option>
+								<option id="com.qnx.qcc.option.linker.security.9141791" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraries.220836649" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
+									<listOptionValue builtIn="false" value="zxing"/>
+									<listOptionValue builtIn="false" value="camapi"/>
+									<listOptionValue builtIn="false" value="img"/>
+									<listOptionValue builtIn="false" value="slog2"/>
+									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="screen"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.linker.167117375" superClass="com.qnx.qcc.inputType.linker">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="com.qnx.qcc.tool.archiver.489682882" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="BarcodeScanner.null.629823540" name="BarcodeScanner"/>
+	</storageModule>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Simulator-Profile">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="Device-Profile">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="Simulator-Coverage">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="Device-Debug">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="simulator"/>
+		<configuration configurationName="Simulator-Debug">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="device"/>
+		<configuration configurationName="Device-Release">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+		<configuration configurationName="Device-Coverage">
+			<resource resourceType="PROJECT" workspacePath="/BarcodeScanner"/>
+		</configuration>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.1963950149">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.1521124627">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.1662874485">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.1167756743">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.1920932411">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.274485450">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.823677416">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.606841429">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.783070498">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.89043708">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.815111702">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.1815235065">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.2137677126">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.1030515335">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+</cproject>

+ 2 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/.settings/com.qnx.tools.ide.core.prefs

xqd
@@ -0,0 +1,2 @@
+QNX_CURRENT_INSTALL=BlackBerry Native SDK 10.2
+eclipse.preferences.version=1

+ 2 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/device/.gitignore

xqd
@@ -0,0 +1,2 @@
+/src
+/public

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/device/libBarcodeScanner.so


+ 19 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/autolink.h

xqd
@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK)  &&  !defined(JSON_DLL_BUILD)  &&  !defined(JSON_IN_CPPTL)
+#  define CPPTL_AUTOLINK_NAME "json"
+#  undef CPPTL_AUTOLINK_DLL
+#  ifdef JSON_DLL
+#   define CPPTL_AUTOLINK_DLL
+#  endif
+#  include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED

+ 43 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/config.h

xqd
@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL!
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED

+ 42 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/features.h

xqd
@@ -0,0 +1,42 @@
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+# include "forwards.h"
+
+namespace Json {
+
+   /** \brief Configuration passed to reader and writer.
+    * This configuration object can be used to force the Reader or Writer
+    * to behave in a standard conforming way.
+    */
+   class JSON_API Features
+   {
+   public:
+      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+       * - C & C++ comments are allowed
+       * - Root object can be any JSON value
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features all();
+
+      /** \brief A configuration that is strictly compatible with the JSON specification.
+       * - Comments are forbidden.
+       * - Root object must be either an array or an object value.
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features strictMode();
+
+      /** \brief Initialize the configuration like JsonConfig::allFeatures;
+       */
+      Features();
+
+      /// \c true if comments are allowed. Default: \c true.
+      bool allowComments_;
+
+      /// \c true if root must be either an array or an object value. Default: \c false.
+      bool strictRoot_;
+   };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED

+ 39 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/forwards.h

xqd
@@ -0,0 +1,39 @@
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+# include "config.h"
+
+namespace Json {
+
+   // writer.h
+   class FastWriter;
+   class StyledWriter;
+
+   // reader.h
+   class Reader;
+
+   // features.h
+   class Features;
+
+   // value.h
+   typedef int Int;
+   typedef unsigned int UInt;
+   class StaticString;
+   class Path;
+   class PathArgument;
+   class Value;
+   class ValueIteratorBase;
+   class ValueIterator;
+   class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   class ValueAllocator;
+   class ValueMapAllocator;
+   class ValueInternalLink;
+   class ValueInternalArray;
+   class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED

+ 10 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/json.h

xqd
@@ -0,0 +1,10 @@
+#ifndef JSON_JSON_H_INCLUDED
+# define JSON_JSON_H_INCLUDED
+
+# include "autolink.h"
+# include "value.h"
+# include "reader.h"
+# include "writer.h"
+# include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED

+ 196 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/reader.h

xqd
@@ -0,0 +1,196 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+    *
+    */
+   class JSON_API Reader
+   {
+   public:
+      typedef char Char;
+      typedef const Char *Location;
+
+      /** \brief Constructs a Reader allowing all features
+       * for parsing.
+       */
+      Reader();
+
+      /** \brief Constructs a Reader allowing the specified feature set
+       * for parsing.
+       */
+      Reader( const Features &features );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const std::string &document, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const char *beginDoc, const char *endDoc, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /// \brief Parse from input stream.
+      /// \see Json::operator>>(std::istream&, Json::Value&).
+      bool parse( std::istream &is,
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       */
+      std::string getFormatedErrorMessages() const;
+
+   private:
+      enum TokenType
+      {
+         tokenEndOfStream = 0,
+         tokenObjectBegin,
+         tokenObjectEnd,
+         tokenArrayBegin,
+         tokenArrayEnd,
+         tokenString,
+         tokenNumber,
+         tokenTrue,
+         tokenFalse,
+         tokenNull,
+         tokenArraySeparator,
+         tokenMemberSeparator,
+         tokenComment,
+         tokenError
+      };
+
+      class Token
+      {
+      public:
+         TokenType type_;
+         Location start_;
+         Location end_;
+      };
+
+      class ErrorInfo
+      {
+      public:
+         Token token_;
+         std::string message_;
+         Location extra_;
+      };
+
+      typedef std::deque<ErrorInfo> Errors;
+
+      bool expectToken( TokenType type, Token &token, const char *message );
+      bool readToken( Token &token );
+      void skipSpaces();
+      bool match( Location pattern, 
+                  int patternLength );
+      bool readComment();
+      bool readCStyleComment();
+      bool readCppStyleComment();
+      bool readString();
+      void readNumber();
+      bool readValue();
+      bool readObject( Token &token );
+      bool readArray( Token &token );
+      bool decodeNumber( Token &token );
+      bool decodeString( Token &token );
+      bool decodeString( Token &token, std::string &decoded );
+      bool decodeDouble( Token &token );
+      bool decodeUnicodeCodePoint( Token &token, 
+                                   Location &current, 
+                                   Location end, 
+                                   unsigned int &unicode );
+      bool decodeUnicodeEscapeSequence( Token &token, 
+                                        Location &current, 
+                                        Location end, 
+                                        unsigned int &unicode );
+      bool addError( const std::string &message, 
+                     Token &token,
+                     Location extra = 0 );
+      bool recoverFromError( TokenType skipUntilToken );
+      bool addErrorAndRecover( const std::string &message, 
+                               Token &token,
+                               TokenType skipUntilToken );
+      void skipUntilSpace();
+      Value &currentValue();
+      Char getNextChar();
+      void getLocationLineAndColumn( Location location,
+                                     int &line,
+                                     int &column ) const;
+      std::string getLocationLineAndColumn( Location location ) const;
+      void addComment( Location begin, 
+                       Location end, 
+                       CommentPlacement placement );
+      void skipCommentTokens( Token &token );
+   
+      typedef std::stack<Value *> Nodes;
+      Nodes nodes_;
+      Errors errors_;
+      std::string document_;
+      Location begin_;
+      Location end_;
+      Location current_;
+      Location lastValueEnd_;
+      Value *lastValue_;
+      std::string commentsBefore_;
+      Features features_;
+      bool collectComments_;
+   };
+
+   /** \brief Read from 'sin' into 'root'.
+
+    Always keep comments from the input JSON.
+
+    This can be used to read a file into a particular sub-object.
+    For example:
+    \code
+    Json::Value root;
+    cin >> root["dir"]["file"];
+    cout << root;
+    \endcode
+    Result:
+    \verbatim
+    {
+	"dir": {
+	    "file": {
+		// The input stream JSON would be nested here.
+	    }
+	}
+    }
+    \endverbatim
+    \throw std::exception on parse error.
+    \see Json::operator<<()
+   */
+   std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED

+ 1069 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/value.h

xqd
@@ -0,0 +1,1069 @@
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+# include "forwards.h"
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+#  include <map>
+# else
+#  include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+#  include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+   /** \brief Type of the value held by a Value object.
+    */
+   enum ValueType
+   {
+      nullValue = 0, ///< 'null' value
+      intValue,      ///< signed integer value
+      uintValue,     ///< unsigned integer value
+      realValue,     ///< double value
+      stringValue,   ///< UTF-8 string value
+      booleanValue,  ///< bool value
+      arrayValue,    ///< array value (ordered list)
+      objectValue    ///< object value (collection of name/value pairs).
+   };
+
+   enum CommentPlacement
+   {
+      commentBefore = 0,        ///< a comment placed on the line before a value
+      commentAfterOnSameLine,   ///< a comment just after a value on the same line
+      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
+      numberOfCommentPlacement
+   };
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+   /** \brief Lightweight wrapper to tag static string.
+    *
+    * Value constructor and objectValue member assignement takes advantage of the
+    * StaticString and avoid the cost of string duplication when storing the
+    * string or the member name.
+    *
+    * Example of usage:
+    * \code
+    * Json::Value aValue( StaticString("some text") );
+    * Json::Value object;
+    * static const StaticString code("code");
+    * object[code] = 1234;
+    * \endcode
+    */
+   class JSON_API StaticString
+   {
+   public:
+      explicit StaticString( const char *czstring )
+         : str_( czstring )
+      {
+      }
+
+      operator const char *() const
+      {
+         return str_;
+      }
+
+      const char *c_str() const
+      {
+         return str_;
+      }
+
+   private:
+      const char *str_;
+   };
+
+   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+    *
+    * This class is a discriminated union wrapper that can represents a:
+    * - signed integer [range: Value::minInt - Value::maxInt]
+    * - unsigned integer (range: 0 - Value::maxUInt)
+    * - double
+    * - UTF-8 string
+    * - boolean
+    * - 'null'
+    * - an ordered list of Value
+    * - collection of name/value pairs (javascript object)
+    *
+    * The type of the held value is represented by a #ValueType and 
+    * can be obtained using type().
+    *
+    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. 
+    * Non const methods will automatically create the a #nullValue element 
+    * if it does not exist. 
+    * The sequence of an #arrayValue will be automatically resize and initialized 
+    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+    *
+    * The get() methods can be used to obtanis default value in the case the required element
+    * does not exist.
+    *
+    * It is possible to iterate over the list of a #objectValue values using 
+    * the getMemberNames() method.
+    */
+   class JSON_API Value 
+   {
+      friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      friend class ValueInternalLink;
+      friend class ValueInternalMap;
+# endif
+   public:
+      typedef std::vector<std::string> Members;
+      typedef ValueIterator iterator;
+      typedef ValueConstIterator const_iterator;
+      typedef Json::UInt UInt;
+      typedef Json::Int Int;
+      typedef UInt ArrayIndex;
+
+      static const Value null;
+      static const Int minInt;
+      static const Int maxInt;
+      static const UInt maxUInt;
+
+   private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+      class CZString 
+      {
+      public:
+         enum DuplicationPolicy 
+         {
+            noDuplication = 0,
+            duplicate,
+            duplicateOnCopy
+         };
+         CZString( int index );
+         CZString( const char *cstr, DuplicationPolicy allocate );
+         CZString( const CZString &other );
+         ~CZString();
+         CZString &operator =( const CZString &other );
+         bool operator<( const CZString &other ) const;
+         bool operator==( const CZString &other ) const;
+         int index() const;
+         const char *c_str() const;
+         bool isStaticString() const;
+      private:
+         void swap( CZString &other );
+         const char *cstr_;
+         int index_;
+      };
+
+   public:
+#  ifndef JSON_USE_CPPTL_SMALLMAP
+      typedef std::map<CZString, Value> ObjectValues;
+#  else
+      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+   public:
+      /** \brief Create a default Value of the given type.
+
+        This is a very useful constructor.
+        To create an empty array, pass arrayValue.
+        To create an empty object, pass objectValue.
+        Another Value can then be set to this one by assignment.
+	This is useful since clear() and resize() will not alter types.
+
+        Examples:
+	\code
+	Json::Value null_value; // null
+	Json::Value arr_value(Json::arrayValue); // []
+	Json::Value obj_value(Json::objectValue); // {}
+	\endcode
+      */
+      Value( ValueType type = nullValue );
+      Value( Int value );
+      Value( UInt value );
+      Value( double value );
+      Value( const char *value );
+      Value( const char *beginValue, const char *endValue );
+      /** \brief Constructs a value from a static string.
+
+       * Like other value string constructor but do not duplicate the string for
+       * internal storage. The given string must remain alive after the call to this
+       * constructor.
+       * Example of usage:
+       * \code
+       * Json::Value aValue( StaticString("some text") );
+       * \endcode
+       */
+      Value( const StaticString &value );
+      Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+      Value( const CppTL::ConstString &value );
+# endif
+      Value( bool value );
+      Value( const Value &other );
+      ~Value();
+
+      Value &operator=( const Value &other );
+      /// Swap values.
+      /// \note Currently, comments are intentionally not swapped, for
+      /// both logic and efficiency.
+      void swap( Value &other );
+
+      ValueType type() const;
+
+      bool operator <( const Value &other ) const;
+      bool operator <=( const Value &other ) const;
+      bool operator >=( const Value &other ) const;
+      bool operator >( const Value &other ) const;
+
+      bool operator ==( const Value &other ) const;
+      bool operator !=( const Value &other ) const;
+
+      int compare( const Value &other );
+
+      const char *asCString() const;
+      std::string asString() const;
+# ifdef JSON_USE_CPPTL
+      CppTL::ConstString asConstString() const;
+# endif
+      Int asInt() const;
+      UInt asUInt() const;
+      double asDouble() const;
+      bool asBool() const;
+
+      bool isNull() const;
+      bool isBool() const;
+      bool isInt() const;
+      bool isUInt() const;
+      bool isIntegral() const;
+      bool isDouble() const;
+      bool isNumeric() const;
+      bool isString() const;
+      bool isArray() const;
+      bool isObject() const;
+
+      bool isConvertibleTo( ValueType other ) const;
+
+      /// Number of values in array or object
+      UInt size() const;
+
+      /// \brief Return true if empty array, empty object, or null;
+      /// otherwise, false.
+      bool empty() const;
+
+      /// Return isNull()
+      bool operator!() const;
+
+      /// Remove all object members and array elements.
+      /// \pre type() is arrayValue, objectValue, or nullValue
+      /// \post type() is unchanged
+      void clear();
+
+      /// Resize the array to size elements. 
+      /// New elements are initialized to null.
+      /// May only be called on nullValue or arrayValue.
+      /// \pre type() is arrayValue or nullValue
+      /// \post type() is arrayValue
+      void resize( UInt size );
+
+      /// Access an array element (zero based index ).
+      /// If the array contains less than index element, then null value are inserted
+      /// in the array so that its size is index+1.
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      Value &operator[]( UInt index );
+      /// Access an array element (zero based index )
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      const Value &operator[]( UInt index ) const;
+      /// If the array contains at least index+1 elements, returns the element value, 
+      /// otherwise returns defaultValue.
+      Value get( UInt index, 
+                 const Value &defaultValue ) const;
+      /// Return true if index < size().
+      bool isValidIndex( UInt index ) const;
+      /// \brief Append value to array at the end.
+      ///
+      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+      Value &append( const Value &value );
+
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const char *key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const char *key ) const;
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const std::string &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const std::string &key ) const;
+      /** \brief Access an object value by name, create a null member if it does not exist.
+
+       * If the object as no entry for that name, then the member name used to store
+       * the new entry is not duplicated.
+       * Example of use:
+       * \code
+       * Json::Value object;
+       * static const StaticString code("code");
+       * object[code] = 1234;
+       * \endcode
+       */
+      Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const CppTL::ConstString &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const char *key, 
+                 const Value &defaultValue ) const;
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const std::string &key,
+                 const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const CppTL::ConstString &key,
+                 const Value &defaultValue ) const;
+# endif
+      /// \brief Remove and return the named member.  
+      ///
+      /// Do nothing if it did not exist.
+      /// \return the removed Value, or null.
+      /// \pre type() is objectValue or nullValue
+      /// \post type() is unchanged
+      Value removeMember( const char* key );
+      /// Same as removeMember(const char*)
+      Value removeMember( const std::string &key );
+
+      /// Return true if the object has a member named key.
+      bool isMember( const char *key ) const;
+      /// Return true if the object has a member named key.
+      bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return true if the object has a member named key.
+      bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+      /// \brief Return a list of the member names.
+      ///
+      /// If null, return an empty list.
+      /// \pre type() is objectValue or nullValue
+      /// \post if type() was nullValue, it remains nullValue
+      Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+//      EnumMemberNames enumMemberNames() const;
+//      EnumValues enumValues() const;
+//# endif
+
+      /// Comments must be //... or /* ... */
+      void setComment( const char *comment,
+                       CommentPlacement placement );
+      /// Comments must be //... or /* ... */
+      void setComment( const std::string &comment,
+                       CommentPlacement placement );
+      bool hasComment( CommentPlacement placement ) const;
+      /// Include delimiters and embedded newlines.
+      std::string getComment( CommentPlacement placement ) const;
+
+      std::string toStyledString() const;
+
+      const_iterator begin() const;
+      const_iterator end() const;
+
+      iterator begin();
+      iterator end();
+
+   private:
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      inline bool isItemAvailable() const
+      {
+         return itemIsUsed_ == 0;
+      }
+
+      inline void setItemUsed( bool isUsed = true )
+      {
+         itemIsUsed_ = isUsed ? 1 : 0;
+      }
+
+      inline bool isMemberNameStatic() const
+      {
+         return memberNameIsStatic_ == 0;
+      }
+
+      inline void setMemberNameIsStatic( bool isStatic )
+      {
+         memberNameIsStatic_ = isStatic ? 1 : 0;
+      }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+   private:
+      struct CommentInfo
+      {
+         CommentInfo();
+         ~CommentInfo();
+
+         void setComment( const char *text );
+
+         char *comment_;
+      };
+
+      //struct MemberNamesTransform
+      //{
+      //   typedef const char *result_type;
+      //   const char *operator()( const CZString &name ) const
+      //   {
+      //      return name.c_str();
+      //   }
+      //};
+
+      union ValueHolder
+      {
+         Int int_;
+         UInt uint_;
+         double real_;
+         bool bool_;
+         char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+         ValueInternalArray *array_;
+         ValueInternalMap *map_;
+#else
+         ObjectValues *map_;
+# endif
+      } value_;
+      ValueType type_ : 8;
+      int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
+      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
+# endif
+      CommentInfo *comments_;
+   };
+
+
+   /** \brief Experimental and untested: represents an element of the "path" to access a node.
+    */
+   class PathArgument
+   {
+   public:
+      friend class Path;
+
+      PathArgument();
+      PathArgument( UInt index );
+      PathArgument( const char *key );
+      PathArgument( const std::string &key );
+
+   private:
+      enum Kind
+      {
+         kindNone = 0,
+         kindIndex,
+         kindKey
+      };
+      std::string key_;
+      UInt index_;
+      Kind kind_;
+   };
+
+   /** \brief Experimental and untested: represents a "path" to access a node.
+    *
+    * Syntax:
+    * - "." => root node
+    * - ".[n]" => elements at index 'n' of root node (an array value)
+    * - ".name" => member named 'name' of root node (an object value)
+    * - ".name1.name2.name3"
+    * - ".[0][1][2].name1[3]"
+    * - ".%" => member name is provided as parameter
+    * - ".[%]" => index is provied as parameter
+    */
+   class Path
+   {
+   public:
+      Path( const std::string &path,
+            const PathArgument &a1 = PathArgument(),
+            const PathArgument &a2 = PathArgument(),
+            const PathArgument &a3 = PathArgument(),
+            const PathArgument &a4 = PathArgument(),
+            const PathArgument &a5 = PathArgument() );
+
+      const Value &resolve( const Value &root ) const;
+      Value resolve( const Value &root, 
+                     const Value &defaultValue ) const;
+      /// Creates the "path" to access the specified node and returns a reference on the node.
+      Value &make( Value &root ) const;
+
+   private:
+      typedef std::vector<const PathArgument *> InArgs;
+      typedef std::vector<PathArgument> Args;
+
+      void makePath( const std::string &path,
+                     const InArgs &in );
+      void addPathInArg( const std::string &path, 
+                         const InArgs &in, 
+                         InArgs::const_iterator &itInArg, 
+                         PathArgument::Kind kind );
+      void invalidPath( const std::string &path, 
+                        int location );
+
+      Args args_;
+   };
+
+   /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
+    *
+    * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
+    *   free an Json::objectValue member name.
+    * - duplicateStringValue() and releaseStringValue() are called similarly to
+    *   duplicate and free a Json::stringValue value.
+    */
+   class ValueAllocator
+   {
+   public:
+      enum { unknown = (unsigned)-1 };
+
+      virtual ~ValueAllocator();
+
+      virtual char *makeMemberName( const char *memberName ) = 0;
+      virtual void releaseMemberName( char *memberName ) = 0;
+      virtual char *duplicateStringValue( const char *value, 
+                                          unsigned int length = unknown ) = 0;
+      virtual void releaseStringValue( char *value ) = 0;
+   };
+
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   /** \brief Allocator to customize Value internal map.
+    * Below is an example of a simple implementation (default implementation actually
+    * use memory pool for speed).
+    * \code
+      class DefaultValueMapAllocator : public ValueMapAllocator
+      {
+      public: // overridden from ValueMapAllocator
+         virtual ValueInternalMap *newMap()
+         {
+            return new ValueInternalMap();
+         }
+
+         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+         {
+            return new ValueInternalMap( other );
+         }
+
+         virtual void destructMap( ValueInternalMap *map )
+         {
+            delete map;
+         }
+
+         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+         {
+            return new ValueInternalLink[size];
+         }
+
+         virtual void releaseMapBuckets( ValueInternalLink *links )
+         {
+            delete [] links;
+         }
+
+         virtual ValueInternalLink *allocateMapLink()
+         {
+            return new ValueInternalLink();
+         }
+
+         virtual void releaseMapLink( ValueInternalLink *link )
+         {
+            delete link;
+         }
+      };
+    * \endcode
+    */ 
+   class JSON_API ValueMapAllocator
+   {
+   public:
+      virtual ~ValueMapAllocator();
+      virtual ValueInternalMap *newMap() = 0;
+      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+      virtual void destructMap( ValueInternalMap *map ) = 0;
+      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+      virtual ValueInternalLink *allocateMapLink() = 0;
+      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+   };
+
+   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+    * \internal previous_ & next_ allows for bidirectional traversal.
+    */
+   class JSON_API ValueInternalLink
+   {
+   public:
+      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+      enum InternalFlags { 
+         flagAvailable = 0,
+         flagUsed = 1
+      };
+
+      ValueInternalLink();
+
+      ~ValueInternalLink();
+
+      Value items_[itemPerLink];
+      char *keys_[itemPerLink];
+      ValueInternalLink *previous_;
+      ValueInternalLink *next_;
+   };
+
+
+   /** \brief A linked page based hash-table implementation used internally by Value.
+    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+    * list in each bucket to handle collision. There is an addional twist in that
+    * each node of the collision linked list is a page containing a fixed amount of
+    * value. This provides a better compromise between memory usage and speed.
+    * 
+    * Each bucket is made up of a chained list of ValueInternalLink. The last
+    * link of a given bucket can be found in the 'previous_' field of the following bucket.
+    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+    * Only the last link of a bucket may contains 'available' item. The last link always
+    * contains at least one element unless is it the bucket one very first link.
+    */
+   class JSON_API ValueInternalMap
+   {
+      friend class ValueIteratorBase;
+      friend class Value;
+   public:
+      typedef unsigned int HashKey;
+      typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState
+      {
+         IteratorState() 
+            : map_(0)
+            , link_(0)
+            , itemIndex_(0)
+            , bucketIndex_(0) 
+         {
+         }
+         ValueInternalMap *map_;
+         ValueInternalLink *link_;
+         BucketIndex itemIndex_;
+         BucketIndex bucketIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalMap();
+      ValueInternalMap( const ValueInternalMap &other );
+      ValueInternalMap &operator =( const ValueInternalMap &other );
+      ~ValueInternalMap();
+
+      void swap( ValueInternalMap &other );
+
+      BucketIndex size() const;
+
+      void clear();
+
+      bool reserveDelta( BucketIndex growth );
+
+      bool reserve( BucketIndex newItemCount );
+
+      const Value *find( const char *key ) const;
+
+      Value *find( const char *key );
+
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+      void remove( const char *key );
+
+      void doActualRemove( ValueInternalLink *link, 
+                           BucketIndex index,
+                           BucketIndex bucketIndex );
+
+      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+      Value &setNewItem( const char *key, 
+                         bool isStatic, 
+                         ValueInternalLink *link, 
+                         BucketIndex index );
+
+      Value &unsafeAdd( const char *key, 
+                        bool isStatic, 
+                        HashKey hashedKey );
+
+      HashKey hash( const char *key ) const;
+
+      int compare( const ValueInternalMap &other ) const;
+
+   private:
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void incrementBucket( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static const char *key( const IteratorState &iterator );
+      static const char *key( const IteratorState &iterator, bool &isStatic );
+      static Value &value( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+
+   private:
+      ValueInternalLink *buckets_;
+      ValueInternalLink *tailLink_;
+      BucketIndex bucketsSize_;
+      BucketIndex itemCount_;
+   };
+
+   /** \brief A simplified deque implementation used internally by Value.
+   * \internal
+   * It is based on a list of fixed "page", each page contains a fixed number of items.
+   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+   * Look-up for an element is as follow:
+   * - compute page index: pageIndex = itemIndex / itemsPerPage
+   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+   *
+   * Insertion is amortized constant time (only the array containing the index of pointers
+   * need to be reallocated when items are appended).
+   */
+   class JSON_API ValueInternalArray
+   {
+      friend class Value;
+      friend class ValueIteratorBase;
+   public:
+      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
+      typedef Value::ArrayIndex ArrayIndex;
+      typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState // Must be a POD
+      {
+         IteratorState() 
+            : array_(0)
+            , currentPageIndex_(0)
+            , currentItemIndex_(0) 
+         {
+         }
+         ValueInternalArray *array_;
+         Value **currentPageIndex_;
+         unsigned int currentItemIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalArray();
+      ValueInternalArray( const ValueInternalArray &other );
+      ValueInternalArray &operator =( const ValueInternalArray &other );
+      ~ValueInternalArray();
+      void swap( ValueInternalArray &other );
+
+      void clear();
+      void resize( ArrayIndex newSize );
+
+      Value &resolveReference( ArrayIndex index );
+
+      Value *find( ArrayIndex index ) const;
+
+      ArrayIndex size() const;
+
+      int compare( const ValueInternalArray &other ) const;
+
+   private:
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static Value &dereference( const IteratorState &iterator );
+      static Value &unsafeDereference( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+      static ArrayIndex indexOf( const IteratorState &iterator );
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+      void makeIndexValid( ArrayIndex index );
+
+      Value **pages_;
+      ArrayIndex size_;
+      PageIndex pageCount_;
+   };
+
+   /** \brief Experimental: do not use. Allocator to customize Value internal array.
+    * Below is an example of a simple implementation (actual implementation use
+    * memory pool).
+      \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destruct( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+      \endcode
+    */ 
+   class JSON_API ValueArrayAllocator
+   {
+   public:
+      virtual ~ValueArrayAllocator();
+      virtual ValueInternalArray *newArray() = 0;
+      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+      virtual void destructArray( ValueInternalArray *array ) = 0;
+      /** \brief Reallocate array page index.
+       * Reallocates an array of pointer on each page.
+       * \param indexes [input] pointer on the current index. May be \c NULL.
+       *                [output] pointer on the new index of at least 
+       *                         \a minNewIndexCount pages. 
+       * \param indexCount [input] current number of pages in the index.
+       *                   [output] number of page the reallocated index can handle.
+       *                            \b MUST be >= \a minNewIndexCount.
+       * \param minNewIndexCount Minimum number of page the new index must be able to
+       *                         handle.
+       */
+      virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                             ValueInternalArray::PageIndex &indexCount,
+                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+      virtual void releaseArrayPageIndex( Value **indexes, 
+                                          ValueInternalArray::PageIndex indexCount ) = 0;
+      virtual Value *allocateArrayPage() = 0;
+      virtual void releaseArrayPage( Value *value ) = 0;
+   };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+   /** \brief base class for Value iterators.
+    *
+    */
+   class ValueIteratorBase
+   {
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef ValueIteratorBase SelfType;
+
+      ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+      bool operator ==( const SelfType &other ) const
+      {
+         return isEqual( other );
+      }
+
+      bool operator !=( const SelfType &other ) const
+      {
+         return !isEqual( other );
+      }
+
+      difference_type operator -( const SelfType &other ) const
+      {
+         return computeDistance( other );
+      }
+
+      /// Return either the index or the member name of the referenced value as a Value.
+      Value key() const;
+
+      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+      UInt index() const;
+
+      /// Return the member name of the referenced Value. "" if it is not an objectValue.
+      const char *memberName() const;
+
+   protected:
+      Value &deref() const;
+
+      void increment();
+
+      void decrement();
+
+      difference_type computeDistance( const SelfType &other ) const;
+
+      bool isEqual( const SelfType &other ) const;
+
+      void copy( const SelfType &other );
+
+   private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      Value::ObjectValues::iterator current_;
+      // Indicates that iterator is for a null value.
+      bool isNull_;
+#else
+      union
+      {
+         ValueInternalArray::IteratorState array_;
+         ValueInternalMap::IteratorState map_;
+      } iterator_;
+      bool isArray_;
+#endif
+   };
+
+   /** \brief const iterator for object and array value.
+    *
+    */
+   class ValueConstIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef const Value &reference;
+      typedef const Value *pointer;
+      typedef ValueConstIterator SelfType;
+
+      ValueConstIterator();
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueConstIterator( const ValueInternalArray::IteratorState &state );
+      ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+      SelfType &operator =( const ValueIteratorBase &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+   /** \brief Iterator for object and array value.
+    */
+   class ValueIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef Value &reference;
+      typedef Value *pointer;
+      typedef ValueIterator SelfType;
+
+      ValueIterator();
+      ValueIterator( const ValueConstIterator &other );
+      ValueIterator( const ValueIterator &other );
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueIterator( const ValueInternalArray::IteratorState &state );
+      ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+
+      SelfType &operator =( const SelfType &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED

+ 174 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json/writer.h

xqd
@@ -0,0 +1,174 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   class Value;
+
+   /** \brief Abstract class for writers.
+    */
+   class JSON_API Writer
+   {
+   public:
+      virtual ~Writer();
+
+      virtual std::string write( const Value &root ) = 0;
+   };
+
+   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+    *
+    * The JSON document is written in a single line. It is not intended for 'human' consumption,
+    * but may be usefull to support feature such as RPC where bandwith is limited.
+    * \sa Reader, Value
+    */
+   class JSON_API FastWriter : public Writer
+   {
+   public:
+      FastWriter();
+      virtual ~FastWriter(){}
+
+      void enableYAMLCompatibility();
+
+   public: // overridden from Writer
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+
+      std::string document_;
+      bool yamlCompatiblityEnabled_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledWriter: public Writer
+   {
+   public:
+      StyledWriter();
+      virtual ~StyledWriter(){}
+
+   public: // overridden from Writer
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param root Value to serialize.
+       * \return String containing the JSON document that represents the root value.
+       */
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::string document_;
+      std::string indentString_;
+      int rightMargin_;
+      int indentSize_;
+      bool addChildValues_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+        to a stream rather than to a string.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \param indentation Each level will be indented by this amount extra.
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledStreamWriter
+   {
+   public:
+      StyledStreamWriter( std::string indentation="\t" );
+      ~StyledStreamWriter(){}
+
+   public:
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param out Stream to write to. (Can be ostringstream, e.g.)
+       * \param root Value to serialize.
+       * \note There is no point in deriving from Writer, since write() should not return a value.
+       */
+      void write( std::ostream &out, const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::ostream* document_;
+      std::string indentString_;
+      int rightMargin_;
+      std::string indentation_;
+      bool addChildValues_;
+   };
+
+   std::string JSON_API valueToString( Int value );
+   std::string JSON_API valueToString( UInt value );
+   std::string JSON_API valueToString( double value );
+   std::string JSON_API valueToString( bool value );
+   std::string JSON_API valueToQuotedString( const char *value );
+
+   /// \brief Output using the StyledStreamWriter.
+   /// \see Json::operator>>()
+   std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED

+ 125 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_batchallocator.h

xqd
@@ -0,0 +1,125 @@
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ * 
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+        ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+   typedef AllocatedType Type;
+
+   BatchAllocator( unsigned int objectsPerPage = 255 )
+      : freeHead_( 0 )
+      , objectsPerPage_( objectsPerPage )
+   {
+//      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+      assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+      assert( objectsPerPage >= 16 );
+      batches_ = allocateBatch( 0 );   // allocated a dummy page
+      currentBatch_ = batches_;
+   }
+
+   ~BatchAllocator()
+   {
+      for ( BatchInfo *batch = batches_; batch;  )
+      {
+         BatchInfo *nextBatch = batch->next_;
+         free( batch );
+         batch = nextBatch;
+      }
+   }
+
+   /// allocate space for an array of objectPerAllocation object.
+   /// @warning it is the responsability of the caller to call objects constructors.
+   AllocatedType *allocate()
+   {
+      if ( freeHead_ ) // returns node from free list.
+      {
+         AllocatedType *object = freeHead_;
+         freeHead_ = *(AllocatedType **)object;
+         return object;
+      }
+      if ( currentBatch_->used_ == currentBatch_->end_ )
+      {
+         currentBatch_ = currentBatch_->next_;
+         while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
+            currentBatch_ = currentBatch_->next_;
+
+         if ( !currentBatch_  ) // no free batch found, allocate a new one
+         { 
+            currentBatch_ = allocateBatch( objectsPerPage_ );
+            currentBatch_->next_ = batches_; // insert at the head of the list
+            batches_ = currentBatch_;
+         }
+      }
+      AllocatedType *allocated = currentBatch_->used_;
+      currentBatch_->used_ += objectPerAllocation;
+      return allocated;
+   }
+
+   /// Release the object.
+   /// @warning it is the responsability of the caller to actually destruct the object.
+   void release( AllocatedType *object )
+   {
+      assert( object != 0 );
+      *(AllocatedType **)object = freeHead_;
+      freeHead_ = object;
+   }
+
+private:
+   struct BatchInfo
+   {
+      BatchInfo *next_;
+      AllocatedType *used_;
+      AllocatedType *end_;
+      AllocatedType buffer_[objectPerAllocation];
+   };
+
+   // disabled copy constructor and assignement operator.
+   BatchAllocator( const BatchAllocator & );
+   void operator =( const BatchAllocator &);
+
+   static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+   {
+      const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+                                + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+      BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+      batch->next_ = 0;
+      batch->used_ = batch->buffer_;
+      batch->end_ = batch->buffer_ + objectsPerPage;
+      return batch;
+   }
+
+   BatchInfo *batches_;
+   BatchInfo *currentBatch_;
+   /// Head of a single linked list within the allocated space of freeed object
+   AllocatedType *freeHead_;
+   unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+

+ 448 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_internalarray.inl

xqd
@@ -0,0 +1,448 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray(); // placement new
+      return array;
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray( other ); // placement new
+      return array;
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      if ( array )
+      {
+         array->~ValueInternalArray();
+         arraysAllocator_.release( array );
+      }
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( pagesAllocator_.allocate() );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         pagesAllocator_.release( value );
+   }
+private:
+   BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+   BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+   static DefaultValueArrayAllocator defaultAllocator;
+   static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+   return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+   DummyArrayAllocatorInitializer() 
+   {
+      arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
+   }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool 
+ValueInternalArray::equals( const IteratorState &x, 
+                            const IteratorState &other )
+{
+   return x.array_ == other.array_  
+          &&  x.currentItemIndex_ == other.currentItemIndex_  
+          &&  x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void 
+ValueInternalArray::increment( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      != it.array_->size_,
+      "ValueInternalArray::increment(): moving iterator beyond end" );
+   ++(it.currentItemIndex_);
+   if ( it.currentItemIndex_ == itemsPerPage )
+   {
+      it.currentItemIndex_ = 0;
+      ++(it.currentPageIndex_);
+   }
+}
+
+
+void 
+ValueInternalArray::decrement( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_ 
+                        &&  it.currentItemIndex_ == 0,
+      "ValueInternalArray::decrement(): moving iterator beyond end" );
+   if ( it.currentItemIndex_ == 0 )
+   {
+      it.currentItemIndex_ = itemsPerPage-1;
+      --(it.currentPageIndex_);
+   }
+   else
+   {
+      --(it.currentItemIndex_);
+   }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+   return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      < it.array_->size_,
+      "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+   return unsafeDereference( it );
+}
+
+void 
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = 0;
+   it.currentPageIndex_ = pages_;
+}
+
+
+void 
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = index % itemsPerPage;
+   it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void 
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+   makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+   : pages_( 0 )
+   , size_( 0 )
+   , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+   : pages_( 0 )
+   , pageCount_( 0 )
+   , size_( other.size_ )
+{
+   PageIndex minNewPages = other.size_ / itemsPerPage;
+   arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+   JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, 
+                        "ValueInternalArray::reserve(): bad reallocation" );
+   IteratorState itOther;
+   other.makeBeginIterator( itOther );
+   Value *value;
+   for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+   {
+      if ( index % itemsPerPage == 0 )
+      {
+         PageIndex pageIndex = index / itemsPerPage;
+         value = arrayAllocator()->allocateArrayPage();
+         pages_[pageIndex] = value;
+      }
+      new (value) Value( dereference( itOther ) );
+   }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+   ValueInternalArray temp( other );
+   swap( temp );
+   return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+   // destroy all constructed items
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it);
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      value->~Value();
+   }
+   // release all pages
+   PageIndex lastPageIndex = size_ / itemsPerPage;
+   for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+      arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+   // release pages index
+   arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void 
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+   Value **tempPages = pages_;
+   pages_ = other.pages_;
+   other.pages_ = tempPages;
+   ArrayIndex tempSize = size_;
+   size_ = other.size_;
+   other.size_ = tempSize;
+   PageIndex tempPageCount = pageCount_;
+   pageCount_ = other.pageCount_;
+   other.pageCount_ = tempPageCount;
+}
+
+void 
+ValueInternalArray::clear()
+{
+   ValueInternalArray dummy;
+   swap( dummy );
+}
+
+
+void 
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize < size_ )
+   {
+      IteratorState it;
+      IteratorState itEnd;
+      makeIterator( it, newSize );
+      makeIterator( itEnd, size_ );
+      for ( ; !equals(it,itEnd); increment(it) )
+      {
+         Value *value = &dereference(it);
+         value->~Value();
+      }
+      PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+      PageIndex lastPageIndex = size_ / itemsPerPage;
+      for ( ; pageIndex < lastPageIndex; ++pageIndex )
+         arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+      size_ = newSize;
+   }
+   else if ( newSize > size_ )
+      resolveReference( newSize );
+}
+
+
+void 
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+   // Need to enlarge page index ?
+   if ( index >= pageCount_ * itemsPerPage )
+   {
+      PageIndex minNewPages = (index + 1) / itemsPerPage;
+      arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+      JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+   }
+
+   // Need to allocate new pages ?
+   ArrayIndex nextPageIndex = 
+      (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+                                  : size_;
+   if ( nextPageIndex <= index )
+   {
+      PageIndex pageIndex = nextPageIndex / itemsPerPage;
+      PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+      for ( ; pageToAllocate-- > 0; ++pageIndex )
+         pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+   }
+
+   // Initialize all new entries
+   IteratorState it;
+   IteratorState itEnd;
+   makeIterator( it, size_ );
+   size_ = index + 1;
+   makeIterator( itEnd, size_ );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      new (value) Value(); // Construct a default value using placement new
+   }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+   if ( index >= size_ )
+      makeIndexValid( index );
+   return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+   if ( index >= size_ )
+      return 0;
+   return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::size() const
+{
+   return size_;
+}
+
+int 
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+   return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+   if ( !iterator.array_ )
+      return ArrayIndex(-1);
+   return ArrayIndex(
+      (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage 
+      + iterator.currentItemIndex_ );
+}
+
+
+int 
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+   int sizeDiff( size_ - other.size_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   
+   for ( ArrayIndex index =0; index < size_; ++index )
+   {
+      int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( 
+         other.pages_[index/itemsPerPage][index%itemsPerPage] );
+      if ( diff != 0 )
+         return diff;
+   }
+   return 0;
+}

+ 607 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_internalmap.inl

xqd
@@ -0,0 +1,607 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+   * This optimization is used by the fast allocator.
+   */
+ValueInternalLink::ValueInternalLink()
+   : previous_( 0 )
+   , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{ 
+   for ( int index =0; index < itemPerLink; ++index )
+   {
+      if ( !items_[index].isItemAvailable() )
+      {
+         if ( !items_[index].isMemberNameStatic() )
+            free( keys_[index] );
+      }
+      else
+         break;
+   }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      return new ValueInternalMap();
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      return new ValueInternalMap( other );
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      delete map;
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      return new ValueInternalLink();
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      delete link;
+   }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap(); // placement new
+      return map;
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap( other ); // placement new
+      return map;
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      if ( map )
+      {
+         map->~ValueInternalMap();
+         mapsAllocator_.release( map );
+      }
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      ValueInternalLink *link = linksAllocator_.allocate();
+      memset( link, 0, sizeof(ValueInternalLink) );
+      return link;
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      link->~ValueInternalLink();
+      linksAllocator_.release( link );
+   }
+private:
+   BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+   BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+   static DefaultValueMapAllocator defaultAllocator;
+   static ValueMapAllocator *mapAllocator = &defaultAllocator;
+   return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+   DummyMapAllocatorInitializer() 
+   {
+      mapAllocator();      // ensure mapAllocator() statics are initialized before main().
+   }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map. 
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+   reserve( other.itemCount_ );
+   IteratorState it;
+   IteratorState itEnd;
+   other.makeBeginIterator( it );
+   other.makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      bool isStatic;
+      const char *memberName = key( it, isStatic );
+      const Value &aValue = value( it );
+      resolveReference(memberName, isStatic) = aValue;
+   }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+   ValueInternalMap dummy( other );
+   swap( dummy );
+   return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+   if ( buckets_ )
+   {
+      for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+      {
+         ValueInternalLink *link = buckets_[bucketIndex].next_;
+         while ( link )
+         {
+            ValueInternalLink *linkToRelease = link;
+            link = link->next_;
+            mapAllocator()->releaseMapLink( linkToRelease );
+         }
+      }
+      mapAllocator()->releaseMapBuckets( buckets_ );
+   }
+}
+
+
+void 
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+   ValueInternalLink *tempBuckets = buckets_;
+   buckets_ = other.buckets_;
+   other.buckets_ = tempBuckets;
+   ValueInternalLink *tempTailLink = tailLink_;
+   tailLink_ = other.tailLink_;
+   other.tailLink_ = tempTailLink;
+   BucketIndex tempBucketsSize = bucketsSize_;
+   bucketsSize_ = other.bucketsSize_;
+   other.bucketsSize_ = tempBucketsSize;
+   BucketIndex tempItemCount = itemCount_;
+   itemCount_ = other.itemCount_;
+   other.itemCount_ = tempItemCount;
+}
+
+
+void 
+ValueInternalMap::clear()
+{
+   ValueInternalMap dummy;
+   swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex 
+ValueInternalMap::size() const
+{
+   return itemCount_;
+}
+
+bool 
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+   return reserve( itemCount_ + growth );
+}
+
+bool 
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+   if ( !buckets_  &&  newItemCount > 0 )
+   {
+      buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+      bucketsSize_ = 1;
+      tailLink_ = &buckets_[0];
+   }
+//   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+   return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+   if ( !bucketsSize_ )
+      return 0;
+   HashKey hashedKey = hash( key );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( const ValueInternalLink *current = &buckets_[bucketIndex]; 
+         current != 0; 
+         current = current->next_ )
+   {
+      for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( current->items_[index].isItemAvailable() )
+            return 0;
+         if ( strcmp( key, current->keys_[index] ) == 0 )
+            return &current->items_[index];
+      }
+   }
+   return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+   const ValueInternalMap *constThis = this;
+   return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+                                    bool isStatic )
+{
+   HashKey hashedKey = hash( key );
+   if ( bucketsSize_ )
+   {
+      BucketIndex bucketIndex = hashedKey % bucketsSize_;
+      ValueInternalLink **previous = 0;
+      BucketIndex index;
+      for ( ValueInternalLink *current = &buckets_[bucketIndex]; 
+            current != 0; 
+            previous = &current->next_, current = current->next_ )
+      {
+         for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+         {
+            if ( current->items_[index].isItemAvailable() )
+               return setNewItem( key, isStatic, current, index );
+            if ( strcmp( key, current->keys_[index] ) == 0 )
+               return current->items_[index];
+         }
+      }
+   }
+
+   reserveDelta( 1 );
+   return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void 
+ValueInternalMap::remove( const char *key )
+{
+   HashKey hashedKey = hash( key );
+   if ( !bucketsSize_ )
+      return;
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( ValueInternalLink *link = &buckets_[bucketIndex]; 
+         link != 0; 
+         link = link->next_ )
+   {
+      BucketIndex index;
+      for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( link->items_[index].isItemAvailable() )
+            return;
+         if ( strcmp( key, link->keys_[index] ) == 0 )
+         {
+            doActualRemove( link, index, bucketIndex );
+            return;
+         }
+      }
+   }
+}
+
+void 
+ValueInternalMap::doActualRemove( ValueInternalLink *link, 
+                                  BucketIndex index,
+                                  BucketIndex bucketIndex )
+{
+   // find last item of the bucket and swap it with the 'removed' one.
+   // set removed items flags to 'available'.
+   // if last page only contains 'available' items, then desallocate it (it's empty)
+   ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+   BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+   for ( ;   
+         lastItemIndex < ValueInternalLink::itemPerLink; 
+         ++lastItemIndex ) // may be optimized with dicotomic search
+   {
+      if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+         break;
+   }
+   
+   BucketIndex lastUsedIndex = lastItemIndex - 1;
+   Value *valueToDelete = &link->items_[index];
+   Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+   if ( valueToDelete != valueToPreserve )
+      valueToDelete->swap( *valueToPreserve );
+   if ( lastUsedIndex == 0 )  // page is now empty
+   {  // remove it from bucket linked list and delete it.
+      ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+      if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
+      {
+         mapAllocator()->releaseMapLink( lastLink );
+         linkPreviousToLast->next_ = 0;
+         lastLink = linkPreviousToLast;
+      }
+   }
+   else
+   {
+      Value dummy;
+      valueToPreserve->swap( dummy ); // restore deleted to default Value.
+      valueToPreserve->setItemUsed( false );
+   }
+   --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+   if ( bucketIndex == bucketsSize_ - 1 )
+      return tailLink_;
+   ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+   if ( !previous )
+      previous = &buckets_[bucketIndex];
+   return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key, 
+                              bool isStatic,
+                              ValueInternalLink *link, 
+                              BucketIndex index )
+{
+   char *duplicatedKey = valueAllocator()->makeMemberName( key );
+   ++itemCount_;
+   link->keys_[index] = duplicatedKey;
+   link->items_[index].setItemUsed();
+   link->items_[index].setMemberNameIsStatic( isStatic );
+   return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key, 
+                             bool isStatic, 
+                             HashKey hashedKey )
+{
+   JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+   ValueInternalLink *link = previousLink;
+   BucketIndex index;
+   for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+   {
+      if ( link->items_[index].isItemAvailable() )
+         break;
+   }
+   if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+   {
+      ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+      index = 0;
+      link->next_ = newLink;
+      previousLink = newLink;
+      link = newLink;
+   }
+   return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey 
+ValueInternalMap::hash( const char *key ) const
+{
+   HashKey hash = 0;
+   while ( *key )
+      hash += *key++ * 37;
+   return hash;
+}
+
+
+int 
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+   int sizeDiff( itemCount_ - other.itemCount_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it );
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      if ( !other.find( key( it ) ) )
+         return 1;
+   }
+
+   // All keys are equals, let's compare values
+   makeBeginIterator( it );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      const Value *otherValue = other.find( key( it ) );
+      int valueDiff = value(it).compare( *otherValue );
+      if ( valueDiff != 0 )
+         return valueDiff;
+   }
+   return 0;
+}
+
+
+void 
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = 0;
+   it.itemIndex_ = 0;
+   it.link_ = buckets_;
+}
+
+
+void 
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = bucketsSize_;
+   it.itemIndex_ = 0;
+   it.link_ = 0;
+}
+
+
+bool 
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+   return x.map_ == other.map_  
+          &&  x.bucketIndex_ == other.bucketIndex_  
+          &&  x.link_ == other.link_
+          &&  x.itemIndex_ == other.itemIndex_;
+}
+
+
+void 
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+   ++iterator.bucketIndex_;
+   JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+      "ValueInternalMap::increment(): attempting to iterate beyond end." );
+   if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+      iterator.link_ = 0;
+   else
+      iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+   iterator.itemIndex_ = 0;
+}
+
+
+void 
+ValueInternalMap::increment( IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+   ++iterator.itemIndex_;
+   if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+   {
+      JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+         "ValueInternalMap::increment(): attempting to iterate beyond end." );
+      iterator.link_ = iterator.link_->next_;
+      if ( iterator.link_ == 0 )
+         incrementBucket( iterator );
+   }
+   else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+   {
+      incrementBucket( iterator );
+   }
+}
+
+
+void 
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+   if ( iterator.itemIndex_ == 0 )
+   {
+      JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+      if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+      {
+         JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+         --(iterator.bucketIndex_);
+      }
+      iterator.link_ = iterator.link_->previous_;
+      iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+   }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int 
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+   int offset = 0;
+   IteratorState it = x;
+   while ( !equals( it, y ) )
+      increment( it );
+   return offset;
+}

+ 892 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_reader.cpp

xqd
@@ -0,0 +1,892 @@
+#include <json/reader.h>
+#include <json/value.h>
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// QNX is strict about declaring C symbols in the std namespace.
+#ifdef __QNXNTO__
+using std::memcpy;
+using std::sprintf;
+using std::sscanf;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+   : allowComments_( true )
+   , strictRoot_( false )
+{
+}
+
+
+Features 
+Features::all()
+{
+   return Features();
+}
+
+
+Features 
+Features::strictMode()
+{
+   Features features;
+   features.allowComments_ = false;
+   features.strictRoot_ = true;
+   return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
+}
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
+}
+
+
+static bool 
+containsNewLine( Reader::Location begin, 
+                 Reader::Location end )
+{
+   for ( ;begin < end; ++begin )
+      if ( *begin == '\n'  ||  *begin == '\r' )
+         return true;
+   return false;
+}
+
+static std::string codePointToUTF8(unsigned int cp)
+{
+   std::string result;
+   
+   // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+   if (cp <= 0x7f) 
+   {
+      result.resize(1);
+      result[0] = static_cast<char>(cp);
+   } 
+   else if (cp <= 0x7FF) 
+   {
+      result.resize(2);
+      result[1] = static_cast<char>(0x80 | (0x3f & cp));
+      result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+   } 
+   else if (cp <= 0xFFFF) 
+   {
+      result.resize(3);
+      result[2] = static_cast<char>(0x80 | (0x3f & cp));
+      result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+      result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+   }
+   else if (cp <= 0x10FFFF) 
+   {
+      result.resize(4);
+      result[3] = static_cast<char>(0x80 | (0x3f & cp));
+      result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+      result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+      result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+   }
+
+   return result;
+}
+
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+   : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+   : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document, 
+               Value &root,
+               bool collectComments )
+{
+   document_ = document;
+   const char *begin = document_.c_str();
+   const char *end = begin + document_.length();
+   return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+               Value &root,
+               bool collectComments )
+{
+   //std::istream_iterator<char> begin(sin);
+   //std::istream_iterator<char> end;
+   // Those would allow streamed input from a file, if parse() were a
+   // template function.
+
+   // Since std::string is reference-counted, this at least does not
+   // create an extra copy.
+   std::string doc;
+   std::getline(sin, doc, (char)EOF);
+   return parse( doc, root, collectComments );
+}
+
+bool 
+Reader::parse( const char *beginDoc, const char *endDoc, 
+               Value &root,
+               bool collectComments )
+{
+   if ( !features_.allowComments_ )
+   {
+      collectComments = false;
+   }
+
+   begin_ = beginDoc;
+   end_ = endDoc;
+   collectComments_ = collectComments;
+   current_ = begin_;
+   lastValueEnd_ = 0;
+   lastValue_ = 0;
+   commentsBefore_ = "";
+   errors_.clear();
+   while ( !nodes_.empty() )
+      nodes_.pop();
+   nodes_.push( &root );
+   
+   bool successful = readValue();
+   Token token;
+   skipCommentTokens( token );
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+      root.setComment( commentsBefore_, commentAfter );
+   if ( features_.strictRoot_ )
+   {
+      if ( !root.isArray()  &&  !root.isObject() )
+      {
+         // Set error location to start of doc, ideally should be first token found in doc
+         token.type_ = tokenError;
+         token.start_ = beginDoc;
+         token.end_ = endDoc;
+         addError( "A valid JSON document must be either an array or an object value.",
+                   token );
+         return false;
+      }
+   }
+   return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+   Token token;
+   skipCommentTokens( token );
+   bool successful = true;
+
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+   {
+      currentValue().setComment( commentsBefore_, commentBefore );
+      commentsBefore_ = "";
+   }
+
+
+   switch ( token.type_ )
+   {
+   case tokenObjectBegin:
+      successful = readObject( token );
+      break;
+   case tokenArrayBegin:
+      successful = readArray( token );
+      break;
+   case tokenNumber:
+      successful = decodeNumber( token );
+      break;
+   case tokenString:
+      successful = decodeString( token );
+      break;
+   case tokenTrue:
+      currentValue() = true;
+      break;
+   case tokenFalse:
+      currentValue() = false;
+      break;
+   case tokenNull:
+      currentValue() = Value();
+      break;
+   default:
+      return addError( "Syntax error: value, object or array expected.", token );
+   }
+
+   if ( collectComments_ )
+   {
+      lastValueEnd_ = current_;
+      lastValue_ = &currentValue();
+   }
+
+   return successful;
+}
+
+
+void 
+Reader::skipCommentTokens( Token &token )
+{
+   if ( features_.allowComments_ )
+   {
+      do
+      {
+         readToken( token );
+      }
+      while ( token.type_ == tokenComment );
+   }
+   else
+   {
+      readToken( token );
+   }
+}
+
+
+bool 
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+   readToken( token );
+   if ( token.type_ != type )
+      return addError( message, token );
+   return true;
+}
+
+
+bool 
+Reader::readToken( Token &token )
+{
+   skipSpaces();
+   token.start_ = current_;
+   Char c = getNextChar();
+   bool ok = true;
+   switch ( c )
+   {
+   case '{':
+      token.type_ = tokenObjectBegin;
+      break;
+   case '}':
+      token.type_ = tokenObjectEnd;
+      break;
+   case '[':
+      token.type_ = tokenArrayBegin;
+      break;
+   case ']':
+      token.type_ = tokenArrayEnd;
+      break;
+   case '"':
+      token.type_ = tokenString;
+      ok = readString();
+      break;
+   case '/':
+      token.type_ = tokenComment;
+      ok = readComment();
+      break;
+   case '0':
+   case '1':
+   case '2':
+   case '3':
+   case '4':
+   case '5':
+   case '6':
+   case '7':
+   case '8':
+   case '9':
+   case '-':
+      token.type_ = tokenNumber;
+      readNumber();
+      break;
+   case 't':
+      token.type_ = tokenTrue;
+      ok = match( "rue", 3 );
+      break;
+   case 'f':
+      token.type_ = tokenFalse;
+      ok = match( "alse", 4 );
+      break;
+   case 'n':
+      token.type_ = tokenNull;
+      ok = match( "ull", 3 );
+      break;
+   case ',':
+      token.type_ = tokenArraySeparator;
+      break;
+   case ':':
+      token.type_ = tokenMemberSeparator;
+      break;
+   case 0:
+      token.type_ = tokenEndOfStream;
+      break;
+   default:
+      ok = false;
+      break;
+   }
+   if ( !ok )
+      token.type_ = tokenError;
+   token.end_ = current_;
+   return true;
+}
+
+
+void 
+Reader::skipSpaces()
+{
+   while ( current_ != end_ )
+   {
+      Char c = *current_;
+      if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
+         ++current_;
+      else
+         break;
+   }
+}
+
+
+bool 
+Reader::match( Location pattern, 
+               int patternLength )
+{
+   if ( end_ - current_ < patternLength )
+      return false;
+   int index = patternLength;
+   while ( index-- )
+      if ( current_[index] != pattern[index] )
+         return false;
+   current_ += patternLength;
+   return true;
+}
+
+
+bool
+Reader::readComment()
+{
+   Location commentBegin = current_ - 1;
+   Char c = getNextChar();
+   bool successful = false;
+   if ( c == '*' )
+      successful = readCStyleComment();
+   else if ( c == '/' )
+      successful = readCppStyleComment();
+   if ( !successful )
+      return false;
+
+   if ( collectComments_ )
+   {
+      CommentPlacement placement = commentBefore;
+      if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
+      {
+         if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
+            placement = commentAfterOnSameLine;
+      }
+
+      addComment( commentBegin, current_, placement );
+   }
+   return true;
+}
+
+
+void 
+Reader::addComment( Location begin, 
+                    Location end, 
+                    CommentPlacement placement )
+{
+   assert( collectComments_ );
+   if ( placement == commentAfterOnSameLine )
+   {
+      assert( lastValue_ != 0 );
+      lastValue_->setComment( std::string( begin, end ), placement );
+   }
+   else
+   {
+      if ( !commentsBefore_.empty() )
+         commentsBefore_ += "\n";
+      commentsBefore_ += std::string( begin, end );
+   }
+}
+
+
+bool 
+Reader::readCStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if ( c == '*'  &&  *current_ == '/' )
+         break;
+   }
+   return getNextChar() == '/';
+}
+
+
+bool 
+Reader::readCppStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if (  c == '\r'  ||  c == '\n' )
+         break;
+   }
+   return true;
+}
+
+
+void 
+Reader::readNumber()
+{
+   while ( current_ != end_ )
+   {
+      if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
+           !in( *current_, '.', 'e', 'E', '+', '-' ) )
+         break;
+      ++current_;
+   }
+}
+
+bool
+Reader::readString()
+{
+   Char c = 0;
+   while ( current_ != end_ )
+   {
+      c = getNextChar();
+      if ( c == '\\' )
+         getNextChar();
+      else if ( c == '"' )
+         break;
+   }
+   return c == '"';
+}
+
+
+bool 
+Reader::readObject( Token &tokenStart )
+{
+   Token tokenName;
+   std::string name;
+   currentValue() = Value( objectValue );
+   while ( readToken( tokenName ) )
+   {
+      bool initialTokenOk = true;
+      while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
+         initialTokenOk = readToken( tokenName );
+      if  ( !initialTokenOk )
+         break;
+      if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
+         return true;
+      if ( tokenName.type_ != tokenString )
+         break;
+      
+      name = "";
+      if ( !decodeString( tokenName, name ) )
+         return recoverFromError( tokenObjectEnd );
+
+      Token colon;
+      if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
+      {
+         return addErrorAndRecover( "Missing ':' after object member name", 
+                                    colon, 
+                                    tokenObjectEnd );
+      }
+      Value &value = currentValue()[ name ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenObjectEnd );
+
+      Token comma;
+      if ( !readToken( comma )
+            ||  ( comma.type_ != tokenObjectEnd  &&  
+                  comma.type_ != tokenArraySeparator &&
+		  comma.type_ != tokenComment ) )
+      {
+         return addErrorAndRecover( "Missing ',' or '}' in object declaration", 
+                                    comma, 
+                                    tokenObjectEnd );
+      }
+      bool finalizeTokenOk = true;
+      while ( comma.type_ == tokenComment &&
+              finalizeTokenOk )
+         finalizeTokenOk = readToken( comma );
+      if ( comma.type_ == tokenObjectEnd )
+         return true;
+   }
+   return addErrorAndRecover( "Missing '}' or object member name", 
+                              tokenName, 
+                              tokenObjectEnd );
+}
+
+
+bool 
+Reader::readArray( Token &tokenStart )
+{
+   currentValue() = Value( arrayValue );
+   skipSpaces();
+   if ( *current_ == ']' ) // empty array
+   {
+      Token endArray;
+      readToken( endArray );
+      return true;
+   }
+   int index = 0;
+   while ( true )
+   {
+      Value &value = currentValue()[ index++ ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenArrayEnd );
+
+      Token token;
+      // Accept Comment after last item in the array.
+      ok = readToken( token );
+      while ( token.type_ == tokenComment  &&  ok )
+      {
+         ok = readToken( token );
+      }
+      bool badTokenType = ( token.type_ == tokenArraySeparator  &&  
+                            token.type_ == tokenArrayEnd );
+      if ( !ok  ||  badTokenType )
+      {
+         return addErrorAndRecover( "Missing ',' or ']' in array declaration", 
+                                    token, 
+                                    tokenArrayEnd );
+      }
+      if ( token.type_ == tokenArrayEnd )
+         break;
+   }
+   return true;
+}
+
+
+bool 
+Reader::decodeNumber( Token &token )
+{
+   bool isDouble = false;
+   for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+   {
+      isDouble = isDouble  
+                 ||  in( *inspect, '.', 'e', 'E', '+' )  
+                 ||  ( *inspect == '-'  &&  inspect != token.start_ );
+   }
+   if ( isDouble )
+      return decodeDouble( token );
+   Location current = token.start_;
+   bool isNegative = *current == '-';
+   if ( isNegative )
+      ++current;
+   Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) 
+                                       : Value::maxUInt) / 10;
+   Value::UInt value = 0;
+   while ( current < token.end_ )
+   {
+      Char c = *current++;
+      if ( c < '0'  ||  c > '9' )
+         return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+      if ( value >= threshold )
+         return decodeDouble( token );
+      value = value * 10 + Value::UInt(c - '0');
+   }
+   if ( isNegative )
+      currentValue() = -Value::Int( value );
+   else if ( value <= Value::UInt(Value::maxInt) )
+      currentValue() = Value::Int( value );
+   else
+      currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeDouble( Token &token )
+{
+   double value = 0;
+   const int bufferSize = 32;
+   int count;
+   int length = int(token.end_ - token.start_);
+   if ( length <= bufferSize )
+   {
+      Char buffer[bufferSize];
+      memcpy( buffer, token.start_, length );
+      buffer[length] = 0;
+      count = sscanf( buffer, "%lf", &value );
+   }
+   else
+   {
+      std::string buffer( token.start_, token.end_ );
+      count = sscanf( buffer.c_str(), "%lf", &value );
+   }
+
+   if ( count != 1 )
+      return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+   currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token )
+{
+   std::string decoded;
+   if ( !decodeString( token, decoded ) )
+      return false;
+   currentValue() = decoded;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token, std::string &decoded )
+{
+   decoded.reserve( token.end_ - token.start_ - 2 );
+   Location current = token.start_ + 1; // skip '"'
+   Location end = token.end_ - 1;      // do not include '"'
+   while ( current != end )
+   {
+      Char c = *current++;
+      if ( c == '"' )
+         break;
+      else if ( c == '\\' )
+      {
+         if ( current == end )
+            return addError( "Empty escape sequence in string", token, current );
+         Char escape = *current++;
+         switch ( escape )
+         {
+         case '"': decoded += '"'; break;
+         case '/': decoded += '/'; break;
+         case '\\': decoded += '\\'; break;
+         case 'b': decoded += '\b'; break;
+         case 'f': decoded += '\f'; break;
+         case 'n': decoded += '\n'; break;
+         case 'r': decoded += '\r'; break;
+         case 't': decoded += '\t'; break;
+         case 'u':
+            {
+               unsigned int unicode;
+               if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+                  return false;
+               decoded += codePointToUTF8(unicode);
+            }
+            break;
+         default:
+            return addError( "Bad escape sequence in string", token, current );
+         }
+      }
+      else
+      {
+         decoded += c;
+      }
+   }
+   return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+
+   if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+      return false;
+   if (unicode >= 0xD800 && unicode <= 0xDBFF)
+   {
+      // surrogate pairs
+      if (end - current < 6)
+         return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+      unsigned int surrogatePair;
+      if (*(current++) == '\\' && *(current++)== 'u')
+      {
+         if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+         {
+            unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+         } 
+         else
+            return false;
+      } 
+      else
+         return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+   }
+   return true;
+}
+
+bool 
+Reader::decodeUnicodeEscapeSequence( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+   if ( end - current < 4 )
+      return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+   unicode = 0;
+   for ( int index =0; index < 4; ++index )
+   {
+      Char c = *current++;
+      unicode *= 16;
+      if ( c >= '0'  &&  c <= '9' )
+         unicode += c - '0';
+      else if ( c >= 'a'  &&  c <= 'f' )
+         unicode += c - 'a' + 10;
+      else if ( c >= 'A'  &&  c <= 'F' )
+         unicode += c - 'A' + 10;
+      else
+         return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+   }
+   return true;
+}
+
+
+bool 
+Reader::addError( const std::string &message, 
+                  Token &token,
+                  Location extra )
+{
+   ErrorInfo info;
+   info.token_ = token;
+   info.message_ = message;
+   info.extra_ = extra;
+   errors_.push_back( info );
+   return false;
+}
+
+
+bool 
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+   int errorCount = int(errors_.size());
+   Token skip;
+   while ( true )
+   {
+      if ( !readToken(skip) )
+         errors_.resize( errorCount ); // discard errors caused by recovery
+      if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
+         break;
+   }
+   errors_.resize( errorCount );
+   return false;
+}
+
+
+bool 
+Reader::addErrorAndRecover( const std::string &message, 
+                            Token &token,
+                            TokenType skipUntilToken )
+{
+   addError( message, token );
+   return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+   return *(nodes_.top());
+}
+
+
+Reader::Char 
+Reader::getNextChar()
+{
+   if ( current_ == end_ )
+      return 0;
+   return *current_++;
+}
+
+
+void 
+Reader::getLocationLineAndColumn( Location location,
+                                  int &line,
+                                  int &column ) const
+{
+   Location current = begin_;
+   Location lastLineStart = current;
+   line = 0;
+   while ( current < location  &&  current != end_ )
+   {
+      Char c = *current++;
+      if ( c == '\r' )
+      {
+         if ( *current == '\n' )
+            ++current;
+         lastLineStart = current;
+         ++line;
+      }
+      else if ( c == '\n' )
+      {
+         lastLineStart = current;
+         ++line;
+      }
+   }
+   // column & line start at 1
+   column = int(location - lastLineStart) + 1;
+   ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+   int line, column;
+   getLocationLineAndColumn( location, line, column );
+   char buffer[18+16+16+1];
+   sprintf( buffer, "Line %d, Column %d", line, column );
+   return buffer;
+}
+
+
+std::string 
+Reader::getFormatedErrorMessages() const
+{
+   std::string formattedMessage;
+   for ( Errors::const_iterator itError = errors_.begin();
+         itError != errors_.end();
+         ++itError )
+   {
+      const ErrorInfo &error = *itError;
+      formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+      formattedMessage += "  " + error.message_ + "\n";
+      if ( error.extra_ )
+         formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+   }
+   return formattedMessage;
+}
+
+
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+    Json::Reader reader;
+    bool ok = reader.parse(sin, root, true);
+    //JSON_ASSERT( ok );
+    if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
+    return sin;
+}
+
+
+} // namespace Json

+ 1726 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_value.cpp

xqd
@@ -0,0 +1,1726 @@
+#include <iostream>
+#include <json/value.h>
+#include <json/writer.h>
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef>    // size_t
+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+# include "json_batchallocator.h"
+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+
+namespace Json {
+
+// QNX is strict about declaring C symbols in the std namespace.
+#ifdef __QNXNTO__
+using std::memcpy;
+using std::strchr;
+using std::strcmp;
+using std::strlen;
+#endif
+
+const Value Value::null;
+const Int Value::minInt = Int( ~(UInt(-1)/2) );
+const Int Value::maxInt = Int( UInt(-1)/2 );
+const UInt Value::maxUInt = UInt(-1);
+
+// A "safe" implementation of strdup. Allow null pointer to be passed. 
+// Also avoid warning on msvc80.
+//
+//inline char *safeStringDup( const char *czstring )
+//{
+//   if ( czstring )
+//   {
+//      const size_t length = (unsigned int)( strlen(czstring) + 1 );
+//      char *newString = static_cast<char *>( malloc( length ) );
+//      memcpy( newString, czstring, length );
+//      return newString;
+//   }
+//   return 0;
+//}
+//
+//inline char *safeStringDup( const std::string &str )
+//{
+//   if ( !str.empty() )
+//   {
+//      const size_t length = str.length();
+//      char *newString = static_cast<char *>( malloc( length + 1 ) );
+//      memcpy( newString, str.c_str(), length );
+//      newString[length] = 0;
+//      return newString;
+//   }
+//   return 0;
+//}
+
+ValueAllocator::~ValueAllocator()
+{
+}
+
+class DefaultValueAllocator : public ValueAllocator
+{
+public:
+   virtual ~DefaultValueAllocator()
+   {
+   }
+
+   virtual char *makeMemberName( const char *memberName )
+   {
+      return duplicateStringValue( memberName );
+   }
+
+   virtual void releaseMemberName( char *memberName )
+   {
+      releaseStringValue( memberName );
+   }
+
+   virtual char *duplicateStringValue( const char *value, 
+                                       unsigned int length = unknown )
+   {
+      //@todo invesgate this old optimization
+      //if ( !value  ||  value[0] == 0 )
+      //   return 0;
+
+      if ( length == unknown )
+         length = (unsigned int)strlen(value);
+      char *newString = static_cast<char *>( malloc( length + 1 ) );
+      memcpy( newString, value, length );
+      newString[length] = 0;
+      return newString;
+   }
+
+   virtual void releaseStringValue( char *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+
+static ValueAllocator *&valueAllocator()
+{
+   static DefaultValueAllocator defaultAllocator;
+   static ValueAllocator *valueAllocator = &defaultAllocator;
+   return valueAllocator;
+}
+
+static struct DummyValueAllocatorInitializer {
+   DummyValueAllocatorInitializer() 
+   {
+      valueAllocator();      // ensure valueAllocator() statics are initialized before main().
+   }
+} dummyValueAllocatorInitializer;
+
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+# include "json_internalarray.inl"
+# include "json_internalmap.inl"
+#endif // JSON_VALUE_USE_INTERNAL_MAP
+
+# include "json_valueiterator.inl"
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+Value::CommentInfo::CommentInfo()
+   : comment_( 0 )
+{
+}
+
+Value::CommentInfo::~CommentInfo()
+{
+   if ( comment_ )
+      valueAllocator()->releaseStringValue( comment_ );
+}
+
+
+void 
+Value::CommentInfo::setComment( const char *text )
+{
+   if ( comment_ )
+      valueAllocator()->releaseStringValue( comment_ );
+   JSON_ASSERT( text );
+   JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
+   // It seems that /**/ style comments are acceptable as well.
+   comment_ = valueAllocator()->duplicateStringValue( text );
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString( int index )
+   : cstr_( 0 )
+   , index_( index )
+{
+}
+
+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
+   : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) 
+                                  : cstr )
+   , index_( allocate )
+{
+}
+
+Value::CZString::CZString( const CZString &other )
+: cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
+                ?  valueAllocator()->makeMemberName( other.cstr_ )
+                : other.cstr_ )
+   , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
+                         : other.index_ )
+{
+}
+
+Value::CZString::~CZString()
+{
+   if ( cstr_  &&  index_ == duplicate )
+      valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
+}
+
+void 
+Value::CZString::swap( CZString &other )
+{
+   std::swap( cstr_, other.cstr_ );
+   std::swap( index_, other.index_ );
+}
+
+Value::CZString &
+Value::CZString::operator =( const CZString &other )
+{
+   CZString temp( other );
+   swap( temp );
+   return *this;
+}
+
+bool 
+Value::CZString::operator<( const CZString &other ) const 
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) < 0;
+   return index_ < other.index_;
+}
+
+bool 
+Value::CZString::operator==( const CZString &other ) const 
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) == 0;
+   return index_ == other.index_;
+}
+
+
+int 
+Value::CZString::index() const
+{
+   return index_;
+}
+
+
+const char *
+Value::CZString::c_str() const
+{
+   return cstr_;
+}
+
+bool 
+Value::CZString::isStaticString() const
+{
+   return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value( ValueType type )
+   : type_( type )
+   , allocated_( 0 )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type )
+   {
+   case nullValue:
+      break;
+   case intValue:
+   case uintValue:
+      value_.int_ = 0;
+      break;
+   case realValue:
+      value_.real_ = 0.0;
+      break;
+   case stringValue:
+      value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues();
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArray();
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMap();
+      break;
+#endif
+   case booleanValue:
+      value_.bool_ = false;
+      break;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+}
+
+
+Value::Value( Int value )
+   : type_( intValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.int_ = value;
+}
+
+
+Value::Value( UInt value )
+   : type_( uintValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.uint_ = value;
+}
+
+Value::Value( double value )
+   : type_( realValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.real_ = value;
+}
+
+Value::Value( const char *value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value );
+}
+
+
+Value::Value( const char *beginValue, 
+              const char *endValue )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( beginValue, 
+                                                            UInt(endValue - beginValue) );
+}
+
+
+Value::Value( const std::string &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), 
+                                                            (unsigned int)value.length() );
+
+}
+
+Value::Value( const StaticString &value )
+   : type_( stringValue )
+   , allocated_( false )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = const_cast<char *>( value.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value( bool value )
+   : type_( booleanValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.bool_ = value;
+}
+
+
+Value::Value( const Value &other )
+   : type_( other.type_ )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      value_ = other.value_;
+      break;
+   case stringValue:
+      if ( other.value_.string_ )
+      {
+         value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
+         allocated_ = true;
+      }
+      else
+         value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues( *other.value_.map_ );
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   if ( other.comments_ )
+   {
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+      for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
+      {
+         const CommentInfo &otherComment = other.comments_[comment];
+         if ( otherComment.comment_ )
+            comments_[comment].setComment( otherComment.comment_ );
+      }
+   }
+}
+
+
+Value::~Value()
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      break;
+   case stringValue:
+      if ( allocated_ )
+         valueAllocator()->releaseStringValue( value_.string_ );
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      delete value_.map_;
+      break;
+#else
+   case arrayValue:
+      arrayAllocator()->destructArray( value_.array_ );
+      break;
+   case objectValue:
+      mapAllocator()->destructMap( value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+
+   if ( comments_ )
+      delete[] comments_;
+}
+
+Value &
+Value::operator=( const Value &other )
+{
+   Value temp( other );
+   swap( temp );
+   return *this;
+}
+
+void 
+Value::swap( Value &other )
+{
+   ValueType temp = type_;
+   type_ = other.type_;
+   other.type_ = temp;
+   std::swap( value_, other.value_ );
+   int temp2 = allocated_;
+   allocated_ = other.allocated_;
+   other.allocated_ = temp2;
+}
+
+ValueType 
+Value::type() const
+{
+   return type_;
+}
+
+
+int 
+Value::compare( const Value &other )
+{
+   /*
+   int typeDelta = other.type_ - type_;
+   switch ( type_ )
+   {
+   case nullValue:
+
+      return other.type_ == type_;
+   case intValue:
+      if ( other.type_.isNumeric()
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      break;
+   case stringValue,
+      break;
+   case arrayValue:
+      delete value_.array_;
+      break;
+   case objectValue:
+      delete value_.map_;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   */
+   return 0;  // unreachable
+}
+
+bool 
+Value::operator <( const Value &other ) const
+{
+   int typeDelta = type_ - other.type_;
+   if ( typeDelta )
+      return typeDelta < 0 ? true : false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+      return value_.int_ < other.value_.int_;
+   case uintValue:
+      return value_.uint_ < other.value_.uint_;
+   case realValue:
+      return value_.real_ < other.value_.real_;
+   case booleanValue:
+      return value_.bool_ < other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == 0  &&  other.value_.string_ )
+             || ( other.value_.string_  
+                  &&  value_.string_  
+                  && strcmp( value_.string_, other.value_.string_ ) < 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      {
+         int delta = int( value_.map_->size() - other.value_.map_->size() );
+         if ( delta )
+            return delta < 0;
+         return (*value_.map_) < (*other.value_.map_);
+      }
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) < 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0;  // unreachable
+}
+
+bool 
+Value::operator <=( const Value &other ) const
+{
+   return !(other > *this);
+}
+
+bool 
+Value::operator >=( const Value &other ) const
+{
+   return !(*this < other);
+}
+
+bool 
+Value::operator >( const Value &other ) const
+{
+   return other < *this;
+}
+
+bool 
+Value::operator ==( const Value &other ) const
+{
+   //if ( type_ != other.type_ )
+   // GCC 2.95.3 says:
+   // attempt to take address of bit-field structure member `Json::Value::type_'
+   // Beats me, but a temp solves the problem.
+   int temp = other.type_;
+   if ( type_ != temp )
+      return false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return value_.int_ == other.value_.int_;
+   case uintValue:
+      return value_.uint_ == other.value_.uint_;
+   case realValue:
+      return value_.real_ == other.value_.real_;
+   case booleanValue:
+      return value_.bool_ == other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == other.value_.string_ )
+             || ( other.value_.string_  
+                  &&  value_.string_  
+                  && strcmp( value_.string_, other.value_.string_ ) == 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() == other.value_.map_->size()
+             && (*value_.map_) == (*other.value_.map_);
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) == 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0;  // unreachable
+}
+
+bool 
+Value::operator !=( const Value &other ) const
+{
+   return !( *this == other );
+}
+
+const char *
+Value::asCString() const
+{
+   JSON_ASSERT( type_ == stringValue );
+   return value_.string_;
+}
+
+
+std::string 
+Value::asString() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return "";
+   case stringValue:
+      return value_.string_ ? value_.string_ : "";
+   case booleanValue:
+      return value_.bool_ ? "true" : "false";
+   case intValue:
+   case uintValue:
+   case realValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString 
+Value::asConstString() const
+{
+   return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+Value::Int 
+Value::asInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
+      return Int( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+Value::UInt 
+Value::asUInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
+      return UInt( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+double 
+Value::asDouble() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0.0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      return value_.real_;
+   case booleanValue:
+      return value_.bool_ ? 1.0 : 0.0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+bool 
+Value::asBool() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+   case uintValue:
+      return value_.int_ != 0;
+   case realValue:
+      return value_.real_ != 0.0;
+   case booleanValue:
+      return value_.bool_;
+   case stringValue:
+      return value_.string_  &&  value_.string_[0] != 0;
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() != 0;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+bool 
+Value::isConvertibleTo( ValueType other ) const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return ( other == nullValue  &&  value_.int_ == 0 )
+             || other == intValue
+             || ( other == uintValue  && value_.int_ >= 0 )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case uintValue:
+      return ( other == nullValue  &&  value_.uint_ == 0 )
+             || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case realValue:
+      return ( other == nullValue  &&  value_.real_ == 0.0 )
+             || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
+             || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case booleanValue:
+      return ( other == nullValue  &&  value_.bool_ == false )
+             || other == intValue
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case stringValue:
+      return other == stringValue
+             || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
+   case arrayValue:
+      return other == arrayValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   case objectValue:
+      return other == objectValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+/// Number of values in array or object
+Value::UInt 
+Value::size() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+   case stringValue:
+      return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:  // size of the array is highest index + 1
+      if ( !value_.map_->empty() )
+      {
+         ObjectValues::const_iterator itLast = value_.map_->end();
+         --itLast;
+         return (*itLast).first.index()+1;
+      }
+      return 0;
+   case objectValue:
+      return Int( value_.map_->size() );
+#else
+   case arrayValue:
+      return Int( value_.array_->size() );
+   case objectValue:
+      return Int( value_.map_->size() );
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+bool 
+Value::empty() const
+{
+   if ( isNull() || isArray() || isObject() )
+      return size() == 0u;
+   else
+      return false;
+}
+
+
+bool
+Value::operator!() const
+{
+   return isNull();
+}
+
+
+void 
+Value::clear()
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
+
+   switch ( type_ )
+   {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_->clear();
+      break;
+#else
+   case arrayValue:
+      value_.array_->clear();
+      break;
+   case objectValue:
+      value_.map_->clear();
+      break;
+#endif
+   default:
+      break;
+   }
+}
+
+void 
+Value::resize( UInt newSize )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   UInt oldSize = size();
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize > oldSize )
+      (*this)[ newSize - 1 ];
+   else
+   {
+      for ( UInt index = newSize; index < oldSize; ++index )
+         value_.map_->erase( index );
+      assert( size() == newSize );
+   }
+#else
+   value_.array_->resize( newSize );
+#endif
+}
+
+
+Value &
+Value::operator[]( UInt index )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::iterator it = value_.map_->lower_bound( key );
+   if ( it != value_.map_->end()  &&  (*it).first == key )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( key, null );
+   it = value_.map_->insert( it, defaultValue );
+   return (*it).second;
+#else
+   return value_.array_->resolveReference( index );
+#endif
+}
+
+
+const Value &
+Value::operator[]( UInt index ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::const_iterator it = value_.map_->find( key );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   Value *value = value_.array_->find( index );
+   return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const char *key )
+{
+   return resolveReference( key, false );
+}
+
+
+Value &
+Value::resolveReference( const char *key, 
+                         bool isStatic )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      *this = Value( objectValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, isStatic ? CZString::noDuplication 
+                                     : CZString::duplicateOnCopy );
+   ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
+   if ( it != value_.map_->end()  &&  (*it).first == actualKey )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( actualKey, null );
+   it = value_.map_->insert( it, defaultValue );
+   Value &value = (*it).second;
+   return value;
+#else
+   return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+
+Value 
+Value::get( UInt index, 
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[index]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+bool 
+Value::isValidIndex( UInt index ) const
+{
+   return index < size();
+}
+
+
+
+const Value &
+Value::operator[]( const char *key ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::const_iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   const Value *value = value_.map_->find( key );
+   return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const std::string &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const std::string &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+
+Value &
+Value::operator[]( const StaticString &key )
+{
+   return resolveReference( key, true );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+# endif
+
+
+Value &
+Value::append( const Value &value )
+{
+   return (*this)[size()] = value;
+}
+
+
+Value 
+Value::get( const char *key, 
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[key]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+Value 
+Value::get( const std::string &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+
+Value
+Value::removeMember( const char* key )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   Value old(it->second);
+   value_.map_->erase(it);
+   return old;
+#else
+   Value *value = value_.map_->find( key );
+   if (value){
+      Value old(*value);
+      value_.map_.remove( key );
+      return old;
+   } else {
+      return null;
+   }
+#endif
+}
+
+Value
+Value::removeMember( const std::string &key )
+{
+   return removeMember( key.c_str() );
+}
+
+# ifdef JSON_USE_CPPTL
+Value 
+Value::get( const CppTL::ConstString &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool 
+Value::isMember( const char *key ) const
+{
+   const Value *value = &((*this)[key]);
+   return value != &null;
+}
+
+
+bool 
+Value::isMember( const std::string &key ) const
+{
+   return isMember( key.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+bool 
+Value::isMember( const CppTL::ConstString &key ) const
+{
+   return isMember( key.c_str() );
+}
+#endif
+
+Value::Members 
+Value::getMemberNames() const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+       return Value::Members();
+   Members members;
+   members.reserve( value_.map_->size() );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ObjectValues::const_iterator it = value_.map_->begin();
+   ObjectValues::const_iterator itEnd = value_.map_->end();
+   for ( ; it != itEnd; ++it )
+      members.push_back( std::string( (*it).first.c_str() ) );
+#else
+   ValueInternalMap::IteratorState it;
+   ValueInternalMap::IteratorState itEnd;
+   value_.map_->makeBeginIterator( it );
+   value_.map_->makeEndIterator( itEnd );
+   for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+      members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+   return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+//   if ( type_ == objectValue )
+//   {
+//      return CppTL::Enum::any(  CppTL::Enum::transform(
+//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+//         MemberNamesTransform() ) );
+//   }
+//   return EnumMemberNames();
+//}
+//
+//
+//EnumValues 
+//Value::enumValues() const
+//{
+//   if ( type_ == objectValue  ||  type_ == arrayValue )
+//      return CppTL::Enum::anyValues( *(value_.map_), 
+//                                     CppTL::Type<const Value &>() );
+//   return EnumValues();
+//}
+//
+//# endif
+
+
+bool
+Value::isNull() const
+{
+   return type_ == nullValue;
+}
+
+
+bool 
+Value::isBool() const
+{
+   return type_ == booleanValue;
+}
+
+
+bool 
+Value::isInt() const
+{
+   return type_ == intValue;
+}
+
+
+bool 
+Value::isUInt() const
+{
+   return type_ == uintValue;
+}
+
+
+bool 
+Value::isIntegral() const
+{
+   return type_ == intValue  
+          ||  type_ == uintValue  
+          ||  type_ == booleanValue;
+}
+
+
+bool 
+Value::isDouble() const
+{
+   return type_ == realValue;
+}
+
+
+bool 
+Value::isNumeric() const
+{
+   return isIntegral() || isDouble();
+}
+
+
+bool 
+Value::isString() const
+{
+   return type_ == stringValue;
+}
+
+
+bool 
+Value::isArray() const
+{
+   return type_ == nullValue  ||  type_ == arrayValue;
+}
+
+
+bool 
+Value::isObject() const
+{
+   return type_ == nullValue  ||  type_ == objectValue;
+}
+
+
+void 
+Value::setComment( const char *comment,
+                   CommentPlacement placement )
+{
+   if ( !comments_ )
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+   comments_[placement].setComment( comment );
+}
+
+
+void 
+Value::setComment( const std::string &comment,
+                   CommentPlacement placement )
+{
+   setComment( comment.c_str(), placement );
+}
+
+
+bool 
+Value::hasComment( CommentPlacement placement ) const
+{
+   return comments_ != 0  &&  comments_[placement].comment_ != 0;
+}
+
+std::string 
+Value::getComment( CommentPlacement placement ) const
+{
+   if ( hasComment(placement) )
+      return comments_[placement].comment_;
+   return "";
+}
+
+
+std::string 
+Value::toStyledString() const
+{
+   StyledWriter writer;
+   return writer.write( *this );
+}
+
+
+Value::const_iterator 
+Value::begin() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+Value::const_iterator 
+Value::end() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+
+Value::iterator 
+Value::begin()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+Value::iterator 
+Value::end()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument()
+   : kind_( kindNone )
+{
+}
+
+
+PathArgument::PathArgument( Value::UInt index )
+   : index_( index )
+   , kind_( kindIndex )
+{
+}
+
+
+PathArgument::PathArgument( const char *key )
+   : key_( key )
+   , kind_( kindKey )
+{
+}
+
+
+PathArgument::PathArgument( const std::string &key )
+   : key_( key.c_str() )
+   , kind_( kindKey )
+{
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path( const std::string &path,
+            const PathArgument &a1,
+            const PathArgument &a2,
+            const PathArgument &a3,
+            const PathArgument &a4,
+            const PathArgument &a5 )
+{
+   InArgs in;
+   in.push_back( &a1 );
+   in.push_back( &a2 );
+   in.push_back( &a3 );
+   in.push_back( &a4 );
+   in.push_back( &a5 );
+   makePath( path, in );
+}
+
+
+void 
+Path::makePath( const std::string &path,
+                const InArgs &in )
+{
+   const char *current = path.c_str();
+   const char *end = current + path.length();
+   InArgs::const_iterator itInArg = in.begin();
+   while ( current != end )
+   {
+      if ( *current == '[' )
+      {
+         ++current;
+         if ( *current == '%' )
+            addPathInArg( path, in, itInArg, PathArgument::kindIndex );
+         else
+         {
+            Value::UInt index = 0;
+            for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
+               index = index * 10 + Value::UInt(*current - '0');
+            args_.push_back( index );
+         }
+         if ( current == end  ||  *current++ != ']' )
+            invalidPath( path, int(current - path.c_str()) );
+      }
+      else if ( *current == '%' )
+      {
+         addPathInArg( path, in, itInArg, PathArgument::kindKey );
+         ++current;
+      }
+      else if ( *current == '.' )
+      {
+         ++current;
+      }
+      else
+      {
+         const char *beginName = current;
+         while ( current != end  &&  !strchr( "[.", *current ) )
+            ++current;
+         args_.push_back( std::string( beginName, current ) );
+      }
+   }
+}
+
+
+void 
+Path::addPathInArg( const std::string &path, 
+                    const InArgs &in, 
+                    InArgs::const_iterator &itInArg, 
+                    PathArgument::Kind kind )
+{
+   if ( itInArg == in.end() )
+   {
+      // Error: missing argument %d
+   }
+   else if ( (*itInArg)->kind_ != kind )
+   {
+      // Error: bad argument type
+   }
+   else
+   {
+      args_.push_back( **itInArg );
+   }
+}
+
+
+void 
+Path::invalidPath( const std::string &path, 
+                   int location )
+{
+   // Error: invalid path.
+}
+
+
+const Value &
+Path::resolve( const Value &root ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+         {
+            // Error: unable to resolve path (array value expected at position...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: unable to resolve path (object value expected at position...)
+         }
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+         {
+            // Error: unable to resolve path (object has no member named '' at position...)
+         }
+      }
+   }
+   return *node;
+}
+
+
+Value 
+Path::resolve( const Value &root, 
+               const Value &defaultValue ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+            return defaultValue;
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+            return defaultValue;
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+            return defaultValue;
+      }
+   }
+   return *node;
+}
+
+
+Value &
+Path::make( Value &root ) const
+{
+   Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray() )
+         {
+            // Error: node is not an array at position ...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: node is not an object at position...
+         }
+         node = &((*node)[arg.key_]);
+      }
+   }
+   return *node;
+}
+
+
+} // namespace Json

+ 292 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_valueiterator.inl

xqd
@@ -0,0 +1,292 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   : current_()
+   , isNull_( true )
+{
+}
+#else
+   : isArray_( true )
+   , isNull_( true )
+{
+   iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+   : current_( current )
+   , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+   : isArray_( true )
+{
+   iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+   : isArray_( false )
+{
+   iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   return current_->second;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::dereference( iterator_.array_ );
+   return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ++current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::increment( iterator_.array_ );
+   ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   --current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::decrement( iterator_.array_ );
+   ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type 
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+   return current_ - other.current_;
+# else
+   // Iterator for null value are initialized using the default
+   // constructor, which initialize current_ to the default
+   // std::map::iterator. As begin() and end() are two instance 
+   // of the default std::map::iterator, they can not be compared.
+   // To allow this, we handle this comparison specifically.
+   if ( isNull_  &&  other.isNull_ )
+   {
+      return 0;
+   }
+
+
+   // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+   // which is the one used by default).
+   // Using a portable hand-made version for non random iterator instead:
+   //   return difference_type( std::distance( current_, other.current_ ) );
+   difference_type myDistance = 0;
+   for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+   {
+      ++myDistance;
+   }
+   return myDistance;
+# endif
+#else
+   if ( isArray_ )
+      return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool 
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   if ( isNull_ )
+   {
+      return other.isNull_;
+   }
+   return current_ == other.current_;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   current_ = other.current_;
+#else
+   if ( isArray_ )
+      iterator_.array_ = other.iterator_.array_;
+   iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value 
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( czstring.c_str() )
+   {
+      if ( czstring.isStaticString() )
+         return Value( StaticString( czstring.c_str() ) );
+      return Value( czstring.c_str() );
+   }
+   return Value( czstring.index() );
+#else
+   if ( isArray_ )
+      return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+   bool isStatic;
+   const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+   if ( isStatic )
+      return Value( StaticString( memberName ) );
+   return Value( memberName );
+#endif
+}
+
+
+UInt 
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( !czstring.c_str() )
+      return czstring.index();
+   return Value::UInt( -1 );
+#else
+   if ( isArray_ )
+      return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+   return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const char *name = (*current_).first.c_str();
+   return name ? name : "";
+#else
+   if ( !isArray_ )
+      return ValueInternalMap::key( iterator_.map_ );
+   return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+   copy( other );
+   return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+   copy( other );
+   return *this;
+}

+ 829 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/json_writer.cpp

xqd
@@ -0,0 +1,829 @@
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch)
+{
+   return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter( const char* str )
+{
+   while ( *str ) 
+   {
+      if ( isControlCharacter( *(str++) ) )
+         return true;
+   }
+   return false;
+}
+static void uintToString( unsigned int value, 
+                          char *&current )
+{
+   *--current = 0;
+   do
+   {
+      *--current = (value % 10) + '0';
+      value /= 10;
+   }
+   while ( value != 0 );
+}
+
+std::string valueToString( Int value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   bool isNegative = value < 0;
+   if ( isNegative )
+      value = -value;
+   uintToString( UInt(value), current );
+   if ( isNegative )
+      *--current = '-';
+   assert( current >= buffer );
+   return current;
+}
+
+
+std::string valueToString( UInt value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   uintToString( value, current );
+   assert( current >= buffer );
+   return current;
+}
+
+std::string valueToString( double value )
+{
+   char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. 
+   sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
+#else	
+   sprintf(buffer, "%#.16g", value); 
+#endif
+   char* ch = buffer + strlen(buffer) - 1;
+   if (*ch != '0') return buffer; // nothing to truncate, so save time
+   while(ch > buffer && *ch == '0'){
+     --ch;
+   }
+   char* last_nonzero = ch;
+   while(ch >= buffer){
+     switch(*ch){
+     case '0':
+     case '1':
+     case '2':
+     case '3':
+     case '4':
+     case '5':
+     case '6':
+     case '7':
+     case '8':
+     case '9':
+       --ch;
+       continue;
+     case '.':
+       // Truncate zeroes to save bytes in output, but keep one.
+       *(last_nonzero+2) = '\0';
+       return buffer;
+     default:
+       return buffer;
+     }
+   }
+   return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+   return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+   // Not sure how to handle unicode...
+   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
+      return std::string("\"") + value + "\"";
+   // We have to walk value and escape any special characters.
+   // Appending to std::string is not efficient, but this should be rare.
+   // (Note: forward slashes are *not* rare, but I am not escaping them.)
+   unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+   std::string result;
+   result.reserve(maxsize); // to avoid lots of mallocs
+   result += "\"";
+   for (const char* c=value; *c != 0; ++c)
+   {
+      switch(*c)
+      {
+         case '\"':
+            result += "\\\"";
+            break;
+         case '\\':
+            result += "\\\\";
+            break;
+         case '\b':
+            result += "\\b";
+            break;
+         case '\f':
+            result += "\\f";
+            break;
+         case '\n':
+            result += "\\n";
+            break;
+         case '\r':
+            result += "\\r";
+            break;
+         case '\t':
+            result += "\\t";
+            break;
+         //case '/':
+            // Even though \/ is considered a legal escape in JSON, a bare
+            // slash is also legal, so I see no reason to escape it.
+            // (I hope I am not misunderstanding something.
+            // blep notes: actually escaping \/ may be useful in javascript to avoid </ 
+            // sequence.
+            // Should add a flag to allow this compatibility mode and prevent this 
+            // sequence from occurring.
+         default:
+            if ( isControlCharacter( *c ) )
+            {
+               std::ostringstream oss;
+               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+               result += oss.str();
+            }
+            else
+            {
+               result += *c;
+            }
+            break;
+      }
+   }
+   result += "\"";
+   return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+   : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void 
+FastWriter::enableYAMLCompatibility()
+{
+   yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string 
+FastWriter::write( const Value &root )
+{
+   document_ = "";
+   writeValue( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+FastWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      document_ += "null";
+      break;
+   case intValue:
+      document_ += valueToString( value.asInt() );
+      break;
+   case uintValue:
+      document_ += valueToString( value.asUInt() );
+      break;
+   case realValue:
+      document_ += valueToString( value.asDouble() );
+      break;
+   case stringValue:
+      document_ += valueToQuotedString( value.asCString() );
+      break;
+   case booleanValue:
+      document_ += valueToString( value.asBool() );
+      break;
+   case arrayValue:
+      {
+         document_ += "[";
+         int size = value.size();
+         for ( int index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ",";
+            writeValue( value[index] );
+         }
+         document_ += "]";
+      }
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         document_ += "{";
+         for ( Value::Members::iterator it = members.begin(); 
+               it != members.end(); 
+               ++it )
+         {
+            const std::string &name = *it;
+            if ( it != members.begin() )
+               document_ += ",";
+            document_ += valueToQuotedString( name.c_str() );
+            document_ += yamlCompatiblityEnabled_ ? ": " 
+                                                  : ":";
+            writeValue( value[name] );
+         }
+         document_ += "}";
+      }
+      break;
+   }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+   : rightMargin_( 74 )
+   , indentSize_( 3 )
+{
+}
+
+
+std::string 
+StyledWriter::write( const Value &root )
+{
+   document_ = "";
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+StyledWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               document_ += " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               document_ += ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            document_ += ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         document_ += "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ", ";
+            document_ += childValues_[index];
+         }
+         document_ += " ]";
+      }
+   }
+}
+
+
+bool 
+StyledWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      document_ += value;
+}
+
+
+void 
+StyledWriter::writeIndent()
+{
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         document_ += '\n';
+   }
+   document_ += indentString_;
+}
+
+
+void 
+StyledWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   document_ += value;
+}
+
+
+void 
+StyledWriter::indent()
+{
+   indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void 
+StyledWriter::unindent()
+{
+   assert( int(indentString_.size()) >= indentSize_ );
+   indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void 
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   document_ += normalizeEOL( root.getComment( commentBefore ) );
+   document_ += "\n";
+}
+
+
+void 
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      document_ += "\n";
+      document_ += normalizeEOL( root.getComment( commentAfter ) );
+      document_ += "\n";
+   }
+}
+
+
+bool 
+StyledWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+   : document_(NULL)
+   , rightMargin_( 74 )
+   , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+   document_ = &out;
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   *document_ << "\n";
+   document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void 
+StyledStreamWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               *document_ << " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               *document_ << ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+	       writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            *document_ << ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         *document_ << "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               *document_ << ", ";
+            *document_ << childValues_[index];
+         }
+         *document_ << " ]";
+      }
+   }
+}
+
+
+bool 
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledStreamWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::writeIndent()
+{
+  /*
+    Some comments in this method would have been nice. ;-)
+
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         *document_ << '\n';
+   }
+  */
+   *document_ << '\n' << indentString_;
+}
+
+
+void 
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::indent()
+{
+   indentString_ += indentation_;
+}
+
+
+void 
+StyledStreamWriter::unindent()
+{
+   assert( indentString_.size() >= indentation_.size() );
+   indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void 
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   *document_ << normalizeEOL( root.getComment( commentBefore ) );
+   *document_ << "\n";
+}
+
+
+void 
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      *document_ << "\n";
+      *document_ << normalizeEOL( root.getComment( commentAfter ) );
+      *document_ << "\n";
+   }
+}
+
+
+bool 
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+   Json::StyledStreamWriter writer;
+   writer.write(sout, root);
+   return sout;
+}
+
+
+} // namespace Json

+ 320 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/plugin.cpp

xqd
@@ -0,0 +1,320 @@
+#include "plugin.h"
+#include "tokenizer.h"
+
+#ifdef _WINDOWS
+#include <windows.h>
+BOOL APIENTRY DllMain( HANDLE hModule,
+                       DWORD ul_reason_for_call,
+                       LPVOID lpReserved )
+{
+    return TRUE;
+}
+#else
+#include <errno.h>
+#include <string.h>
+
+extern int errno;
+#endif
+
+SendPluginEv SendPluginEvent;
+
+string g_GetSysErrMsg( void )
+{
+    string strError = "Unknown";
+    // Problem loading
+#ifdef _WINDOWS
+    int nErrorCode = GetLastError();
+    LPTSTR s;
+    if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL, nErrorCode, 0, ( LPTSTR ) &s, 0, NULL ) )
+    {
+        strError = s;
+    }
+    else
+    {
+        char szBuf[ 20 ];
+        _snprintf_s( szBuf, _countof(szBuf), 19, "%d", nErrorCode );
+        strError = szBuf;
+    }
+#else
+    char szError[80];
+    if ( strerror_r( errno, szError, sizeof(szError)  ) )
+    {
+        strError = "no description found";
+    }
+    else
+    {
+        strError = szError;
+    }
+#endif
+    return strError;
+}
+
+void g_sleep( unsigned int mseconds )
+{
+#ifdef _WINDOWS
+    Sleep( mseconds );
+#else
+    usleep( mseconds * 1000 );
+#endif
+}
+
+string& g_trim( string& str )
+{
+    // Whitespace characters
+    char whspc[] = " \t\r\n\v\f";
+
+    // Whack off first part
+    size_t pos = str.find_first_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( 0, pos, "" );
+
+    // Whack off trailing stuff
+    pos = str.find_last_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( pos + 1, str.length() - pos, "" );
+
+    return str;
+}
+
+void g_tokenize( const string& str, const string& delimiters, vector<string>& tokens )
+{
+    tokenize( str, tokens, delimiters );
+}
+
+char* SetEventFunc( SendPluginEv funcPtr )
+{
+    static char * szObjList = onGetObjList();
+    SendPluginEvent = funcPtr;
+    return szObjList;
+}
+
+
+const int nMAXSIZE = 512;
+char* g_pszRetVal = NULL;
+
+//-----------------------------------------------------------
+// Map from an object Id to an object instance
+//-----------------------------------------------------------
+typedef std::map<string, JSExt*> StringToJExt_T;
+
+//-----------------------------------------------------------
+// Map from a browser context to an id mapping
+//-----------------------------------------------------------
+typedef std::map<void*, StringToJExt_T*> VoidToMap_T;
+
+VoidToMap_T g_context2Map;
+
+class GlobalSharedModule
+{
+
+public:
+    GlobalSharedModule( void )
+    {
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    ~GlobalSharedModule()
+    {
+        delete [] g_pszRetVal;
+
+        VoidToMap_T::iterator posMaps;
+
+        for ( posMaps = g_context2Map.begin(); posMaps != g_context2Map.end(); ++posMaps )
+        {
+            StringToJExt_T& id2Obj = *posMaps->second;
+            StringToJExt_T::iterator posMap;
+
+            for ( posMap = id2Obj.begin(); posMap != id2Obj.end(); ++posMap )
+            {
+                JSExt* pJSExt = posMap->second;
+
+                if ( pJSExt->CanDelete() )
+                {
+                    delete pJSExt;
+                }
+            }
+
+            id2Obj.erase( id2Obj.begin(), id2Obj.end() );
+        }
+
+        g_context2Map.erase( g_context2Map.begin(), g_context2Map.end() );
+    }
+};
+
+GlobalSharedModule g_sharedModule;
+
+char* g_str2global( const string& strRetVal )
+{
+    int nLen = strRetVal.size();
+
+    if ( nLen >= nMAXSIZE )
+    {
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nLen + 1 ];
+    }
+
+    else
+    {
+        // To minimaize the number of memory reallocations, the assumption
+        // is that in most times this will be the case
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    strcpy( g_pszRetVal, strRetVal.c_str() );
+    return g_pszRetVal;
+}
+
+bool g_unregisterObject( const string& strObjId, void* pContext )
+{
+    // Called by the plugin extension implementation
+    // if the extension handles the deletion of its object
+
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        return false;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+    if ( r == mapID2Obj.end() )
+    {
+        return false;
+    }
+
+    mapID2Obj.erase( strObjId );
+    return true;
+}
+
+char* InvokeFunction( const char* szCommand, void* pContext )
+{
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        pID2Obj = new StringToJExt_T;
+        g_context2Map[ pContext ] = pID2Obj;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    string strFullCommand = szCommand;
+    vector<string> arParams;
+    g_tokenize( strFullCommand, " ", arParams );
+    string strCommand = arParams[ 0 ];
+    string strRetVal = szERROR;
+
+    if ( strCommand == szCREATE )
+    {
+        string strClassName = arParams[ 1 ];
+        string strObjId = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r != mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Object already exists.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = onCreateObject( strClassName, strObjId );
+
+        if ( pJSExt == NULL )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Unknown object type ";
+            strRetVal += strClassName;
+            return g_str2global( strRetVal );
+        }
+
+        pJSExt->m_pContext = pContext;
+        mapID2Obj[ strObjId ] = pJSExt;
+
+        strRetVal = szOK;
+        strRetVal += strObjId;
+        return g_str2global( strRetVal );
+    }
+    else
+    if ( strCommand == szINVOKE )
+    {
+        string strObjId = arParams[ 1 ];
+        string strMethod = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r == mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :No object found for id.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = r->second;
+
+        size_t nLoc = strFullCommand.find( strObjId );
+
+        if ( nLoc == string::npos )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Internal InvokeMethod error.";
+            return g_str2global( strRetVal );
+        }
+
+        if ( strMethod == szDISPOSE )
+        {
+            StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+            if ( r == mapID2Obj.end() )
+            {
+                strRetVal = szERROR;
+                strRetVal += strObjId;
+                return g_str2global( strRetVal );
+            }
+
+            JSExt * pJSExt = mapID2Obj[ strObjId ];
+
+            if ( pJSExt->CanDelete() )
+            {
+                delete pJSExt;
+            }
+
+            mapID2Obj.erase( strObjId );
+            strRetVal = szOK;
+            strRetVal += strObjId;
+            return g_str2global( strRetVal );
+        }
+
+        size_t nSuffixLoc = nLoc + strObjId.size();
+        string strInvoke = strFullCommand.substr( nSuffixLoc );
+        strInvoke = g_trim( strInvoke );
+        strRetVal = pJSExt->InvokeMethod( strInvoke );
+        return g_str2global( strRetVal );
+    }
+
+    strRetVal += " :Unknown command ";
+    strRetVal += strCommand;
+    return g_str2global( strRetVal );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+

+ 70 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/plugin.h

xqd
@@ -0,0 +1,70 @@
+#ifndef _PLUGIN_H
+#define _PLUGIN_H
+
+#include <map>
+#include <string>
+#include <vector>
+#include <unistd.h>
+//#include "tokenizer.h"
+
+using namespace std;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%% Functions exported by this DLL
+//%% Should always be only SetEventFunc and InvokeFunction
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// g++ requires extern "C" otherwise the names of SetEventFunc and InvokeFunction
+// are mangled C++ style. MS Visual Studio doesn't seem to care though.
+extern "C"
+{
+    typedef void (*SendPluginEv)( const char* szEvent, void* pContext );
+    char* SetEventFunc(SendPluginEv funcPtr);
+    char* InvokeFunction( const char* szCommand, void* pContext );
+}
+
+// JNEXT Framework function of the form:
+// typedef void (*SendPluginEv)( const char* szEvent );
+// used to notify JavaScript of an asynchronous event
+extern SendPluginEv SendPluginEvent;
+
+/////////////////////////////////////////////////////////////////////////
+// Constants and methods common to all JNEXT extensions types
+/////////////////////////////////////////////////////////////////////////
+#define szERROR         "Error "
+#define szOK            "Ok "
+
+#define szDISPOSE       "Dispose"
+#define szINVOKE        "InvokeMethod"
+#define szCREATE        "CreateObj"
+
+/////////////////////////////////////////////////////////////////////////
+// Utility functions
+/////////////////////////////////////////////////////////////////////////
+string& g_trim( string& str );
+void g_tokenize(const string& str,const string& delimiters, vector<string>& tokens);
+char* g_str2static( const string& strRetVal );
+void g_sleep( unsigned int mseconds );
+bool g_unregisterObject( const string& strObjId, void* pContext );
+
+
+/////////////////////////////////////////////////////////////////////////
+// Abstract extension object
+/////////////////////////////////////////////////////////////////////////
+class JSExt
+{
+public:
+    virtual ~JSExt() {};
+    virtual string InvokeMethod( const string& strCommand ) = 0;
+    virtual bool CanDelete( void ) = 0;
+    virtual void TryDelete( void ) {}
+public:
+    void* m_pContext;
+};
+
+/////////////////////////////////////////////////////////////////////////
+// Callback functions to be implemented by the plugin implementation
+/////////////////////////////////////////////////////////////////////////
+extern char* onGetObjList( void );
+extern JSExt* onCreateObject( const string& strClassName, const string& strObjId );
+
+#endif

+ 222 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/tokenizer.cpp

xqd
@@ -0,0 +1,222 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+you must not claim that you wrote the original software.
+If you use this software in a product, an acknowledgment
+in the product documentation would be appreciated but is
+not required.
+
+2. Altered source versions must be plainly marked as such,
+and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		Jörg Wiedenmann
+	
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+
+	history:	2006-01-28, Original version
+				2006-03-04, Fixed a small parsing bug, thanks Elias.
+*********************************************************************/
+
+#include "tokenizer.h"
+
+using namespace std;
+
+void tokenize ( const string& str, vector<string>& result,
+			   const string& delimiters, const string& delimiters_preserve,
+			   const string& quote, const string& esc )
+{
+	// clear the vector
+	if ( false == result.empty() )
+	{
+		result.clear();
+	}
+
+	string::size_type pos = 0; // the current position (char) in the string
+	char ch = 0; // buffer for the current character
+	char delimiter = 0;	// the buffer for the delimiter char which
+							// will be added to the tokens if the delimiter
+							// is preserved
+	char current_quote = 0; // the char of the current open quote
+	bool quoted = false; // indicator if there is an open quote
+	string token;  // string buffer for the token
+	bool token_complete = false; // indicates if the current token is
+								 // read to be added to the result vector
+	string::size_type len = str.length();  // length of the input-string
+
+	// for every char in the input-string
+	while ( len > pos )
+	{
+		// get the character of the string and reset the delimiter buffer
+		ch = str.at(pos);
+		delimiter = 0;
+
+		// assume ch isn't a delimiter
+		bool add_char = true;
+
+		// check ...
+
+		// ... if the delimiter is an escaped character
+		bool escaped = false; // indicates if the next char is protected
+		if ( false == esc.empty() ) // check if esc-chars are  provided
+		{
+			if ( string::npos != esc.find_first_of(ch) )
+			{
+				// get the escaped char
+				++pos;
+				if ( pos < len ) // if there are more chars left
+				{
+					// get the next one
+					ch = str.at(pos);
+
+					// add the escaped character to the token
+					add_char = true;
+				}
+				else // cannot get any more characters
+				{
+					// don't add the esc-char
+					add_char = false;
+				}
+
+				// ignore the remaining delimiter checks
+				escaped = true;
+			}
+		}
+
+		// ... if the delimiter is a quote
+		if ( false == quote.empty() && false == escaped )
+		{
+			// if quote chars are provided and the char isn't protected
+			if ( string::npos != quote.find_first_of(ch) )
+			{
+				// if not quoted, set state to open quote and set
+				// the quote character
+				if ( false == quoted )
+				{
+					quoted = true;
+					current_quote = ch;
+
+					// don't add the quote-char to the token
+					add_char = false;
+				}
+				else // if quote is open already
+				{
+					// check if it is the matching character to close it
+					if ( current_quote == ch )
+					{
+						// close quote and reset the quote character
+						quoted = false;
+						current_quote = 0;
+
+						// don't add the quote-char to the token
+						add_char = false;
+					}
+				} // else
+			}
+		}
+
+		// ... if the delimiter isn't preserved
+		if ( false == delimiters.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter is provided and the char isn't protected by
+			// quote or escape char
+			if ( string::npos != delimiters.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+			}
+		}
+
+		// ... if the delimiter is preserved - add it as a token
+		bool add_delimiter = false;
+		if ( false == delimiters_preserve.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter which will be preserved is provided and the
+			// char isn't protected by quote or escape char
+			if ( string::npos != delimiters_preserve.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+
+				// add the delimiter
+				delimiter = ch;
+				add_delimiter = true;
+			}
+		}
+
+
+		// add the character to the token
+		if ( true == add_char )
+		{
+			// add the current char
+			token.push_back( ch );
+		}
+
+		// add the token if it is complete
+		if ( true == token_complete && false == token.empty() )
+		{
+			// add the token string
+			result.push_back( token );
+
+			// clear the contents
+			token.clear();
+
+			// build the next token
+			token_complete = false;
+		}
+
+		// add the delimiter
+		if ( true == add_delimiter )
+		{
+			// the next token is the delimiter
+			string delim_token;
+			delim_token.push_back( delimiter );
+			result.push_back( delim_token );
+
+			// REMOVED: 2006-03-04, Bugfix
+		}
+
+		// repeat for the next character
+		++pos;
+	} // while
+
+	// add the final token
+	if ( false == token.empty() )
+	{
+		result.push_back( token );
+	}
+}

+ 55 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/public/tokenizer.h

xqd
@@ -0,0 +1,55 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+	you must not claim that you wrote the original software.
+	If you use this software in a product, an acknowledgment
+	in the product documentation would be appreciated but is
+	not required.
+
+2. Altered source versions must be plainly marked as such,
+	and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		Jörg Wiedenmann
+
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+*********************************************************************/
+
+#include <vector>
+#include <string>
+using namespace std;
+
+// Function to break up a string into tokens
+//
+// Parameters:
+//-----------
+// str = the input string that will be tokenized
+// result = the tokens for str
+// delimiters = the delimiter characters
+// delimiters preserve = same as above, but the delimiter characters
+//		will be put into the result as a token
+// quote = characters to protect the enclosed characters
+// esc = characters to protect a single character
+//
+
+void tokenize ( const string& str, vector<string>& result,
+			const string& delimiters, const string& delimiters_preserve = "",
+			const string& quote = "\"", const string& esc = "\\" );

+ 2 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/simulator/.gitignore

xqd
@@ -0,0 +1,2 @@
+/public
+/src

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/simulator/libBarcodeScanner.so


+ 104 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/Logger.cpp

xqd
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013 BlackBerry Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Logger.hpp"
+#include "barcodescanner_js.hpp"
+#include <slog2.h>
+
+namespace webworks {
+
+Logger::Logger(const char* name, BarcodeScannerJS *parent): m_pParent(parent) {
+	buffer_config.buffer_set_name = name;
+	buffer_config.num_buffers = 2;
+	buffer_config.verbosity_level = SLOG2_DEBUG1;
+
+	/* Configure the first buffer, using 7 x 4KB pages.  This larger buffer will be used for
+	   very chatty logging.  Our goal is to have 30-60 seconds of history at any given time,
+	   so we will want to log at a rate of around one log line with a string of 16 bytes
+	   long every 150 milliseconds.
+	*/
+
+	buffer_config.buffer_config[0].buffer_name = "low_priority";
+	buffer_config.buffer_config[0].num_pages = 7;
+
+	/* Configure the second buffer, which we will use for high level info logging that is very
+	   infrequent, but we want a longer history (hours or maybe even over a day or two).  This
+	   buffer uses 1 x 4KB.
+	*/
+
+	buffer_config.buffer_config[1].buffer_name = "high_priority";
+	buffer_config.buffer_config[1].num_pages = 1;
+
+	/* Register the buffer set. */
+
+	if( -1 == slog2_register( &buffer_config, buffer_handle, 0 ) ) {
+		fprintf( stderr, "Error registering slogger2 buffer!\n" );
+	} else {
+		info("Created slogger2 buffers");
+	}
+
+}
+
+Logger::~Logger() {
+	critical("slogger2 buffers reset");
+	slog2_reset();
+}
+
+int Logger::log(slog2_buffer_t buffer, _Uint8t severity, const char* message) {
+	return slog2c(buffer, 0, severity, message);
+}
+
+int Logger::debug(const char* message) {
+	return log(lowPriorityBuffer(), SLOG2_DEBUG1, message);
+}
+
+int Logger::info(const char* message) {
+	return log(lowPriorityBuffer(), SLOG2_INFO, message);
+}
+
+int Logger::notice(const char* message) {
+	return log(lowPriorityBuffer(), SLOG2_NOTICE, message);
+}
+
+int Logger::warn(const char* message) {
+	return log(lowPriorityBuffer(), SLOG2_WARNING, message);
+}
+
+int Logger::error(const char* message) {
+	return log(hiPriorityBuffer(), SLOG2_ERROR, message);
+}
+
+int Logger::critical(const char* message) {
+	return log(hiPriorityBuffer(), SLOG2_CRITICAL, message);
+}
+
+int Logger::setVerbosity(_Uint8t verbosity) {
+	return slog2_set_verbosity(buffer_handle[0], verbosity);
+}
+
+_Uint8t Logger::getVerbosity() {
+	return slog2_get_verbosity(buffer_handle[0]);
+}
+
+slog2_buffer_t Logger::hiPriorityBuffer() {
+	return buffer_handle[1];
+}
+
+slog2_buffer_t Logger::lowPriorityBuffer() {
+	return buffer_handle[0];
+}
+
+} /* namespace webworks */

+ 49 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/Logger.hpp

xqd
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 BlackBerry Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOGGER_HPP_
+#define LOGGER_HPP_
+
+#include <string>
+#include <slog2.h>
+
+class BarcodeScannerJS;
+
+namespace webworks {
+
+class Logger {
+public:
+	explicit Logger(const char* name, BarcodeScannerJS *parent = NULL);
+	virtual ~Logger();
+	int debug(const char* message);
+	int info(const char* message);
+	int notice(const char* message);
+	int warn(const char* message);
+	int error(const char* message);
+	int critical(const char* message);
+	int setVerbosity(_Uint8t verbosity);
+	_Uint8t getVerbosity();
+	slog2_buffer_t hiPriorityBuffer();
+	slog2_buffer_t lowPriorityBuffer();
+private:
+	BarcodeScannerJS *m_pParent;
+	slog2_buffer_set_config_t buffer_config;
+	slog2_buffer_t buffer_handle[2];
+	int log(slog2_buffer_t buffer, _Uint8t severity, const char* message);
+};
+
+} /* namespace webworks */
+#endif /* LOGGER_HPP_ */

+ 105 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_js.cpp

xqd
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013-2014 BlackBerry Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../public/tokenizer.h"
+#include "barcodescanner_js.hpp"
+#include "barcodescanner_ndk.hpp"
+
+using namespace std;
+
+/**
+ * Default constructor.
+ */
+BarcodeScannerJS::BarcodeScannerJS(const std::string& id) :
+        m_id(id) {
+	m_pLogger = new webworks::Logger("BarcodeScannerJS", this);
+    m_pBarcodeScannerController = new webworks::BarcodeScannerNDK(this);
+}
+
+/**
+ * BarcodeScannerJS destructor.
+ */
+BarcodeScannerJS::~BarcodeScannerJS() {
+    if (m_pBarcodeScannerController)
+    		delete m_pBarcodeScannerController;
+	if (m_pLogger)
+		delete m_pLogger;
+}
+
+webworks::Logger* BarcodeScannerJS::getLog() {
+	return m_pLogger;
+}
+
+/**
+ * This method returns the list of objects implemented by this native
+ * extension.
+ */
+char* onGetObjList() {
+    static char name[] = "BarcodeScannerJS";
+    return name;
+}
+
+/**
+ * This method is used by JNext to instantiate the BarcodeScannerJS object when
+ * an object is created on the JavaScript server side.
+ */
+JSExt* onCreateObject(const string& className, const string& id) {
+    if (className == "BarcodeScannerJS") {
+        return new BarcodeScannerJS(id);
+    }
+
+    return NULL;
+}
+
+/**
+ * Method used by JNext to determine if the object can be deleted.
+ */
+bool BarcodeScannerJS::CanDelete() {
+    return true;
+}
+
+/**
+ * It will be called from JNext JavaScript side with passed string.
+ * This method implements the interface for the JavaScript to native binding
+ * for invoking native code. This method is triggered when JNext.invoke is
+ * called on the JavaScript side with this native objects id.
+ */
+string BarcodeScannerJS::InvokeMethod(const std::string& command) {
+    // command appears with parameters following after a space
+	size_t commandIndex = command.find_first_of(" ");
+	std::string strCommand = command.substr(0, commandIndex);
+	size_t callbackIndex = command.find_first_of(" ", commandIndex + 1);
+	std::string callbackId = command.substr(commandIndex + 1, callbackIndex - commandIndex - 1);
+	std::string arg = command.substr(callbackIndex + 1, command.length());
+
+    if (strCommand == "startRead") {
+        m_pBarcodeScannerController->startRead(callbackId, arg);
+    }
+    else if (strCommand == "stopRead") {
+        m_pBarcodeScannerController->stopRead(callbackId);
+    }
+
+    strCommand.append(";");
+    strCommand.append(command);
+    return strCommand;
+}
+
+// Notifies JavaScript of an event
+void BarcodeScannerJS::NotifyEvent(const std::string& event) {
+    std::string eventString = m_id + " ";
+    eventString.append(event);
+    SendPluginEvent(eventString.c_str(), m_pContext);
+}

+ 41 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_js.hpp

xqd
@@ -0,0 +1,41 @@
+/*
+* Copyright 2013-2014 BlackBerry Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef BARCODESCANNERJS_HPP_
+#define BARCODESCANNERJS_HPP_
+
+#include "../public/plugin.h"
+#include "barcodescanner_ndk.hpp"
+#include "Logger.hpp"
+#include <string>
+
+class BarcodeScannerJS: public JSExt {
+
+public:
+    explicit BarcodeScannerJS(const std::string& id);
+    virtual ~BarcodeScannerJS();
+    virtual bool CanDelete();
+    virtual std::string InvokeMethod(const std::string& command);
+    void NotifyEvent(const std::string& event);
+    webworks::Logger* getLog();
+    webworks::BarcodeScannerNDK *m_pBarcodeScannerController;
+private:
+    std::string m_id;
+    // Definition of a pointer to the actual native extension code
+    webworks::Logger *m_pLogger;
+};
+
+#endif /* BarcodeScannerJS_HPP_ */

+ 709 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_ndk.cpp

xqd
@@ -0,0 +1,709 @@
+/*
+ * Copyright 2013-2015 BlackBerry Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <json/reader.h>
+#include <json/writer.h>
+
+#include <zxing/common/GreyscaleLuminanceSource.h>
+#include <zxing/common/HybridBinarizer.h>
+#include <zxing/MultiFormatReader.h>
+#include <img/img.h>
+#include <stdio.h>
+#include <bps/bps.h>
+#include <bps/event.h>
+#include <bps/navigator.h>
+#include <bps/screen.h>
+#include <screen/screen.h>
+#include <pthread.h>
+
+#include "barcodescanner_ndk.hpp"
+#include "barcodescanner_js.hpp"
+
+#include <string>
+#include <sstream>
+
+using namespace zxing;
+
+namespace webworks {
+
+BarcodeScannerJS* eventDispatcher = NULL;
+// Variables for native viewfinder screen
+static screen_window_t vf_win = NULL;
+static uint32_t vfRotation = 0;
+static bool touch = false;
+
+
+#define MUTEX_LOCK() pthread_mutex_trylock(&m_lock)
+#define MUTEX_UNLOCK() pthread_mutex_unlock(&m_lock)
+
+static pthread_mutex_t m_lock;
+static pthread_t m_thread = 0;
+
+    /*
+     * getCameraErrorDesc
+     *
+     * Returns a descriptive error message for a given camera error code
+     */
+    const char* getCameraErrorDesc(camera_error_t err) {
+        switch (err) {
+        case CAMERA_EOK:
+            return "The function call to the camera completed successfully.";
+        case CAMERA_EAGAIN:
+            return "The specified camera was not available. Try again.";
+        case CAMERA_EINVAL:
+            return "The camera call failed because of an invalid parameter.";
+        case CAMERA_ENODEV:
+            return "No such camera was found.";
+        case CAMERA_EMFILE:
+            return "The camera called failed because of a file table overflow.";
+        case CAMERA_EBADF:
+            return "Indicates that an invalid handle to a @c camera_handle_t value was used.";
+        case CAMERA_EACCESS:
+            return "Indicates that the necessary permissions to access the camera are not available.";
+        case CAMERA_EBADR:
+            return "Indicates that an invalid file descriptor was used.";
+        case CAMERA_ENOENT:
+            return "Indicates that the access a file or directory that does not exist.";
+        case CAMERA_ENOMEM:
+            return "Indicates that memory allocation failed.";
+        case CAMERA_EOPNOTSUPP:
+            return "Indicates that the requested operation is not supported.";
+        case CAMERA_ETIMEDOUT:
+            return "The function call failed due to communication problem or time-out with the camera.";
+        case CAMERA_EALREADY:
+            return "Indicates an operation on the camera is already in progress. In addition, this error can indicate that an error could not be completed because it was already completed. For example, if you called the @c camera_stop_video() function but the camera had already stopped recording video, this error code would be returned.";
+        case CAMERA_EUNINIT:
+            return "Indicates that the Camera Library is not initialized.";
+        case CAMERA_EREGFAULT:
+            return "Indicates that registration of a callback failed.";
+        case CAMERA_EMICINUSE:
+            return "Indicates that it failed to open because microphone is already in use.";
+        }
+        return NULL;
+    }
+
+
+    /*
+     * viewfinder_callback
+     *
+     * This callback is invoked when an image frame from the camera viewfinder becomes available.
+     * The frame is analyzed to determine if a barcode can be matched.
+     * Frames come in NV12 format which makes code analysis very fast.
+     */
+    void viewfinder_callback(camera_handle_t handle,camera_buffer_t* buf,void* arg) {
+        camera_frame_nv12_t* data = (camera_frame_nv12_t*)(&(buf->framedesc));
+        uint8_t* buff = buf->framebuf;
+        int stride = data->stride;
+        int width = data->width;
+        int height = data->height;
+        if ( eventDispatcher != NULL ){
+//            eventDispatcher->getLog()->debug("Frame received");
+        }
+
+        try {
+            Ref<LuminanceSource> source(new GreyscaleLuminanceSource((unsigned char *)buff, stride, height, 0,0,width,height));
+
+            Ref<Binarizer> binarizer(new HybridBinarizer(source));
+            Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
+            Ref<Result> result;
+
+            // setup the code reader
+            MultiFormatReader *reader = new MultiFormatReader();
+            DecodeHints *hints = new DecodeHints();
+
+            hints->addFormat(BarcodeFormat_QR_CODE);
+            hints->addFormat(BarcodeFormat_EAN_8);
+            hints->addFormat(BarcodeFormat_EAN_13);
+            hints->addFormat(BarcodeFormat_UPC_A);
+            hints->addFormat(BarcodeFormat_UPC_E);
+            hints->addFormat(BarcodeFormat_DATA_MATRIX);
+            hints->addFormat(BarcodeFormat_CODE_128);
+            hints->addFormat(BarcodeFormat_CODE_39);
+            hints->addFormat(BarcodeFormat_ITF);
+            hints->addFormat(BarcodeFormat_AZTEC);
+
+			// attempt to decode and retrieve a valid QR code from the image bitmap
+			result = reader->decode(bitmap, *hints);
+
+            std::string newBarcodeData = result->getText()->getText().data();
+
+            Json::FastWriter writer;
+            Json::Value root;
+            root["text"] = newBarcodeData;
+            root["format"] = barcodeFormatNames[result->getBarcodeFormat()];
+            root["cancelled"] = false;
+
+            // notify caller that a valid QR code has been decoded
+            if ( eventDispatcher != NULL){
+            	std::string event = "community.barcodescanner.codefound.native";
+            	event.insert(0, " ");
+            	event.insert(0, (char *) arg);
+            	eventDispatcher->NotifyEvent(event + " " + writer.write(root));
+            	eventDispatcher->getLog()->debug("This is the detected Barcode");
+            	eventDispatcher->getLog()->debug(newBarcodeData.c_str());
+            }
+
+        }
+        catch (const std::exception& ex)
+        {
+            // Uncomment this if you need to verify scanning
+            if ( eventDispatcher != NULL ){
+//               eventDispatcher->getLog()->warn("Scan error");
+//               eventDispatcher->getLog()->warn(ex.what());
+            }
+        }
+    }
+
+    std::string convertIntToString(int i) {
+		stringstream ss;
+		ss << i;
+		return ss.str();
+	}
+
+
+    /*
+     * Constructor for Barcode Scanner NDK class
+     */
+    BarcodeScannerNDK::BarcodeScannerNDK(BarcodeScannerJS *parent): threadHalt(false) {
+    	cbId = new char[1000];
+        m_pParent     = parent;
+        eventDispatcher = parent;
+        mCameraHandle = CAMERA_HANDLE_INVALID;
+    }
+
+    BarcodeScannerNDK::~BarcodeScannerNDK() {
+    	delete[] cbId;
+    }
+
+    webworks::Logger* BarcodeScannerNDK::getLog() {
+        return m_pParent->getLog();
+    }
+
+    void interrogateWindowCV(screen_window_t window, Logger* log, string description, int property) {
+        char* value = new char[256];
+        int ok = screen_get_window_property_cv(window, property, 256, value);
+        if (ok == 0) {
+            log->info(description.c_str());
+            log->info(value);
+        } else {
+            log->warn("Unable to interpret value for");
+            log->warn(description.c_str());
+        }
+    }
+
+    void interrogateWindowIV(screen_window_t window, Logger* log, string description, int property) {
+        int value = -1;
+        int ok = screen_get_window_property_iv(window, property, &value);
+        if (ok == 0) {
+            log->info(description.c_str());
+            log->info(convertIntToString(value).c_str());
+        } else {
+            log->warn("Unable to interpret value for");
+            log->warn(description.c_str());
+        }
+    }
+
+    void interrogateWindow(screen_window_t window, Logger* log) {
+        log->info("Window Details--->");
+        interrogateWindowCV(window, log, "Window ID", SCREEN_PROPERTY_ID_STRING);
+        interrogateWindowIV(window, log, "Window Type", SCREEN_PROPERTY_TYPE);
+        interrogateWindowIV(window, log, "Window Owner PID", SCREEN_PROPERTY_OWNER_PID);
+        interrogateWindowCV(window, log, "Window Group", SCREEN_PROPERTY_GROUP);
+        interrogateWindowIV(window, log, "Window Z Order", SCREEN_PROPERTY_ZORDER);
+        interrogateWindowIV(window, log, "Window Visible", SCREEN_PROPERTY_VISIBLE);
+        log->info("Window Interrogation complete");
+    }
+
+    void *HandleEvents(void *args) {
+        BarcodeScannerNDK *parent = static_cast<BarcodeScannerNDK *>(args);
+        parent->getLog()->debug("BarcodeScannerNDK EventHandler");
+
+        /**
+         * Creating a native viewfinder screen
+         */
+        const int usage = SCREEN_USAGE_NATIVE;
+        screen_window_t screen_win;
+        screen_buffer_t screen_buf = NULL;
+        int rect[4] = { 0, 0, 0, 0 };
+
+        if(screen_create_window_type(&screen_win, parent->windowContext, SCREEN_CHILD_WINDOW) == -1) {
+            parent->getLog()->error("screen_create_window() failed");;
+        }
+        screen_join_window_group(screen_win, parent->windowGroup);
+        char * groupCheck = new char[256];
+        screen_get_window_property_cv(screen_win, SCREEN_PROPERTY_GROUP, 256, groupCheck);
+        parent->getLog()->info("Window Group Check");
+        parent->getLog()->info(groupCheck);
+        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
+        int r = 0;
+        screen_display_t display = NULL;
+        screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void**)&display);
+        if (display != NULL) {
+            screen_get_display_property_iv(display, SCREEN_PROPERTY_ROTATION, &r);
+            parent->getLog()->debug("Current Display Rotation");
+            parent->getLog()->debug(convertIntToString(r).c_str());
+        }
+        screen_create_window_buffers(screen_win, 1);
+        screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf);
+        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
+        // The screen (and backing buffer) don't take into account the rotation, so we need to swap the size.
+        if (r == 90 || r == 270) {
+            int swap = rect[2];
+            rect[2] = rect[3];
+            rect[3] = swap;
+        }
+        // Set the window size and the buffer follows along
+        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SIZE, rect+2);
+        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
+
+        parent->getLog()->debug("Screen Buffer Size:");
+        parent->getLog()->debug(convertIntToString(rect[0]).c_str());
+        parent->getLog()->debug(convertIntToString(rect[1]).c_str());
+        parent->getLog()->debug(convertIntToString(rect[2]).c_str());
+        parent->getLog()->debug(convertIntToString(rect[3]).c_str());
+
+        int type = -1;
+        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_TYPE, &type);
+        parent->getLog()->debug("Window Type");
+        parent->getLog()->debug(convertIntToString(type).c_str());
+
+        // fill the window with a flat colour
+        int attribs[] = { SCREEN_BLIT_COLOR, 0x00333333, SCREEN_BLIT_END };
+        screen_fill(parent->windowContext, screen_buf, attribs);
+        screen_post_window(screen_win, screen_buf, 1, rect, 0);
+        // position the window at an arbitrary z-order
+        int i = 1;
+        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &i);
+        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &i);
+        parent->getLog()->debug("Current Zorder");
+        parent->getLog()->debug(convertIntToString(i).c_str());
+        int visible = 1;
+        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_VISIBLE, &visible);
+        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_VISIBLE, &visible);
+        parent->getLog()->debug("Visible?");
+        parent->getLog()->debug(convertIntToString(visible).c_str());
+        screen_flush_context(parent->windowContext, 0);
+
+        parent->getLog()->debug("Created Background window");
+
+        if (parent->windowContext) {
+            if (BPS_SUCCESS == screen_request_events(parent->windowContext)) {
+                parent->getLog()->debug("Requested Events");
+            } else {
+                parent->getLog()->error("Unable to request events");
+                return NULL;
+            }
+        }
+
+        screen_group_t group;
+        screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_GROUP, (void **)&group);
+        char* groupName = new char[256];
+        screen_get_group_property_cv(group, SCREEN_PROPERTY_NAME, 256, groupName);
+        parent->getLog()->debug("Group Found");
+        parent->getLog()->debug(groupName);
+
+        // reset Touch value before starting up listening for touch events
+        touch = false;
+
+        while(!parent->isThreadHalt()) {
+            MUTEX_LOCK();
+
+            int domain;
+            // Get the first event in the queue.
+            bps_event_t *event = NULL;
+            if (BPS_SUCCESS != bps_get_event(&event, 0)) {
+                parent->getLog()->warn("bps_get_event() failed");
+            }
+
+            // Handle all events in the queue.
+            while (event) {
+                if (touch) {
+                    // HandleScreenEvent got a tap on the screen
+                    // Shutdown the scanning
+                    parent->cancelScan();
+                    break;
+                }
+                if (event) {
+                    domain = bps_event_get_domain(event);
+                    parent->getLog()->debug("BPS Event");
+                    if (domain == screen_get_domain()) {
+                        parent->getLog()->debug("BPS Screen Event");
+                        parent->handleScreenEvent(event, parent->getLog(), parent->windowGroup);
+                    }
+                }
+                if (BPS_SUCCESS != bps_get_event(&event, 0)) {
+                    parent->getLog()->error("bps_get_event() failed");
+//                                return;
+                }
+            }
+
+            MUTEX_UNLOCK();
+
+            // Poll at 10hz
+            usleep(100000);
+        }
+        // stop screen events on this thread
+        if(screen_stop_events(parent->windowContext) == -1) {
+            parent->getLog()->error("screen_stop_events failed");
+        }
+        screen_destroy_window(screen_win);
+        return NULL;
+    }
+
+    void BarcodeScannerNDK::handleScreenEvent(bps_event_t *event, Logger* log, const char* windowGroup) {
+        int eventType, objectType, eventProperty;
+
+        screen_event_t screen_event = screen_event_get_event(event);
+        screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType);
+
+        switch (eventType) {
+        case SCREEN_EVENT_MTOUCH_RELEASE:
+        case SCREEN_EVENT_MTOUCH_TOUCH:
+        case SCREEN_EVENT_MTOUCH_MOVE:
+            log->info("Touch Event");
+            touch = true;
+            break;
+        case SCREEN_EVENT_CREATE:
+            log->info("Screen Create Event");
+            if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void **)&vf_win) == -1) {
+                log->error("screen_get_event_property_pv(SCREEN_PROPERTY_WINDOW)");
+            } else {
+                log->info("viewfinder window found!");
+            }
+            break;
+        case SCREEN_EVENT_IDLE:
+            log->debug("Screen Idle");
+            break;
+        case SCREEN_EVENT_POST:
+            log->debug("Screen posted first frame");
+            if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void **)&vf_win) == -1) {
+                log->error("screen_get_event_property_pv(SCREEN_PROPERTY_WINDOW)");
+            } else {
+                interrogateWindow(vf_win, log);
+                int i = 100;
+                screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_ZORDER, &i);
+                screen_get_window_property_iv(vf_win, SCREEN_PROPERTY_ZORDER, &i);
+                log->debug("Current Zorder");
+                log->debug(convertIntToString(i).c_str());
+                // make viewfinder window visible
+                i = 1;
+                screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_VISIBLE, &i);
+                screen_get_window_property_iv(vf_win, SCREEN_PROPERTY_VISIBLE, &i);
+                log->debug("Visible?");
+                log->debug(convertIntToString(i).c_str());
+                // Rotate the window as needed
+                screen_get_window_property_iv(vf_win, SCREEN_PROPERTY_ROTATION, &i);
+                log->debug("Current Rotation");
+                log->debug(convertIntToString(i).c_str());
+                i = 360 - vfRotation;
+                screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_ROTATION, &i);
+                screen_get_window_property_iv(vf_win, SCREEN_PROPERTY_ROTATION, &i);
+                log->debug("Rotation");
+                log->debug(convertIntToString(i).c_str());
+                // Make full screen
+                screen_display_t display = NULL;
+                screen_get_window_property_pv(vf_win, SCREEN_PROPERTY_DISPLAY, (void **)&display);
+                if (display != NULL) {
+                    log->debug("Found a Display");
+                    int size[2] = { 0, 0 };
+                    screen_get_display_property_iv(display, SCREEN_PROPERTY_SIZE, size);
+                    log->debug("Display Size");
+                    log->debug(convertIntToString(size[0]).c_str());
+                    log->debug(convertIntToString(size[1]).c_str());
+                    int r = 0;
+                    screen_get_display_property_iv(display, SCREEN_PROPERTY_ROTATION, &r);
+                    log->debug("Current Display Rotation");
+                    log->debug(convertIntToString(r).c_str());
+                    if (r == 90 || r == 270) {
+                        int swap = size[0];
+                        size[0] = size[1];
+                        size[1] = swap;
+                    }
+                    screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_SIZE, size);
+                    screen_get_window_property_iv(vf_win, SCREEN_PROPERTY_SIZE, size);
+                    log->debug("Window Size");
+                    log->debug(convertIntToString(size[0]).c_str());
+                    log->debug(convertIntToString(size[1]).c_str());
+                }
+
+            }
+            break;
+        case SCREEN_EVENT_CLOSE:
+            log->debug("Screen closed");
+            break;
+        case SCREEN_EVENT_INPUT:
+            log->debug("Screen input event");
+            break;
+        case SCREEN_EVENT_PROPERTY:
+            log->debug("Screen property event");
+            screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
+            log->debug("Object Type");
+            log->debug(convertIntToString(objectType).c_str());
+            screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_NAME, &eventProperty);
+            log->debug("Property Name");
+            log->debug(convertIntToString(eventProperty).c_str());
+            break;
+        default:
+            log->warn("Unhandled Screen Event Type");
+            log->warn(convertIntToString(eventType).c_str());
+            break;
+        }
+    }
+
+    bool BarcodeScannerNDK::StartEvents() {
+        if (!m_thread) {
+            threadHalt = false;
+            pthread_attr_t thread_attr;
+            pthread_attr_init(&thread_attr);
+            pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+            int error = pthread_create(&m_thread, &thread_attr, HandleEvents, static_cast<void *>(this));
+            pthread_attr_destroy(&thread_attr);
+            if (error) {
+                m_pParent->getLog()->error("Thread Failed to start");
+                m_thread = 0;
+                return false;
+            } else {
+                m_pParent->getLog()->info("Thread Started");
+                MUTEX_LOCK();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    void BarcodeScannerNDK::StopEvents() {
+        if (m_thread) {
+            MUTEX_LOCK();
+            threadHalt = true;
+            MUTEX_UNLOCK();
+            m_pParent->getLog()->debug("BarcodeScannerNDK joining event thread");
+            pthread_join(m_thread, NULL);
+            m_thread = 0;
+            m_pParent->getLog()->debug("BarcodeScannerNDK event thread stopped");
+        }
+    }
+
+
+    // getter for the stop value
+    bool BarcodeScannerNDK::isThreadHalt() {
+        bool isThreadHalt;
+        MUTEX_LOCK();
+        isThreadHalt = threadHalt;
+        MUTEX_UNLOCK();
+        return isThreadHalt;
+    }
+
+    void BarcodeScannerNDK::cancelScan() {
+        m_pParent->getLog()->warn("Cancel Scan");
+        std::string event = "community.barcodescanner.codefound.native";
+        std::string callbackId = cbId;
+        Json::FastWriter writer;
+        Json::Value root;
+
+        // Scan cancelled by user
+        root["text"] = "";
+        root["format"] = "";
+        root["cancelled"] = true;
+
+        m_pParent->NotifyEvent(callbackId + " "  + event + " " + writer.write(root));
+    }
+
+    /*
+     * BarcodeScannerNDK::startRead
+     *
+     * This method is called to start a QR code read. A connection is opened to the device camera
+     * and the photo viewfinder is started.
+     */
+    int BarcodeScannerNDK::startRead(const string &callbackId, const string &arg) {
+    	std::string errorEvent = "community.barcodescanner.errorfound.native";
+        Json::FastWriter writer;
+        Json::Value root;
+
+        // Important for maintaining proper event queue support on 10.2.1
+        bps_initialize();
+
+        std::string handle;
+        std::string group;
+        Json::Reader reader;
+        Json::Value input;
+        bool parse = reader.parse(arg, input);
+
+        if (!parse) {
+            m_pParent->getLog()->error("Parse Error");
+            Json::Value error;
+            root["state"] = "Parsing JSON object";
+            root["error"] = "Cannot parse JSON object";
+            root["description"] = "";
+            m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(error));
+            return EIO;
+        } else {
+            handle = input["handle"].asString();
+            group = input["group"].asString();
+        }
+
+        std::copy(callbackId.begin(), callbackId.end(), this->cbId);
+        this->cbId[callbackId.size()] = '\0';
+
+        this->windowHandle = handle;
+        m_pParent->getLog()->info("Window Handle");
+        m_pParent->getLog()->info(handle.c_str());
+        // the jsScreenWindowHandle of the UIWebView that we passed in
+        int windowPointer = (int) strtol(handle.c_str(), NULL, 10);
+        // As an integer is the actual window handle
+        screen_window_t window = (screen_window_t) windowPointer;
+        interrogateWindow(window, m_pParent->getLog());
+        // Create a group for the main window
+        windowGroup = new char[group.length()+1];
+        std::strcpy (windowGroup, group.c_str());
+        m_pParent->getLog()->debug("Window Group using:");
+        m_pParent->getLog()->debug(windowGroup);
+
+        int getContext = screen_get_window_property_pv(window, SCREEN_PROPERTY_CONTEXT, (void **)&windowContext);
+        if (getContext == -1) {
+            m_pParent->getLog()->critical("Unable to get Context");
+            root["state"] = "Get App Window Context";
+            root["error"] = getContext;
+            root["description"] = "Unable to get application context";
+            m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+            return EIO;
+        }
+
+        StartEvents();
+
+        camera_error_t err;
+        // Open the camera first before running any operations on it
+        err = camera_open(CAMERA_UNIT_REAR,CAMERA_MODE_RW | CAMERA_MODE_ROLL,&mCameraHandle);
+
+        if ( err != CAMERA_EOK){
+            m_pParent->getLog()->error("Ran into an issue when initializing the camera");
+            m_pParent->getLog()->error(getCameraErrorDesc( err ));
+            root["state"] = "Open Camera";
+            root["error"] = err;
+            root["description"] = getCameraErrorDesc( err );
+            m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+            return EIO;
+        }
+
+        // We want maximum framerate from the viewfinder which will scan for codes
+        int numRates = 0;
+		err = camera_get_photo_vf_framerates(mCameraHandle, true, 0, &numRates, NULL, NULL);
+		double* camFramerates = new double[numRates];
+		bool maxmin = false;
+		err = camera_get_photo_vf_framerates(mCameraHandle, true, numRates, &numRates, camFramerates, &maxmin);
+
+		// do we need to rotate the viewfinder?
+
+		err = camera_get_photovf_property(mCameraHandle, CAMERA_IMGPROP_ROTATION, &vfRotation);
+		m_pParent->getLog()->debug("Viewfinder Rotation");
+		m_pParent->getLog()->debug(convertIntToString(vfRotation).c_str());
+
+		m_pParent->getLog()->debug("Camera Window Group");
+		m_pParent->getLog()->debug(windowGroup);
+		// We're going to have the viewfinder window join our app's window group, and start an embedded window
+		err = camera_set_photovf_property(mCameraHandle,
+		    CAMERA_IMGPROP_WIN_GROUPID, windowGroup,
+		    CAMERA_IMGPROP_WIN_ID, "my_viewfinder");
+		if ( err != CAMERA_EOK){
+		    m_pParent->getLog()->error("Ran into an issue when configuring the camera viewfinder");
+		    m_pParent->getLog()->error(getCameraErrorDesc( err ));
+			root["state"] = "Set VF Props";
+			root["error"] = err;
+			root["description"] = getCameraErrorDesc( err );
+			m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+			return EIO;
+		}
+
+		// Starting viewfinder up which will call the viewfinder callback - this gets the NV12 images for scanning
+        err = camera_start_photo_viewfinder( mCameraHandle, &viewfinder_callback, NULL, this->cbId);
+        if ( err != CAMERA_EOK) {
+            m_pParent->getLog()->error("Ran into a strange issue when starting up the camera viewfinder");
+            m_pParent->getLog()->error(getCameraErrorDesc( err ));
+            root["state"] = "ViewFinder Start";
+            root["error"] = err;
+            root["description"] = getCameraErrorDesc( err );
+            m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+            return EIO;
+        }
+
+        // Focus mode can't be set until the viewfinder is started. We need Continuous Macro for barcodes
+        err = camera_set_focus_mode(mCameraHandle, CAMERA_FOCUSMODE_CONTINUOUS_MACRO);
+		if ( err != CAMERA_EOK){
+		    m_pParent->getLog()->error("Ran into an issue when setting focus mode");
+		    m_pParent->getLog()->error(getCameraErrorDesc( err ));
+			root["state"] = "Set Focus Mode";
+			root["error"] = err;
+			root["description"] =  getCameraErrorDesc( err );
+			m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+			return EIO;
+		}
+
+        std::string successEvent = "community.barcodescanner.started.native";
+        root["successful"] = true;
+        m_pParent->NotifyEvent(callbackId + " " + successEvent + " " + writer.write(root));
+        return EOK;
+    }
+
+
+    /*
+     * BarcodeScannerNDK::stopRead
+     *
+     * This method is called to clean up following successful detection of a barcode.
+     * Calling this method will stop the viewfinder and close an open connection to the device camera.
+     */
+    int BarcodeScannerNDK::stopRead(const string &callbackId) {
+    	std::string errorEvent = "community.barcodescanner.errorfound.native";
+		Json::FastWriter writer;
+		Json::Value root;
+        camera_error_t err;
+
+        // Stop events first so that you don't get better response from the screen
+        StopEvents();
+
+        err = camera_stop_photo_viewfinder(mCameraHandle);
+        if ( err != CAMERA_EOK)
+        {
+            m_pParent->getLog()->error("Error with turning off the photo viewfinder");
+            m_pParent->getLog()->error(getCameraErrorDesc( err ));
+            root["error"] = err;
+		    root["description"] = getCameraErrorDesc( err );
+		    m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+            return EIO;
+        }
+
+        //check to see if the camera is open, if it is open, then close it
+        err = camera_close(mCameraHandle);
+        if ( err != CAMERA_EOK){
+            m_pParent->getLog()->error("Error with closing the camera");
+            m_pParent->getLog()->error(getCameraErrorDesc( err ));
+            root["error"] = err;
+            root["description"] = getCameraErrorDesc( err );
+            m_pParent->NotifyEvent(callbackId + " " + errorEvent + " " + writer.write(root));
+            return EIO;
+        }
+
+        std::string successEvent = "community.barcodescanner.ended.native";
+        root["successful"] = true;
+        mCameraHandle = CAMERA_HANDLE_INVALID;
+        m_pParent->NotifyEvent(callbackId + " " + successEvent + " " + writer.write(root));
+
+        // Important for maintaining proper event queue support on 10.2.1
+        bps_shutdown();
+
+        return EOK;
+    }
+
+}

+ 55 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/native/src/barcodescanner_ndk.hpp

xqd
@@ -0,0 +1,55 @@
+/*
+* Copyright 2013-2015 BlackBerry Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef BARCODESCANNERNDK_HPP_
+#define BARCODESCANNERNDK_HPP_
+
+#include <camera/camera_api.h>
+#include "Logger.hpp"
+#include <bps/event.h>
+#include <string>
+
+class BarcodeScannerJS;
+
+namespace webworks {
+
+class BarcodeScannerNDK {
+public:
+    explicit BarcodeScannerNDK(BarcodeScannerJS *parent = NULL);
+    virtual ~BarcodeScannerNDK();
+
+    int startRead(const std::string& callbackId, const std::string& handle);
+    int stopRead(const std::string& callbackId);
+    bool isThreadHalt();
+    void StopEvents();
+    bool StartEvents();
+    Logger* getLog();
+    void handleScreenEvent(bps_event_t *event, Logger* log, const char* windowGroup);
+    void cancelScan();
+    char* windowGroup;
+    screen_context_t windowContext;
+    char* cbId;
+
+private:
+    BarcodeScannerJS *m_pParent;
+    camera_handle_t mCameraHandle;
+    bool threadHalt;
+    std::string windowHandle;
+};
+
+} // namespace webworks
+
+#endif /* BARCODESCANNERNDK_H_ */

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 147 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/blackberry10/qrcode.js


+ 24 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/browser/BarcodeScannerProxy.js

xqd
@@ -0,0 +1,24 @@
+function scan(success, error) {
+    var code = window.prompt("Enter barcode value (empty value will fire the error handler):");
+    if(code) {
+        var result = {
+            text:code,
+            format:"Fake",
+            cancelled:false
+        };
+        success(result);
+    } else {
+        error("No barcode");
+    }
+}
+
+function encode(type, data, success, errorCallback) {
+    success();
+}
+
+module.exports = {
+    scan: scan,
+    encode: encode
+};
+
+require("cordova/exec/proxy").add("BarcodeScanner",module.exports);

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/beep.caf


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch.png


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch@2x.png


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.bundle/torch@3x.png


+ 1183 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/CDVBarcodeScanner.mm

xqd
@@ -0,0 +1,1183 @@
+/*
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright 2011 Matt Kane. All rights reserved.
+ * Copyright (c) 2011, IBM Corporation
+ */
+
+#import <AVFoundation/AVFoundation.h>
+#import <AssetsLibrary/AssetsLibrary.h>
+
+//------------------------------------------------------------------------------
+// use the all-in-one version of zxing that we built
+//------------------------------------------------------------------------------
+#import "zxing-all-in-one.h"
+#import <Cordova/CDVPlugin.h>
+
+
+//------------------------------------------------------------------------------
+// Delegate to handle orientation functions
+//------------------------------------------------------------------------------
+@protocol CDVBarcodeScannerOrientationDelegate <NSObject>
+
+- (NSUInteger)supportedInterfaceOrientations;
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
+- (BOOL)shouldAutorotate;
+
+@end
+
+//------------------------------------------------------------------------------
+// Adds a shutter button to the UI, and changes the scan from continuous to
+// only performing a scan when you click the shutter button.  For testing.
+//------------------------------------------------------------------------------
+#define USE_SHUTTER 0
+
+//------------------------------------------------------------------------------
+@class CDVbcsProcessor;
+@class CDVbcsViewController;
+
+//------------------------------------------------------------------------------
+// plugin class
+//------------------------------------------------------------------------------
+@interface CDVBarcodeScanner : CDVPlugin {}
+- (NSString*)isScanNotPossible;
+- (void)scan:(CDVInvokedUrlCommand*)command;
+- (void)encode:(CDVInvokedUrlCommand*)command;
+- (void)returnImage:(NSString*)filePath format:(NSString*)format callback:(NSString*)callback;
+- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback;
+- (void)returnError:(NSString*)message callback:(NSString*)callback;
+@end
+
+//------------------------------------------------------------------------------
+// class that does the grunt work
+//------------------------------------------------------------------------------
+@interface CDVbcsProcessor : NSObject <AVCaptureMetadataOutputObjectsDelegate> {}
+@property (nonatomic, retain) CDVBarcodeScanner*           plugin;
+@property (nonatomic, retain) NSString*                   callback;
+@property (nonatomic, retain) UIViewController*           parentViewController;
+@property (nonatomic, retain) CDVbcsViewController*        viewController;
+@property (nonatomic, retain) AVCaptureSession*           captureSession;
+@property (nonatomic, retain) AVCaptureVideoPreviewLayer* previewLayer;
+@property (nonatomic, retain) NSString*                   alternateXib;
+@property (nonatomic, retain) NSMutableArray*             results;
+@property (nonatomic, retain) NSString*                   formats;
+@property (nonatomic)         BOOL                        is1D;
+@property (nonatomic)         BOOL                        is2D;
+@property (nonatomic)         BOOL                        capturing;
+@property (nonatomic)         BOOL                        isFrontCamera;
+@property (nonatomic)         BOOL                        isShowFlipCameraButton;
+@property (nonatomic)         BOOL                        isShowTorchButton;
+@property (nonatomic)         BOOL                        isFlipped;
+@property (nonatomic)         BOOL                        isTransitionAnimated;
+@property (nonatomic)         BOOL                        isSuccessBeepEnabled;
+
+
+- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback parentViewController:(UIViewController*)parentViewController alterateOverlayXib:(NSString *)alternateXib;
+- (void)scanBarcode;
+- (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format;
+- (void)barcodeScanFailed:(NSString*)message;
+- (void)barcodeScanCancelled;
+- (void)openDialog;
+- (NSString*)setUpCaptureSession;
+- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection;
+- (NSString*)formatStringFrom:(zxing::BarcodeFormat)format;
+- (UIImage*)getImageFromSample:(CMSampleBufferRef)sampleBuffer;
+- (zxing::Ref<zxing::LuminanceSource>) getLuminanceSourceFromSample:(CMSampleBufferRef)sampleBuffer imageBytes:(uint8_t**)ptr;
+- (UIImage*) getImageFromLuminanceSource:(zxing::LuminanceSource*)luminanceSource;
+- (void)dumpImage:(UIImage*)image;
+@end
+
+//------------------------------------------------------------------------------
+// Qr encoder processor
+//------------------------------------------------------------------------------
+@interface CDVqrProcessor: NSObject
+@property (nonatomic, retain) CDVBarcodeScanner*          plugin;
+@property (nonatomic, retain) NSString*                   callback;
+@property (nonatomic, retain) NSString*                   stringToEncode;
+@property                     NSInteger                   size;
+
+- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode;
+- (void)generateImage;
+@end
+
+//------------------------------------------------------------------------------
+// view controller for the ui
+//------------------------------------------------------------------------------
+@interface CDVbcsViewController : UIViewController <CDVBarcodeScannerOrientationDelegate> {}
+@property (nonatomic, retain) CDVbcsProcessor*  processor;
+@property (nonatomic, retain) NSString*        alternateXib;
+@property (nonatomic)         BOOL             shutterPressed;
+@property (nonatomic, retain) IBOutlet UIView* overlayView;
+// unsafe_unretained is equivalent to assign - used to prevent retain cycles in the property below
+@property (nonatomic, unsafe_unretained) id orientationDelegate;
+
+- (id)initWithProcessor:(CDVbcsProcessor*)processor alternateOverlay:(NSString *)alternateXib;
+- (void)startCapturing;
+- (UIView*)buildOverlayView;
+- (UIImage*)buildReticleImage;
+- (void)shutterButtonPressed;
+- (IBAction)cancelButtonPressed:(id)sender;
+
+@end
+
+//------------------------------------------------------------------------------
+// plugin class
+//------------------------------------------------------------------------------
+@implementation CDVBarcodeScanner
+
+//--------------------------------------------------------------------------
+- (NSString*)isScanNotPossible {
+    NSString* result = nil;
+
+    Class aClass = NSClassFromString(@"AVCaptureSession");
+    if (aClass == nil) {
+        return @"AVFoundation Framework not available";
+    }
+
+    return result;
+}
+
+-(BOOL)notHasPermission
+{
+    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+    return (authStatus == AVAuthorizationStatusDenied ||
+            authStatus == AVAuthorizationStatusRestricted);
+}
+
+
+
+//--------------------------------------------------------------------------
+- (void)scan:(CDVInvokedUrlCommand*)command {
+    CDVbcsProcessor* processor;
+    NSString*       callback;
+    NSString*       capabilityError;
+
+    callback = command.callbackId;
+
+    NSDictionary* options;
+    if (command.arguments.count == 0) {
+      options = [NSDictionary dictionary];
+    } else {
+      options = command.arguments[0];
+    }
+
+    BOOL preferFrontCamera = [options[@"preferFrontCamera"] boolValue];
+    BOOL showFlipCameraButton = [options[@"showFlipCameraButton"] boolValue];
+    BOOL showTorchButton = [options[@"showTorchButton"] boolValue];
+    BOOL disableAnimations = [options[@"disableAnimations"] boolValue];
+    BOOL disableSuccessBeep = [options[@"disableSuccessBeep"] boolValue];
+
+    // We allow the user to define an alternate xib file for loading the overlay.
+    NSString *overlayXib = options[@"overlayXib"];
+
+    capabilityError = [self isScanNotPossible];
+    if (capabilityError) {
+        [self returnError:capabilityError callback:callback];
+        return;
+    } else if ([self notHasPermission]) {
+        NSString * error = NSLocalizedString(@"Access to the camera has been prohibited; please enable it in the Settings app to continue.",nil);
+        [self returnError:error callback:callback];
+        return;
+    }
+
+    processor = [[[CDVbcsProcessor alloc]
+                initWithPlugin:self
+                      callback:callback
+          parentViewController:self.viewController
+            alterateOverlayXib:overlayXib
+            ] autorelease];
+    // queue [processor scanBarcode] to run on the event loop
+
+    if (preferFrontCamera) {
+      processor.isFrontCamera = true;
+    }
+
+    if (showFlipCameraButton) {
+      processor.isShowFlipCameraButton = true;
+    }
+
+    if (showTorchButton) {
+      processor.isShowTorchButton = true;
+    }
+
+    processor.isSuccessBeepEnabled = !disableSuccessBeep;
+
+    processor.isTransitionAnimated = !disableAnimations;
+
+    processor.formats = options[@"formats"];
+
+    [processor performSelector:@selector(scanBarcode) withObject:nil afterDelay:0];
+}
+
+//--------------------------------------------------------------------------
+- (void)encode:(CDVInvokedUrlCommand*)command {
+    if([command.arguments count] < 1)
+        [self returnError:@"Too few arguments!" callback:command.callbackId];
+
+    CDVqrProcessor* processor;
+    NSString*       callback;
+    callback = command.callbackId;
+
+    processor = [[CDVqrProcessor alloc]
+                 initWithPlugin:self
+                 callback:callback
+                 stringToEncode: command.arguments[0][@"data"]
+                 ];
+
+    [processor retain];
+    [processor retain];
+    [processor retain];
+    // queue [processor generateImage] to run on the event loop
+    [processor performSelector:@selector(generateImage) withObject:nil afterDelay:0];
+}
+
+- (void)returnImage:(NSString*)filePath format:(NSString*)format callback:(NSString*)callback{
+    NSMutableDictionary* resultDict = [[[NSMutableDictionary alloc] init] autorelease];
+    resultDict[@"format"] = format;
+    resultDict[@"file"] = filePath;
+
+    CDVPluginResult* result = [CDVPluginResult
+                               resultWithStatus: CDVCommandStatus_OK
+                               messageAsDictionary:resultDict
+                               ];
+
+    [[self commandDelegate] sendPluginResult:result callbackId:callback];
+}
+
+//--------------------------------------------------------------------------
+- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback{
+    NSNumber* cancelledNumber = @(cancelled ? 1 : 0);
+
+    NSMutableDictionary* resultDict = [[NSMutableDictionary new] autorelease];
+    resultDict[@"text"] = scannedText;
+    resultDict[@"format"] = format;
+    resultDict[@"cancelled"] = cancelledNumber;
+
+    CDVPluginResult* result = [CDVPluginResult
+                               resultWithStatus: CDVCommandStatus_OK
+                               messageAsDictionary: resultDict
+                               ];
+    [self.commandDelegate sendPluginResult:result callbackId:callback];
+}
+
+//--------------------------------------------------------------------------
+- (void)returnError:(NSString*)message callback:(NSString*)callback {
+    CDVPluginResult* result = [CDVPluginResult
+                               resultWithStatus: CDVCommandStatus_ERROR
+                               messageAsString: message
+                               ];
+
+    [self.commandDelegate sendPluginResult:result callbackId:callback];
+}
+
+@end
+
+//------------------------------------------------------------------------------
+// class that does the grunt work
+//------------------------------------------------------------------------------
+@implementation CDVbcsProcessor
+
+@synthesize plugin               = _plugin;
+@synthesize callback             = _callback;
+@synthesize parentViewController = _parentViewController;
+@synthesize viewController       = _viewController;
+@synthesize captureSession       = _captureSession;
+@synthesize previewLayer         = _previewLayer;
+@synthesize alternateXib         = _alternateXib;
+@synthesize is1D                 = _is1D;
+@synthesize is2D                 = _is2D;
+@synthesize capturing            = _capturing;
+@synthesize results              = _results;
+
+SystemSoundID _soundFileObject;
+
+//--------------------------------------------------------------------------
+- (id)initWithPlugin:(CDVBarcodeScanner*)plugin
+            callback:(NSString*)callback
+parentViewController:(UIViewController*)parentViewController
+  alterateOverlayXib:(NSString *)alternateXib {
+    self = [super init];
+    if (!self) return self;
+
+    self.plugin               = plugin;
+    self.callback             = callback;
+    self.parentViewController = parentViewController;
+    self.alternateXib         = alternateXib;
+
+    self.is1D      = YES;
+    self.is2D      = YES;
+    self.capturing = NO;
+    self.results = [[NSMutableArray new] autorelease];
+
+    CFURLRef soundFileURLRef  = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("CDVBarcodeScanner.bundle/beep"), CFSTR ("caf"), NULL);
+    AudioServicesCreateSystemSoundID(soundFileURLRef, &_soundFileObject);
+
+    return self;
+}
+
+//--------------------------------------------------------------------------
+- (void)dealloc {
+    self.plugin = nil;
+    self.callback = nil;
+    self.parentViewController = nil;
+    self.viewController = nil;
+    self.captureSession = nil;
+    self.previewLayer = nil;
+    self.alternateXib = nil;
+    self.results = nil;
+
+    self.capturing = NO;
+
+    AudioServicesRemoveSystemSoundCompletion(_soundFileObject);
+    AudioServicesDisposeSystemSoundID(_soundFileObject);
+
+    [super dealloc];
+}
+
+//--------------------------------------------------------------------------
+- (void)scanBarcode {
+
+//    self.captureSession = nil;
+//    self.previewLayer = nil;
+    NSString* errorMessage = [self setUpCaptureSession];
+    if (errorMessage) {
+        [self barcodeScanFailed:errorMessage];
+        return;
+    }
+
+    self.viewController = [[[CDVbcsViewController alloc] initWithProcessor: self alternateOverlay:self.alternateXib] autorelease];
+    // here we set the orientation delegate to the MainViewController of the app (orientation controlled in the Project Settings)
+    self.viewController.orientationDelegate = self.plugin.viewController;
+
+    // delayed [self openDialog];
+    [self performSelector:@selector(openDialog) withObject:nil afterDelay:1];
+}
+
+//--------------------------------------------------------------------------
+- (void)openDialog {
+    [self.parentViewController
+     presentViewController:self.viewController
+     animated:self.isTransitionAnimated completion:nil
+     ];
+}
+
+//--------------------------------------------------------------------------
+- (void)barcodeScanDone:(void (^)(void))callbackBlock {
+    self.capturing = NO;
+    [self.captureSession stopRunning];
+    [self.parentViewController dismissViewControllerAnimated:self.isTransitionAnimated completion:callbackBlock];
+
+    // viewcontroller holding onto a reference to us, release them so they
+    // will release us
+    self.viewController = nil;
+}
+
+//--------------------------------------------------------------------------
+- (BOOL)checkResult:(NSString *)result {
+    [self.results addObject:result];
+
+    NSInteger treshold = 7;
+
+    if (self.results.count > treshold) {
+        [self.results removeObjectAtIndex:0];
+    }
+
+    if (self.results.count < treshold)
+    {
+        return NO;
+    }
+
+    BOOL allEqual = YES;
+    NSString *compareString = self.results[0];
+
+    for (NSString *aResult in self.results)
+    {
+        if (![compareString isEqualToString:aResult])
+        {
+            allEqual = NO;
+            //NSLog(@"Did not fit: %@",self.results);
+            break;
+        }
+    }
+
+    return allEqual;
+}
+
+//--------------------------------------------------------------------------
+- (void)barcodeScanSucceeded:(NSString*)text format:(NSString*)format {
+    dispatch_sync(dispatch_get_main_queue(), ^{
+        if (self.isSuccessBeepEnabled) {
+            AudioServicesPlaySystemSound(_soundFileObject);
+        }
+        [self barcodeScanDone:^{
+            [self.plugin returnSuccess:text format:format cancelled:FALSE flipped:FALSE callback:self.callback];
+        }];
+    });
+}
+
+//--------------------------------------------------------------------------
+- (void)barcodeScanFailed:(NSString*)message {
+    dispatch_sync(dispatch_get_main_queue(), ^{
+        [self barcodeScanDone:^{
+            [self.plugin returnError:message callback:self.callback];
+        }];
+    });
+}
+
+//--------------------------------------------------------------------------
+- (void)barcodeScanCancelled {
+    [self barcodeScanDone:^{
+        [self.plugin returnSuccess:@"" format:@"" cancelled:TRUE flipped:self.isFlipped callback:self.callback];
+    }];
+    if (self.isFlipped) {
+        self.isFlipped = NO;
+    }
+}
+
+- (void)flipCamera {
+    self.isFlipped = YES;
+    self.isFrontCamera = !self.isFrontCamera;
+    [self barcodeScanDone:^{
+        if (self.isFlipped) {
+            self.isFlipped = NO;
+        }
+    [self performSelector:@selector(scanBarcode) withObject:nil afterDelay:0.1];
+    }];
+}
+
+- (void)toggleTorch {
+  AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+  [device lockForConfiguration:nil];
+  if (device.flashActive) {
+    [device setTorchMode:AVCaptureTorchModeOff];
+    [device setFlashMode:AVCaptureFlashModeOff];
+  } else {
+    [device setTorchModeOnWithLevel:AVCaptureMaxAvailableTorchLevel error:nil];
+    [device setFlashMode:AVCaptureFlashModeOn];
+  }
+  [device unlockForConfiguration];
+}
+
+//--------------------------------------------------------------------------
+- (NSString*)setUpCaptureSession {
+    NSError* error = nil;
+
+    AVCaptureSession* captureSession = [[[AVCaptureSession alloc] init] autorelease];
+    self.captureSession = captureSession;
+
+       AVCaptureDevice* __block device = nil;
+    if (self.isFrontCamera) {
+
+        NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+        [devices enumerateObjectsUsingBlock:^(AVCaptureDevice *obj, NSUInteger idx, BOOL *stop) {
+            if (obj.position == AVCaptureDevicePositionFront) {
+                device = obj;
+            }
+        }];
+    } else {
+        device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+        if (!device) return @"unable to obtain video capture device";
+
+    }
+
+    // set focus params if available to improve focusing
+    [device lockForConfiguration:&error];
+    if (error == nil) {
+        if([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
+            [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
+        }
+        if([device isAutoFocusRangeRestrictionSupported]) {
+            [device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNear];
+        }
+    }
+    [device unlockForConfiguration];
+
+    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
+    if (!input) return @"unable to obtain video capture device input";
+
+    AVCaptureMetadataOutput* output = [[[AVCaptureMetadataOutput alloc] init] autorelease];
+    if (!output) return @"unable to obtain video capture output";
+
+    [output setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)];
+
+    if ([captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
+      captureSession.sessionPreset = AVCaptureSessionPresetHigh;
+    } else if ([captureSession canSetSessionPreset:AVCaptureSessionPresetMedium]) {
+      captureSession.sessionPreset = AVCaptureSessionPresetMedium;
+    } else {
+      return @"unable to preset high nor medium quality video capture";
+    }
+
+    if ([captureSession canAddInput:input]) {
+        [captureSession addInput:input];
+    }
+    else {
+        return @"unable to add video capture device input to session";
+    }
+
+    if ([captureSession canAddOutput:output]) {
+        [captureSession addOutput:output];
+    }
+    else {
+        return @"unable to add video capture output to session";
+    }
+    
+    [output setMetadataObjectTypes:[self formatObjectTypes]];
+
+    // setup capture preview layer
+    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
+    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
+
+    // run on next event loop pass [captureSession startRunning]
+    [captureSession performSelector:@selector(startRunning) withObject:nil afterDelay:0];
+
+    return nil;
+}
+
+//--------------------------------------------------------------------------
+// this method gets sent the captured frames
+//--------------------------------------------------------------------------
+- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection*)connection {
+
+    if (!self.capturing) return;
+
+#if USE_SHUTTER
+    if (!self.viewController.shutterPressed) return;
+    self.viewController.shutterPressed = NO;
+
+    UIView* flashView = [[UIView alloc] initWithFrame:self.viewController.view.frame];
+    [flashView setBackgroundColor:[UIColor whiteColor]];
+    [self.viewController.view.window addSubview:flashView];
+
+    [UIView
+     animateWithDuration:.4f
+     animations:^{
+         [flashView setAlpha:0.f];
+     }
+     completion:^(BOOL finished){
+         [flashView removeFromSuperview];
+     }
+     ];
+
+    //         [self dumpImage: [[self getImageFromSample:sampleBuffer] autorelease]];
+#endif
+
+
+    try {
+        // This will bring in multiple entities if there are multiple 2D codes in frame.
+        for (AVMetadataObject *metaData in metadataObjects) {
+            AVMetadataMachineReadableCodeObject* code = (AVMetadataMachineReadableCodeObject*)[self.previewLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject*)metaData];
+
+            if ([self checkResult:code.stringValue]) {
+                [self barcodeScanSucceeded:code.stringValue format:[self formatStringFromMetadata:code]];
+            }
+        }
+    }
+    catch (...) {
+        //            NSLog(@"decoding: unknown exception");
+        //            [self barcodeScanFailed:@"unknown exception decoding barcode"];
+    }
+
+    //        NSTimeInterval timeElapsed  = [NSDate timeIntervalSinceReferenceDate] - timeStart;
+    //        NSLog(@"decoding completed in %dms", (int) (timeElapsed * 1000));
+
+}
+
+//--------------------------------------------------------------------------
+// convert barcode format to string
+//--------------------------------------------------------------------------
+- (NSString*)formatStringFrom:(zxing::BarcodeFormat)format {
+    if (format == zxing::BarcodeFormat_QR_CODE)      return @"QR_CODE";
+    if (format == zxing::BarcodeFormat_DATA_MATRIX)  return @"DATA_MATRIX";
+    if (format == zxing::BarcodeFormat_UPC_E)        return @"UPC_E";
+    if (format == zxing::BarcodeFormat_UPC_A)        return @"UPC_A";
+    if (format == zxing::BarcodeFormat_EAN_8)        return @"EAN_8";
+    if (format == zxing::BarcodeFormat_EAN_13)       return @"EAN_13";
+    if (format == zxing::BarcodeFormat_CODE_128)     return @"CODE_128";
+    if (format == zxing::BarcodeFormat_CODE_39)      return @"CODE_39";
+    if (format == zxing::BarcodeFormat_ITF)          return @"ITF";
+    return @"???";
+}
+
+//--------------------------------------------------------------------------
+// convert metadata object information to barcode format string
+//--------------------------------------------------------------------------
+- (NSString*)formatStringFromMetadata:(AVMetadataMachineReadableCodeObject*)format {
+    if (format.type == AVMetadataObjectTypeQRCode)          return @"QR_CODE";
+    if (format.type == AVMetadataObjectTypeAztecCode)       return @"AZTEC";
+    if (format.type == AVMetadataObjectTypeDataMatrixCode)  return @"DATA_MATRIX";
+    if (format.type == AVMetadataObjectTypeUPCECode)        return @"UPC_E";
+    // According to Apple documentation, UPC_A is EAN13 with a leading 0.
+    if (format.type == AVMetadataObjectTypeEAN13Code && [format.stringValue characterAtIndex:0] == '0') return @"UPC_A";
+    if (format.type == AVMetadataObjectTypeEAN8Code)        return @"EAN_8";
+    if (format.type == AVMetadataObjectTypeEAN13Code)       return @"EAN_13";
+    if (format.type == AVMetadataObjectTypeCode128Code)     return @"CODE_128";
+    if (format.type == AVMetadataObjectTypeCode93Code)      return @"CODE_93";
+    if (format.type == AVMetadataObjectTypeCode39Code)      return @"CODE_39";
+    if (format.type == AVMetadataObjectTypeITF14Code)          return @"ITF";
+    if (format.type == AVMetadataObjectTypePDF417Code)      return @"PDF_417";
+    return @"???";
+}
+
+//--------------------------------------------------------------------------
+// convert string formats to metadata objects
+//--------------------------------------------------------------------------
+- (NSArray*) formatObjectTypes {
+    NSArray *supportedFormats = nil;
+    if (self.formats != nil) {
+        supportedFormats = [self.formats componentsSeparatedByString:@","];
+    }
+    
+    NSMutableArray * formatObjectTypes = [NSMutableArray array];
+    
+    if (self.formats == nil || [supportedFormats containsObject:@"QR_CODE"]) [formatObjectTypes addObject:AVMetadataObjectTypeQRCode];
+    if (self.formats == nil || [supportedFormats containsObject:@"AZTEC"]) [formatObjectTypes addObject:AVMetadataObjectTypeAztecCode];
+    if (self.formats == nil || [supportedFormats containsObject:@"DATA_MATRIX"]) [formatObjectTypes addObject:AVMetadataObjectTypeDataMatrixCode];
+    if (self.formats == nil || [supportedFormats containsObject:@"UPC_E"]) [formatObjectTypes addObject:AVMetadataObjectTypeUPCECode];
+    if (self.formats == nil || [supportedFormats containsObject:@"EAN_8"]) [formatObjectTypes addObject:AVMetadataObjectTypeEAN8Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"EAN_13"]) [formatObjectTypes addObject:AVMetadataObjectTypeEAN13Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"CODE_128"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode128Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"CODE_93"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode93Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"CODE_39"]) [formatObjectTypes addObject:AVMetadataObjectTypeCode39Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"ITF"]) [formatObjectTypes addObject:AVMetadataObjectTypeITF14Code];
+    if (self.formats == nil || [supportedFormats containsObject:@"PDF_417"]) [formatObjectTypes addObject:AVMetadataObjectTypePDF417Code];
+    
+    return formatObjectTypes;
+}
+
+//--------------------------------------------------------------------------
+// convert capture's sample buffer (scanned picture) into the thing that
+// zxing needs.
+//--------------------------------------------------------------------------
+- (zxing::Ref<zxing::LuminanceSource>) getLuminanceSourceFromSample:(CMSampleBufferRef)sampleBuffer imageBytes:(uint8_t**)ptr {
+    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
+    CVPixelBufferLockBaseAddress(imageBuffer, 0);
+
+    size_t   bytesPerRow =            CVPixelBufferGetBytesPerRow(imageBuffer);
+    size_t   width       =            CVPixelBufferGetWidth(imageBuffer);
+    size_t   height      =            CVPixelBufferGetHeight(imageBuffer);
+    uint8_t* baseAddress = (uint8_t*) CVPixelBufferGetBaseAddress(imageBuffer);
+
+    // only going to get 90% of the min(width,height) of the captured image
+    size_t    greyWidth  = 9 * MIN(width, height) / 10;
+    uint8_t*  greyData   = (uint8_t*) malloc(greyWidth * greyWidth);
+
+    // remember this pointer so we can free it later
+    *ptr = greyData;
+
+    if (!greyData) {
+        CVPixelBufferUnlockBaseAddress(imageBuffer,0);
+        throw new zxing::ReaderException("out of memory");
+    }
+
+    size_t offsetX = (width  - greyWidth) / 2;
+    size_t offsetY = (height - greyWidth) / 2;
+
+    // pixel-by-pixel ...
+    for (size_t i=0; i<greyWidth; i++) {
+        for (size_t j=0; j<greyWidth; j++) {
+            // i,j are the coordinates from the sample buffer
+            // ni, nj are the coordinates in the LuminanceSource
+            // in this case, there's a rotation taking place
+            size_t ni = greyWidth-j;
+            size_t nj = i;
+
+            size_t baseOffset = (j+offsetY)*bytesPerRow + (i + offsetX)*4;
+
+            // convert from color to grayscale
+            // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
+            size_t value = 0.11 * baseAddress[baseOffset] +
+            0.59 * baseAddress[baseOffset + 1] +
+            0.30 * baseAddress[baseOffset + 2];
+
+            greyData[nj*greyWidth + ni] = value;
+        }
+    }
+
+    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
+
+    using namespace zxing;
+
+    Ref<LuminanceSource> luminanceSource (
+                                          new GreyscaleLuminanceSource(greyData, (int)greyWidth, (int)greyWidth, 0, 0, (int)greyWidth, (int)greyWidth)
+                                          );
+
+    return luminanceSource;
+}
+
+//--------------------------------------------------------------------------
+// for debugging
+//--------------------------------------------------------------------------
+- (UIImage*) getImageFromLuminanceSource:(zxing::LuminanceSource*)luminanceSource  {
+    unsigned char* bytes = luminanceSource->getMatrix();
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
+    CGContextRef context = CGBitmapContextCreate(
+                                                 bytes,
+                                                 luminanceSource->getWidth(), luminanceSource->getHeight(), 8, luminanceSource->getWidth(),
+                                                 colorSpace,
+                                                 kCGImageAlphaNone
+                                                 );
+
+    CGImageRef cgImage = CGBitmapContextCreateImage(context);
+    UIImage*   image   = [[UIImage alloc] initWithCGImage:cgImage];
+
+    CGContextRelease(context);
+    CGColorSpaceRelease(colorSpace);
+    CGImageRelease(cgImage);
+    free(bytes);
+
+    return image;
+}
+
+//--------------------------------------------------------------------------
+// for debugging
+//--------------------------------------------------------------------------
+- (UIImage*)getImageFromSample:(CMSampleBufferRef)sampleBuffer {
+    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
+    CVPixelBufferLockBaseAddress(imageBuffer, 0);
+
+    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
+    size_t width       = CVPixelBufferGetWidth(imageBuffer);
+    size_t height      = CVPixelBufferGetHeight(imageBuffer);
+
+    uint8_t* baseAddress    = (uint8_t*) CVPixelBufferGetBaseAddress(imageBuffer);
+    int      length         = (int)(height * bytesPerRow);
+    uint8_t* newBaseAddress = (uint8_t*) malloc(length);
+    memcpy(newBaseAddress, baseAddress, length);
+    baseAddress = newBaseAddress;
+
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGContextRef context = CGBitmapContextCreate(
+                                                 baseAddress,
+                                                 width, height, 8, bytesPerRow,
+                                                 colorSpace,
+                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst
+                                                 );
+
+    CGImageRef cgImage = CGBitmapContextCreateImage(context);
+    UIImage*   image   = [[UIImage alloc] initWithCGImage:cgImage];
+
+    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
+    CGContextRelease(context);
+    CGColorSpaceRelease(colorSpace);
+    CGImageRelease(cgImage);
+
+    free(baseAddress);
+
+    return image;
+}
+
+//--------------------------------------------------------------------------
+// for debugging
+//--------------------------------------------------------------------------
+- (void)dumpImage:(UIImage*)image {
+    NSLog(@"writing image to library: %dx%d", (int)image.size.width, (int)image.size.height);
+    ALAssetsLibrary* assetsLibrary = [[[ALAssetsLibrary alloc] init] autorelease];
+    [assetsLibrary
+     writeImageToSavedPhotosAlbum:image.CGImage
+     orientation:ALAssetOrientationUp
+     completionBlock:^(NSURL* assetURL, NSError* error){
+         if (error) NSLog(@"   error writing image to library");
+         else       NSLog(@"   wrote image to library %@", assetURL);
+     }
+     ];
+}
+
+@end
+
+//------------------------------------------------------------------------------
+// qr encoder processor
+//------------------------------------------------------------------------------
+@implementation CDVqrProcessor
+@synthesize plugin               = _plugin;
+@synthesize callback             = _callback;
+@synthesize stringToEncode       = _stringToEncode;
+@synthesize size                 = _size;
+
+- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode{
+    self = [super init];
+    if (!self) return self;
+
+    self.plugin          = plugin;
+    self.callback        = callback;
+    self.stringToEncode  = stringToEncode;
+    self.size            = 300;
+
+    return self;
+}
+
+//--------------------------------------------------------------------------
+- (void)dealloc {
+    self.plugin = nil;
+    self.callback = nil;
+    self.stringToEncode = nil;
+
+    [super dealloc];
+}
+//--------------------------------------------------------------------------
+- (void)generateImage{
+    /* setup qr filter */
+    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
+    [filter setDefaults];
+
+    /* set filter's input message
+     * the encoding string has to be convert to a UTF-8 encoded NSData object */
+    [filter setValue:[self.stringToEncode dataUsingEncoding:NSUTF8StringEncoding]
+              forKey:@"inputMessage"];
+
+    /* on ios >= 7.0  set low image error correction level */
+    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_7_0)
+        [filter setValue:@"L" forKey:@"inputCorrectionLevel"];
+
+    /* prepare cgImage */
+    CIImage *outputImage = [filter outputImage];
+    CIContext *context = [CIContext contextWithOptions:nil];
+    CGImageRef cgImage = [context createCGImage:outputImage
+                                       fromRect:[outputImage extent]];
+
+    /* returned qr code image */
+    UIImage *qrImage = [UIImage imageWithCGImage:cgImage
+                                           scale:1.
+                                     orientation:UIImageOrientationUp];
+    /* resize generated image */
+    CGFloat width = _size;
+    CGFloat height = _size;
+
+    UIGraphicsBeginImageContext(CGSizeMake(width, height));
+
+    CGContextRef ctx = UIGraphicsGetCurrentContext();
+    CGContextSetInterpolationQuality(ctx, kCGInterpolationNone);
+    [qrImage drawInRect:CGRectMake(0, 0, width, height)];
+    qrImage = UIGraphicsGetImageFromCurrentImageContext();
+
+    /* clean up */
+    UIGraphicsEndImageContext();
+    CGImageRelease(cgImage);
+
+    /* save image to file */
+    NSString* fileName = [[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingString:@".jpg"];
+    NSString* filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
+    [UIImageJPEGRepresentation(qrImage, 1.0) writeToFile:filePath atomically:YES];
+
+    /* return file path back to cordova */
+    [self.plugin returnImage:filePath format:@"QR_CODE" callback: self.callback];
+}
+@end
+
+//------------------------------------------------------------------------------
+// view controller for the ui
+//------------------------------------------------------------------------------
+@implementation CDVbcsViewController
+@synthesize processor      = _processor;
+@synthesize shutterPressed = _shutterPressed;
+@synthesize alternateXib   = _alternateXib;
+@synthesize overlayView    = _overlayView;
+
+//--------------------------------------------------------------------------
+- (id)initWithProcessor:(CDVbcsProcessor*)processor alternateOverlay:(NSString *)alternateXib {
+    self = [super init];
+    if (!self) return self;
+
+    self.processor = processor;
+    self.shutterPressed = NO;
+    self.alternateXib = alternateXib;
+    self.overlayView = nil;
+    return self;
+}
+
+//--------------------------------------------------------------------------
+- (void)dealloc {
+    self.view = nil;
+    self.processor = nil;
+    self.shutterPressed = NO;
+    self.alternateXib = nil;
+    self.overlayView = nil;
+    [super dealloc];
+}
+
+//--------------------------------------------------------------------------
+- (void)loadView {
+    self.view = [[UIView alloc] initWithFrame: self.processor.parentViewController.view.frame];
+
+    // setup capture preview layer
+    AVCaptureVideoPreviewLayer* previewLayer = self.processor.previewLayer;
+    previewLayer.frame = self.view.bounds;
+    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
+
+    if ([previewLayer.connection isVideoOrientationSupported]) {
+        [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
+    }
+
+    [self.view.layer insertSublayer:previewLayer below:[[self.view.layer sublayers] objectAtIndex:0]];
+
+    [self.view addSubview:[self buildOverlayView]];
+}
+
+//--------------------------------------------------------------------------
+- (void)viewWillAppear:(BOOL)animated {
+
+    // set video orientation to what the camera sees
+    self.processor.previewLayer.connection.videoOrientation = (AVCaptureVideoOrientation) [[UIApplication sharedApplication] statusBarOrientation];
+
+    // this fixes the bug when the statusbar is landscape, and the preview layer
+    // starts up in portrait (not filling the whole view)
+    self.processor.previewLayer.frame = self.view.bounds;
+}
+
+//--------------------------------------------------------------------------
+- (void)viewDidAppear:(BOOL)animated {
+    [self startCapturing];
+
+    [super viewDidAppear:animated];
+}
+
+//--------------------------------------------------------------------------
+- (void)startCapturing {
+    self.processor.capturing = YES;
+}
+
+//--------------------------------------------------------------------------
+- (void)shutterButtonPressed {
+    self.shutterPressed = YES;
+}
+
+//--------------------------------------------------------------------------
+- (IBAction)cancelButtonPressed:(id)sender {
+    [self.processor performSelector:@selector(barcodeScanCancelled) withObject:nil afterDelay:0];
+}
+
+- (void)flipCameraButtonPressed:(id)sender
+{
+    [self.processor performSelector:@selector(flipCamera) withObject:nil afterDelay:0];
+}
+
+- (void)torchButtonPressed:(id)sender
+{
+  [self.processor performSelector:@selector(toggleTorch) withObject:nil afterDelay:0];
+}
+
+//--------------------------------------------------------------------------
+- (UIView *)buildOverlayViewFromXib
+{
+    [[NSBundle mainBundle] loadNibNamed:self.alternateXib owner:self options:NULL];
+
+    if ( self.overlayView == nil )
+    {
+        NSLog(@"%@", @"An error occurred loading the overlay xib.  It appears that the overlayView outlet is not set.");
+        return nil;
+    }
+
+    return self.overlayView;
+}
+
+//--------------------------------------------------------------------------
+- (UIView*)buildOverlayView {
+
+    if ( nil != self.alternateXib )
+    {
+        return [self buildOverlayViewFromXib];
+    }
+    CGRect bounds = self.view.bounds;
+    bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
+
+    UIView* overlayView = [[UIView alloc] initWithFrame:bounds];
+    overlayView.autoresizesSubviews = YES;
+    overlayView.autoresizingMask    = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+    overlayView.opaque              = NO;
+
+    UIToolbar* toolbar = [[UIToolbar alloc] init];
+    toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+
+    id cancelButton = [[[UIBarButtonItem alloc]
+                       initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
+                       target:(id)self
+                       action:@selector(cancelButtonPressed:)
+                       ] autorelease];
+
+
+    id flexSpace = [[[UIBarButtonItem alloc]
+                    initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
+                    target:nil
+                    action:nil
+                    ] autorelease];
+
+    id flipCamera = [[[UIBarButtonItem alloc]
+                       initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
+                       target:(id)self
+                       action:@selector(flipCameraButtonPressed:)
+                       ] autorelease];
+
+    NSMutableArray *items;
+
+#if USE_SHUTTER
+    id shutterButton = [[[UIBarButtonItem alloc]
+                        initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
+                        target:(id)self
+                        action:@selector(shutterButtonPressed)
+                        ] autorelease];
+
+    if (_processor.isShowFlipCameraButton) {
+      items = [NSMutableArray arrayWithObjects:flexSpace, cancelButton, flexSpace, flipCamera, shutterButton, nil];
+    } else {
+      items = [NSMutableArray arrayWithObjects:flexSpace, cancelButton, flexSpace, shutterButton, nil];
+    }
+#else
+    if (_processor.isShowFlipCameraButton) {
+      items = [@[flexSpace, cancelButton, flexSpace, flipCamera] mutableCopy];
+    } else {
+      items = [@[flexSpace, cancelButton, flexSpace] mutableCopy];
+    }
+#endif
+
+    if (_processor.isShowTorchButton && !_processor.isFrontCamera) {
+      AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+      if ([device hasTorch] && [device hasFlash]) {
+        NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"CDVBarcodeScanner" withExtension:@"bundle"];
+        NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
+        NSString *imagePath = [bundle pathForResource:@"torch" ofType:@"png"];
+        UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
+
+        id torchButton = [[[UIBarButtonItem alloc]
+                           initWithImage:image
+                                   style:UIBarButtonItemStylePlain
+                                  target:(id)self
+                                  action:@selector(torchButtonPressed:)
+                           ] autorelease];
+
+      [items insertObject:torchButton atIndex:0];
+    }
+  }
+
+    toolbar.items = items;
+
+    bounds = overlayView.bounds;
+
+    [toolbar sizeToFit];
+    CGFloat toolbarHeight  = [toolbar frame].size.height;
+    CGFloat rootViewHeight = CGRectGetHeight(bounds);
+    CGFloat rootViewWidth  = CGRectGetWidth(bounds);
+    CGRect  rectArea       = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight);
+    [toolbar setFrame:rectArea];
+
+    [overlayView addSubview: toolbar];
+
+    UIImage* reticleImage = [self buildReticleImage];
+    UIView* reticleView = [[[UIImageView alloc] initWithImage:reticleImage] autorelease];
+    CGFloat minAxis = MIN(rootViewHeight, rootViewWidth);
+
+    rectArea = CGRectMake(
+        (CGFloat) (0.5 * (rootViewWidth  - minAxis)),
+        (CGFloat) (0.5 * (rootViewHeight - minAxis)),
+        minAxis,
+        minAxis
+    );
+
+    [reticleView setFrame:rectArea];
+
+    reticleView.opaque           = NO;
+    reticleView.contentMode      = UIViewContentModeScaleAspectFit;
+    reticleView.autoresizingMask = (UIViewAutoresizing) (0
+        | UIViewAutoresizingFlexibleLeftMargin
+        | UIViewAutoresizingFlexibleRightMargin
+        | UIViewAutoresizingFlexibleTopMargin
+        | UIViewAutoresizingFlexibleBottomMargin)
+    ;
+
+    [overlayView addSubview: reticleView];
+
+    return overlayView;
+}
+
+//--------------------------------------------------------------------------
+
+#define RETICLE_SIZE    500.0f
+#define RETICLE_WIDTH    10.0f
+#define RETICLE_OFFSET   60.0f
+#define RETICLE_ALPHA     0.4f
+
+//-------------------------------------------------------------------------
+// builds the green box and red line
+//-------------------------------------------------------------------------
+- (UIImage*)buildReticleImage {
+    UIImage* result;
+    UIGraphicsBeginImageContext(CGSizeMake(RETICLE_SIZE, RETICLE_SIZE));
+    CGContextRef context = UIGraphicsGetCurrentContext();
+
+    if (self.processor.is1D) {
+        UIColor* color = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:RETICLE_ALPHA];
+        CGContextSetStrokeColorWithColor(context, color.CGColor);
+        CGContextSetLineWidth(context, RETICLE_WIDTH);
+        CGContextBeginPath(context);
+        CGFloat lineOffset = (CGFloat) (RETICLE_OFFSET+(0.5*RETICLE_WIDTH));
+        CGContextMoveToPoint(context, lineOffset, RETICLE_SIZE/2);
+        CGContextAddLineToPoint(context, RETICLE_SIZE-lineOffset, (CGFloat) (0.5*RETICLE_SIZE));
+        CGContextStrokePath(context);
+    }
+
+    if (self.processor.is2D) {
+        UIColor* color = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:RETICLE_ALPHA];
+        CGContextSetStrokeColorWithColor(context, color.CGColor);
+        CGContextSetLineWidth(context, RETICLE_WIDTH);
+        CGContextStrokeRect(context,
+                            CGRectMake(
+                                       RETICLE_OFFSET,
+                                       RETICLE_OFFSET,
+                                       RETICLE_SIZE-2*RETICLE_OFFSET,
+                                       RETICLE_SIZE-2*RETICLE_OFFSET
+                                       )
+                            );
+    }
+
+    result = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    return result;
+}
+
+#pragma mark CDVBarcodeScannerOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+    return YES;
+}
+
+- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
+{
+    return [[UIApplication sharedApplication] statusBarOrientation];
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    return UIInterfaceOrientationMaskAll;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
+- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
+{
+    [UIView setAnimationsEnabled:NO];
+    AVCaptureVideoPreviewLayer* previewLayer = self.processor.previewLayer;
+    previewLayer.frame = self.view.bounds;
+
+    if (orientation == UIInterfaceOrientationLandscapeLeft) {
+        [previewLayer setOrientation:AVCaptureVideoOrientationLandscapeLeft];
+    } else if (orientation == UIInterfaceOrientationLandscapeRight) {
+        [previewLayer setOrientation:AVCaptureVideoOrientationLandscapeRight];
+    } else if (orientation == UIInterfaceOrientationPortrait) {
+        [previewLayer setOrientation:AVCaptureVideoOrientationPortrait];
+    } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
+        [previewLayer setOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
+    }
+
+    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
+    [UIView setAnimationsEnabled:YES];
+}
+
+@end

+ 185 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/scannerOverlay.xib

xqd
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1280</int>
+		<string key="IBDocument.SystemVersion">11C74</string>
+		<string key="IBDocument.InterfaceBuilderVersion">1938</string>
+		<string key="IBDocument.AppKitVersion">1138.23</string>
+		<string key="IBDocument.HIToolboxVersion">567.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			<string key="NS.object.0">933</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>IBUINavigationItem</string>
+			<string>IBUIBarButtonItem</string>
+			<string>IBUIView</string>
+			<string>IBUINavigationBar</string>
+			<string>IBProxyObject</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="IBProxyObject" id="372490531">
+				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+			<object class="IBProxyObject" id="975951072">
+				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+			<object class="IBUIView" id="191373211">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">274</int>
+				<array class="NSMutableArray" key="NSSubviews">
+					<object class="IBUINavigationBar" id="1064216609">
+						<reference key="NSNextResponder" ref="191373211"/>
+						<int key="NSvFlags">290</int>
+						<string key="NSFrameSize">{320, 44}</string>
+						<reference key="NSSuperview" ref="191373211"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView"/>
+						<string key="NSReuseIdentifierKey">_NS:260</string>
+						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+						<int key="IBUIBarStyle">1</int>
+						<array class="NSMutableArray" key="IBUIItems">
+							<object class="IBUINavigationItem" id="240626599">
+								<reference key="IBUINavigationBar" ref="1064216609"/>
+								<string key="IBUITitle">Barcode Scanner</string>
+								<object class="IBUIBarButtonItem" key="IBUILeftBarButtonItem" id="1053701234">
+									<string key="IBUITitle">Cancel</string>
+									<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+									<int key="IBUIStyle">1</int>
+									<reference key="IBUINavigationItem" ref="240626599"/>
+								</object>
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+							</object>
+						</array>
+					</object>
+				</array>
+				<string key="NSFrameSize">{320, 460}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<reference key="NSNextKeyView" ref="1064216609"/>
+				<object class="NSColor" key="IBUIBackgroundColor">
+					<int key="NSColorSpace">3</int>
+					<bytes key="NSWhite">MSAwAA</bytes>
+					<object class="NSColorSpace" key="NSCustomColorSpace">
+						<int key="NSID">2</int>
+					</object>
+				</object>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">overlayView</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="191373211"/>
+					</object>
+					<int key="connectionID">9</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="191373211"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="1064216609"/>
+						</array>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="372490531"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="975951072"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="1064216609"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="240626599"/>
+						</array>
+						<reference key="parent" ref="191373211"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="240626599"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="1053701234"/>
+						</array>
+						<reference key="parent" ref="1064216609"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="1053701234"/>
+						<reference key="parent" ref="240626599"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.CustomClassName">PGbcsViewController</string>
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="-2.CustomClassName">UIResponder</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="3.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">11</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<array class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<object class="IBPartialClassDescription">
+					<string key="className">PGbcsViewController</string>
+					<string key="superclassName">UIViewController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">overlayView</string>
+						<string key="NS.object.0">UIView</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">overlayView</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">overlayView</string>
+							<string key="candidateClassName">UIView</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/PGbcsViewController.h</string>
+					</object>
+				</object>
+			</array>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<string key="IBCocoaTouchPluginVersion">933</string>
+	</data>
+</archive>

+ 11982 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/zxing-all-in-one.cpp

xqd
@@ -0,0 +1,11982 @@
+
+#include "zxing-all-in-one.h"
+
+// file: zxing/BarcodeFormat.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/BarcodeFormat.h>
+
+namespace zxing {
+
+const char *barcodeFormatNames[] = {
+    "None",
+    "QR_CODE",
+    "DATA_MATRIX",
+    "UPC_E",
+    "UPC_A",
+    "EAN_8",
+    "EAN_13",
+    "CODE_128",
+    "CODE_39",
+    "ITF"
+};
+
+}
+
+// file: zxing/Binarizer.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Binarizer.cpp
+ *  zxing
+ *
+ *  Created by Ralf Kistner on 16/10/2009.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *  Modified by Lukasz Warchol on 02/02/2010.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Binarizer.h>
+
+namespace zxing {
+
+	Binarizer::Binarizer(Ref<LuminanceSource> source) : source_(source) {
+  }
+
+	Binarizer::~Binarizer() {
+	}
+
+	Ref<LuminanceSource> Binarizer::getLuminanceSource() const {
+		return source_;
+	}
+
+}
+
+// file: zxing/BinaryBitmap.cpp
+
+/*
+ *  BinaryBitmap.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/BinaryBitmap.h>
+
+namespace zxing {
+
+	BinaryBitmap::BinaryBitmap(Ref<Binarizer> binarizer) : binarizer_(binarizer) {
+
+	}
+
+	BinaryBitmap::~BinaryBitmap() {
+	}
+
+	Ref<BitArray> BinaryBitmap::getBlackRow(int y, Ref<BitArray> row) {
+		return binarizer_->getBlackRow(y, row);
+	}
+
+	Ref<BitMatrix> BinaryBitmap::getBlackMatrix() {
+		return binarizer_->getBlackMatrix();
+	}
+
+	int BinaryBitmap::getWidth() const {
+		return getLuminanceSource()->getWidth();
+	}
+
+	int BinaryBitmap::getHeight() const {
+		return getLuminanceSource()->getHeight();
+	}
+
+	Ref<LuminanceSource> BinaryBitmap::getLuminanceSource() const {
+		return binarizer_->getLuminanceSource();
+	}
+
+
+	bool BinaryBitmap::isCropSupported() const {
+	  return getLuminanceSource()->isCropSupported();
+	}
+
+	Ref<BinaryBitmap> BinaryBitmap::crop(int left, int top, int width, int height) {
+	  return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->crop(left, top, width, height))));
+	}
+
+	bool BinaryBitmap::isRotateSupported() const {
+	  return getLuminanceSource()->isRotateSupported();
+	}
+
+	Ref<BinaryBitmap> BinaryBitmap::rotateCounterClockwise() {
+	  return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->rotateCounterClockwise())));
+	}
+}
+
+// file: zxing/DecodeHints.cpp
+
+/*
+ *  DecodeHintType.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/DecodeHints.h>
+// #include <zxing/common/IllegalArgumentException.h>
+namespace zxing {
+
+const DecodeHintType DecodeHints::CHARACTER_SET;
+
+const DecodeHints DecodeHints::PRODUCT_HINT(
+    BARCODEFORMAT_UPC_E_HINT |
+    BARCODEFORMAT_UPC_A_HINT |
+    BARCODEFORMAT_EAN_8_HINT |
+    BARCODEFORMAT_EAN_13_HINT);
+
+const DecodeHints DecodeHints::ONED_HINT(
+    BARCODEFORMAT_UPC_E_HINT |
+    BARCODEFORMAT_UPC_A_HINT |
+    BARCODEFORMAT_EAN_8_HINT |
+    BARCODEFORMAT_EAN_13_HINT |
+    BARCODEFORMAT_CODE_128_HINT |
+    BARCODEFORMAT_CODE_39_HINT |
+    BARCODEFORMAT_ITF_HINT);
+
+const DecodeHints DecodeHints::DEFAULT_HINT(
+    BARCODEFORMAT_UPC_E_HINT |
+    BARCODEFORMAT_UPC_A_HINT |
+    BARCODEFORMAT_EAN_8_HINT |
+    BARCODEFORMAT_EAN_13_HINT |
+    BARCODEFORMAT_CODE_128_HINT |
+    BARCODEFORMAT_CODE_39_HINT |
+    BARCODEFORMAT_ITF_HINT |
+    BARCODEFORMAT_DATA_MATRIX_HINT |
+    BARCODEFORMAT_QR_CODE_HINT);
+
+DecodeHints::DecodeHints() {
+  hints = 0;
+}
+
+DecodeHints::DecodeHints(DecodeHintType init) {
+  hints = init;
+}
+
+void DecodeHints::addFormat(BarcodeFormat toadd) {
+  switch (toadd) {
+    case BarcodeFormat_QR_CODE: hints |= BARCODEFORMAT_QR_CODE_HINT; break;
+    case BarcodeFormat_DATA_MATRIX: hints |= BARCODEFORMAT_DATA_MATRIX_HINT; break;
+    case BarcodeFormat_UPC_E: hints |= BARCODEFORMAT_UPC_E_HINT; break;
+    case BarcodeFormat_UPC_A: hints |= BARCODEFORMAT_UPC_A_HINT; break;
+    case BarcodeFormat_EAN_8: hints |= BARCODEFORMAT_EAN_8_HINT; break;
+    case BarcodeFormat_EAN_13: hints |= BARCODEFORMAT_EAN_13_HINT; break;
+    case BarcodeFormat_CODE_128: hints |= BARCODEFORMAT_CODE_128_HINT; break;
+    case BarcodeFormat_CODE_39: hints |= BARCODEFORMAT_CODE_39_HINT; break;
+    case BarcodeFormat_ITF: hints |= BARCODEFORMAT_ITF_HINT; break;
+    default: throw IllegalArgumentException("Unrecognizd barcode format");
+  }
+}
+
+bool DecodeHints::containsFormat(BarcodeFormat tocheck) const {
+  DecodeHintType checkAgainst;
+  switch (tocheck) {
+    case BarcodeFormat_QR_CODE: checkAgainst = BARCODEFORMAT_QR_CODE_HINT; break;
+    case BarcodeFormat_DATA_MATRIX: checkAgainst = BARCODEFORMAT_DATA_MATRIX_HINT; break;
+    case BarcodeFormat_UPC_E: checkAgainst = BARCODEFORMAT_UPC_E_HINT; break;
+    case BarcodeFormat_UPC_A: checkAgainst = BARCODEFORMAT_UPC_A_HINT; break;
+    case BarcodeFormat_EAN_8: checkAgainst = BARCODEFORMAT_EAN_8_HINT; break;
+    case BarcodeFormat_EAN_13: checkAgainst = BARCODEFORMAT_EAN_13_HINT; break;
+    case BarcodeFormat_CODE_128: checkAgainst = BARCODEFORMAT_CODE_128_HINT; break;
+    case BarcodeFormat_CODE_39: checkAgainst = BARCODEFORMAT_CODE_39_HINT; break;
+    case BarcodeFormat_ITF: checkAgainst = BARCODEFORMAT_ITF_HINT; break;
+    default: throw IllegalArgumentException("Unrecognizd barcode format");
+  }
+  return (hints & checkAgainst);
+}
+
+void DecodeHints::setTryHarder(bool toset) {
+  if (toset) {
+    hints |= TRYHARDER_HINT;
+  } else {
+    hints &= ~TRYHARDER_HINT;
+  }
+}
+
+bool DecodeHints::getTryHarder() const {
+  return (hints & TRYHARDER_HINT);
+}
+
+void DecodeHints::setResultPointCallback(Ref<ResultPointCallback> const& _callback) {
+    callback = _callback;
+}
+
+Ref<ResultPointCallback> DecodeHints::getResultPointCallback() const {
+    return callback;
+}
+
+} /* namespace */
+
+// file: zxing/Exception.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Exception.cpp
+ *  ZXing
+ *
+ *  Created by Christian Brunschen on 03/06/2008.
+ *  Copyright 2008-2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ */
+
+// #include <zxing/Exception.h>
+
+namespace zxing {
+
+Exception::Exception() {}
+
+Exception::Exception(const char *msg) :
+    message(msg) {
+}
+
+const char* Exception::what() const throw() {
+  return message.c_str();
+}
+
+Exception::~Exception() throw() {
+}
+
+}
+
+// file: zxing/FormatException.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  FormatException.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/FormatException.h>
+
+namespace zxing {
+
+FormatException::FormatException() {}
+
+FormatException::FormatException(const char *msg) :
+    ReaderException(msg) {
+}
+
+FormatException::~FormatException() throw() {
+}
+
+}
+
+// file: zxing/LuminanceSource.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  LuminanceSource.cpp
+ *  zxing
+ *
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <sstream>
+// #include <zxing/LuminanceSource.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+
+LuminanceSource::LuminanceSource() {
+}
+
+LuminanceSource::~LuminanceSource() {
+}
+
+bool LuminanceSource::isCropSupported() const {
+  return false;
+}
+
+Ref<LuminanceSource> LuminanceSource::crop(int left, int top, int width, int height) {
+  (void)left;
+  (void)top;
+  (void)width;
+  (void)height;
+  throw IllegalArgumentException("This luminance source does not support cropping.");
+}
+
+bool LuminanceSource::isRotateSupported() const {
+  return false;
+}
+
+Ref<LuminanceSource> LuminanceSource::rotateCounterClockwise() {
+  throw IllegalArgumentException("This luminance source does not support rotation.");
+}
+
+LuminanceSource::operator std::string() {
+  unsigned char* row = 0;
+  std::ostringstream oss;
+  for (int y = 0; y < getHeight(); y++) {
+    row = getRow(y, row);
+    for (int x = 0; x < getWidth(); x++) {
+      int luminance = row[x] & 0xFF;
+      char c;
+      if (luminance < 0x40) {
+        c = '#';
+      } else if (luminance < 0x80) {
+        c = '+';
+      } else if (luminance < 0xC0) {
+        c = '.';
+      } else {
+        c = ' ';
+      }
+      oss << c;
+    }
+    oss << '\n';
+  }
+  delete [] row;
+  return oss.str();
+}
+
+
+
+}
+
+// file: zxing/MultiFormatReader.cpp
+
+/*
+ *  MultiFormatBarcodeReader.cpp
+ *  ZXing
+ *
+ *  Created by Lukasz Warchol on 10-01-26.
+ *  Modified by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/MultiFormatReader.h>
+// #include <zxing/qrcode/QRCodeReader.h>
+// #include <zxing/datamatrix/DataMatrixReader.h>
+// #include <zxing/oned/MultiFormatUPCEANReader.h>
+// #include <zxing/oned/MultiFormatOneDReader.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  MultiFormatReader::MultiFormatReader() {
+
+  }
+
+  Ref<Result> MultiFormatReader::decode(Ref<BinaryBitmap> image) {
+    setHints(DecodeHints::DEFAULT_HINT);
+    return decodeInternal(image);
+  }
+
+  Ref<Result> MultiFormatReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+    setHints(hints);
+    return decodeInternal(image);
+  }
+
+  Ref<Result> MultiFormatReader::decodeWithState(Ref<BinaryBitmap> image) {
+    // Make sure to set up the default state so we don't crash
+    if (readers_.size() == 0) {
+      setHints(DecodeHints::DEFAULT_HINT);
+    }
+    return decodeInternal(image);
+  }
+
+  void MultiFormatReader::setHints(DecodeHints hints) {
+    hints_ = hints;
+    readers_.clear();
+    bool tryHarder = hints.getTryHarder();
+
+    bool addOneDReader = hints.containsFormat(BarcodeFormat_UPC_E) ||
+                         hints.containsFormat(BarcodeFormat_UPC_A) ||
+                         hints.containsFormat(BarcodeFormat_EAN_8) ||
+                         hints.containsFormat(BarcodeFormat_EAN_13) ||
+                         hints.containsFormat(BarcodeFormat_CODE_128) ||
+                         hints.containsFormat(BarcodeFormat_CODE_39) ||
+                         hints.containsFormat(BarcodeFormat_ITF);
+    if (addOneDReader && !tryHarder) {
+      readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
+    }
+    if (hints.containsFormat(BarcodeFormat_QR_CODE)) {
+      readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
+    }
+    if (hints.containsFormat(BarcodeFormat_DATA_MATRIX)) {
+      readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader()));
+    }
+    //TODO: add PDF417 here once PDF417 reader is implemented
+    if (addOneDReader && tryHarder) {
+      readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
+    }
+    if (readers_.size() == 0) {
+      if (!tryHarder) {
+        readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
+      }
+      readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
+      if (tryHarder) {
+        readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
+      }
+    }
+  }
+
+  Ref<Result> MultiFormatReader::decodeInternal(Ref<BinaryBitmap> image) {
+    for (unsigned int i = 0; i < readers_.size(); i++) {
+      try {
+        return readers_[i]->decode(image, hints_);
+      } catch (ReaderException const& re) {
+        // continue
+      }
+    }
+    throw ReaderException("No code detected");
+  }
+
+  MultiFormatReader::~MultiFormatReader() {
+
+  }
+}
+
+// file: zxing/NotFoundException.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ * Copyright 20011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/NotFoundException.h>
+
+namespace zxing {
+
+  NotFoundException::NotFoundException(const char *msg)
+    : ReaderException(msg) {}
+
+  NotFoundException::~NotFoundException() throw() {
+  }
+
+}
+
+// file: zxing/Reader.cpp
+
+/*
+ *  Reader.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Reader.h>
+
+namespace zxing {
+
+Reader::~Reader() { }
+
+Ref<Result> Reader::decode(Ref<BinaryBitmap> image) {
+  return decode(image, DecodeHints::DEFAULT_HINT);
+}
+
+}
+
+// file: zxing/ReaderException.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  ReaderException.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008-2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+
+ReaderException::ReaderException() {}
+
+ReaderException::ReaderException(const char *msg) :
+    Exception(msg) {
+}
+
+ReaderException::~ReaderException() throw() {
+}
+
+}
+
+// file: zxing/Result.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Result.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Result.h>
+
+namespace zxing {
+using namespace std;
+
+Result::Result(Ref<String> text, ArrayRef<unsigned char> rawBytes, std::vector<Ref<ResultPoint> > resultPoints,
+               BarcodeFormat format) :
+  text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format) {
+}
+
+Result::~Result() {
+}
+
+Ref<String> Result::getText() {
+  return text_;
+}
+
+ArrayRef<unsigned char> Result::getRawBytes() {
+  return rawBytes_;
+}
+
+const std::vector<Ref<ResultPoint> >& Result::getResultPoints() const {
+  return resultPoints_;
+}
+
+std::vector<Ref<ResultPoint> >& Result::getResultPoints() {
+  return resultPoints_;
+}
+
+BarcodeFormat Result::getBarcodeFormat() const {
+  return format_;
+}
+
+ostream& operator<<(ostream &out, Result& result) {
+  if (result.text_ != 0) {
+    out << result.text_->getText();
+  } else {
+    out << "[" << result.rawBytes_->size() << " bytes]";
+  }
+  return out;
+}
+
+}
+
+// file: zxing/ResultPoint.cpp
+
+/*
+ *  ResultPoint.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPoint.h>
+// #include <math.h>
+
+namespace zxing {
+
+ResultPoint::ResultPoint() : posX_(0), posY_(0) {}
+
+ResultPoint::ResultPoint(float x, float y) : posX_(x), posY_(y) {}
+
+ResultPoint::~ResultPoint() {}
+
+float ResultPoint::getX() const {
+  return posX_;
+}
+
+float ResultPoint::getY() const {
+  return posY_;
+}
+
+bool ResultPoint::equals(Ref<ResultPoint> other) {
+  return posX_ == other->getX() && posY_ == other->getY();
+}
+
+/**
+ * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
+ * BC < AC and the angle between BC and BA is less than 180 degrees.
+ */
+void ResultPoint::orderBestPatterns(std::vector<Ref<ResultPoint> > &patterns) {
+    // Find distances between pattern centers
+    float zeroOneDistance = distance(patterns[0]->getX(), patterns[1]->getX(),patterns[0]->getY(), patterns[1]->getY());
+    float oneTwoDistance = distance(patterns[1]->getX(), patterns[2]->getX(),patterns[1]->getY(), patterns[2]->getY());
+    float zeroTwoDistance = distance(patterns[0]->getX(), patterns[2]->getX(),patterns[0]->getY(), patterns[2]->getY());
+
+    Ref<ResultPoint> pointA, pointB, pointC;
+    // Assume one closest to other two is B; A and C will just be guesses at first
+    if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
+      pointB = patterns[0];
+      pointA = patterns[1];
+      pointC = patterns[2];
+    } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
+      pointB = patterns[1];
+      pointA = patterns[0];
+      pointC = patterns[2];
+    } else {
+      pointB = patterns[2];
+      pointA = patterns[0];
+      pointC = patterns[1];
+    }
+
+    // Use cross product to figure out whether A and C are correct or flipped.
+    // This asks whether BC x BA has a positive z component, which is the arrangement
+    // we want for A, B, C. If it's negative, then we've got it flipped around and
+    // should swap A and C.
+    if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
+      Ref<ResultPoint> temp = pointA;
+      pointA = pointC;
+      pointC = temp;
+    }
+
+    patterns[0] = pointA;
+    patterns[1] = pointB;
+    patterns[2] = pointC;
+}
+
+float ResultPoint::distance(Ref<ResultPoint> point1, Ref<ResultPoint> point2) {
+  return distance(point1->getX(), point1->getY(), point2->getX(), point2->getY());
+}
+
+float ResultPoint::distance(float x1, float x2, float y1, float y2) {
+  float xDiff = x1 - x2;
+  float yDiff = y1 - y2;
+  return (float) sqrt((double) (xDiff * xDiff + yDiff * yDiff));
+}
+
+float ResultPoint::crossProductZ(Ref<ResultPoint> pointA, Ref<ResultPoint> pointB, Ref<ResultPoint> pointC) {
+  float bX = pointB->getX();
+  float bY = pointB->getY();
+  return ((pointC->getX() - bX) * (pointA->getY() - bY)) - ((pointC->getY() - bY) * (pointA->getX() - bX));
+}
+}
+
+// file: zxing/ResultPointCallback.cpp
+
+/*
+ *  ResultPointCallback.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPointCallback.h>
+
+namespace zxing {
+
+ResultPointCallback::~ResultPointCallback() {}
+
+}
+
+// file: zxing/common/Array.cpp
+
+/*
+ *  Array.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 07/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Array.h>
+
+
+// file: zxing/common/BitArray.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/BitArray.h>
+
+using namespace std;
+
+namespace zxing {
+
+
+size_t BitArray::wordsForBits(size_t bits) {
+  int arraySize = (bits + bitsPerWord_ - 1) >> logBits_;
+  return arraySize;
+}
+
+BitArray::BitArray(size_t size) :
+    size_(size), bits_(wordsForBits(size), (const unsigned int)0) {
+}
+
+BitArray::~BitArray() {
+}
+
+size_t BitArray::getSize() {
+  return size_;
+}
+
+void BitArray::setBulk(size_t i, unsigned int newBits) {
+  bits_[i >> logBits_] = newBits;
+}
+
+void BitArray::setRange(int start, int end) {
+  if (end < start) {
+    throw IllegalArgumentException("invalid call to BitArray::setRange");
+  }
+  if (end == start) {
+    return;
+  }
+  end--; // will be easier to treat this as the last actually set bit -- inclusive
+  int firstInt = start >> 5;
+  int lastInt = end >> 5;
+  for (int i = firstInt; i <= lastInt; i++) {
+    int firstBit = i > firstInt ? 0 : start & 0x1F;
+    int lastBit = i < lastInt ? 31 : end & 0x1F;
+    int mask;
+    if (firstBit == 0 && lastBit == 31) {
+      mask = -1;
+    } else {
+      mask = 0;
+      for (int j = firstBit; j <= lastBit; j++) {
+        mask |= 1 << j;
+      }
+    }
+    bits_[i] |= mask;
+  }
+}
+
+void BitArray::clear() {
+  size_t max = bits_.size();
+  for (size_t i = 0; i < max; i++) {
+    bits_[i] = 0;
+  }
+}
+
+bool BitArray::isRange(size_t start, size_t end, bool value) {
+  if (end < start) {
+    throw IllegalArgumentException("end must be after start");
+  }
+  if (end == start) {
+    return true;
+  }
+  // treat the 'end' as inclusive, rather than exclusive
+  end--;
+  size_t firstWord = start >> logBits_;
+  size_t lastWord = end >> logBits_;
+  for (size_t i = firstWord; i <= lastWord; i++) {
+    size_t firstBit = i > firstWord ? 0 : start & bitsMask_;
+    size_t lastBit = i < lastWord ? bitsPerWord_ - 1: end & bitsMask_;
+    unsigned int mask;
+    if (firstBit == 0 && lastBit == bitsPerWord_ - 1) {
+      mask = numeric_limits<unsigned int>::max();
+    } else {
+      mask = 0;
+      for (size_t j = firstBit; j <= lastBit; j++) {
+        mask |= 1 << j;
+      }
+    }
+    if (value) {
+      if ((bits_[i] & mask) != mask) {
+        return false;
+      }
+    } else {
+      if ((bits_[i] & mask) != 0) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+vector<unsigned int>& BitArray::getBitArray() {
+  return bits_;
+}
+
+void BitArray::reverse() {
+  std::vector<unsigned int> newBits(bits_.size(),(const unsigned int) 0);
+  for (size_t i = 0; i < size_; i++) {
+    if (get(size_ - i - 1)) {
+      newBits[i >> logBits_] |= 1<< (i & bitsMask_);
+    }
+  }
+  bits_ = newBits;
+}
+}
+
+// file: zxing/common/BitMatrix.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+// #include <iostream>
+// #include <sstream>
+// #include <string>
+
+using std::ostream;
+using std::ostringstream;
+
+using zxing::BitMatrix;
+using zxing::BitArray;
+using zxing::Ref;
+
+namespace {
+  size_t wordsForSize(size_t width,
+                      size_t height,
+                      unsigned int bitsPerWord,
+                      unsigned int logBits) {
+    size_t bits = width * height;
+    int arraySize = (bits + bitsPerWord - 1) >> logBits;
+    return arraySize;
+  }
+}
+
+BitMatrix::BitMatrix(size_t dimension) :
+  width_(dimension), height_(dimension), words_(0), bits_(NULL) {
+  words_ = wordsForSize(width_, height_, bitsPerWord, logBits);
+  bits_ = new unsigned int[words_];
+  clear();
+}
+
+BitMatrix::BitMatrix(size_t width, size_t height) :
+  width_(width), height_(height), words_(0), bits_(NULL) {
+  words_ = wordsForSize(width_, height_, bitsPerWord, logBits);
+  bits_ = new unsigned int[words_];
+  clear();
+}
+
+BitMatrix::~BitMatrix() {
+  delete[] bits_;
+}
+
+
+void BitMatrix::flip(size_t x, size_t y) {
+  size_t offset = x + width_ * y;
+  bits_[offset >> logBits] ^= 1 << (offset & bitsMask);
+}
+
+void BitMatrix::clear() {
+  std::fill(bits_, bits_+words_, 0);
+}
+
+void BitMatrix::setRegion(size_t left, size_t top, size_t width, size_t height) {
+  if ((long)top < 0 || (long)left < 0) {
+    throw IllegalArgumentException("topI and leftJ must be nonnegative");
+  }
+  if (height < 1 || width < 1) {
+    throw IllegalArgumentException("height and width must be at least 1");
+  }
+  size_t right = left + width;
+  size_t bottom = top + height;
+  if (right > width_ || bottom > height_) {
+    throw IllegalArgumentException("top + height and left + width must be <= matrix dimension");
+  }
+  for (size_t y = top; y < bottom; y++) {
+    int yOffset = width_ * y;
+    for (size_t x = left; x < right; x++) {
+      size_t offset = x + yOffset;
+      bits_[offset >> logBits] |= 1 << (offset & bitsMask);
+    }
+  }
+}
+
+Ref<BitArray> BitMatrix::getRow(int y, Ref<BitArray> row) {
+  if (row.empty() || row->getSize() < width_) {
+    row = new BitArray(width_);
+  } else {
+    row->clear();
+  }
+  size_t start = y * width_;
+  size_t end = start + width_ - 1; // end is inclusive
+  size_t firstWord = start >> logBits;
+  size_t lastWord = end >> logBits;
+  size_t bitOffset = start & bitsMask;
+  for (size_t i = firstWord; i <= lastWord; i++) {
+    size_t firstBit = i > firstWord ? 0 : start & bitsMask;
+    size_t lastBit = i < lastWord ? bitsPerWord - 1 : end & bitsMask;
+    unsigned int mask;
+    if (firstBit == 0 && lastBit == logBits) {
+      mask = std::numeric_limits<unsigned int>::max();
+    } else {
+      mask = 0;
+      for (size_t j = firstBit; j <= lastBit; j++) {
+        mask |= 1 << j;
+      }
+    }
+    row->setBulk((i - firstWord) << logBits, (bits_[i] & mask) >> bitOffset);
+    if (firstBit == 0 && bitOffset != 0) {
+      unsigned int prevBulk = row->getBitArray()[i - firstWord - 1];
+      prevBulk |= (bits_[i] & mask) << (bitsPerWord - bitOffset);
+      row->setBulk((i - firstWord - 1) << logBits, prevBulk);
+    }
+  }
+  return row;
+}
+
+size_t BitMatrix::getWidth() const {
+  return width_;
+}
+
+size_t BitMatrix::getHeight() const {
+  return height_;
+}
+
+size_t BitMatrix::getDimension() const {
+  return width_;
+}
+
+unsigned int* BitMatrix::getBits() const {
+  return bits_;
+}
+
+namespace zxing {
+  ostream& operator<<(ostream &out, const BitMatrix &bm) {
+    for (size_t y = 0; y < bm.height_; y++) {
+      for (size_t x = 0; x < bm.width_; x++) {
+        out << (bm.get(x, y) ? "X " : "  ");
+      }
+      out << "\n";
+    }
+    return out;
+  }
+}
+
+const char* BitMatrix::description() {
+  ostringstream out;
+  out << *this;
+  return out.str().c_str();
+}
+
+// file: zxing/common/BitSource.cpp
+
+/*
+ *  BitSource.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 09/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/BitSource.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+
+int BitSource::readBits(int numBits) {
+  if (numBits < 0 || numBits > 32) {
+    throw IllegalArgumentException("cannot read <1 or >32 bits");
+  } else if (numBits > available()) {
+    throw IllegalArgumentException("reading more bits than are available");
+  }
+
+  int result = 0;
+
+  // First, read remainder from current byte
+  if (bitOffset_ > 0) {
+    int bitsLeft = 8 - bitOffset_;
+    int toRead = numBits < bitsLeft ? numBits : bitsLeft;
+    int bitsToNotRead = bitsLeft - toRead;
+    int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;
+    result = (bytes_[byteOffset_] & mask) >> bitsToNotRead;
+    numBits -= toRead;
+    bitOffset_ += toRead;
+    if (bitOffset_ == 8) {
+      bitOffset_ = 0;
+      byteOffset_++;
+    }
+  }
+
+  // Next read whole bytes
+  if (numBits > 0) {
+    while (numBits >= 8) {
+      result = (result << 8) | (bytes_[byteOffset_] & 0xFF);
+      byteOffset_++;
+      numBits -= 8;
+    }
+
+
+    // Finally read a partial byte
+    if (numBits > 0) {
+      int bitsToNotRead = 8 - numBits;
+      int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;
+      result = (result << numBits) | ((bytes_[byteOffset_] & mask) >> bitsToNotRead);
+      bitOffset_ += numBits;
+    }
+  }
+
+  return result;
+}
+
+int BitSource::available() {
+  return 8 * (bytes_.size() - byteOffset_) - bitOffset_;
+}
+}
+
+// file: zxing/common/CharacterSetECI.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ * Copyright 2008-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/CharacterSetECI.h>
+// #include <sstream>
+// #include <zxing/common/IllegalArgumentException.h>
+
+using std::string;
+
+using zxing::common::CharacterSetECI;
+using zxing::IllegalArgumentException;
+
+std::map<int, CharacterSetECI*> CharacterSetECI::VALUE_TO_ECI;
+std::map<std::string, CharacterSetECI*> CharacterSetECI::NAME_TO_ECI;
+
+const bool CharacterSetECI::inited = CharacterSetECI::init_tables();
+
+bool CharacterSetECI::init_tables() {
+  addCharacterSet(0, "Cp437");
+  { char const* s[] = {"ISO8859_1", "ISO-8859-1", 0};
+    addCharacterSet(1, s); }
+  addCharacterSet(2, "Cp437");
+  { char const* s[] = {"ISO8859_1", "ISO-8859-1", 0};
+    addCharacterSet(3, s); }
+  addCharacterSet(4, "ISO8859_2");
+  addCharacterSet(5, "ISO8859_3");
+  addCharacterSet(6, "ISO8859_4");
+  addCharacterSet(7, "ISO8859_5");
+  addCharacterSet(8, "ISO8859_6");
+  addCharacterSet(9, "ISO8859_7");
+  addCharacterSet(10, "ISO8859_8");
+  addCharacterSet(11, "ISO8859_9");
+  addCharacterSet(12, "ISO8859_10");
+  addCharacterSet(13, "ISO8859_11");
+  addCharacterSet(15, "ISO8859_13");
+  addCharacterSet(16, "ISO8859_14");
+  addCharacterSet(17, "ISO8859_15");
+  addCharacterSet(18, "ISO8859_16");
+  { char const* s[] = {"SJIS", "Shift_JIS", 0};
+    addCharacterSet(20, s ); }
+  return true;
+}
+
+CharacterSetECI::CharacterSetECI(int value, char const* encodingName_)
+  : ECI(value), encodingName(encodingName_) {}
+
+char const* CharacterSetECI::getEncodingName() {
+  return encodingName;
+}
+
+void CharacterSetECI::addCharacterSet(int value, char const* encodingName) {
+  CharacterSetECI* eci = new CharacterSetECI(value, encodingName);
+  VALUE_TO_ECI[value] = eci; // can't use valueOf
+  NAME_TO_ECI[string(encodingName)] = eci;
+}
+
+void CharacterSetECI::addCharacterSet(int value, char const* const* encodingNames) {
+  CharacterSetECI* eci = new CharacterSetECI(value, encodingNames[0]);
+  VALUE_TO_ECI[value] = eci;
+  for (int i = 0; encodingNames[i]; i++) {
+    NAME_TO_ECI[string(encodingNames[i])] = eci;
+  }
+}
+
+CharacterSetECI* CharacterSetECI::getCharacterSetECIByValue(int value) {
+  if (value < 0 || value >= 900) {
+    std::ostringstream oss;
+    oss << "Bad ECI value: " << value;
+    throw IllegalArgumentException(oss.str().c_str());
+  }
+  return VALUE_TO_ECI[value];
+}
+
+CharacterSetECI* CharacterSetECI::getCharacterSetECIByName(string const& name) {
+  return NAME_TO_ECI[name];
+}
+
+// file: zxing/common/Counted.cpp
+
+/*
+ *  Counted.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 07/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+
+using namespace std;
+
+template<class T>
+ostream& operator<<(ostream &out, Ref<T>& ref) {
+  out << "Ref(" << (ref.object_ ? (*ref.object_) : "NULL") << ")";
+  return out;
+}
+}
+
+// file: zxing/common/DecoderResult.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  DecoderResult.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008-2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/DecoderResult.h>
+
+using namespace std;
+using namespace zxing;
+
+DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes,
+                             Ref<String> text,
+                             ArrayRef< ArrayRef<unsigned char> >& byteSegments,
+                             string const& ecLevel) :
+  rawBytes_(rawBytes),
+  text_(text),
+  byteSegments_(byteSegments),
+  ecLevel_(ecLevel) {}
+
+DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes,
+                             Ref<String> text)
+  : rawBytes_(rawBytes), text_(text) {}
+
+ArrayRef<unsigned char> DecoderResult::getRawBytes() {
+  return rawBytes_;
+}
+
+Ref<String> DecoderResult::getText() {
+  return text_;
+}
+
+// file: zxing/common/DetectorResult.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  DetectorResult.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 14/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/DetectorResult.h>
+
+namespace zxing {
+
+DetectorResult::DetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points, Ref<PerspectiveTransform> transform) :
+  bits_(bits), points_(points), transform_(transform) {
+}
+
+Ref<BitMatrix> DetectorResult::getBits() {
+  return bits_;
+}
+
+std::vector<Ref<ResultPoint> > DetectorResult::getPoints() {
+  return points_;
+}
+
+Ref<PerspectiveTransform> DetectorResult::getTransform() {
+  return transform_;
+}
+
+}
+
+// file: zxing/common/ECI.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ * Copyright 2008-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/ECI.h>
+// #include <sstream>
+// #include <zxing/common/CharacterSetECI.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+using zxing::common::ECI;
+using zxing::IllegalArgumentException;
+
+ECI::ECI(int value_) : value(value_) {}
+
+int ECI::getValue() const {
+  return value;
+}
+
+ECI* ECI::getECIByValue(int value) {
+  if (value < 0 || value > 999999) {
+    std::ostringstream oss;
+    oss << "Bad ECI value: " << value;
+    throw IllegalArgumentException(oss.str().c_str());
+  }
+  if (value < 900) { // Character set ECIs use 000000 - 000899
+    return CharacterSetECI::getCharacterSetECIByValue(value);
+  }
+  return 0;
+}
+
+// file: zxing/common/EdgeDetector.cpp
+
+/*
+ *  EdgeDetector.cpp
+ *  zxing
+ *
+ *  Created by Ralf Kistner on 7/12/2009.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/EdgeDetector.h>
+// #include <algorithm>
+// #include <cmath>
+
+using namespace std;
+
+namespace zxing {
+namespace EdgeDetector {
+
+void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation) {
+  float xdist = end.x - start.x;
+  float ydist = end.y - start.y;
+  float length = sqrt(xdist * xdist + ydist * ydist);
+
+
+  int var;
+
+  if (abs(xdist) > abs(ydist)) {
+    // Horizontal
+    if (xdist < 0)
+      skip = -skip;
+
+    var = int(abs(deviation * length / xdist));
+
+    float dy = ydist / xdist * skip;
+    bool left = (skip < 0) ^ invert;
+    int x = int(start.x);
+
+    int steps = int(xdist / skip);
+    for (int i = 0; i < steps; i++) {
+      x += skip;
+      if (x < 0 || x >= (int)image.getWidth())
+        continue; // In case we start off the edge
+      int my = int(start.y + dy * i);
+      int ey = min(my + var + 1, (int)image.getHeight() - 1);
+      int sy = max(my - var, 0);
+      for (int y = sy + 1; y < ey; y++) {
+        if (left) {
+          if (image.get(x, y) && !image.get(x, y + 1)) {
+            points.push_back(Point(x, y + 0.5f));
+          }
+        } else {
+          if (!image.get(x, y) && image.get(x, y + 1)) {
+            points.push_back(Point(x, y + 0.5f));
+          }
+        }
+      }
+    }
+  } else {
+    // Vertical
+    if (ydist < 0)
+      skip = -skip;
+
+    var = int(abs(deviation * length / ydist));
+
+    float dx = xdist / ydist * skip;
+    bool down = (skip > 0) ^ invert;
+    int y = int(start.y);
+
+    int steps = int(ydist / skip);
+    for (int i = 0; i < steps; i++) {
+      y += skip;
+      if (y < 0 || y >= (int)image.getHeight())
+        continue; // In case we start off the edge
+      int mx = int(start.x + dx * i);
+      int ex = min(mx + var + 1, (int)image.getWidth() - 1);
+      int sx = max(mx - var, 0);
+      for (int x = sx + 1; x < ex; x++) {
+        if (down) {
+          if (image.get(x, y) && !image.get(x + 1, y)) {
+            points.push_back(Point(x + 0.5f, y));
+          }
+
+        } else {
+          if (!image.get(x, y) && image.get(x + 1, y)) {
+            points.push_back(Point(x + 0.5f, y));
+          }
+        }
+
+      }
+    }
+
+  }
+}
+
+Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip) {
+  float t = threshold * threshold;
+
+  Point start = estimate.start;
+  Point end = estimate.end;
+
+  vector<Point> edges;
+  edges.clear();
+  findEdgePoints(edges, image, start, end, invert, skip, deviation);
+
+  int n = edges.size();
+
+  float xdist = end.x - start.x;
+  float ydist = end.y - start.y;
+
+  bool horizontal = abs(xdist) > abs(ydist);
+
+  float max = 0;
+  Line bestLine(start, end);  // prepopulate with the given line, in case we can't find any line for some reason
+
+  for (int i = -deviation; i < deviation; i++) {
+    float x1, y1;
+    if (horizontal) {
+      y1 = start.y + i;
+      x1 = start.x - i * ydist / xdist;
+    } else {
+      y1 = start.y - i * xdist / ydist;
+      x1 = start.x + i;
+    }
+
+    for (int j = -deviation; j < deviation; j++) {
+      float x2, y2;
+      if (horizontal) {
+        y2 = end.y + j;
+        x2 = end.x - j * ydist / xdist;
+      } else {
+        y2 = end.y - j * xdist / ydist;
+        x2 = end.x + j;
+      }
+
+      float dx = x1 - x2;
+      float dy = y1 - y2;
+      float length = sqrt(dx * dx + dy * dy);
+
+      float score = 0;
+
+      for(int k = 0; k < n; k++) {
+        const Point& edge = edges[k];
+        float dist = ((x1 - edge.x) * dy - (y1 - edge.y) * dx) / length;
+        // Similar to least squares method
+        float s = t - dist * dist;
+        if (s > 0)
+          score += s;
+      }
+
+      if (score > max) {
+        max = score;
+        bestLine.start = Point(x1, y1);
+        bestLine.end = Point(x2, y2);
+      }
+    }
+  }
+
+  return bestLine;
+}
+
+Point intersection(Line a, Line b) {
+  float dxa = a.start.x - a.end.x;
+  float dxb = b.start.x - b.end.x;
+  float dya = a.start.y - a.end.y;
+  float dyb = b.start.y - b.end.y;
+
+  float p = a.start.x * a.end.y - a.start.y * a.end.x;
+  float q = b.start.x * b.end.y - b.start.y * b.end.x;
+  float denom = dxa * dyb - dya * dxb;
+  if(denom == 0)  // Lines don't intersect
+    return Point(INFINITY, INFINITY);
+
+  float x = (p * dxb - dxa * q) / denom;
+  float y = (p * dyb - dya * q) / denom;
+
+  return Point(x, y);
+}
+
+} // namespace EdgeDetector
+} // namespace zxing
+
+// file: zxing/common/GlobalHistogramBinarizer.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  GlobalHistogramBinarizer.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/GlobalHistogramBinarizer.h>
+// #include <zxing/common/IllegalArgumentException.h>
+// #include <zxing/common/Array.h>
+
+namespace zxing {
+using namespace std;
+
+const int LUMINANCE_BITS_25 = 5;
+const int LUMINANCE_SHIFT_25 = 8 - LUMINANCE_BITS_25;
+const int LUMINANCE_BUCKETS_25 = 1 << LUMINANCE_BITS_25;
+
+GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) :
+  Binarizer(source), cached_matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
+
+}
+
+GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
+}
+
+
+Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
+  if (y == cached_row_num_) {
+    if (cached_row_ != NULL) {
+      return cached_row_;
+    } else {
+      throw IllegalArgumentException("Too little dynamic range in luminance");
+    }
+  }
+
+  vector<int> histogram(LUMINANCE_BUCKETS_25, 0);
+  LuminanceSource& source = *getLuminanceSource();
+  int width = source.getWidth();
+  if (row == NULL || static_cast<int>(row->getSize()) < width) {
+    row = new BitArray(width);
+  } else {
+    row->clear();
+  }
+
+  //TODO(flyashi): cache this instead of allocating and deleting per row
+  unsigned char* row_pixels = NULL;
+  try {
+    row_pixels = new unsigned char[width];
+    row_pixels = source.getRow(y, row_pixels);
+    for (int x = 0; x < width; x++) {
+      histogram[row_pixels[x] >> LUMINANCE_SHIFT_25]++;
+    }
+    int blackPoint = estimate(histogram);
+
+    BitArray& array = *row;
+    int left = row_pixels[0];
+    int center = row_pixels[1];
+    for (int x = 1; x < width - 1; x++) {
+      int right = row_pixels[x + 1];
+      // A simple -1 4 -1 box filter with a weight of 2.
+      int luminance = ((center << 2) - left - right) >> 1;
+      if (luminance < blackPoint) {
+        array.set(x);
+      }
+      left = center;
+      center = right;
+    }
+
+    cached_row_ = row;
+    cached_row_num_ = y;
+    delete [] row_pixels;
+    return row;
+  } catch (IllegalArgumentException const& iae) {
+    // Cache the fact that this row failed.
+    cached_row_ = NULL;
+    cached_row_num_ = y;
+    delete [] row_pixels;
+    throw iae;
+  }
+}
+
+Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
+  if (cached_matrix_ != NULL) {
+    return cached_matrix_;
+  }
+
+  // Faster than working with the reference
+  LuminanceSource& source = *getLuminanceSource();
+  int width = source.getWidth();
+  int height = source.getHeight();
+  vector<int> histogram(LUMINANCE_BUCKETS_25, 0);
+
+  // Quickly calculates the histogram by sampling four rows from the image.
+  // This proved to be more robust on the blackbox tests than sampling a
+  // diagonal as we used to do.
+  ArrayRef<unsigned char> ref (width);
+  unsigned char* row = &ref[0];
+  for (int y = 1; y < 5; y++) {
+    int rownum = height * y / 5;
+    int right = (width << 2) / 5;
+    row = source.getRow(rownum, row);
+    for (int x = width / 5; x < right; x++) {
+      histogram[row[x] >> LUMINANCE_SHIFT_25]++;
+    }
+  }
+
+  int blackPoint = estimate(histogram);
+
+  Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
+  BitMatrix& matrix = *matrix_ref;
+  for (int y = 0; y < height; y++) {
+    row = source.getRow(y, row);
+    for (int x = 0; x < width; x++) {
+      if (row[x] < blackPoint)
+        matrix.set(x, y);
+    }
+  }
+
+  cached_matrix_ = matrix_ref;
+  // delete [] row;
+  return matrix_ref;
+}
+
+int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
+  int numBuckets = histogram.size();
+  int maxBucketCount = 0;
+
+  // Find tallest peak in histogram
+  int firstPeak = 0;
+  int firstPeakSize = 0;
+  for (int i = 0; i < numBuckets; i++) {
+    if (histogram[i] > firstPeakSize) {
+      firstPeak = i;
+      firstPeakSize = histogram[i];
+    }
+    if (histogram[i] > maxBucketCount) {
+      maxBucketCount = histogram[i];
+    }
+  }
+
+  // Find second-tallest peak -- well, another peak that is tall and not
+  // so close to the first one
+  int secondPeak = 0;
+  int secondPeakScore = 0;
+  for (int i = 0; i < numBuckets; i++) {
+    int distanceToBiggest = i - firstPeak;
+    // Encourage more distant second peaks by multiplying by square of distance
+    int score = histogram[i] * distanceToBiggest * distanceToBiggest;
+    if (score > secondPeakScore) {
+      secondPeak = i;
+      secondPeakScore = score;
+    }
+  }
+
+  // Put firstPeak first
+  if (firstPeak > secondPeak) {
+    int temp = firstPeak;
+    firstPeak = secondPeak;
+    secondPeak = temp;
+  }
+
+  // Kind of arbitrary; if the two peaks are very close, then we figure there is
+  // so little dynamic range in the image, that discriminating black and white
+  // is too error-prone.
+  // Decoding the image/line is either pointless, or may in some cases lead to
+  // a false positive for 1D formats, which are relatively lenient.
+  // We arbitrarily say "close" is
+  // "<= 1/16 of the total histogram buckets apart"
+  if (secondPeak - firstPeak <= numBuckets >> 4) {
+    throw IllegalArgumentException("Too little dynamic range in luminance");
+  }
+
+  // Find a valley between them that is low and closer to the white peak
+  int bestValley = secondPeak - 1;
+  int bestValleyScore = -1;
+  for (int i = secondPeak - 1; i > firstPeak; i--) {
+    int fromFirst = i - firstPeak;
+    // Favor a "valley" that is not too close to either peak -- especially not
+    // the black peak -- and that has a low value of course
+    int score = fromFirst * fromFirst * (secondPeak - i) *
+      (maxBucketCount - histogram[i]);
+    if (score > bestValleyScore) {
+      bestValley = i;
+      bestValleyScore = score;
+    }
+  }
+
+  return bestValley << LUMINANCE_SHIFT_25;
+}
+
+Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) {
+  return Ref<Binarizer> (new GlobalHistogramBinarizer(source));
+}
+
+} // namespace zxing
+
+// file: zxing/common/GreyscaleLuminanceSource.cpp
+
+/*
+ *  GreyscaleLuminanceSource.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/GreyscaleLuminanceSource.h>
+// #include <zxing/common/GreyscaleRotatedLuminanceSource.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+
+GreyscaleLuminanceSource::GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth,
+    int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
+    dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
+    height_(height) {
+
+  if (left + width > dataWidth || top + height > dataHeight || top < 0 || left < 0) {
+    throw IllegalArgumentException("Crop rectangle does not fit within image data.");
+  }
+}
+
+unsigned char* GreyscaleLuminanceSource::getRow(int y, unsigned char* row) {
+  if (y < 0 || y >= this->getHeight()) {
+    throw IllegalArgumentException("Requested row is outside the image.");
+  }
+  int width = getWidth();
+  // TODO(flyashi): determine if row has enough size.
+  if (row == NULL) {
+    row = new unsigned char[width_];
+  }
+  int offset = (y + top_) * dataWidth_ + left_;
+  memcpy(row, &greyData_[offset], width);
+  return row;
+}
+
+unsigned char* GreyscaleLuminanceSource::getMatrix() {
+  int size = width_ * height_;
+  unsigned char* result = new unsigned char[size];
+  if (left_ == 0 && top_ == 0 && dataWidth_ == width_ && dataHeight_ == height_) {
+    memcpy(result, greyData_, size);
+  } else {
+    for (int row = 0; row < height_; row++) {
+      memcpy(result + row * width_, greyData_ + (top_ + row) * dataWidth_ + left_, width_);
+    }
+  }
+  return result;
+}
+
+Ref<LuminanceSource> GreyscaleLuminanceSource::rotateCounterClockwise() {
+  // Intentionally flip the left, top, width, and height arguments as needed. dataWidth and
+  // dataHeight are always kept unrotated.
+  return Ref<LuminanceSource> (new GreyscaleRotatedLuminanceSource(greyData_, dataWidth_,
+      dataHeight_, top_, left_, height_, width_));
+}
+
+} /* namespace */
+
+// file: zxing/common/GreyscaleRotatedLuminanceSource.cpp
+
+/*
+ *  GreyscaleRotatedLuminanceSource.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// #include <zxing/common/GreyscaleRotatedLuminanceSource.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+
+// Note that dataWidth and dataHeight are not reversed, as we need to be able to traverse the
+// greyData correctly, which does not get rotated.
+GreyscaleRotatedLuminanceSource::GreyscaleRotatedLuminanceSource(unsigned char* greyData,
+    int dataWidth, int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
+    dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
+    height_(height) {
+
+  // Intentionally comparing to the opposite dimension since we're rotated.
+  if (left + width > dataHeight || top + height > dataWidth) {
+    throw IllegalArgumentException("Crop rectangle does not fit within image data.");
+  }
+}
+
+// The API asks for rows, but we're rotated, so we return columns.
+unsigned char* GreyscaleRotatedLuminanceSource::getRow(int y, unsigned char* row) {
+  if (y < 0 || y >= getHeight()) {
+    throw IllegalArgumentException("Requested row is outside the image");
+  }
+  int width = getWidth();
+  if (row == NULL) {
+    row = new unsigned char[width];
+  }
+  int offset = (left_ * dataWidth_) + (dataWidth_ - (y + top_));
+  for (int x = 0; x < width; x++) {
+    row[x] = greyData_[offset];
+    offset += dataWidth_;
+  }
+  return row;
+}
+
+unsigned char* GreyscaleRotatedLuminanceSource::getMatrix() {
+  unsigned char* result = new unsigned char[width_ * height_];
+  // This depends on getRow() honoring its second parameter.
+  for (int y = 0; y < height_; y++) {
+    getRow(y, &result[y * width_]);
+  }
+  return result;
+}
+
+} // namespace
+
+// file: zxing/common/GridSampler.cpp
+
+/*
+ *  GridSampler.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 18/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/GridSampler.h>
+// #include <zxing/common/PerspectiveTransform.h>
+// #include <zxing/ReaderException.h>
+// #include <iostream>
+// #include <sstream>
+
+namespace zxing {
+using namespace std;
+
+GridSampler GridSampler::gridSampler;
+
+GridSampler::GridSampler() {
+}
+
+Ref<BitMatrix> GridSampler::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
+  Ref<BitMatrix> bits(new BitMatrix(dimension));
+  vector<float> points(dimension << 1, (const float)0.0f);
+  for (int y = 0; y < dimension; y++) {
+    int max = points.size();
+    float yValue = (float)y + 0.5f;
+    for (int x = 0; x < max; x += 2) {
+      points[x] = (float)(x >> 1) + 0.5f;
+      points[x + 1] = yValue;
+    }
+    transform->transformPoints(points);
+    checkAndNudgePoints(image, points);
+    for (int x = 0; x < max; x += 2) {
+      if (image->get((int)points[x], (int)points[x + 1])) {
+        bits->set(x >> 1, y);
+      }
+    }
+  }
+  return bits;
+}
+
+Ref<BitMatrix> GridSampler::sampleGrid(Ref<BitMatrix> image, int dimensionX, int dimensionY, Ref<PerspectiveTransform> transform) {
+  Ref<BitMatrix> bits(new BitMatrix(dimensionX, dimensionY));
+  vector<float> points(dimensionX << 1, (const float)0.0f);
+  for (int y = 0; y < dimensionY; y++) {
+    int max = points.size();
+    float yValue = (float)y + 0.5f;
+    for (int x = 0; x < max; x += 2) {
+      points[x] = (float)(x >> 1) + 0.5f;
+      points[x + 1] = yValue;
+    }
+    transform->transformPoints(points);
+    checkAndNudgePoints(image, points);
+    for (int x = 0; x < max; x += 2) {
+      if (image->get((int)points[x], (int)points[x + 1])) {
+        bits->set(x >> 1, y);
+      }
+    }
+  }
+  return bits;
+}
+
+Ref<BitMatrix> GridSampler::sampleGrid(Ref<BitMatrix> image, int dimension, float p1ToX, float p1ToY, float p2ToX,
+                                       float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX,
+                                       float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY) {
+  Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY,
+                                      p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY));
+
+  return sampleGrid(image, dimension, transform);
+
+}
+
+void GridSampler::checkAndNudgePoints(Ref<BitMatrix> image, vector<float> &points) {
+  int width = image->getWidth();
+  int height = image->getHeight();
+
+
+  // The Java code assumes that if the start and end points are in bounds, the rest will also be.
+  // However, in some unusual cases points in the middle may also be out of bounds.
+  // Since we can't rely on an ArrayIndexOutOfBoundsException like Java, we check every point.
+
+  for (size_t offset = 0; offset < points.size(); offset += 2) {
+    int x = (int)points[offset];
+    int y = (int)points[offset + 1];
+    if (x < -1 || x > width || y < -1 || y > height) {
+      ostringstream s;
+      s << "Transformed point out of bounds at " << x << "," << y;
+      throw ReaderException(s.str().c_str());
+    }
+
+    if (x == -1) {
+      points[offset] = 0.0f;
+    } else if (x == width) {
+      points[offset] = width - 1;
+    }
+    if (y == -1) {
+      points[offset + 1] = 0.0f;
+    } else if (y == height) {
+      points[offset + 1] = height - 1;
+    }
+  }
+
+}
+
+GridSampler &GridSampler::getInstance() {
+  return gridSampler;
+}
+}
+
+// file: zxing/common/HybridBinarizer.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  HybridBinarizer.cpp
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/HybridBinarizer.h>
+
+// #include <zxing/common/IllegalArgumentException.h>
+
+using namespace std;
+using namespace zxing;
+
+namespace {
+  const int BLOCK_SIZE_POWER = 3;
+  const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER;
+  const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
+  const int MINIMUM_DIMENSION = BLOCK_SIZE * 5;
+}
+
+HybridBinarizer::HybridBinarizer(Ref<LuminanceSource> source) :
+  GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
+}
+
+HybridBinarizer::~HybridBinarizer() {
+}
+
+
+Ref<Binarizer>
+HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
+  return Ref<Binarizer> (new HybridBinarizer(source));
+}
+
+Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
+  // Calculates the final BitMatrix once for all requests. This could
+  // be called once from the constructor instead, but there are some
+  // advantages to doing it lazily, such as making profiling easier,
+  // and not doing heavy lifting when callers don't expect it.
+  if (matrix_) {
+    return matrix_;
+  }
+  LuminanceSource& source = *getLuminanceSource();
+  if (source.getWidth() >= MINIMUM_DIMENSION &&
+      source.getHeight() >= MINIMUM_DIMENSION) {
+    unsigned char* luminances = source.getMatrix();
+    int width = source.getWidth();
+    int height = source.getHeight();
+    int subWidth = width >> BLOCK_SIZE_POWER;
+    if ((width & BLOCK_SIZE_MASK) != 0) {
+      subWidth++;
+    }
+    int subHeight = height >> BLOCK_SIZE_POWER;
+    if ((height & BLOCK_SIZE_MASK) != 0) {
+      subHeight++;
+    }
+    int* blackPoints =
+      calculateBlackPoints(luminances, subWidth, subHeight, width, height);
+
+    Ref<BitMatrix> newMatrix (new BitMatrix(width, height));
+    calculateThresholdForBlock(luminances,
+                               subWidth,
+                               subHeight,
+                               width,
+                               height,
+                               blackPoints,
+                               newMatrix);
+    matrix_ = newMatrix;
+
+    // N.B.: these deletes are inadequate if anything between the new
+    // and this point can throw.  As of this writing, it doesn't look
+    // like they do.
+
+    delete [] blackPoints;
+    delete [] luminances;
+  } else {
+    // If the image is too small, fall back to the global histogram approach.
+    matrix_ = GlobalHistogramBinarizer::getBlackMatrix();
+  }
+  return matrix_;
+}
+
+void
+HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances,
+                                            int subWidth,
+                                            int subHeight,
+                                            int width,
+                                            int height,
+                                            int blackPoints[],
+                                            Ref<BitMatrix> const& matrix) {
+  for (int y = 0; y < subHeight; y++) {
+    int yoffset = y << BLOCK_SIZE_POWER;
+    if (yoffset + BLOCK_SIZE >= height) {
+      yoffset = height - BLOCK_SIZE;
+    }
+    for (int x = 0; x < subWidth; x++) {
+      int xoffset = x << BLOCK_SIZE_POWER;
+      if (xoffset + BLOCK_SIZE >= width) {
+        xoffset = width - BLOCK_SIZE;
+      }
+      int left = (x > 1) ? x : 2;
+      left = (left < subWidth - 2) ? left : subWidth - 3;
+      int top = (y > 1) ? y : 2;
+      top = (top < subHeight - 2) ? top : subHeight - 3;
+      int sum = 0;
+      for (int z = -2; z <= 2; z++) {
+        int *blackRow = &blackPoints[(top + z) * subWidth];
+        sum += blackRow[left - 2];
+        sum += blackRow[left - 1];
+        sum += blackRow[left];
+        sum += blackRow[left + 1];
+        sum += blackRow[left + 2];
+      }
+      int average = sum / 25;
+      threshold8x8Block(luminances, xoffset, yoffset, average, width, matrix);
+    }
+  }
+}
+
+void HybridBinarizer::threshold8x8Block(unsigned char* luminances,
+                                        int xoffset,
+                                        int yoffset,
+                                        int threshold,
+                                        int stride,
+                                        Ref<BitMatrix> const& matrix) {
+  for (int y = 0, offset = yoffset * stride + xoffset;
+       y < BLOCK_SIZE;
+       y++,  offset += stride) {
+    for (int x = 0; x < BLOCK_SIZE; x++) {
+      int pixel = luminances[offset + x] & 0xff;
+      if (pixel <= threshold) {
+        matrix->set(xoffset + x, yoffset + y);
+      }
+    }
+  }
+}
+
+namespace {
+  inline int getBlackPointFromNeighbors(int* blackPoints, int subWidth, int x, int y) {
+    return (blackPoints[(y-1)*subWidth+x] +
+            2*blackPoints[y*subWidth+x-1] +
+            blackPoints[(y-1)*subWidth+x-1]) >> 2;
+  }
+}
+
+int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
+    int width, int height) {
+  int *blackPoints = new int[subHeight * subWidth];
+  for (int y = 0; y < subHeight; y++) {
+    int yoffset = y << BLOCK_SIZE_POWER;
+    if (yoffset + BLOCK_SIZE >= height) {
+      yoffset = height - BLOCK_SIZE;
+    }
+    for (int x = 0; x < subWidth; x++) {
+      int xoffset = x << BLOCK_SIZE_POWER;
+      if (xoffset + BLOCK_SIZE >= width) {
+        xoffset = width - BLOCK_SIZE;
+      }
+      int sum = 0;
+      int min = 0xFF;
+      int max = 0;
+      for (int yy = 0, offset = yoffset * width + xoffset;
+           yy < BLOCK_SIZE;
+           yy++, offset += width) {
+        for (int xx = 0; xx < BLOCK_SIZE; xx++) {
+          int pixel = luminances[offset + xx] & 0xFF;
+          sum += pixel;
+          if (pixel < min) {
+            min = pixel;
+          }
+          if (pixel > max) {
+            max = pixel;
+          }
+        }
+      }
+
+      // See
+      // http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
+      int average = sum >> 6;
+      if (max - min <= 24) {
+        average = min >> 1;
+        if (y > 0 && x > 0) {
+          int bp = getBlackPointFromNeighbors(blackPoints, subWidth, x, y);
+          if (min < bp) {
+            average = bp;
+          }
+        }
+      }
+      blackPoints[y * subWidth + x] = average;
+    }
+  }
+  return blackPoints;
+}
+
+
+// file: zxing/common/IllegalArgumentException.cpp
+
+/*
+ *  IllegalArgumentException.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 06/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+
+IllegalArgumentException::IllegalArgumentException(const char *msg) :
+    Exception(msg) {
+}
+IllegalArgumentException::~IllegalArgumentException() throw() {
+
+}
+}
+
+// file: zxing/common/PerspectiveTransform.cpp
+
+/*
+ *  PerspectiveTransform.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 12/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/PerspectiveTransform.h>
+
+namespace zxing {
+using namespace std;
+
+PerspectiveTransform::PerspectiveTransform(float inA11, float inA21,
+                                           float inA31, float inA12,
+                                           float inA22, float inA32,
+                                           float inA13, float inA23,
+                                           float inA33) :
+  a11(inA11), a12(inA12), a13(inA13), a21(inA21), a22(inA22), a23(inA23),
+  a31(inA31), a32(inA32), a33(inA33) {}
+
+Ref<PerspectiveTransform> PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,
+    float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,
+    float x3p, float y3p) {
+  Ref<PerspectiveTransform> qToS = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
+  Ref<PerspectiveTransform> sToQ =
+    PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
+  return sToQ->times(qToS);
+}
+
+Ref<PerspectiveTransform> PerspectiveTransform::squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2,
+    float y2, float x3, float y3) {
+  float dy2 = y3 - y2;
+  float dy3 = y0 - y1 + y2 - y3;
+  if (dy2 == 0.0f && dy3 == 0.0f) {
+    Ref<PerspectiveTransform> result(new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f,
+                                     0.0f, 1.0f));
+    return result;
+  } else {
+    float dx1 = x1 - x2;
+    float dx2 = x3 - x2;
+    float dx3 = x0 - x1 + x2 - x3;
+    float dy1 = y1 - y2;
+    float denominator = dx1 * dy2 - dx2 * dy1;
+    float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
+    float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
+    Ref<PerspectiveTransform> result(new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0
+                                     + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f));
+    return result;
+  }
+}
+
+Ref<PerspectiveTransform> PerspectiveTransform::quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2,
+    float y2, float x3, float y3) {
+  // Here, the adjoint serves as the inverse:
+  return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3)->buildAdjoint();
+}
+
+Ref<PerspectiveTransform> PerspectiveTransform::buildAdjoint() {
+  // Adjoint is the transpose of the cofactor matrix:
+  Ref<PerspectiveTransform> result(new PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32
+                                   - a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22,
+                                   a13 * a21 - a11 * a23, a11 * a22 - a12 * a21));
+  return result;
+}
+
+Ref<PerspectiveTransform> PerspectiveTransform::times(Ref<PerspectiveTransform> other) {
+  Ref<PerspectiveTransform> result(new PerspectiveTransform(a11 * other->a11 + a21 * other->a12 + a31 * other->a13,
+                                   a11 * other->a21 + a21 * other->a22 + a31 * other->a23, a11 * other->a31 + a21 * other->a32 + a31
+                                   * other->a33, a12 * other->a11 + a22 * other->a12 + a32 * other->a13, a12 * other->a21 + a22
+                                   * other->a22 + a32 * other->a23, a12 * other->a31 + a22 * other->a32 + a32 * other->a33, a13
+                                   * other->a11 + a23 * other->a12 + a33 * other->a13, a13 * other->a21 + a23 * other->a22 + a33
+                                   * other->a23, a13 * other->a31 + a23 * other->a32 + a33 * other->a33));
+  return result;
+}
+
+void PerspectiveTransform::transformPoints(vector<float> &points) {
+  int max = points.size();
+  for (int i = 0; i < max; i += 2) {
+    float x = points[i];
+    float y = points[i + 1];
+    float denominator = a13 * x + a23 * y + a33;
+    points[i] = (a11 * x + a21 * y + a31) / denominator;
+    points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
+  }
+}
+
+ostream& operator<<(ostream& out, const PerspectiveTransform &pt) {
+  out << pt.a11 << ", " << pt.a12 << ", " << pt.a13 << ", \n";
+  out << pt.a21 << ", " << pt.a22 << ", " << pt.a23 << ", \n";
+  out << pt.a31 << ", " << pt.a32 << ", " << pt.a33 << "\n";
+  return out;
+}
+
+}
+
+// file: zxing/common/Str.cpp
+
+/*
+ *  String.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Str.h>
+
+namespace zxing {
+using namespace std;
+
+String::String(const std::string &text) :
+    text_(text) {
+}
+const std::string& String::getText() const {
+  return text_;
+}
+
+ostream &operator<<(ostream &out, const String &s) {
+  out << s.text_;
+  return out;
+}
+
+}
+
+// file: zxing/common/StringUtils.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+/*
+ * Copyright (C) 2010-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/StringUtils.h>
+// #include <zxing/DecodeHints.h>
+
+using namespace std;
+using namespace zxing;
+using namespace zxing::common;
+
+// N.B.: these are the iconv strings for at least some versions of iconv
+
+char const* const StringUtils::PLATFORM_DEFAULT_ENCODING = "UTF-8";
+char const* const StringUtils::ASCII = "ASCII";
+char const* const StringUtils::SHIFT_JIS = "SHIFT_JIS";
+char const* const StringUtils::GB2312 = "GBK";
+char const* const StringUtils::EUC_JP = "EUC-JP";
+char const* const StringUtils::UTF8 = "UTF-8";
+char const* const StringUtils::ISO88591 = "ISO8859-1";
+const bool StringUtils::ASSUME_SHIFT_JIS = false;
+
+string
+StringUtils::guessEncoding(unsigned char* bytes, int length, Hashtable const& hints) {
+  Hashtable::const_iterator i = hints.find(DecodeHints::CHARACTER_SET);
+  if (i != hints.end()) {
+    return i->second;
+  }
+  // Does it start with the UTF-8 byte order mark? then guess it's UTF-8
+  if (length > 3 &&
+      bytes[0] == (unsigned char) 0xEF &&
+      bytes[1] == (unsigned char) 0xBB &&
+      bytes[2] == (unsigned char) 0xBF) {
+    return UTF8;
+  }
+  // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
+  // which should be by far the most common encodings. ISO-8859-1
+  // should not have bytes in the 0x80 - 0x9F range, while Shift_JIS
+  // uses this as a first byte of a two-byte character. If we see this
+  // followed by a valid second byte in Shift_JIS, assume it is Shift_JIS.
+  // If we see something else in that second byte, we'll make the risky guess
+  // that it's UTF-8.
+  bool canBeISO88591 = true;
+  bool canBeShiftJIS = true;
+  bool canBeUTF8 = true;
+  int utf8BytesLeft = 0;
+  int maybeDoubleByteCount = 0;
+  int maybeSingleByteKatakanaCount = 0;
+  bool sawLatin1Supplement = false;
+  bool sawUTF8Start = false;
+  bool lastWasPossibleDoubleByteStart = false;
+
+  for (int i = 0;
+       i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8);
+       i++) {
+
+    int value = bytes[i] & 0xFF;
+
+    // UTF-8 stuff
+    if (value >= 0x80 && value <= 0xBF) {
+      if (utf8BytesLeft > 0) {
+        utf8BytesLeft--;
+      }
+    } else {
+      if (utf8BytesLeft > 0) {
+        canBeUTF8 = false;
+      }
+      if (value >= 0xC0 && value <= 0xFD) {
+        sawUTF8Start = true;
+        int valueCopy = value;
+        while ((valueCopy & 0x40) != 0) {
+          utf8BytesLeft++;
+          valueCopy <<= 1;
+        }
+      }
+    }
+
+    // ISO-8859-1 stuff
+
+    if ((value == 0xC2 || value == 0xC3) && i < length - 1) {
+      // This is really a poor hack. The slightly more exotic characters people might want to put in
+      // a QR Code, by which I mean the Latin-1 supplement characters (e.g. u-umlaut) have encodings
+      // that start with 0xC2 followed by [0xA0,0xBF], or start with 0xC3 followed by [0x80,0xBF].
+      int nextValue = bytes[i + 1] & 0xFF;
+      if (nextValue <= 0xBF &&
+          ((value == 0xC2 && nextValue >= 0xA0) || (value == 0xC3 && nextValue >= 0x80))) {
+        sawLatin1Supplement = true;
+      }
+    }
+    if (value >= 0x7F && value <= 0x9F) {
+      canBeISO88591 = false;
+    }
+
+    // Shift_JIS stuff
+
+    if (value >= 0xA1 && value <= 0xDF) {
+      // count the number of characters that might be a Shift_JIS single-byte Katakana character
+      if (!lastWasPossibleDoubleByteStart) {
+        maybeSingleByteKatakanaCount++;
+      }
+    }
+    if (!lastWasPossibleDoubleByteStart &&
+        ((value >= 0xF0 && value <= 0xFF) || value == 0x80 || value == 0xA0)) {
+      canBeShiftJIS = false;
+    }
+    if ((value >= 0x81 && value <= 0x9F) || (value >= 0xE0 && value <= 0xEF)) {
+      // These start double-byte characters in Shift_JIS. Let's see if it's followed by a valid
+      // second byte.
+      if (lastWasPossibleDoubleByteStart) {
+        // If we just checked this and the last byte for being a valid double-byte
+        // char, don't check starting on this byte. If this and the last byte
+        // formed a valid pair, then this shouldn't be checked to see if it starts
+        // a double byte pair of course.
+        lastWasPossibleDoubleByteStart = false;
+      } else {
+        // ... otherwise do check to see if this plus the next byte form a valid
+        // double byte pair encoding a character.
+        lastWasPossibleDoubleByteStart = true;
+        if (i >= length - 1) {
+          canBeShiftJIS = false;
+        } else {
+          int nextValue = bytes[i + 1] & 0xFF;
+          if (nextValue < 0x40 || nextValue > 0xFC) {
+            canBeShiftJIS = false;
+          } else {
+            maybeDoubleByteCount++;
+          }
+          // There is some conflicting information out there about which bytes can follow which in
+          // double-byte Shift_JIS characters. The rule above seems to be the one that matches practice.
+        }
+      }
+    } else {
+      lastWasPossibleDoubleByteStart = false;
+    }
+  }
+  if (utf8BytesLeft > 0) {
+    canBeUTF8 = false;
+  }
+
+  // Easy -- if assuming Shift_JIS and no evidence it can't be, done
+  if (canBeShiftJIS && ASSUME_SHIFT_JIS) {
+    return SHIFT_JIS;
+  }
+  if (canBeUTF8 && sawUTF8Start) {
+    return UTF8;
+  }
+  // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough. The crude heuristic is:
+  // - If we saw
+  //   - at least 3 bytes that starts a double-byte value (bytes that are rare in ISO-8859-1), or
+  //   - over 5% of bytes could be single-byte Katakana (also rare in ISO-8859-1),
+  // - and, saw no sequences that are invalid in Shift_JIS, then we conclude Shift_JIS
+  if (canBeShiftJIS && (maybeDoubleByteCount >= 3 || 20 * maybeSingleByteKatakanaCount > length)) {
+    return SHIFT_JIS;
+  }
+  // Otherwise, we default to ISO-8859-1 unless we know it can't be
+  if (!sawLatin1Supplement && canBeISO88591) {
+    return ISO88591;
+  }
+  // Otherwise, we take a wild guess with platform encoding
+  return PLATFORM_DEFAULT_ENCODING;
+}
+
+// file: zxing/common/detector/MonochromeRectangleDetector.cpp
+
+/*
+ *  MonochromeRectangleDetector.cpp
+ *  y_wmk
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 y_wmk authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/NotFoundException.h>
+// #include <zxing/common/detector/MonochromeRectangleDetector.h>
+// #include <sstream>
+
+namespace zxing {
+using namespace std;
+
+std::vector<Ref<ResultPoint> > MonochromeRectangleDetector::detect() {
+    int height = image_->getHeight();
+    int width = image_->getWidth();
+    int halfHeight = height >> 1;
+    int halfWidth = width >> 1;
+    int deltaY = max(1, height / (MAX_MODULES << 3));
+    int deltaX = max(1, width / (MAX_MODULES << 3));
+
+    int top = 0;
+    int bottom = height;
+    int left = 0;
+    int right = width;
+    Ref<ResultPoint> pointA(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, -deltaY, top, bottom, halfWidth >> 1));
+    top = (int) pointA->getY() - 1;;
+    Ref<ResultPoint> pointB(findCornerFromCenter(halfWidth, -deltaX, left, right,
+        halfHeight, 0, top, bottom, halfHeight >> 1));
+    left = (int) pointB->getX() - 1;
+    Ref<ResultPoint> pointC(findCornerFromCenter(halfWidth, deltaX, left, right,
+        halfHeight, 0, top, bottom, halfHeight >> 1));
+    right = (int) pointC->getX() + 1;
+    Ref<ResultPoint> pointD(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, deltaY, top, bottom, halfWidth >> 1));
+    bottom = (int) pointD->getY() + 1;
+
+    // Go try to find point A again with better information -- might have been off at first.
+    pointA.reset(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, -deltaY, top, bottom, halfWidth >> 2));
+
+	  std::vector<Ref<ResultPoint> > corners(4);
+  	corners[0].reset(pointA);
+  	corners[1].reset(pointB);
+  	corners[2].reset(pointC);
+  	corners[3].reset(pointD);
+    return corners;
+  }
+
+Ref<ResultPoint> MonochromeRectangleDetector::findCornerFromCenter(int centerX, int deltaX, int left, int right,
+      int centerY, int deltaY, int top, int bottom, int maxWhiteRun) {
+	  Ref<TwoInts> lastRange(NULL);
+    for (int y = centerY, x = centerX;
+         y < bottom && y >= top && x < right && x >= left;
+         y += deltaY, x += deltaX) {
+      Ref<TwoInts> range(NULL);
+      if (deltaX == 0) {
+        // horizontal slices, up and down
+        range = blackWhiteRange(y, maxWhiteRun, left, right, true);
+      } else {
+        // vertical slices, left and right
+        range = blackWhiteRange(x, maxWhiteRun, top, bottom, false);
+      }
+      if (range == NULL) {
+        if (lastRange == NULL) {
+			    throw NotFoundException("Couldn't find corners (lastRange = NULL) ");
+        } else {
+        // lastRange was found
+        if (deltaX == 0) {
+          int lastY = y - deltaY;
+          if (lastRange->start < centerX) {
+            if (lastRange->end > centerX) {
+              // straddle, choose one or the other based on direction
+			        Ref<ResultPoint> result(new ResultPoint(deltaY > 0 ? lastRange->start : lastRange->end, lastY));
+			        return result;
+            }
+			      Ref<ResultPoint> result(new ResultPoint(lastRange->start, lastY));
+			      return result;
+          } else {
+			      Ref<ResultPoint> result(new ResultPoint(lastRange->end, lastY));
+			      return result;
+            }
+        } else {
+          int lastX = x - deltaX;
+          if (lastRange->start < centerY) {
+            if (lastRange->end > centerY) {
+			        Ref<ResultPoint> result(new ResultPoint(lastX, deltaX < 0 ? lastRange->start : lastRange->end));
+			        return result;
+            }
+			      Ref<ResultPoint> result(new ResultPoint(lastX, lastRange->start));
+			      return result;
+          } else {
+			      Ref<ResultPoint> result(new ResultPoint(lastX, lastRange->end));
+			      return result;
+            }
+          }
+        }
+      }
+      lastRange = range;
+    }
+    throw NotFoundException("Couldn't find corners");
+  }
+
+Ref<TwoInts> MonochromeRectangleDetector::blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
+      bool horizontal) {
+
+	  int center = (minDim + maxDim) >> 1;
+
+    // Scan left/up first
+    int start = center;
+    while (start >= minDim) {
+      if (horizontal ? image_->get(start, fixedDimension) : image_->get(fixedDimension, start)) {
+        start--;
+      } else {
+        int whiteRunStart = start;
+        do {
+          start--;
+        } while (start >= minDim && !(horizontal ? image_->get(start, fixedDimension) :
+            image_->get(fixedDimension, start)));
+        int whiteRunSize = whiteRunStart - start;
+        if (start < minDim || whiteRunSize > maxWhiteRun) {
+          start = whiteRunStart;
+          break;
+        }
+      }
+    }
+    start++;
+
+    // Then try right/down
+    int end = center;
+    while (end < maxDim) {
+      if (horizontal ? image_->get(end, fixedDimension) : image_->get(fixedDimension, end)) {
+        end++;
+      } else {
+        int whiteRunStart = end;
+        do {
+          end++;
+        } while (end < maxDim && !(horizontal ? image_->get(end, fixedDimension) :
+            image_->get(fixedDimension, end)));
+        int whiteRunSize = end - whiteRunStart;
+        if (end >= maxDim || whiteRunSize > maxWhiteRun) {
+          end = whiteRunStart;
+          break;
+        }
+      }
+    }
+    end--;
+    Ref<TwoInts> result(NULL);
+    if (end > start) {
+		  result = new TwoInts;
+      result->start = start;
+      result->end = end;
+    }
+    return result;
+  }
+}
+
+// file: zxing/common/detector/WhiteRectangleDetector.cpp
+
+/*
+ *  WhiteRectangleDetector.cpp
+ *  y_wmk
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 y_wmk authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/NotFoundException.h>
+// #include <zxing/common/detector/WhiteRectangleDetector.h>
+// #include <math.h>
+// #include <sstream>
+
+namespace zxing {
+using namespace std;
+
+int WhiteRectangleDetector::INIT_SIZE = 30;
+int WhiteRectangleDetector::CORR = 1;
+
+
+WhiteRectangleDetector::WhiteRectangleDetector(Ref<BitMatrix> image) : image_(image) {
+  width_ = image->getWidth();
+  height_ = image->getHeight();
+}
+
+/**
+ * <p>
+ * Detects a candidate barcode-like rectangular region within an image. It
+ * starts around the center of the image, increases the size of the candidate
+ * region until it finds a white rectangular region.
+ * </p>
+ *
+ * @return {@link vector<Ref<ResultPoint> >} describing the corners of the rectangular
+ *         region. The first and last points are opposed on the diagonal, as
+ *         are the second and third. The first point will be the topmost
+ *         point and the last, the bottommost. The second point will be
+ *         leftmost and the third, the rightmost
+ * @throws NotFoundException if no Data Matrix Code can be found
+*/
+std::vector<Ref<ResultPoint> > WhiteRectangleDetector::detect() {
+  int left = (width_ - INIT_SIZE) >> 1;
+  int right = (width_ + INIT_SIZE) >> 1;
+  int up = (height_ - INIT_SIZE) >> 1;
+  int down = (height_ + INIT_SIZE) >> 1;
+  if (up < 0 || left < 0 || down >= height_ || right >= width_) {
+    throw NotFoundException("Invalid dimensions WhiteRectangleDetector");
+  }
+
+  bool sizeExceeded = false;
+  bool aBlackPointFoundOnBorder = true;
+  bool atLeastOneBlackPointFoundOnBorder = false;
+
+  while (aBlackPointFoundOnBorder) {
+    aBlackPointFoundOnBorder = false;
+
+    // .....
+    // .   |
+    // .....
+    bool rightBorderNotWhite = true;
+    while (rightBorderNotWhite && right < width_) {
+      rightBorderNotWhite = containsBlackPoint(up, down, right, false);
+      if (rightBorderNotWhite) {
+        right++;
+        aBlackPointFoundOnBorder = true;
+      }
+    }
+
+    if (right >= width_) {
+      sizeExceeded = true;
+      break;
+    }
+
+    // .....
+    // .   .
+    // .___.
+    bool bottomBorderNotWhite = true;
+    while (bottomBorderNotWhite && down < height_) {
+      bottomBorderNotWhite = containsBlackPoint(left, right, down, true);
+      if (bottomBorderNotWhite) {
+        down++;
+        aBlackPointFoundOnBorder = true;
+      }
+    }
+
+    if (down >= height_) {
+      sizeExceeded = true;
+      break;
+    }
+
+    // .....
+    // |   .
+    // .....
+    bool leftBorderNotWhite = true;
+    while (leftBorderNotWhite && left >= 0) {
+      leftBorderNotWhite = containsBlackPoint(up, down, left, false);
+      if (leftBorderNotWhite) {
+        left--;
+        aBlackPointFoundOnBorder = true;
+      }
+    }
+
+    if (left < 0) {
+      sizeExceeded = true;
+      break;
+    }
+
+    // .___.
+    // .   .
+    // .....
+    bool topBorderNotWhite = true;
+    while (topBorderNotWhite && up >= 0) {
+      topBorderNotWhite = containsBlackPoint(left, right, up, true);
+      if (topBorderNotWhite) {
+        up--;
+        aBlackPointFoundOnBorder = true;
+      }
+    }
+
+    if (up < 0) {
+      sizeExceeded = true;
+      break;
+    }
+
+    if (aBlackPointFoundOnBorder) {
+      atLeastOneBlackPointFoundOnBorder = true;
+    }
+
+  }
+  if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {
+
+    int maxSize = right - left;
+
+    Ref<ResultPoint> z(NULL);
+    //go up right
+    for (int i = 1; i < maxSize; i++) {
+      z = getBlackPointOnSegment(left, down - i, left + i, down);
+      if (z != NULL) {
+        break;
+      }
+    }
+
+    if (z == NULL) {
+      throw NotFoundException("z == NULL");
+    }
+
+    Ref<ResultPoint> t(NULL);
+    //go down right
+    for (int i = 1; i < maxSize; i++) {
+      t = getBlackPointOnSegment(left, up + i, left + i, up);
+      if (t != NULL) {
+        break;
+      }
+    }
+
+    if (t == NULL) {
+      throw NotFoundException("t == NULL");
+    }
+
+    Ref<ResultPoint> x(NULL);
+    //go down left
+    for (int i = 1; i < maxSize; i++) {
+      x = getBlackPointOnSegment(right, up + i, right - i, up);
+      if (x != NULL) {
+        break;
+      }
+    }
+
+    if (x == NULL) {
+      throw NotFoundException("x == NULL");
+    }
+
+    Ref<ResultPoint> y(NULL);
+    //go up left
+    for (int i = 1; i < maxSize; i++) {
+      y = getBlackPointOnSegment(right, down - i, right - i, down);
+      if (y != NULL) {
+        break;
+      }
+    }
+
+    if (y == NULL) {
+      throw NotFoundException("y == NULL");
+    }
+
+    return centerEdges(y, z, x, t);
+
+  } else {
+    throw NotFoundException("No black point found on border");
+  }
+}
+
+/**
+ * Ends up being a bit faster than Math.round(). This merely rounds its
+ * argument to the nearest int, where x.5 rounds up.
+ */
+int WhiteRectangleDetector::round(float d) {
+  return (int) (d + 0.5f);
+}
+
+Ref<ResultPoint> WhiteRectangleDetector::getBlackPointOnSegment(float aX, float aY, float bX, float bY) {
+  int dist = distanceL2(aX, aY, bX, bY);
+  float xStep = (bX - aX) / dist;
+  float yStep = (bY - aY) / dist;
+  for (int i = 0; i < dist; i++) {
+    int x = round(aX + i * xStep);
+    int y = round(aY + i * yStep);
+    if (image_->get(x, y)) {
+      Ref<ResultPoint> point(new ResultPoint(x, y));
+      return point;
+    }
+  }
+  Ref<ResultPoint> point(NULL);
+  return point;
+}
+
+int WhiteRectangleDetector::distanceL2(float aX, float aY, float bX, float bY) {
+  float xDiff = aX - bX;
+  float yDiff = aY - bY;
+  return round((float)sqrt(xDiff * xDiff + yDiff * yDiff));
+}
+
+/**
+ * recenters the points of a constant distance towards the center
+ *
+ * @param y bottom most point
+ * @param z left most point
+ * @param x right most point
+ * @param t top most point
+ * @return {@link vector<Ref<ResultPoint> >} describing the corners of the rectangular
+ *         region. The first and last points are opposed on the diagonal, as
+ *         are the second and third. The first point will be the topmost
+ *         point and the last, the bottommost. The second point will be
+ *         leftmost and the third, the rightmost
+ */
+vector<Ref<ResultPoint> > WhiteRectangleDetector::centerEdges(Ref<ResultPoint> y, Ref<ResultPoint> z,
+                                  Ref<ResultPoint> x, Ref<ResultPoint> t) {
+
+  //
+  //       t            t
+  //  z                      x
+  //        x    OR    z
+  //   y                    y
+  //
+
+  float yi = y->getX();
+  float yj = y->getY();
+  float zi = z->getX();
+  float zj = z->getY();
+  float xi = x->getX();
+  float xj = x->getY();
+  float ti = t->getX();
+  float tj = t->getY();
+
+  std::vector<Ref<ResultPoint> > corners(4);
+  if (yi < (float)width_/2) {
+    Ref<ResultPoint> pointA(new ResultPoint(ti - CORR, tj + CORR));
+    Ref<ResultPoint> pointB(new ResultPoint(zi + CORR, zj + CORR));
+    Ref<ResultPoint> pointC(new ResultPoint(xi - CORR, xj - CORR));
+    Ref<ResultPoint> pointD(new ResultPoint(yi + CORR, yj - CORR));
+	  corners[0].reset(pointA);
+	  corners[1].reset(pointB);
+	  corners[2].reset(pointC);
+	  corners[3].reset(pointD);
+  } else {
+    Ref<ResultPoint> pointA(new ResultPoint(ti + CORR, tj + CORR));
+    Ref<ResultPoint> pointB(new ResultPoint(zi + CORR, zj - CORR));
+    Ref<ResultPoint> pointC(new ResultPoint(xi - CORR, xj + CORR));
+    Ref<ResultPoint> pointD(new ResultPoint(yi - CORR, yj - CORR));
+	  corners[0].reset(pointA);
+	  corners[1].reset(pointB);
+	  corners[2].reset(pointC);
+	  corners[3].reset(pointD);
+  }
+  return corners;
+}
+
+/**
+ * Determines whether a segment contains a black point
+ *
+ * @param a          min value of the scanned coordinate
+ * @param b          max value of the scanned coordinate
+ * @param fixed      value of fixed coordinate
+ * @param horizontal set to true if scan must be horizontal, false if vertical
+ * @return true if a black point has been found, else false.
+ */
+bool WhiteRectangleDetector::containsBlackPoint(int a, int b, int fixed, bool horizontal) {
+  if (horizontal) {
+    for (int x = a; x <= b; x++) {
+      if (image_->get(x, fixed)) {
+        return true;
+      }
+    }
+  } else {
+    for (int y = a; y <= b; y++) {
+      if (image_->get(fixed, y)) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+}
+
+// file: zxing/common/reedsolomon/GF256.cpp
+
+/*
+ *  GF256.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 05/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <iostream>
+// #include <zxing/common/reedsolomon/GF256.h>
+// #include <zxing/common/reedsolomon/GF256Poly.h>
+// #include <zxing/common/IllegalArgumentException.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+using namespace std;
+
+static inline ArrayRef<int> makeArray(int value) {
+  ArrayRef<int> valuesRef(new Array<int> (value, 1));
+  return valuesRef;
+}
+
+static inline Ref<GF256Poly> refPoly(GF256 &field, int value) {
+  ArrayRef<int> values(makeArray(value));
+  Ref<GF256Poly> result(new GF256Poly(field, values));
+  return result;
+}
+
+GF256::GF256(int primitive) :
+    exp_(256, (const int)0), log_(256, (const int)0), zero_(refPoly(*this, 0)), one_(refPoly(*this, 1)) {
+  int x = 1;
+  for (int i = 0; i < 256; i++) {
+    exp_[i] = x;
+    x <<= 1;
+    if (x >= 0x100) {
+      x ^= primitive;
+    }
+  }
+
+  // log(0) == 0, but should never be used
+  log_[0] = 0;
+  for (int i = 0; i < 255; i++) {
+    log_[exp_[i]] = i;
+  }
+}
+
+Ref<GF256Poly> GF256::getZero() {
+  return zero_;
+}
+
+Ref<GF256Poly> GF256::getOne() {
+  return one_;
+}
+
+Ref<GF256Poly> GF256::buildMonomial(int degree, int coefficient) {
+#ifdef DEBUG
+  cout << __FUNCTION__ << "\n";
+#endif
+  if (degree < 0) {
+    throw IllegalArgumentException("Degree must be non-negative");
+  }
+  if (coefficient == 0) {
+    return zero_;
+  }
+  int nCoefficients = degree + 1;
+  ArrayRef<int> coefficients(new Array<int> (nCoefficients));
+  coefficients[0] = coefficient;
+  Ref<GF256Poly> result(new GF256Poly(*this, coefficients));
+  return result;
+}
+
+int GF256::addOrSubtract(int a, int b) {
+  return a ^ b;
+}
+
+int GF256::exp(int a) {
+  return exp_[a];
+}
+
+int GF256::log(int a) {
+  if (a == 0) {
+    throw IllegalArgumentException("Cannot take the logarithm of 0");
+  }
+  return log_[a];
+}
+
+int GF256::inverse(int a) {
+  if (a == 0) {
+    throw IllegalArgumentException("Cannot calculate the inverse of 0");
+  }
+  return exp_[255 - log_[a]];
+}
+
+int GF256::multiply(int a, int b) {
+  if (a == 0 || b == 0) {
+    return 0;
+  }
+  int logSum = log_[a] + log_[b];
+  // index is a sped-up alternative to logSum % 255 since sum
+  // is in [0,510]. Thanks to jmsachs for the idea
+  return exp_[(logSum & 0xFF) + (logSum >> 8)];
+}
+
+GF256 GF256::QR_CODE_FIELD(0x011D); // x^8 + x^4 + x^3 + x^2 + 1
+GF256 GF256::DATA_MATRIX_FIELD(0x012D); // x^8 + x^5 + x^3 + x^2 + 1
+
+ostream& operator<<(ostream& out, const GF256& field) {
+  out << "Field[\nexp=(";
+  out << field.exp_[0];
+  for (int i = 1; i < 256; i++) {
+    out << "," << field.exp_[i];
+  }
+  out << "),\nlog=(";
+  out << field.log_[0];
+  for (int i = 1; i < 256; i++) {
+    out << "," << field.log_[i];
+  }
+  out << ")\n]";
+  return out;
+}
+
+}
+
+// file: zxing/common/reedsolomon/GF256Poly.cpp
+
+/*
+ *  GF256Poly.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 05/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <iostream>
+// #include <sstream>
+// #include <zxing/common/reedsolomon/GF256Poly.h>
+// #include <zxing/common/reedsolomon/GF256.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+using namespace std;
+
+void GF256Poly::fixCoefficients() {
+  int coefficientsLength = coefficients.size();
+  if (coefficientsLength > 1 && coefficients[0] == 0) {
+    // Leading term must be non-zero for anything except
+    // the constant polynomial "0"
+    int firstNonZero = 1;
+    while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) {
+      firstNonZero++;
+    }
+    if (firstNonZero == coefficientsLength) {
+      coefficientsLength = field.getZero()->coefficients.size();
+      coefficients.reset(new Array<int> (coefficientsLength));
+      *coefficients = *(field.getZero()->coefficients);
+    } else {
+      ArrayRef<int> c(coefficients);
+      coefficientsLength -= firstNonZero;
+      coefficients.reset(new Array<int> (coefficientsLength));
+      for (int i = 0; i < coefficientsLength; i++) {
+        coefficients[i] = c[i + firstNonZero];
+      }
+    }
+  }
+}
+
+GF256Poly::GF256Poly(GF256 &f, ArrayRef<int> c) :
+    Counted(), field(f), coefficients(c) {
+  fixCoefficients();
+}
+
+GF256Poly::~GF256Poly() {
+
+}
+
+int GF256Poly::getDegree() {
+  return coefficients.size() - 1;
+}
+
+bool GF256Poly::isZero() {
+  return coefficients[0] == 0;
+}
+
+int GF256Poly::getCoefficient(int degree) {
+  return coefficients[coefficients.size() - 1 - degree];
+}
+
+int GF256Poly::evaluateAt(int a) {
+  if (a == 0) {
+    return getCoefficient(0);
+  }
+  int size = coefficients.size();
+  if (a == 1) {
+    // Just the sum of the coefficients
+    int result = 0;
+    for (int i = 0; i < size; i++) {
+      result = GF256::addOrSubtract(result, coefficients[i]);
+    }
+    return result;
+  }
+  int result = coefficients[0];
+  for (int i = 1; i < size; i++) {
+    result = GF256::addOrSubtract(field.multiply(a, result), coefficients[i]);
+  }
+  return result;
+}
+
+Ref<GF256Poly> GF256Poly::addOrSubtract(Ref<GF256Poly> b) {
+  if (&field != &b->field) {
+    throw IllegalArgumentException("Fields must be the same");
+  }
+  if (isZero()) {
+    return b;
+  }
+  if (b->isZero()) {
+    return Ref<GF256Poly>(this);
+  }
+
+  ArrayRef<int> largerCoefficients = coefficients;
+  ArrayRef<int> smallerCoefficients = b->coefficients;
+  if (smallerCoefficients.size() > largerCoefficients.size()) {
+    ArrayRef<int> tmp(smallerCoefficients);
+    smallerCoefficients = largerCoefficients;
+    largerCoefficients = tmp;
+  }
+
+  ArrayRef<int> sumDiff(new Array<int> (largerCoefficients.size()));
+
+  unsigned lengthDiff = largerCoefficients.size() - smallerCoefficients.size();
+  for (unsigned i = 0; i < lengthDiff; i++) {
+    sumDiff[i] = largerCoefficients[i];
+  }
+  for (unsigned i = lengthDiff; i < largerCoefficients.size(); i++) {
+    sumDiff[i] = GF256::addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
+  }
+  return Ref<GF256Poly>(new GF256Poly(field, sumDiff));
+}
+
+Ref<GF256Poly> GF256Poly::multiply(Ref<GF256Poly> b) {
+  if (&field != &b->field) {
+    throw IllegalArgumentException("Fields must be the same");
+  }
+  if (isZero() || b->isZero()) {
+    return field.getZero();
+  }
+  ArrayRef<int> aCoefficients = coefficients;
+  int aLength = aCoefficients.size();
+  ArrayRef<int> bCoefficients = b->coefficients;
+  int bLength = bCoefficients.size();
+  int productLength = aLength + bLength - 1;
+  ArrayRef<int> product(new Array<int> (productLength));
+  for (int i = 0; i < aLength; i++) {
+    int aCoeff = aCoefficients[i];
+    for (int j = 0; j < bLength; j++) {
+      product[i + j] = GF256::addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));
+    }
+  }
+
+  return Ref<GF256Poly>(new GF256Poly(field, product));
+}
+
+Ref<GF256Poly> GF256Poly::multiply(int scalar) {
+  if (scalar == 0) {
+    return field.getZero();
+  }
+  if (scalar == 1) {
+    return Ref<GF256Poly>(this);
+  }
+  int size = coefficients.size();
+  ArrayRef<int> product(new Array<int> (size));
+  for (int i = 0; i < size; i++) {
+    product[i] = field.multiply(coefficients[i], scalar);
+  }
+  return Ref<GF256Poly>(new GF256Poly(field, product));
+}
+
+Ref<GF256Poly> GF256Poly::multiplyByMonomial(int degree, int coefficient) {
+  if (degree < 0) {
+    throw IllegalArgumentException("Degree must be non-negative");
+  }
+  if (coefficient == 0) {
+    return field.getZero();
+  }
+  int size = coefficients.size();
+  ArrayRef<int> product(new Array<int> (size + degree));
+  for (int i = 0; i < size; i++) {
+    product[i] = field.multiply(coefficients[i], coefficient);
+  }
+  return Ref<GF256Poly>(new GF256Poly(field, product));
+}
+
+const char *GF256Poly::description() const {
+  ostringstream result;
+  result << *this;
+  return result.str().c_str();
+}
+
+ostream& operator<<(ostream& out, const GF256Poly& p) {
+  GF256Poly &poly = const_cast<GF256Poly&>(p);
+  out << "Poly[" << poly.coefficients.size() << "]";
+  if (poly.coefficients.size() > 0) {
+    out << "(" << poly.coefficients[0];
+    for (unsigned i = 1; i < poly.coefficients.size(); i++) {
+      out << "," << poly.coefficients[i];
+    }
+    out << ")";
+  }
+  return out;
+}
+
+}
+
+// file: zxing/common/reedsolomon/ReedSolomonDecoder.cpp
+
+/*
+ *  ReedSolomonDecoder.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 05/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <iostream>
+
+// #include <memory>
+// #include <zxing/common/reedsolomon/ReedSolomonDecoder.h>
+// #include <zxing/common/reedsolomon/GF256.h>
+// #include <zxing/common/reedsolomon/GF256Poly.h>
+// #include <zxing/common/reedsolomon/ReedSolomonException.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+using namespace std;
+
+namespace zxing {
+
+ReedSolomonDecoder::ReedSolomonDecoder(GF256 &fld) :
+    field(fld) {
+}
+
+ReedSolomonDecoder::~ReedSolomonDecoder() {
+}
+
+void ReedSolomonDecoder::decode(ArrayRef<int> received, int twoS) {
+
+  Ref<GF256Poly> poly(new GF256Poly(field, received));
+
+
+#ifdef DEBUG
+  cout << "decoding with poly " << *poly << "\n";
+#endif
+
+  ArrayRef<int> syndromeCoefficients(new Array<int> (twoS));
+
+
+#ifdef DEBUG
+  cout << "syndromeCoefficients array = " <<
+       syndromeCoefficients.array_ << "\n";
+#endif
+
+  bool dataMatrix = (&field == &GF256::DATA_MATRIX_FIELD);
+  bool noError = true;
+  for (int i = 0; i < twoS; i++) {
+    int eval = poly->evaluateAt(field.exp(dataMatrix ? i + 1 : i));
+    syndromeCoefficients[syndromeCoefficients->size() - 1 - i] = eval;
+    if (eval != 0) {
+      noError = false;
+    }
+  }
+  if (noError) {
+    return;
+  }
+
+  Ref<GF256Poly> syndrome(new GF256Poly(field, syndromeCoefficients));
+  Ref<GF256Poly> monomial(field.buildMonomial(twoS, 1));
+  vector<Ref<GF256Poly> > sigmaOmega(runEuclideanAlgorithm(monomial, syndrome, twoS));
+  ArrayRef<int> errorLocations = findErrorLocations(sigmaOmega[0]);
+  ArrayRef<int> errorMagitudes = findErrorMagnitudes(sigmaOmega[1], errorLocations, dataMatrix);
+  for (unsigned i = 0; i < errorLocations->size(); i++) {
+    int position = received->size() - 1 - field.log(errorLocations[i]);
+    //TODO: check why the position would be invalid
+    if (position < 0 || (size_t)position >= received.size())
+      throw IllegalArgumentException("Invalid position (ReedSolomonDecoder)");
+    received[position] = GF256::addOrSubtract(received[position], errorMagitudes[i]);
+  }
+}
+
+vector<Ref<GF256Poly> > ReedSolomonDecoder::runEuclideanAlgorithm(Ref<GF256Poly> a, Ref<GF256Poly> b, int R) {
+  // Assume a's degree is >= b's
+  if (a->getDegree() < b->getDegree()) {
+    Ref<GF256Poly> tmp = a;
+    a = b;
+    b = tmp;
+  }
+
+  Ref<GF256Poly> rLast(a);
+  Ref<GF256Poly> r(b);
+  Ref<GF256Poly> sLast(field.getOne());
+  Ref<GF256Poly> s(field.getZero());
+  Ref<GF256Poly> tLast(field.getZero());
+  Ref<GF256Poly> t(field.getOne());
+
+
+  // Run Euclidean algorithm until r's degree is less than R/2
+  while (r->getDegree() >= R / 2) {
+    Ref<GF256Poly> rLastLast(rLast);
+    Ref<GF256Poly> sLastLast(sLast);
+    Ref<GF256Poly> tLastLast(tLast);
+    rLast = r;
+    sLast = s;
+    tLast = t;
+
+
+    // Divide rLastLast by rLast, with quotient q and remainder r
+    if (rLast->isZero()) {
+      // Oops, Euclidean algorithm already terminated?
+      throw ReedSolomonException("r_{i-1} was zero");
+    }
+    r = rLastLast;
+    Ref<GF256Poly> q(field.getZero());
+    int denominatorLeadingTerm = rLast->getCoefficient(rLast->getDegree());
+    int dltInverse = field.inverse(denominatorLeadingTerm);
+    while (r->getDegree() >= rLast->getDegree() && !r->isZero()) {
+      int degreeDiff = r->getDegree() - rLast->getDegree();
+      int scale = field.multiply(r->getCoefficient(r->getDegree()), dltInverse);
+      q = q->addOrSubtract(field.buildMonomial(degreeDiff, scale));
+      r = r->addOrSubtract(rLast->multiplyByMonomial(degreeDiff, scale));
+    }
+
+    s = q->multiply(sLast)->addOrSubtract(sLastLast);
+    t = q->multiply(tLast)->addOrSubtract(tLastLast);
+  }
+
+  int sigmaTildeAtZero = t->getCoefficient(0);
+  if (sigmaTildeAtZero == 0) {
+    throw ReedSolomonException("sigmaTilde(0) was zero");
+  }
+
+  int inverse = field.inverse(sigmaTildeAtZero);
+  Ref<GF256Poly> sigma(t->multiply(inverse));
+  Ref<GF256Poly> omega(r->multiply(inverse));
+
+
+#ifdef DEBUG
+  cout << "t = " << *t << "\n";
+  cout << "r = " << *r << "\n";
+  cout << "sigma = " << *sigma << "\n";
+  cout << "omega = " << *omega << "\n";
+#endif
+
+  vector<Ref<GF256Poly> > result(2);
+  result[0] = sigma;
+  result[1] = omega;
+  return result;
+}
+
+ArrayRef<int> ReedSolomonDecoder::findErrorLocations(Ref<GF256Poly> errorLocator) {
+  // This is a direct application of Chien's search
+  int numErrors = errorLocator->getDegree();
+  if (numErrors == 1) { // shortcut
+    ArrayRef<int> result(1);
+    result[0] = errorLocator->getCoefficient(1);
+    return result;
+  }
+  ArrayRef<int> result(numErrors);
+  int e = 0;
+  for (int i = 1; i < 256 && e < numErrors; i++) {
+    // cout << "errorLocator(" << i << ") == " << errorLocator->evaluateAt(i) << "\n";
+    if (errorLocator->evaluateAt(i) == 0) {
+      result[e] = field.inverse(i);
+      e++;
+    }
+  }
+  if (e != numErrors) {
+    throw ReedSolomonException("Error locator degree does not match number of roots");
+  }
+  return result;
+}
+
+ArrayRef<int> ReedSolomonDecoder::findErrorMagnitudes(Ref<GF256Poly> errorEvaluator, ArrayRef<int> errorLocations, bool dataMatrix) {
+  // This is directly applying Forney's Formula
+  int s = errorLocations.size();
+  ArrayRef<int> result(s);
+  for (int i = 0; i < s; i++) {
+    int xiInverse = field.inverse(errorLocations[i]);
+    int denominator = 1;
+    for (int j = 0; j < s; j++) {
+      if (i != j) {
+        denominator = field.multiply(denominator, GF256::addOrSubtract(1, field.multiply(errorLocations[j],
+                                     xiInverse)));
+      }
+    }
+    result[i] = field.multiply(errorEvaluator->evaluateAt(xiInverse), field.inverse(denominator));
+
+    if (dataMatrix) {
+      result[i] = field.multiply(result[i], xiInverse);
+	}
+  }
+  return result;
+}
+}
+
+// file: zxing/common/reedsolomon/ReedSolomonException.cpp
+
+/*
+ *  ReedSolomonException.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 06/05/2008.
+ *  Copyright 2008 Google UK. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/reedsolomon/ReedSolomonException.h>
+
+namespace zxing {
+ReedSolomonException::ReedSolomonException(const char *msg) throw() :
+    Exception(msg) {
+}
+ReedSolomonException::~ReedSolomonException() throw() {
+}
+
+}
+
+// file: zxing/datamatrix/DataMatrixReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  DataMatrixReader.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/DataMatrixReader.h>
+// #include <zxing/datamatrix/detector/Detector.h>
+// #include <iostream>
+
+namespace zxing {
+namespace datamatrix {
+
+using namespace std;
+
+DataMatrixReader::DataMatrixReader() :
+    decoder_() {
+}
+
+Ref<Result> DataMatrixReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+  (void)hints;
+#ifdef DEBUG
+  cout << "decoding image " << image.object_ << ":\n" << flush;
+#endif
+
+  Detector detector(image->getBlackMatrix());
+
+
+#ifdef DEBUG
+  cout << "(1) created detector " << &detector << "\n" << flush;
+#endif
+
+  Ref<DetectorResult> detectorResult(detector.detect());
+#ifdef DEBUG
+  cout << "(2) detected, have detectorResult " << detectorResult.object_ << "\n" << flush;
+#endif
+
+  std::vector<Ref<ResultPoint> > points(detectorResult->getPoints());
+
+
+#ifdef DEBUG
+  cout << "(3) extracted points " << &points << "\n" << flush;
+  cout << "found " << points.size() << " points:\n";
+  for (size_t i = 0; i < points.size(); i++) {
+    cout << "   " << points[i]->getX() << "," << points[i]->getY() << "\n";
+  }
+  cout << "bits:\n";
+  cout << *(detectorResult->getBits()) << "\n";
+#endif
+
+  Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult->getBits()));
+#ifdef DEBUG
+  cout << "(4) decoded, have decoderResult " << decoderResult.object_ << "\n" << flush;
+#endif
+
+  Ref<Result> result(
+    new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_DATA_MATRIX));
+#ifdef DEBUG
+  cout << "(5) created result " << result.object_ << ", returning\n" << flush;
+#endif
+
+  return result;
+}
+
+DataMatrixReader::~DataMatrixReader() {
+}
+
+}
+}
+
+// file: zxing/datamatrix/Version.cpp
+
+/*
+ *  Version.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/Version.h>
+// #include <limits>
+// #include <iostream>
+
+namespace zxing {
+namespace datamatrix {
+using namespace std;
+
+ECB::ECB(int count, int dataCodewords) :
+    count_(count), dataCodewords_(dataCodewords) {
+}
+
+int ECB::getCount() {
+  return count_;
+}
+
+int ECB::getDataCodewords() {
+  return dataCodewords_;
+}
+
+ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks) :
+    ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks) {
+}
+
+ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2) :
+    ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks1) {
+  ecBlocks_.push_back(ecBlocks2);
+}
+
+int ECBlocks::getECCodewords() {
+  return ecCodewords_;
+}
+
+std::vector<ECB*>& ECBlocks::getECBlocks() {
+  return ecBlocks_;
+}
+
+ECBlocks::~ECBlocks() {
+  for (size_t i = 0; i < ecBlocks_.size(); i++) {
+    delete ecBlocks_[i];
+  }
+}
+
+vector<Ref<Version> > Version::VERSIONS;
+static int N_VERSIONS = Version::buildVersions();
+
+Version::Version(int versionNumber, int symbolSizeRows, int symbolSizeColumns, int dataRegionSizeRows,
+		int dataRegionSizeColumns, ECBlocks* ecBlocks) : versionNumber_(versionNumber),
+		symbolSizeRows_(symbolSizeRows), symbolSizeColumns_(symbolSizeColumns),
+		dataRegionSizeRows_(dataRegionSizeRows), dataRegionSizeColumns_(dataRegionSizeColumns),
+		ecBlocks_(ecBlocks), totalCodewords_(0) {
+    // Calculate the total number of codewords
+    int total = 0;
+    int ecCodewords = ecBlocks_->getECCodewords();
+    vector<ECB*> &ecbArray = ecBlocks_->getECBlocks();
+    for (unsigned int i = 0; i < ecbArray.size(); i++) {
+      ECB *ecBlock = ecbArray[i];
+      total += ecBlock->getCount() * (ecBlock->getDataCodewords() + ecCodewords);
+    }
+    totalCodewords_ = total;
+}
+
+Version::~Version() {
+    delete ecBlocks_;
+}
+
+int Version::getVersionNumber() {
+  return versionNumber_;
+}
+
+int Version::getSymbolSizeRows() {
+  return symbolSizeRows_;
+}
+
+int Version::getSymbolSizeColumns() {
+  return symbolSizeColumns_;
+}
+
+int Version::getDataRegionSizeRows() {
+  return dataRegionSizeRows_;
+}
+
+int Version::getDataRegionSizeColumns() {
+  return dataRegionSizeColumns_;
+}
+
+int Version::getTotalCodewords() {
+  return totalCodewords_;
+}
+
+ECBlocks* Version::getECBlocks() {
+  return ecBlocks_;
+}
+
+Ref<Version> Version::getVersionForDimensions(int numRows, int numColumns) {
+    if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) {
+      throw ReaderException("Number of rows and columns must be even");
+    }
+
+    // TODO(bbrown): This is doing a linear search through the array of versions.
+    // If we interleave the rectangular versions with the square versions we could
+    // do a binary search.
+    for (int i = 0; i < N_VERSIONS; ++i){
+      Ref<Version> version(VERSIONS[i]);
+      if (version->getSymbolSizeRows() == numRows && version->getSymbolSizeColumns() == numColumns) {
+        return version;
+      }
+    }
+    throw ReaderException("Error version not found");
+  }
+
+/**
+ * See ISO 16022:2006 5.5.1 Table 7
+ */
+int Version::buildVersions() {
+  VERSIONS.push_back(Ref<Version>(new Version(1, 10, 10, 8, 8,
+            					  new ECBlocks(5, new ECB(1, 3)))));
+  VERSIONS.push_back(Ref<Version>(new Version(2, 12, 12, 10, 10,
+            					  new ECBlocks(7, new ECB(1, 5)))));
+  VERSIONS.push_back(Ref<Version>(new Version(3, 14, 14, 12, 12,
+            					  new ECBlocks(10, new ECB(1, 8)))));
+  VERSIONS.push_back(Ref<Version>(new Version(4, 16, 16, 14, 14,
+            					  new ECBlocks(12, new ECB(1, 12)))));
+  VERSIONS.push_back(Ref<Version>(new Version(5, 18, 18, 16, 16,
+            					  new ECBlocks(14, new ECB(1, 18)))));
+  VERSIONS.push_back(Ref<Version>(new Version(6, 20, 20, 18, 18,
+            					  new ECBlocks(18, new ECB(1, 22)))));
+  VERSIONS.push_back(Ref<Version>(new Version(7, 22, 22, 20, 20,
+            					  new ECBlocks(20, new ECB(1, 30)))));
+  VERSIONS.push_back(Ref<Version>(new Version(8, 24, 24, 22, 22,
+            					  new ECBlocks(24, new ECB(1, 36)))));
+  VERSIONS.push_back(Ref<Version>(new Version(9, 26, 26, 24, 24,
+            					  new ECBlocks(28, new ECB(1, 44)))));
+  VERSIONS.push_back(Ref<Version>(new Version(10, 32, 32, 14, 14,
+            					  new ECBlocks(36, new ECB(1, 62)))));
+  VERSIONS.push_back(Ref<Version>(new Version(11, 36, 36, 16, 16,
+            					  new ECBlocks(42, new ECB(1, 86)))));
+  VERSIONS.push_back(Ref<Version>(new Version(12, 40, 40, 18, 18,
+            					  new ECBlocks(48, new ECB(1, 114)))));
+  VERSIONS.push_back(Ref<Version>(new Version(13, 44, 44, 20, 20,
+            					  new ECBlocks(56, new ECB(1, 144)))));
+  VERSIONS.push_back(Ref<Version>(new Version(14, 48, 48, 22, 22,
+            					  new ECBlocks(68, new ECB(1, 174)))));
+  VERSIONS.push_back(Ref<Version>(new Version(15, 52, 52, 24, 24,
+            					  new ECBlocks(42, new ECB(2, 102)))));
+  VERSIONS.push_back(Ref<Version>(new Version(16, 64, 64, 14, 14,
+            					  new ECBlocks(56, new ECB(2, 140)))));
+  VERSIONS.push_back(Ref<Version>(new Version(17, 72, 72, 16, 16,
+            					  new ECBlocks(36, new ECB(4, 92)))));
+  VERSIONS.push_back(Ref<Version>(new  Version(18, 80, 80, 18, 18,
+            					  new ECBlocks(48, new ECB(4, 114)))));
+  VERSIONS.push_back(Ref<Version>(new Version(19, 88, 88, 20, 20,
+            					  new ECBlocks(56, new ECB(4, 144)))));
+  VERSIONS.push_back(Ref<Version>(new Version(20, 96, 96, 22, 22,
+            					  new ECBlocks(68, new ECB(4, 174)))));
+  VERSIONS.push_back(Ref<Version>(new Version(21, 104, 104, 24, 24,
+            					  new ECBlocks(56, new ECB(6, 136)))));
+  VERSIONS.push_back(Ref<Version>(new Version(22, 120, 120, 18, 18,
+            					  new ECBlocks(68, new ECB(6, 175)))));
+  VERSIONS.push_back(Ref<Version>(new Version(23, 132, 132, 20, 20,
+            					  new ECBlocks(62, new ECB(8, 163)))));
+  VERSIONS.push_back(Ref<Version>(new Version(24, 144, 144, 22, 22,
+            					  new ECBlocks(62, new ECB(8, 156), new ECB(2, 155)))));
+  VERSIONS.push_back(Ref<Version>(new Version(25, 8, 18, 6, 16,
+            					  new ECBlocks(7, new ECB(1, 5)))));
+  VERSIONS.push_back(Ref<Version>(new Version(26, 8, 32, 6, 14,
+            					  new ECBlocks(11, new ECB(1, 10)))));
+  VERSIONS.push_back(Ref<Version>(new Version(27, 12, 26, 10, 24,
+					              new ECBlocks(14, new ECB(1, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(28, 12, 36, 10, 16,
+					              new ECBlocks(18, new ECB(1, 22)))));
+  VERSIONS.push_back(Ref<Version>(new Version(29, 16, 36, 14, 16,
+					              new ECBlocks(24, new ECB(1, 32)))));
+  VERSIONS.push_back(Ref<Version>(new Version(30, 16, 48, 14, 22,
+					              new ECBlocks(28, new ECB(1, 49)))));
+  return VERSIONS.size();
+}
+}
+}
+
+// file: zxing/datamatrix/decoder/BitMatrixParser.cpp
+
+/*
+ *  BitMatrixParser.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/decoder/BitMatrixParser.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+// #include <iostream>
+
+namespace zxing {
+namespace datamatrix {
+
+int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) {
+  return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1;
+}
+
+BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) : bitMatrix_(NULL),
+                                                             parsedVersion_(NULL),
+                                                             readBitMatrix_(NULL) {
+  size_t dimension = bitMatrix->getDimension();
+  if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0)
+    throw ReaderException("Dimension must be even, > 8 < 144");
+
+  parsedVersion_ = readVersion(bitMatrix);
+  bitMatrix_ = extractDataRegion(bitMatrix);
+  readBitMatrix_ = new BitMatrix(bitMatrix_->getWidth(), bitMatrix_->getHeight());
+}
+
+Ref<Version> BitMatrixParser::readVersion(Ref<BitMatrix> bitMatrix) {
+  if (parsedVersion_ != 0) {
+    return parsedVersion_;
+  }
+
+  int numRows = bitMatrix->getHeight();//getDimension();
+  int numColumns = bitMatrix->getWidth();//numRows;
+
+  Ref<Version> version = parsedVersion_->getVersionForDimensions(numRows, numColumns);
+  if (version != 0) {
+    return version;
+  }
+  throw ReaderException("Couldn't decode version");
+}
+
+ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
+  	ArrayRef<unsigned char> result(parsedVersion_->getTotalCodewords());
+  	int resultOffset = 0;
+    int row = 4;
+    int column = 0;
+
+    int numRows = bitMatrix_->getHeight();
+    int numColumns = bitMatrix_->getWidth();
+
+    bool corner1Read = false;
+    bool corner2Read = false;
+    bool corner3Read = false;
+    bool corner4Read = false;
+
+    // Read all of the codewords
+    do {
+      // Check the four corner cases
+      if ((row == numRows) && (column == 0) && !corner1Read) {
+        result[resultOffset++] = (unsigned char) readCorner1(numRows, numColumns);
+        row -= 2;
+        column +=2;
+        corner1Read = true;
+      } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read) {
+        result[resultOffset++] = (unsigned char) readCorner2(numRows, numColumns);
+        row -= 2;
+        column +=2;
+        corner2Read = true;
+      } else if ((row == numRows+4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read) {
+        result[resultOffset++] = (unsigned char) readCorner3(numRows, numColumns);
+        row -= 2;
+        column +=2;
+        corner3Read = true;
+      } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read) {
+        result[resultOffset++] = (unsigned char) readCorner4(numRows, numColumns);
+        row -= 2;
+        column +=2;
+        corner4Read = true;
+      } else {
+        // Sweep upward diagonally to the right
+        do {
+          if ((row < numRows) && (column >= 0) && !readBitMatrix_->get(column, row)) {
+            result[resultOffset++] = (unsigned char) readUtah(row, column, numRows, numColumns);
+          }
+          row -= 2;
+          column +=2;
+        } while ((row >= 0) && (column < numColumns));
+        row += 1;
+        column +=3;
+
+        // Sweep downward diagonally to the left
+        do {
+          if ((row >= 0) && (column < numColumns) && !readBitMatrix_->get(column, row)) {
+             result[resultOffset++] = (unsigned char) readUtah(row, column, numRows, numColumns);
+          }
+          row += 2;
+          column -=2;
+        } while ((row < numRows) && (column >= 0));
+        row += 3;
+        column +=1;
+      }
+    } while ((row < numRows) || (column < numColumns));
+
+    if (resultOffset != parsedVersion_->getTotalCodewords()) {
+      throw ReaderException("Did not read all codewords");
+    }
+    return result;
+}
+
+bool BitMatrixParser::readModule(int row, int column, int numRows, int numColumns) {
+    // Adjust the row and column indices based on boundary wrapping
+    if (row < 0) {
+      row += numRows;
+      column += 4 - ((numRows + 4) & 0x07);
+    }
+    if (column < 0) {
+      column += numColumns;
+      row += 4 - ((numColumns + 4) & 0x07);
+    }
+    readBitMatrix_->set(column, row);
+    return bitMatrix_->get(column, row);
+  }
+
+int BitMatrixParser::readUtah(int row, int column, int numRows, int numColumns) {
+    int currentByte = 0;
+    if (readModule(row - 2, column - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row - 2, column - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row - 1, column - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row - 1, column - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row - 1, column, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row, column - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row, column - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(row, column, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    return currentByte;
+  }
+
+int BitMatrixParser::readCorner1(int numRows, int numColumns) {
+    int currentByte = 0;
+    if (readModule(numRows - 1, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 1, 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 1, 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(2, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(3, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    return currentByte;
+  }
+
+int BitMatrixParser::readCorner2(int numRows, int numColumns) {
+    int currentByte = 0;
+    if (readModule(numRows - 3, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 2, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 1, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 4, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 3, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    return currentByte;
+  }
+
+int BitMatrixParser::readCorner3(int numRows, int numColumns) {
+    int currentByte = 0;
+    if (readModule(numRows - 1, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 1, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 3, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 3, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    return currentByte;
+  }
+
+int BitMatrixParser::readCorner4(int numRows, int numColumns) {
+    int currentByte = 0;
+    if (readModule(numRows - 3, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 2, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(numRows - 1, 0, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 2, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(0, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(1, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(2, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    currentByte <<= 1;
+    if (readModule(3, numColumns - 1, numRows, numColumns)) {
+      currentByte |= 1;
+    }
+    return currentByte;
+  }
+
+Ref<BitMatrix> BitMatrixParser::extractDataRegion(Ref<BitMatrix> bitMatrix) {
+    int symbolSizeRows = parsedVersion_->getSymbolSizeRows();
+    int symbolSizeColumns = parsedVersion_->getSymbolSizeColumns();
+
+    if ((int)bitMatrix->getHeight() != symbolSizeRows) {
+      throw IllegalArgumentException("Dimension of bitMatrix must match the version size");
+    }
+
+    int dataRegionSizeRows = parsedVersion_->getDataRegionSizeRows();
+    int dataRegionSizeColumns = parsedVersion_->getDataRegionSizeColumns();
+
+    int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows;
+    int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns;
+
+    int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;
+    int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;
+
+    Ref<BitMatrix> bitMatrixWithoutAlignment(new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow));
+    for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {
+      int dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;
+      for (int dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {
+        int dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;
+        for (int i = 0; i < dataRegionSizeRows; ++i) {
+          int readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;
+          int writeRowOffset = dataRegionRowOffset + i;
+          for (int j = 0; j < dataRegionSizeColumns; ++j) {
+            int readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;
+            if (bitMatrix->get(readColumnOffset, readRowOffset)) {
+              int writeColumnOffset = dataRegionColumnOffset + j;
+              bitMatrixWithoutAlignment->set(writeColumnOffset, writeRowOffset);
+            }
+          }
+        }
+      }
+    }
+    return bitMatrixWithoutAlignment;
+}
+
+}
+}
+
+// file: zxing/datamatrix/decoder/DataBlock.cpp
+
+/*
+ *  DataBlock.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/decoder/DataBlock.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+namespace datamatrix {
+
+using namespace std;
+
+DataBlock::DataBlock(int numDataCodewords, ArrayRef<unsigned char> codewords) :
+    numDataCodewords_(numDataCodewords), codewords_(codewords) {
+}
+
+int DataBlock::getNumDataCodewords() {
+  return numDataCodewords_;
+}
+
+ArrayRef<unsigned char> DataBlock::getCodewords() {
+  return codewords_;
+}
+
+std::vector<Ref<DataBlock> > DataBlock::getDataBlocks(ArrayRef<unsigned char> rawCodewords, Version *version) {
+  // Figure out the number and size of data blocks used by this version and
+  // error correction level
+  ECBlocks* ecBlocks = version->getECBlocks();
+
+  // First count the total number of data blocks
+  int totalBlocks = 0;
+  vector<ECB*> ecBlockArray = ecBlocks->getECBlocks();
+  for (size_t i = 0; i < ecBlockArray.size(); i++) {
+    totalBlocks += ecBlockArray[i]->getCount();
+  }
+
+  // Now establish DataBlocks of the appropriate size and number of data codewords
+  std::vector<Ref<DataBlock> > result(totalBlocks);
+  int numResultBlocks = 0;
+  for (size_t j = 0; j < ecBlockArray.size(); j++) {
+    ECB *ecBlock = ecBlockArray[j];
+    for (int i = 0; i < ecBlock->getCount(); i++) {
+      int numDataCodewords = ecBlock->getDataCodewords();
+      int numBlockCodewords = ecBlocks->getECCodewords() + numDataCodewords;
+      ArrayRef<unsigned char> buffer(numBlockCodewords);
+      Ref<DataBlock> blockRef(new DataBlock(numDataCodewords, buffer));
+      result[numResultBlocks++] = blockRef;
+    }
+  }
+
+  // All blocks have the same amount of data, except that the last n
+  // (where n may be 0) have 1 more byte. Figure out where these start.
+  int shorterBlocksTotalCodewords = result[0]->codewords_.size();
+  int longerBlocksStartAt = result.size() - 1;
+  while (longerBlocksStartAt >= 0) {
+    int numCodewords = result[longerBlocksStartAt]->codewords_.size();
+    if (numCodewords == shorterBlocksTotalCodewords) {
+      break;
+    }
+    if (numCodewords != shorterBlocksTotalCodewords + 1) {
+      throw IllegalArgumentException("Data block sizes differ by more than 1");
+    }
+    longerBlocksStartAt--;
+  }
+  longerBlocksStartAt++;
+
+  int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks->getECCodewords();
+  // The last elements of result may be 1 element longer;
+  // first fill out as many elements as all of them have
+  int rawCodewordsOffset = 0;
+  for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
+    for (int j = 0; j < numResultBlocks; j++) {
+      result[j]->codewords_[i] = rawCodewords[rawCodewordsOffset++];
+    }
+  }
+  // Fill out the last data block in the longer ones
+  for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {
+    result[j]->codewords_[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
+  }
+  // Now add in error correction blocks
+  int max = result[0]->codewords_.size();
+  for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
+    for (int j = 0; j < numResultBlocks; j++) {
+      int iOffset = j < longerBlocksStartAt ? i : i + 1;
+      result[j]->codewords_[iOffset] = rawCodewords[rawCodewordsOffset++];
+    }
+  }
+
+  if ((size_t)rawCodewordsOffset != rawCodewords.size()) {
+    throw IllegalArgumentException("rawCodewordsOffset != rawCodewords.length");
+  }
+
+  return result;
+}
+
+}
+}
+
+// file: zxing/datamatrix/decoder/DecodedBitStreamParser.cpp
+
+/*
+ *  DecodedBitStreamParser.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/FormatException.h>
+// #include <zxing/datamatrix/decoder/DecodedBitStreamParser.h>
+// #include <iostream>
+// #include <zxing/common/DecoderResult.h>
+
+namespace zxing {
+namespace datamatrix {
+
+using namespace std;
+
+const char DecodedBitStreamParser::C40_BASIC_SET_CHARS[] = {
+    '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+};
+
+const char DecodedBitStreamParser::C40_SHIFT2_SET_CHARS[] = {
+    '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
+    '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_'
+};
+
+const char DecodedBitStreamParser::TEXT_BASIC_SET_CHARS[] = {
+    '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
+};
+
+const char DecodedBitStreamParser::TEXT_SHIFT3_SET_CHARS[] = {
+    '\'', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (char) 127
+};
+
+Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<unsigned char> bytes) {
+  Ref<BitSource> bits(new BitSource(bytes));
+  ostringstream result;
+  ostringstream resultTrailer;
+  vector<unsigned char> byteSegments;
+  int mode = ASCII_ENCODE;
+  do {
+    if (mode == ASCII_ENCODE) {
+      mode = decodeAsciiSegment(bits, result, resultTrailer);
+    } else {
+      switch (mode) {
+        case C40_ENCODE:
+          decodeC40Segment(bits, result);
+          break;
+        case TEXT_ENCODE:
+          decodeTextSegment(bits, result);
+          break;
+        case ANSIX12_ENCODE:
+          decodeAnsiX12Segment(bits, result);
+          break;
+        case EDIFACT_ENCODE:
+          decodeEdifactSegment(bits, result);
+          break;
+        case BASE256_ENCODE:
+          decodeBase256Segment(bits, result, byteSegments);
+          break;
+        default:
+          throw FormatException("Unsupported mode indicator");
+      }
+      mode = ASCII_ENCODE;
+    }
+  } while (mode != PAD_ENCODE && bits->available() > 0);
+
+  if (resultTrailer.str().size() > 0) {
+    result << resultTrailer.str();
+  }
+  ArrayRef<unsigned char> rawBytes(bytes);
+  Ref<String> text(new String(result.str()));
+  return Ref<DecoderResult>(new DecoderResult(rawBytes, text));
+}
+
+int DecodedBitStreamParser::decodeAsciiSegment(Ref<BitSource> bits, ostringstream & result,
+  ostringstream & resultTrailer) {
+  bool upperShift = false;
+  do {
+    int oneByte = bits->readBits(8);
+    if (oneByte == 0) {
+      throw FormatException("Not enough bits to decode");
+    } else if (oneByte <= 128) {  // ASCII data (ASCII value + 1)
+      oneByte = upperShift ? (oneByte + 128) : oneByte;
+      // upperShift = false;
+      result << (char) (oneByte - 1);
+      return ASCII_ENCODE;
+    } else if (oneByte == 129) {  // Pad
+      return PAD_ENCODE;
+    } else if (oneByte <= 229) {  // 2-digit data 00-99 (Numeric Value + 130)
+      int value = oneByte - 130;
+      if (value < 10) { // padd with '0' for single digit values
+        result << '0';
+      }
+      result << value;
+    } else if (oneByte == 230) {  // Latch to C40 encodation
+      return C40_ENCODE;
+    } else if (oneByte == 231) {  // Latch to Base 256 encodation
+      return BASE256_ENCODE;
+    } else if (oneByte == 232) {  // FNC1
+      result << ((char) 29); // translate as ASCII 29
+    } else if (oneByte == 233 || oneByte == 234) {
+      // Structured Append, Reader Programming
+      // Ignore these symbols for now
+      // throw FormatException.getInstance();
+    } else if (oneByte == 235) {  // Upper Shift (shift to Extended ASCII)
+      upperShift = true;
+    } else if (oneByte == 236) {  // 05 Macro
+        result << ("[)>RS05GS");
+        resultTrailer << ("RSEOT");
+    } else if (oneByte == 237) {  // 06 Macro
+      result << ("[)>RS06GS");
+      resultTrailer <<  ("RSEOT");
+    } else if (oneByte == 238) {  // Latch to ANSI X12 encodation
+      return ANSIX12_ENCODE;
+    } else if (oneByte == 239) {  // Latch to Text encodation
+      return TEXT_ENCODE;
+    } else if (oneByte == 240) {  // Latch to EDIFACT encodation
+      return EDIFACT_ENCODE;
+    } else if (oneByte == 241) {  // ECI Character
+      // TODO(bbrown): I think we need to support ECI
+      // throw FormatException.getInstance();
+      // Ignore this symbol for now
+    } else if (oneByte >= 242) { // Not to be used in ASCII encodation
+      // ... but work around encoders that end with 254, latch back to ASCII
+      if (oneByte == 254 && bits->available() == 0) {
+        // Ignore
+      } else {
+        throw FormatException("Not to be used in ASCII encodation");
+      }
+    }
+  } while (bits->available() > 0);
+  return ASCII_ENCODE;
+}
+
+void DecodedBitStreamParser::decodeC40Segment(Ref<BitSource> bits, ostringstream & result) {
+  // Three C40 values are encoded in a 16-bit value as
+  // (1600 * C1) + (40 * C2) + C3 + 1
+  // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
+  bool upperShift = false;
+
+  int* cValues = new int[3];
+  int shift = 0;
+  do {
+    // If there is only one byte left then it will be encoded as ASCII
+    if (bits->available() == 8) {
+      return;
+    }
+    int firstByte = bits->readBits(8);
+    if (firstByte == 254) {  // Unlatch codeword
+      return;
+    }
+
+    parseTwoBytes(firstByte, bits->readBits(8), cValues);
+
+    for (int i = 0; i < 3; i++) {
+      int cValue = cValues[i];
+      switch (shift) {
+        case 0:
+          if (cValue < 3) {
+            shift = cValue + 1;
+          } else {
+            if (upperShift) {
+              result << (char) (C40_BASIC_SET_CHARS[cValue] + 128);
+              upperShift = false;
+            } else {
+              result << C40_BASIC_SET_CHARS[cValue];
+            }
+          }
+          break;
+        case 1:
+          if (upperShift) {
+            result << (char) (cValue + 128);
+            upperShift = false;
+          } else {
+            result << (char) cValue;
+          }
+          shift = 0;
+          break;
+        case 2:
+          if (cValue < 27) {
+            if (upperShift) {
+              result << (char) (C40_SHIFT2_SET_CHARS[cValue] + 128);
+              upperShift = false;
+            } else {
+              result << C40_SHIFT2_SET_CHARS[cValue];
+            }
+          } else if (cValue == 27) {  // FNC1
+            result << ((char) 29); // translate as ASCII 29
+          } else if (cValue == 30) {  // Upper Shift
+            upperShift = true;
+          } else {
+            throw FormatException("decodeC40Segment: Upper Shift");
+          }
+          shift = 0;
+          break;
+        case 3:
+          if (upperShift) {
+            result << (char) (cValue + 224);
+            upperShift = false;
+          } else {
+            result << (char) (cValue + 96);
+          }
+          shift = 0;
+          break;
+        default:
+          throw FormatException("decodeC40Segment: no case");
+      }
+    }
+  } while (bits->available() > 0);
+}
+
+void DecodedBitStreamParser::decodeTextSegment(Ref<BitSource> bits, ostringstream & result) {
+  // Three Text values are encoded in a 16-bit value as
+  // (1600 * C1) + (40 * C2) + C3 + 1
+  // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
+  bool upperShift = false;
+
+  int* cValues = new int[3];
+  int shift = 0;
+  do {
+    // If there is only one byte left then it will be encoded as ASCII
+    if (bits->available() == 8) {
+      return;
+    }
+    int firstByte = bits->readBits(8);
+    if (firstByte == 254) {  // Unlatch codeword
+      return;
+    }
+
+    parseTwoBytes(firstByte, bits->readBits(8), cValues);
+
+    for (int i = 0; i < 3; i++) {
+      int cValue = cValues[i];
+      switch (shift) {
+        case 0:
+          if (cValue < 3) {
+            shift = cValue + 1;
+          } else {
+            if (upperShift) {
+              result << (char) (TEXT_BASIC_SET_CHARS[cValue] + 128);
+              upperShift = false;
+            } else {
+              result << (TEXT_BASIC_SET_CHARS[cValue]);
+            }
+          }
+          break;
+        case 1:
+          if (upperShift) {
+            result << (char) (cValue + 128);
+            upperShift = false;
+          } else {
+            result << (char) (cValue);
+          }
+          shift = 0;
+          break;
+        case 2:
+          // Shift 2 for Text is the same encoding as C40
+          if (cValue < 27) {
+            if (upperShift) {
+              result << (char) (C40_SHIFT2_SET_CHARS[cValue] + 128);
+              upperShift = false;
+            } else {
+              result << (C40_SHIFT2_SET_CHARS[cValue]);
+            }
+          } else if (cValue == 27) {  // FNC1
+            result << ((char) 29); // translate as ASCII 29
+          } else if (cValue == 30) {  // Upper Shift
+            upperShift = true;
+          } else {
+            throw FormatException("decodeTextSegment: Upper Shift");
+          }
+          shift = 0;
+          break;
+        case 3:
+          if (upperShift) {
+            result << (char) (TEXT_SHIFT3_SET_CHARS[cValue] + 128);
+            upperShift = false;
+          } else {
+            result << (TEXT_SHIFT3_SET_CHARS[cValue]);
+          }
+          shift = 0;
+          break;
+        default:
+          throw FormatException("decodeTextSegment: no case");
+      }
+    }
+  } while (bits->available() > 0);
+}
+
+void DecodedBitStreamParser::decodeAnsiX12Segment(Ref<BitSource> bits, ostringstream & result) {
+  // Three ANSI X12 values are encoded in a 16-bit value as
+  // (1600 * C1) + (40 * C2) + C3 + 1
+
+  int* cValues = new int[3];
+  do {
+    // If there is only one byte left then it will be encoded as ASCII
+    if (bits->available() == 8) {
+      return;
+    }
+    int firstByte = bits->readBits(8);
+    if (firstByte == 254) {  // Unlatch codeword
+      return;
+    }
+
+    parseTwoBytes(firstByte, bits->readBits(8), cValues);
+
+    for (int i = 0; i < 3; i++) {
+      int cValue = cValues[i];
+      if (cValue == 0) {  // X12 segment terminator <CR>
+        result << '\r';
+      } else if (cValue == 1) {  // X12 segment separator *
+        result << '*';
+      } else if (cValue == 2) {  // X12 sub-element separator >
+        result << '>';
+      } else if (cValue == 3) {  // space
+        result << ' ';
+      } else if (cValue < 14) {  // 0 - 9
+        result << (char) (cValue + 44);
+      } else if (cValue < 40) {  // A - Z
+        result << (char) (cValue + 51);
+      } else {
+        throw FormatException("decodeAnsiX12Segment: no case");
+      }
+    }
+  } while (bits->available() > 0);
+}
+
+void DecodedBitStreamParser::parseTwoBytes(int firstByte, int secondByte, int*& result) {
+  int fullBitValue = (firstByte << 8) + secondByte - 1;
+  int temp = fullBitValue / 1600;
+  result[0] = temp;
+  fullBitValue -= temp * 1600;
+  temp = fullBitValue / 40;
+  result[1] = temp;
+  result[2] = fullBitValue - temp * 40;
+}
+
+void DecodedBitStreamParser::decodeEdifactSegment(Ref<BitSource> bits, ostringstream & result) {
+  bool unlatch = false;
+  do {
+    // If there is only two or less bytes left then it will be encoded as ASCII
+    if (bits->available() <= 16) {
+      return;
+    }
+
+    for (int i = 0; i < 4; i++) {
+      int edifactValue = bits->readBits(6);
+
+      // Check for the unlatch character
+      if (edifactValue == 0x2B67) {  // 011111
+        unlatch = true;
+        // If we encounter the unlatch code then continue reading because the Codeword triple
+        // is padded with 0's
+      }
+
+      if (!unlatch) {
+        if ((edifactValue & 0x20) == 0) {  // no 1 in the leading (6th) bit
+          edifactValue |= 0x40;  // Add a leading 01 to the 6 bit binary value
+        }
+        result << (char)(edifactValue);
+      }
+    }
+  } while (!unlatch && bits->available() > 0);
+}
+
+void DecodedBitStreamParser::decodeBase256Segment(Ref<BitSource> bits, ostringstream& result, vector<unsigned char> byteSegments) {
+  // Figure out how long the Base 256 Segment is.
+  int codewordPosition = 1 + bits->getByteOffset(); // position is 1-indexed
+  int d1 = unrandomize255State(bits->readBits(8), codewordPosition++);
+  int count;
+  if (d1 == 0) {  // Read the remainder of the symbol
+    count = bits->available() / 8;
+  } else if (d1 < 250) {
+    count = d1;
+  } else {
+    count = 250 * (d1 - 249) + unrandomize255State(bits->readBits(8), codewordPosition++);
+  }
+
+  // We're seeing NegativeArraySizeException errors from users.
+  if (count < 0) {
+    throw FormatException("NegativeArraySizeException");
+  }
+
+  unsigned char* bytes = new unsigned char[count];
+  for (int i = 0; i < count; i++) {
+    // Have seen this particular error in the wild, such as at
+    // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
+    if (bits->available() < 8) {
+      throw FormatException("byteSegments");
+    }
+    bytes[i] = unrandomize255State(bits->readBits(8), codewordPosition++);
+    byteSegments.push_back(bytes[i]);
+    result << (char)bytes[i];
+  }
+}
+}
+}
+
+
+// file: zxing/datamatrix/decoder/Decoder.cpp
+
+/*
+ *  Decoder.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/decoder/Decoder.h>
+// #include <zxing/datamatrix/decoder/BitMatrixParser.h>
+// #include <zxing/datamatrix/decoder/DataBlock.h>
+// #include <zxing/datamatrix/decoder/DecodedBitStreamParser.h>
+// #include <zxing/datamatrix/Version.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/reedsolomon/ReedSolomonException.h>
+
+namespace zxing {
+namespace datamatrix {
+
+using namespace std;
+
+Decoder::Decoder() :
+    rsDecoder_(GF256::DATA_MATRIX_FIELD) {
+}
+
+
+void Decoder::correctErrors(ArrayRef<unsigned char> codewordBytes, int numDataCodewords) {
+  int numCodewords = codewordBytes->size();
+  ArrayRef<int> codewordInts(numCodewords);
+  for (int i = 0; i < numCodewords; i++) {
+    codewordInts[i] = codewordBytes[i] & 0xff;
+  }
+  int numECCodewords = numCodewords - numDataCodewords;
+  try {
+    rsDecoder_.decode(codewordInts, numECCodewords);
+  } catch (ReedSolomonException const& ex) {
+    ReaderException rex(ex.what());
+    throw rex;
+  }
+  // Copy back into array of bytes -- only need to worry about the bytes that were data
+  // We don't care about errors in the error-correction codewords
+  for (int i = 0; i < numDataCodewords; i++) {
+    codewordBytes[i] = (unsigned char)codewordInts[i];
+  }
+}
+
+Ref<DecoderResult> Decoder::decode(Ref<BitMatrix> bits) {
+  // Construct a parser and read version, error-correction level
+  BitMatrixParser parser(bits);
+  Version *version = parser.readVersion(bits);
+
+  // Read codewords
+  ArrayRef<unsigned char> codewords(parser.readCodewords());
+  // Separate into data blocks
+  std::vector<Ref<DataBlock> > dataBlocks = DataBlock::getDataBlocks(codewords, version);
+
+  int dataBlocksCount = dataBlocks.size();
+
+  // Count total number of data bytes
+  int totalBytes = 0;
+  for (int i = 0; i < dataBlocksCount; i++) {
+    totalBytes += dataBlocks[i]->getNumDataCodewords();
+  }
+  ArrayRef<unsigned char> resultBytes(totalBytes);
+
+  // Error-correct and copy data blocks together into a stream of bytes
+  for (int j = 0; j < dataBlocksCount; j++) {
+    Ref<DataBlock> dataBlock(dataBlocks[j]);
+    ArrayRef<unsigned char> codewordBytes = dataBlock->getCodewords();
+    int numDataCodewords = dataBlock->getNumDataCodewords();
+    correctErrors(codewordBytes, numDataCodewords);
+    for (int i = 0; i < numDataCodewords; i++) {
+      // De-interlace data blocks.
+      resultBytes[i * dataBlocksCount + j] = codewordBytes[i];
+    }
+  }
+  // Decode the contents of that stream of bytes
+  DecodedBitStreamParser decodedBSParser;
+  return Ref<DecoderResult> (decodedBSParser.decode(resultBytes));
+}
+}
+}
+
+// file: zxing/datamatrix/detector/CornerPoint.cpp
+
+/*
+ *  CornerPoint.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/datamatrix/detector/CornerPoint.h>
+
+
+namespace zxing {
+	namespace datamatrix {
+
+		using namespace std;
+
+		CornerPoint::CornerPoint(float posX, float posY) :
+		  ResultPoint(posX,posY), counter_(0) {
+		}
+
+		int CornerPoint::getCount() const {
+			return counter_;
+		}
+
+		void CornerPoint::incrementCount() {
+			counter_++;
+		}
+
+		bool CornerPoint::equals(Ref<CornerPoint> other) const {
+			return posX_ == other->getX() && posY_ == other->getY();
+		}
+
+	}
+}
+
+// file: zxing/datamatrix/detector/Detector.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Detector.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPoint.h>
+// #include <zxing/common/GridSampler.h>
+// #include <zxing/datamatrix/detector/Detector.h>
+// #include <cmath>
+// #include <sstream>
+// #include <cstdlib>
+
+namespace zxing {
+namespace datamatrix {
+
+using namespace std;
+
+ResultPointsAndTransitions::ResultPointsAndTransitions() {
+  Ref<ResultPoint> ref(new ResultPoint(0, 0));
+  from_ = ref;
+  to_ = ref;
+  transitions_ = 0;
+}
+
+ResultPointsAndTransitions::ResultPointsAndTransitions(Ref<ResultPoint> from, Ref<ResultPoint> to,
+    int transitions)
+    : to_(to), from_(from), transitions_(transitions) {
+}
+
+Ref<ResultPoint> ResultPointsAndTransitions::getFrom() {
+  return from_;
+}
+
+Ref<ResultPoint> ResultPointsAndTransitions::getTo() {
+  return to_;
+}
+
+int ResultPointsAndTransitions::getTransitions() {
+  return transitions_;
+}
+
+Detector::Detector(Ref<BitMatrix> image)
+    : image_(image) {
+}
+
+Ref<BitMatrix> Detector::getImage() {
+  return image_;
+}
+
+Ref<DetectorResult> Detector::detect() {
+  Ref<WhiteRectangleDetector> rectangleDetector_(new WhiteRectangleDetector(image_));
+  std::vector<Ref<ResultPoint> > ResultPoints = rectangleDetector_->detect();
+  Ref<ResultPoint> pointA = ResultPoints[0];
+  Ref<ResultPoint> pointB = ResultPoints[1];
+  Ref<ResultPoint> pointC = ResultPoints[2];
+  Ref<ResultPoint> pointD = ResultPoints[3];
+
+  // Point A and D are across the diagonal from one another,
+  // as are B and C. Figure out which are the solid black lines
+  // by counting transitions
+  std::vector<Ref<ResultPointsAndTransitions> > transitions(4);
+  transitions[0].reset(transitionsBetween(pointA, pointB));
+  transitions[1].reset(transitionsBetween(pointA, pointC));
+  transitions[2].reset(transitionsBetween(pointB, pointD));
+  transitions[3].reset(transitionsBetween(pointC, pointD));
+  insertionSort(transitions);
+
+  // Sort by number of transitions. First two will be the two solid sides; last two
+  // will be the two alternating black/white sides
+  Ref<ResultPointsAndTransitions> lSideOne(transitions[0]);
+  Ref<ResultPointsAndTransitions> lSideTwo(transitions[1]);
+
+  // Figure out which point is their intersection by tallying up the number of times we see the
+  // endpoints in the four endpoints. One will show up twice.
+  Ref<ResultPoint> maybeTopLeft;
+  Ref<ResultPoint> bottomLeft;
+  Ref<ResultPoint> maybeBottomRight;
+  if (lSideOne->getFrom()->equals(lSideOne->getTo())) {
+    bottomLeft = lSideOne->getFrom();
+    maybeTopLeft = lSideTwo->getFrom();
+    maybeBottomRight = lSideTwo->getTo();
+  } else if (lSideOne->getFrom()->equals(lSideTwo->getFrom())) {
+    bottomLeft = lSideOne->getFrom();
+    maybeTopLeft = lSideOne->getTo();
+    maybeBottomRight = lSideTwo->getTo();
+  } else if (lSideOne->getFrom()->equals(lSideTwo->getTo())) {
+    bottomLeft = lSideOne->getFrom();
+    maybeTopLeft = lSideOne->getTo();
+    maybeBottomRight = lSideTwo->getFrom();
+  } else if (lSideOne->getTo()->equals(lSideTwo->getFrom())) {
+    bottomLeft = lSideOne->getTo();
+    maybeTopLeft = lSideOne->getFrom();
+    maybeBottomRight = lSideTwo->getTo();
+  } else if (lSideOne->getTo()->equals(lSideTwo->getTo())) {
+    bottomLeft = lSideOne->getTo();
+    maybeTopLeft = lSideOne->getFrom();
+    maybeBottomRight = lSideTwo->getFrom();
+  } else {
+    bottomLeft = lSideTwo->getFrom();
+    maybeTopLeft = lSideOne->getTo();
+    maybeBottomRight = lSideOne->getFrom();
+  }
+
+  // Bottom left is correct but top left and bottom right might be switched
+  std::vector<Ref<ResultPoint> > corners(3);
+  corners[0].reset(maybeTopLeft);
+  corners[1].reset(bottomLeft);
+  corners[2].reset(maybeBottomRight);
+
+  // Use the dot product trick to sort them out
+  ResultPoint::orderBestPatterns(corners);
+
+  // Now we know which is which:
+  Ref<ResultPoint> bottomRight(corners[0]);
+  bottomLeft = corners[1];
+  Ref<ResultPoint> topLeft(corners[2]);
+
+  // Which point didn't we find in relation to the "L" sides? that's the top right corner
+  Ref<ResultPoint> topRight;
+  if (!(pointA->equals(bottomRight) || pointA->equals(bottomLeft) || pointA->equals(topLeft))) {
+    topRight = pointA;
+  } else if (!(pointB->equals(bottomRight) || pointB->equals(bottomLeft)
+      || pointB->equals(topLeft))) {
+    topRight = pointB;
+  } else if (!(pointC->equals(bottomRight) || pointC->equals(bottomLeft)
+      || pointC->equals(topLeft))) {
+    topRight = pointC;
+  } else {
+    topRight = pointD;
+  }
+
+  // Next determine the dimension by tracing along the top or right side and counting black/white
+  // transitions. Since we start inside a black module, we should see a number of transitions
+  // equal to 1 less than the code dimension. Well, actually 2 less, because we are going to
+  // end on a black module:
+
+  // The top right point is actually the corner of a module, which is one of the two black modules
+  // adjacent to the white module at the top right. Tracing to that corner from either the top left
+  // or bottom right should work here.
+
+  int dimensionTop = transitionsBetween(topLeft, topRight)->getTransitions();
+  int dimensionRight = transitionsBetween(bottomRight, topRight)->getTransitions();
+
+  //dimensionTop++;
+  if ((dimensionTop & 0x01) == 1) {
+    // it can't be odd, so, round... up?
+    dimensionTop++;
+  }
+  dimensionTop += 2;
+
+  //dimensionRight++;
+  if ((dimensionRight & 0x01) == 1) {
+    // it can't be odd, so, round... up?
+    dimensionRight++;
+  }
+  dimensionRight += 2;
+
+  Ref<BitMatrix> bits;
+  Ref<PerspectiveTransform> transform;
+  Ref<ResultPoint> correctedTopRight;
+
+
+  // Rectanguar symbols are 6x16, 6x28, 10x24, 10x32, 14x32, or 14x44. If one dimension is more
+  // than twice the other, it's certainly rectangular, but to cut a bit more slack we accept it as
+  // rectangular if the bigger side is at least 7/4 times the other:
+  if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) {
+    // The matrix is rectangular
+    correctedTopRight = correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight,
+        dimensionTop, dimensionRight);
+    if (correctedTopRight == NULL) {
+      correctedTopRight = topRight;
+    }
+
+    dimensionTop = transitionsBetween(topLeft, correctedTopRight)->getTransitions();
+    dimensionRight = transitionsBetween(bottomRight, correctedTopRight)->getTransitions();
+
+    if ((dimensionTop & 0x01) == 1) {
+      // it can't be odd, so, round... up?
+      dimensionTop++;
+    }
+
+    if ((dimensionRight & 0x01) == 1) {
+      // it can't be odd, so, round... up?
+      dimensionRight++;
+    }
+
+    transform = createTransform(topLeft, correctedTopRight, bottomLeft, bottomRight, dimensionTop,
+        dimensionRight);
+    bits = sampleGrid(image_, dimensionTop, dimensionRight, transform);
+
+  } else {
+    // The matrix is square
+    int dimension = min(dimensionRight, dimensionTop);
+
+    // correct top right point to match the white module
+    correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension);
+    if (correctedTopRight == NULL) {
+      correctedTopRight = topRight;
+    }
+
+    // Redetermine the dimension using the corrected top right point
+    int dimensionCorrected = max(transitionsBetween(topLeft, correctedTopRight)->getTransitions(),
+        transitionsBetween(bottomRight, correctedTopRight)->getTransitions());
+    dimensionCorrected++;
+    if ((dimensionCorrected & 0x01) == 1) {
+      dimensionCorrected++;
+    }
+
+    transform = createTransform(topLeft, correctedTopRight, bottomLeft, bottomRight,
+        dimensionCorrected, dimensionCorrected);
+    bits = sampleGrid(image_, dimensionCorrected, dimensionCorrected, transform);
+  }
+
+  std::vector<Ref<ResultPoint> > points(4);
+  points[0].reset(topLeft);
+  points[1].reset(bottomLeft);
+  points[2].reset(correctedTopRight);
+  points[3].reset(bottomRight);
+  Ref<DetectorResult> detectorResult(new DetectorResult(bits, points, transform));
+  return detectorResult;
+}
+
+/**
+ * Calculates the position of the white top right module using the output of the rectangle detector
+ * for a rectangular matrix
+ */
+Ref<ResultPoint> Detector::correctTopRightRectangular(Ref<ResultPoint> bottomLeft,
+    Ref<ResultPoint> bottomRight, Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight,
+    int dimensionTop, int dimensionRight) {
+
+  float corr = distance(bottomLeft, bottomRight) / (float) dimensionTop;
+  int norm = distance(topLeft, topRight);
+  float cos = (topRight->getX() - topLeft->getX()) / norm;
+  float sin = (topRight->getY() - topLeft->getY()) / norm;
+
+  Ref<ResultPoint> c1(
+      new ResultPoint(topRight->getX() + corr * cos, topRight->getY() + corr * sin));
+
+  corr = distance(bottomLeft, topLeft) / (float) dimensionRight;
+  norm = distance(bottomRight, topRight);
+  cos = (topRight->getX() - bottomRight->getX()) / norm;
+  sin = (topRight->getY() - bottomRight->getY()) / norm;
+
+  Ref<ResultPoint> c2(
+      new ResultPoint(topRight->getX() + corr * cos, topRight->getY() + corr * sin));
+
+  if (!isValid(c1)) {
+    if (isValid(c2)) {
+      return c2;
+    }
+    return Ref<ResultPoint>(NULL);
+  }
+  if (!isValid(c2)) {
+    return c1;
+  }
+
+  int l1 = abs(dimensionTop - transitionsBetween(topLeft, c1)->getTransitions())
+      + abs(dimensionRight - transitionsBetween(bottomRight, c1)->getTransitions());
+  int l2 = abs(dimensionTop - transitionsBetween(topLeft, c2)->getTransitions())
+      + abs(dimensionRight - transitionsBetween(bottomRight, c2)->getTransitions());
+
+  return l1 <= l2 ? c1 : c2;
+}
+
+/**
+ * Calculates the position of the white top right module using the output of the rectangle detector
+ * for a square matrix
+ */
+Ref<ResultPoint> Detector::correctTopRight(Ref<ResultPoint> bottomLeft,
+    Ref<ResultPoint> bottomRight, Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight,
+    int dimension) {
+
+  float corr = distance(bottomLeft, bottomRight) / (float) dimension;
+  int norm = distance(topLeft, topRight);
+  float cos = (topRight->getX() - topLeft->getX()) / norm;
+  float sin = (topRight->getY() - topLeft->getY()) / norm;
+
+  Ref<ResultPoint> c1(
+      new ResultPoint(topRight->getX() + corr * cos, topRight->getY() + corr * sin));
+
+  corr = distance(bottomLeft, bottomRight) / (float) dimension;
+  norm = distance(bottomRight, topRight);
+  cos = (topRight->getX() - bottomRight->getX()) / norm;
+  sin = (topRight->getY() - bottomRight->getY()) / norm;
+
+  Ref<ResultPoint> c2(
+      new ResultPoint(topRight->getX() + corr * cos, topRight->getY() + corr * sin));
+
+  if (!isValid(c1)) {
+    if (isValid(c2)) {
+      return c2;
+    }
+    return Ref<ResultPoint>(NULL);
+  }
+  if (!isValid(c2)) {
+    return c1;
+  }
+
+  int l1 = abs(
+      transitionsBetween(topLeft, c1)->getTransitions()
+          - transitionsBetween(bottomRight, c1)->getTransitions());
+  int l2 = abs(
+      transitionsBetween(topLeft, c2)->getTransitions()
+          - transitionsBetween(bottomRight, c2)->getTransitions());
+
+  return l1 <= l2 ? c1 : c2;
+}
+
+bool Detector::isValid(Ref<ResultPoint> p) {
+  return p->getX() >= 0 && p->getX() < image_->getWidth() && p->getY() > 0
+      && p->getY() < image_->getHeight();
+}
+
+// L2 distance
+int Detector::distance(Ref<ResultPoint> a, Ref<ResultPoint> b) {
+  return round(
+      (float) sqrt(
+          (double) (a->getX() - b->getX()) * (a->getX() - b->getX())
+              + (a->getY() - b->getY()) * (a->getY() - b->getY())));
+}
+
+Ref<ResultPointsAndTransitions> Detector::transitionsBetween(Ref<ResultPoint> from,
+    Ref<ResultPoint> to) {
+  // See QR Code Detector, sizeOfBlackWhiteBlackRun()
+  int fromX = (int) from->getX();
+  int fromY = (int) from->getY();
+  int toX = (int) to->getX();
+  int toY = (int) to->getY();
+  bool steep = abs(toY - fromY) > abs(toX - fromX);
+  if (steep) {
+    int temp = fromX;
+    fromX = fromY;
+    fromY = temp;
+    temp = toX;
+    toX = toY;
+    toY = temp;
+  }
+
+  int dx = abs(toX - fromX);
+  int dy = abs(toY - fromY);
+  int error = -dx >> 1;
+  int ystep = fromY < toY ? 1 : -1;
+  int xstep = fromX < toX ? 1 : -1;
+  int transitions = 0;
+  bool inBlack = image_->get(steep ? fromY : fromX, steep ? fromX : fromY);
+  for (int x = fromX, y = fromY; x != toX; x += xstep) {
+    bool isBlack = image_->get(steep ? y : x, steep ? x : y);
+    if (isBlack != inBlack) {
+      transitions++;
+      inBlack = isBlack;
+    }
+    error += dy;
+    if (error > 0) {
+      if (y == toY) {
+        break;
+      }
+      y += ystep;
+      error -= dx;
+    }
+  }
+  Ref<ResultPointsAndTransitions> result(new ResultPointsAndTransitions(from, to, transitions));
+  return result;
+}
+
+Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft,
+    Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft, Ref<ResultPoint> bottomRight,
+    int dimensionX, int dimensionY) {
+
+  Ref<PerspectiveTransform> transform(
+      PerspectiveTransform::quadrilateralToQuadrilateral(
+          0.5f,
+          0.5f,
+          dimensionX - 0.5f,
+          0.5f,
+          dimensionX - 0.5f,
+          dimensionY - 0.5f,
+          0.5f,
+          dimensionY - 0.5f,
+          topLeft->getX(),
+          topLeft->getY(),
+          topRight->getX(),
+          topRight->getY(),
+          bottomRight->getX(),
+          bottomRight->getY(),
+          bottomLeft->getX(),
+          bottomLeft->getY()));
+  return transform;
+}
+
+Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimensionX, int dimensionY,
+    Ref<PerspectiveTransform> transform) {
+  GridSampler &sampler = GridSampler::getInstance();
+  return sampler.sampleGrid(image, dimensionX, dimensionY, transform);
+}
+
+void Detector::insertionSort(std::vector<Ref<ResultPointsAndTransitions> > &vector) {
+  int max = vector.size();
+  bool swapped = true;
+  Ref<ResultPointsAndTransitions> value;
+  Ref<ResultPointsAndTransitions> valueB;
+  do {
+    swapped = false;
+    for (int i = 1; i < max; i++) {
+      value = vector[i - 1];
+      if (compare(value, (valueB = vector[i])) > 0){
+        swapped = true;
+        vector[i - 1].reset(valueB);
+        vector[i].reset(value);
+      }
+    }
+  } while (swapped);
+}
+
+int Detector::compare(Ref<ResultPointsAndTransitions> a, Ref<ResultPointsAndTransitions> b) {
+  return a->getTransitions() - b->getTransitions();
+}
+}
+}
+
+// file: zxing/datamatrix/detector/DetectorException.cpp
+
+/*
+ * DetectorException.cpp
+ *
+ *  Created on: Aug 26, 2011
+ *      Author: luiz
+ */
+
+// #include "DetectorException.h"
+
+namespace zxing {
+namespace datamatrix {
+
+DetectorException::DetectorException(const char *msg) :
+    Exception(msg) {
+
+}
+
+DetectorException::~DetectorException() throw () {
+  // TODO Auto-generated destructor stub
+}
+
+}
+} /* namespace zxing */
+
+// file: zxing/datamatrix/detector/MonochromeRectangleDetector.cpp
+
+/*
+ *  MonochromeRectangleDetector.cpp
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+// #include <zxing/datamatrix/detector/MonochromeRectangleDetector.h>
+// #include <sstream>
+
+namespace zxing {
+namespace datamatrix {
+
+std::vector<Ref<CornerPoint> > MonochromeRectangleDetector::detect() {
+    int height = image_->getHeight();
+    int width = image_->getWidth();
+    int halfHeight = height >> 1;
+    int halfWidth = width >> 1;
+    int deltaY = max(1, height / (MAX_MODULES << 3));
+    int deltaX = max(1, width / (MAX_MODULES << 3));
+
+    int top = 0;
+    int bottom = height;
+    int left = 0;
+    int right = width;
+    Ref<CornerPoint> pointA(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, -deltaY, top, bottom, halfWidth >> 1));
+    top = (int) pointA->getY() - 1;
+    Ref<CornerPoint> pointB(findCornerFromCenter(halfWidth, -deltaX, left, right,
+        halfHeight, 0, top, bottom, halfHeight >> 1));
+    left = (int) pointB->getX() - 1;
+    Ref<CornerPoint> pointC(findCornerFromCenter(halfWidth, deltaX, left, right,
+        halfHeight, 0, top, bottom, halfHeight >> 1));
+    right = (int) pointC->getX() + 1;
+    Ref<CornerPoint> pointD(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, deltaY, top, bottom, halfWidth >> 1));
+    bottom = (int) pointD->getY() + 1;
+
+    // Go try to find point A again with better information -- might have been off at first.
+    pointA.reset(findCornerFromCenter(halfWidth, 0, left, right,
+        halfHeight, -deltaY, top, bottom, halfWidth >> 2));
+	  std::vector<Ref<CornerPoint> > corners(4);
+
+  	corners[0].reset(pointA);
+  	corners[1].reset(pointB);
+  	corners[2].reset(pointC);
+  	corners[3].reset(pointD);
+    return corners;
+  }
+
+Ref<CornerPoint> MonochromeRectangleDetector::findCornerFromCenter(int centerX, int deltaX, int left, int right,
+      int centerY, int deltaY, int top, int bottom, int maxWhiteRun) {
+	Ref<TwoInts> lastRange(NULL);
+    for (int y = centerY, x = centerX;
+         y < bottom && y >= top && x < right && x >= left;
+         y += deltaY, x += deltaX) {
+    Ref<TwoInts> range(NULL);
+      if (deltaX == 0) {
+        // horizontal slices, up and down
+        range = blackWhiteRange(y, maxWhiteRun, left, right, true);
+      } else {
+        // vertical slices, left and right
+        range = blackWhiteRange(x, maxWhiteRun, top, bottom, false);
+      }
+      if (range == NULL) {
+        if (lastRange == NULL) {
+			    throw ReaderException("Couldn't find corners (lastRange = NULL) ");
+        } else {
+        // lastRange was found
+        if (deltaX == 0) {
+          int lastY = y - deltaY;
+          if (lastRange->start < centerX) {
+            if (lastRange->end > centerX) {
+              // straddle, choose one or the other based on direction
+			        Ref<CornerPoint> result(new CornerPoint(deltaY > 0 ? lastRange->start : lastRange->end, lastY));
+			        return result;
+            }
+			      Ref<CornerPoint> result(new CornerPoint(lastRange->start, lastY));
+			      return result;
+          } else {
+			      Ref<CornerPoint> result(new CornerPoint(lastRange->end, lastY));
+			      return result;
+            }
+        } else {
+          int lastX = x - deltaX;
+          if (lastRange->start < centerY) {
+            if (lastRange->end > centerY) {
+			        Ref<CornerPoint> result(new CornerPoint(lastX, deltaX < 0 ? lastRange->start : lastRange->end));
+			        return result;
+            }
+			      Ref<CornerPoint> result(new CornerPoint(lastX, lastRange->start));
+			      return result;
+          } else {
+			      Ref<CornerPoint> result(new CornerPoint(lastX, lastRange->end));
+			      return result;
+            }
+          }
+        }
+      }
+      lastRange = range;
+    }
+    throw ReaderException("Couldn't find corners");
+  }
+
+Ref<TwoInts> MonochromeRectangleDetector::blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
+      bool horizontal) {
+
+	  int center = (minDim + maxDim) >> 1;
+
+    // Scan left/up first
+    int start = center;
+    while (start >= minDim) {
+      if (horizontal ? image_->get(start, fixedDimension) : image_->get(fixedDimension, start)) {
+        start--;
+      } else {
+        int whiteRunStart = start;
+        do {
+          start--;
+        } while (start >= minDim && !(horizontal ? image_->get(start, fixedDimension) :
+            image_->get(fixedDimension, start)));
+        int whiteRunSize = whiteRunStart - start;
+        if (start < minDim || whiteRunSize > maxWhiteRun) {
+          start = whiteRunStart;
+          break;
+        }
+      }
+    }
+    start++;
+
+    // Then try right/down
+    int end = center;
+    while (end < maxDim) {
+      if (horizontal ? image_->get(end, fixedDimension) : image_->get(fixedDimension, end)) {
+        end++;
+      } else {
+        int whiteRunStart = end;
+        do {
+          end++;
+        } while (end < maxDim && !(horizontal ? image_->get(end, fixedDimension) :
+            image_->get(fixedDimension, end)));
+        int whiteRunSize = end - whiteRunStart;
+        if (end >= maxDim || whiteRunSize > maxWhiteRun) {
+          end = whiteRunStart;
+          break;
+        }
+      }
+    }
+    end--;
+    Ref<TwoInts> result(NULL);
+    if (end > start) {
+		result = new TwoInts;
+      result->start = start;
+      result->end = end;
+    }
+    return result;
+  }
+}
+}
+
+// file: zxing/multi/ByQuadrantReader.cpp
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/ByQuadrantReader.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+namespace multi {
+
+ByQuadrantReader::ByQuadrantReader(Reader& delegate) : delegate_(delegate) {}
+
+ByQuadrantReader::~ByQuadrantReader(){}
+
+Ref<Result> ByQuadrantReader::decode(Ref<BinaryBitmap> image){
+  return decode(image, DecodeHints::DEFAULT_HINT);
+}
+
+Ref<Result> ByQuadrantReader::decode(Ref<BinaryBitmap> image, DecodeHints hints){
+  int width = image->getWidth();
+  int height = image->getHeight();
+  int halfWidth = width / 2;
+  int halfHeight = height / 2;
+  Ref<BinaryBitmap> topLeft = image->crop(0, 0, halfWidth, halfHeight);
+  try {
+    return delegate_.decode(topLeft, hints);
+  } catch (ReaderException re) {
+    // continue
+  }
+
+  Ref<BinaryBitmap> topRight = image->crop(halfWidth, 0, halfWidth, halfHeight);
+  try {
+    return delegate_.decode(topRight, hints);
+  } catch (ReaderException re) {
+    // continue
+  }
+
+  Ref<BinaryBitmap> bottomLeft = image->crop(0, halfHeight, halfWidth, halfHeight);
+  try {
+    return delegate_.decode(bottomLeft, hints);
+  } catch (ReaderException re) {
+    // continue
+  }
+
+  Ref<BinaryBitmap> bottomRight = image->crop(halfWidth, halfHeight, halfWidth, halfHeight);
+  try {
+    return delegate_.decode(bottomRight, hints);
+  } catch (ReaderException re) {
+    // continue
+  }
+
+  int quarterWidth = halfWidth / 2;
+  int quarterHeight = halfHeight / 2;
+  Ref<BinaryBitmap> center = image->crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
+  return delegate_.decode(center, hints);
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/multi/GenericMultipleBarcodeReader.cpp
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/GenericMultipleBarcodeReader.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/ResultPoint.h>
+
+namespace zxing {
+namespace multi {
+GenericMultipleBarcodeReader::GenericMultipleBarcodeReader(Reader& delegate) :
+  delegate_(delegate)
+{
+}
+
+GenericMultipleBarcodeReader::~GenericMultipleBarcodeReader(){}
+
+std::vector<Ref<Result> > GenericMultipleBarcodeReader::decodeMultiple(
+  Ref<BinaryBitmap> image, DecodeHints hints)
+{
+  std::vector<Ref<Result> > results;
+  doDecodeMultiple(image, hints, results, 0, 0);
+  if (results.empty()){
+    throw ReaderException("No code detected");
+  }
+  return results;
+}
+
+void GenericMultipleBarcodeReader::doDecodeMultiple(Ref<BinaryBitmap> image,
+  DecodeHints hints, std::vector<Ref<Result> >& results, int xOffset, int yOffset)
+{
+  Ref<Result> result;
+  try {
+    result = delegate_.decode(image, hints);
+  } catch (ReaderException re) {
+    return;
+  }
+  bool alreadyFound = false;
+  for (unsigned int i = 0; i < results.size(); i++) {
+    Ref<Result> existingResult = results[i];
+    if (existingResult->getText()->getText() == result->getText()->getText()) {
+      alreadyFound = true;
+      break;
+    }
+  }
+  if (alreadyFound) {
+    return;
+  }
+
+  results.push_back(translateResultPoints(result, xOffset, yOffset));
+  const std::vector<Ref<ResultPoint> > resultPoints = result->getResultPoints();
+  if (resultPoints.empty()) {
+    return;
+  }
+
+  int width = image->getWidth();
+  int height = image->getHeight();
+  float minX = width;
+  float minY = height;
+  float maxX = 0.0f;
+  float maxY = 0.0f;
+  for (unsigned int i = 0; i < resultPoints.size(); i++) {
+    Ref<ResultPoint> point = resultPoints[i];
+    float x = point->getX();
+    float y = point->getY();
+    if (x < minX) {
+      minX = x;
+    }
+    if (y < minY) {
+      minY = y;
+    }
+    if (x > maxX) {
+      maxX = x;
+    }
+    if (y > maxY) {
+      maxY = y;
+    }
+  }
+
+  // Decode left of barcode
+  if (minX > MIN_DIMENSION_TO_RECUR) {
+    doDecodeMultiple(image->crop(0, 0, (int) minX, height),
+                     hints, results, xOffset, yOffset);
+  }
+  // Decode above barcode
+  if (minY > MIN_DIMENSION_TO_RECUR) {
+    doDecodeMultiple(image->crop(0, 0, width, (int) minY),
+                     hints, results, xOffset, yOffset);
+  }
+  // Decode right of barcode
+  if (maxX < width - MIN_DIMENSION_TO_RECUR) {
+    doDecodeMultiple(image->crop((int) maxX, 0, width - (int) maxX, height),
+                     hints, results, xOffset + (int) maxX, yOffset);
+  }
+  // Decode below barcode
+  if (maxY < height - MIN_DIMENSION_TO_RECUR) {
+    doDecodeMultiple(image->crop(0, (int) maxY, width, height - (int) maxY),
+                     hints, results, xOffset, yOffset + (int) maxY);
+  }
+}
+
+Ref<Result> GenericMultipleBarcodeReader::translateResultPoints(Ref<Result> result, int xOffset, int yOffset){
+  const std::vector<Ref<ResultPoint> > oldResultPoints = result->getResultPoints();
+  if (oldResultPoints.empty()) {
+    return result;
+  }
+  std::vector<Ref<ResultPoint> > newResultPoints;
+  for (unsigned int i = 0; i < oldResultPoints.size(); i++) {
+    Ref<ResultPoint> oldPoint = oldResultPoints[i];
+    newResultPoints.push_back(Ref<ResultPoint>(new ResultPoint(oldPoint->getX() + xOffset, oldPoint->getY() + yOffset)));
+  }
+  return Ref<Result>(new Result(result->getText(), result->getRawBytes(), newResultPoints, result->getBarcodeFormat()));
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/multi/MultipleBarcodeReader.cpp
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/MultipleBarcodeReader.h>
+
+namespace zxing {
+namespace multi {
+
+MultipleBarcodeReader::~MultipleBarcodeReader() { }
+
+std::vector<Ref<Result> > MultipleBarcodeReader::decodeMultiple(Ref<BinaryBitmap> image) {
+  return decodeMultiple(image, DecodeHints::DEFAULT_HINT);
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/multi/qrcode/QRCodeMultiReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/qrcode/QRCodeMultiReader.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/multi/qrcode/detector/MultiDetector.h>
+// #include <zxing/BarcodeFormat.h>
+
+namespace zxing {
+namespace multi {
+QRCodeMultiReader::QRCodeMultiReader(){}
+
+QRCodeMultiReader::~QRCodeMultiReader(){}
+
+std::vector<Ref<Result> > QRCodeMultiReader::decodeMultiple(Ref<BinaryBitmap> image,
+  DecodeHints hints)
+{
+  std::vector<Ref<Result> > results;
+  MultiDetector detector(image->getBlackMatrix());
+
+  std::vector<Ref<DetectorResult> > detectorResult =  detector.detectMulti(hints);
+  for (unsigned int i = 0; i < detectorResult.size(); i++) {
+    try {
+      Ref<DecoderResult> decoderResult = getDecoder().decode(detectorResult[i]->getBits());
+      std::vector<Ref<ResultPoint> > points = detectorResult[i]->getPoints();
+      Ref<Result> result = Ref<Result>(new Result(decoderResult->getText(),
+      decoderResult->getRawBytes(),
+      points, BarcodeFormat_QR_CODE));
+      // result->putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult->getByteSegments());
+      // result->putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult->getECLevel().toString());
+      results.push_back(result);
+    } catch (ReaderException re) {
+    // ignore and continue
+    }
+  }
+  if (results.empty()){
+    throw ReaderException("No code detected");
+  }
+  return results;
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/multi/qrcode/detector/MultiDetector.cpp
+
+/*
+ *  Copyright 2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/qrcode/detector/MultiDetector.h>
+// #include <zxing/multi/qrcode/detector/MultiFinderPatternFinder.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+namespace multi {
+using namespace zxing::qrcode;
+
+MultiDetector::MultiDetector(Ref<BitMatrix> image) : Detector(image) {}
+
+MultiDetector::~MultiDetector(){}
+
+std::vector<Ref<DetectorResult> > MultiDetector::detectMulti(DecodeHints hints){
+  Ref<BitMatrix> image = getImage();
+  MultiFinderPatternFinder finder = MultiFinderPatternFinder(image, hints.getResultPointCallback());
+  std::vector<Ref<FinderPatternInfo> > info = finder.findMulti(hints);
+  std::vector<Ref<DetectorResult> > result;
+  for(unsigned int i = 0; i < info.size(); i++){
+    try{
+      result.push_back(processFinderPatternInfo(info[i]));
+    } catch (ReaderException e){
+      // ignore
+    }
+  }
+
+  return result;
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/multi/qrcode/detector/MultiFinderPatternFinder.cpp
+
+/*
+ *  Copyright 2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <algorithm>
+// #include <math.h>
+// #include <stdlib.h>
+// #include <zxing/multi/qrcode/detector/MultiFinderPatternFinder.h>
+// #include <zxing/DecodeHints.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing{
+namespace multi {
+using namespace zxing::qrcode;
+
+const float MultiFinderPatternFinder::MAX_MODULE_COUNT_PER_EDGE = 180;
+const float MultiFinderPatternFinder::MIN_MODULE_COUNT_PER_EDGE = 9;
+const float MultiFinderPatternFinder::DIFF_MODSIZE_CUTOFF_PERCENT = 0.05f;
+const float MultiFinderPatternFinder::DIFF_MODSIZE_CUTOFF = 0.5f;
+
+bool compareModuleSize(Ref<FinderPattern> a, Ref<FinderPattern> b){
+    float value = a->getEstimatedModuleSize() - b->getEstimatedModuleSize();
+    return value < 0.0;
+}
+
+
+MultiFinderPatternFinder::MultiFinderPatternFinder(Ref<BitMatrix> image,
+  Ref<ResultPointCallback> resultPointCallback) :
+    FinderPatternFinder(image, resultPointCallback)
+{
+}
+
+MultiFinderPatternFinder::~MultiFinderPatternFinder(){}
+
+std::vector<Ref<FinderPatternInfo> > MultiFinderPatternFinder::findMulti(DecodeHints const& hints){
+  bool tryHarder = hints.getTryHarder();
+  Ref<BitMatrix> image = image_; // Protected member
+  int maxI = image->getHeight();
+  int maxJ = image->getWidth();
+  // We are looking for black/white/black/white/black modules in
+  // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far
+
+  // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
+  // image, and then account for the center being 3 modules in size. This gives the smallest
+  // number of pixels the center could be, so skip this often. When trying harder, look for all
+  // QR versions regardless of how dense they are.
+  int iSkip = (int) (maxI / (MAX_MODULES * 4.0f) * 3);
+  if (iSkip < MIN_SKIP || tryHarder) {
+    iSkip = MIN_SKIP;
+  }
+
+  int stateCount[5];
+  for (int i = iSkip - 1; i < maxI; i += iSkip) {
+    // Get a row of black/white values
+    stateCount[0] = 0;
+    stateCount[1] = 0;
+    stateCount[2] = 0;
+    stateCount[3] = 0;
+    stateCount[4] = 0;
+    int currentState = 0;
+    for (int j = 0; j < maxJ; j++) {
+      if (image->get(j, i)) {
+        // Black pixel
+        if ((currentState & 1) == 1) { // Counting white pixels
+          currentState++;
+        }
+        stateCount[currentState]++;
+      } else { // White pixel
+        if ((currentState & 1) == 0) { // Counting black pixels
+          if (currentState == 4) { // A winner?
+            if (foundPatternCross(stateCount)) { // Yes
+              bool confirmed = handlePossibleCenter(stateCount, i, j);
+              if (!confirmed) {
+                do { // Advance to next black pixel
+                  j++;
+                } while (j < maxJ && !image->get(j, i));
+                  j--; // back up to that last white pixel
+              }
+              // Clear state to start looking again
+              currentState = 0;
+              stateCount[0] = 0;
+              stateCount[1] = 0;
+              stateCount[2] = 0;
+              stateCount[3] = 0;
+              stateCount[4] = 0;
+            } else { // No, shift counts back by two
+              stateCount[0] = stateCount[2];
+              stateCount[1] = stateCount[3];
+              stateCount[2] = stateCount[4];
+              stateCount[3] = 1;
+              stateCount[4] = 0;
+              currentState = 3;
+            }
+          } else {
+            stateCount[++currentState]++;
+          }
+        } else { // Counting white pixels
+            stateCount[currentState]++;
+        }
+      }
+    } // for j=...
+
+    if (foundPatternCross(stateCount)) {
+      handlePossibleCenter(stateCount, i, maxJ);
+    } // end if foundPatternCross
+  } // for i=iSkip-1 ...
+  std::vector<std::vector<Ref<FinderPattern> > > patternInfo = selectBestPatterns();
+  std::vector<Ref<FinderPatternInfo> > result;
+  for (unsigned int i = 0; i < patternInfo.size(); i++) {
+    std::vector<Ref<FinderPattern> > pattern = patternInfo[i];
+    FinderPatternFinder::orderBestPatterns(pattern);
+    result.push_back(Ref<FinderPatternInfo>(new FinderPatternInfo(pattern)));
+  }
+  return result;
+}
+
+std::vector<std::vector<Ref<FinderPattern> > > MultiFinderPatternFinder::selectBestPatterns(){
+  std::vector<Ref<FinderPattern> > possibleCenters = possibleCenters_;
+
+  int size = possibleCenters.size();
+
+  if (size < 3) {
+    // Couldn't find enough finder patterns
+    throw ReaderException("No code detected");
+  }
+
+  std::vector<std::vector<Ref<FinderPattern> > > results;
+
+  /*
+  * Begin HE modifications to safely detect multiple codes of equal size
+  */
+  if (size == 3) {
+    results.push_back(possibleCenters_);
+    return results;
+  }
+
+  // Sort by estimated module size to speed up the upcoming checks
+  //TODO do a sort based on module size
+  std::sort(possibleCenters.begin(), possibleCenters.end(), compareModuleSize);
+
+  /*
+  * Now lets start: build a list of tuples of three finder locations that
+  *  - feature similar module sizes
+  *  - are placed in a distance so the estimated module count is within the QR specification
+  *  - have similar distance between upper left/right and left top/bottom finder patterns
+  *  - form a triangle with 90° angle (checked by comparing top right/bottom left distance
+  *    with pythagoras)
+  *
+  * Note: we allow each point to be used for more than one code region: this might seem
+  * counterintuitive at first, but the performance penalty is not that big. At this point,
+  * we cannot make a good quality decision whether the three finders actually represent
+  * a QR code, or are just by chance layouted so it looks like there might be a QR code there.
+  * So, if the layout seems right, lets have the decoder try to decode.
+  */
+
+  for (int i1 = 0; i1 < (size - 2); i1++) {
+    Ref<FinderPattern> p1 = possibleCenters[i1];
+    for (int i2 = i1 + 1; i2 < (size - 1); i2++) {
+      Ref<FinderPattern> p2 = possibleCenters[i2];
+      // Compare the expected module sizes; if they are really off, skip
+      float vModSize12 = (p1->getEstimatedModuleSize() - p2->getEstimatedModuleSize()) / std::min(p1->getEstimatedModuleSize(), p2->getEstimatedModuleSize());
+      float vModSize12A = abs(p1->getEstimatedModuleSize() - p2->getEstimatedModuleSize());
+      if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT) {
+        // break, since elements are ordered by the module size deviation there cannot be
+        // any more interesting elements for the given p1.
+        break;
+      }
+      for (int i3 = i2 + 1; i3 < size; i3++) {
+        Ref<FinderPattern> p3 = possibleCenters[i3];
+        // Compare the expected module sizes; if they are really off, skip
+        float vModSize23 = (p2->getEstimatedModuleSize() - p3->getEstimatedModuleSize()) / std::min(p2->getEstimatedModuleSize(), p3->getEstimatedModuleSize());
+        float vModSize23A = abs(p2->getEstimatedModuleSize() - p3->getEstimatedModuleSize());
+        if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT) {
+          // break, since elements are ordered by the module size deviation there cannot be
+          // any more interesting elements for the given p1.
+          break;
+        }
+        std::vector<Ref<FinderPattern> > test;
+        test.push_back(p1);
+        test.push_back(p2);
+        test.push_back(p3);
+        FinderPatternFinder::orderBestPatterns(test);
+        // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal
+        Ref<FinderPatternInfo> info = Ref<FinderPatternInfo>(new FinderPatternInfo(test));
+        float dA = FinderPatternFinder::distance(info->getTopLeft(), info->getBottomLeft());
+        float dC = FinderPatternFinder::distance(info->getTopRight(), info->getBottomLeft());
+        float dB = FinderPatternFinder::distance(info->getTopLeft(), info->getTopRight());
+        // Check the sizes
+        float estimatedModuleCount = (dA + dB) / (p1->getEstimatedModuleSize() * 2.0f);
+        if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE || estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE) {
+          continue;
+        }
+        // Calculate the difference of the edge lengths in percent
+        float vABBC = abs((dA - dB) / std::min(dA, dB));
+        if (vABBC >= 0.1f) {
+          continue;
+        }
+        // Calculate the diagonal length by assuming a 90° angle at topleft
+        float dCpy = (float) sqrt(dA * dA + dB * dB);
+        // Compare to the real distance in %
+        float vPyC = abs((dC - dCpy) / std::min(dC, dCpy));
+        if (vPyC >= 0.1f) {
+          continue;
+        }
+        // All tests passed!
+        results.push_back(test);
+      } // end iterate p3
+    } // end iterate p2
+  } // end iterate p1
+  if (results.empty()){
+    // Nothing found!
+    throw ReaderException("No code detected");
+  }
+  return results;
+}
+
+} // End zxing::multi namespace
+} // End zxing namespace
+
+// file: zxing/oned/Code128Reader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "Code128Reader.h"
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/ReaderException.h>
+// #include <math.h>
+// #include <string.h>
+// #include <sstream>
+
+namespace zxing {
+	namespace oned {
+
+		const int CODE_PATTERNS_LENGTH = 107;
+		const int countersLength = 6;
+		static const int CODE_PATTERNS[CODE_PATTERNS_LENGTH][countersLength] = {
+			{2, 1, 2, 2, 2, 2}, /* 0 */
+			{2, 2, 2, 1, 2, 2},
+			{2, 2, 2, 2, 2, 1},
+			{1, 2, 1, 2, 2, 3},
+			{1, 2, 1, 3, 2, 2},
+			{1, 3, 1, 2, 2, 2}, /* 5 */
+			{1, 2, 2, 2, 1, 3},
+			{1, 2, 2, 3, 1, 2},
+			{1, 3, 2, 2, 1, 2},
+			{2, 2, 1, 2, 1, 3},
+			{2, 2, 1, 3, 1, 2}, /* 10 */
+			{2, 3, 1, 2, 1, 2},
+			{1, 1, 2, 2, 3, 2},
+			{1, 2, 2, 1, 3, 2},
+			{1, 2, 2, 2, 3, 1},
+			{1, 1, 3, 2, 2, 2}, /* 15 */
+			{1, 2, 3, 1, 2, 2},
+			{1, 2, 3, 2, 2, 1},
+			{2, 2, 3, 2, 1, 1},
+			{2, 2, 1, 1, 3, 2},
+			{2, 2, 1, 2, 3, 1}, /* 20 */
+			{2, 1, 3, 2, 1, 2},
+			{2, 2, 3, 1, 1, 2},
+			{3, 1, 2, 1, 3, 1},
+			{3, 1, 1, 2, 2, 2},
+			{3, 2, 1, 1, 2, 2}, /* 25 */
+			{3, 2, 1, 2, 2, 1},
+			{3, 1, 2, 2, 1, 2},
+			{3, 2, 2, 1, 1, 2},
+			{3, 2, 2, 2, 1, 1},
+			{2, 1, 2, 1, 2, 3}, /* 30 */
+			{2, 1, 2, 3, 2, 1},
+			{2, 3, 2, 1, 2, 1},
+			{1, 1, 1, 3, 2, 3},
+			{1, 3, 1, 1, 2, 3},
+			{1, 3, 1, 3, 2, 1}, /* 35 */
+			{1, 1, 2, 3, 1, 3},
+			{1, 3, 2, 1, 1, 3},
+			{1, 3, 2, 3, 1, 1},
+			{2, 1, 1, 3, 1, 3},
+			{2, 3, 1, 1, 1, 3}, /* 40 */
+			{2, 3, 1, 3, 1, 1},
+			{1, 1, 2, 1, 3, 3},
+			{1, 1, 2, 3, 3, 1},
+			{1, 3, 2, 1, 3, 1},
+			{1, 1, 3, 1, 2, 3}, /* 45 */
+			{1, 1, 3, 3, 2, 1},
+			{1, 3, 3, 1, 2, 1},
+			{3, 1, 3, 1, 2, 1},
+			{2, 1, 1, 3, 3, 1},
+			{2, 3, 1, 1, 3, 1}, /* 50 */
+			{2, 1, 3, 1, 1, 3},
+			{2, 1, 3, 3, 1, 1},
+			{2, 1, 3, 1, 3, 1},
+			{3, 1, 1, 1, 2, 3},
+			{3, 1, 1, 3, 2, 1}, /* 55 */
+			{3, 3, 1, 1, 2, 1},
+			{3, 1, 2, 1, 1, 3},
+			{3, 1, 2, 3, 1, 1},
+			{3, 3, 2, 1, 1, 1},
+			{3, 1, 4, 1, 1, 1}, /* 60 */
+			{2, 2, 1, 4, 1, 1},
+			{4, 3, 1, 1, 1, 1},
+			{1, 1, 1, 2, 2, 4},
+			{1, 1, 1, 4, 2, 2},
+			{1, 2, 1, 1, 2, 4}, /* 65 */
+			{1, 2, 1, 4, 2, 1},
+			{1, 4, 1, 1, 2, 2},
+			{1, 4, 1, 2, 2, 1},
+			{1, 1, 2, 2, 1, 4},
+			{1, 1, 2, 4, 1, 2}, /* 70 */
+			{1, 2, 2, 1, 1, 4},
+			{1, 2, 2, 4, 1, 1},
+			{1, 4, 2, 1, 1, 2},
+			{1, 4, 2, 2, 1, 1},
+			{2, 4, 1, 2, 1, 1}, /* 75 */
+			{2, 2, 1, 1, 1, 4},
+			{4, 1, 3, 1, 1, 1},
+			{2, 4, 1, 1, 1, 2},
+			{1, 3, 4, 1, 1, 1},
+			{1, 1, 1, 2, 4, 2}, /* 80 */
+			{1, 2, 1, 1, 4, 2},
+			{1, 2, 1, 2, 4, 1},
+			{1, 1, 4, 2, 1, 2},
+			{1, 2, 4, 1, 1, 2},
+			{1, 2, 4, 2, 1, 1}, /* 85 */
+			{4, 1, 1, 2, 1, 2},
+			{4, 2, 1, 1, 1, 2},
+			{4, 2, 1, 2, 1, 1},
+			{2, 1, 2, 1, 4, 1},
+			{2, 1, 4, 1, 2, 1}, /* 90 */
+			{4, 1, 2, 1, 2, 1},
+			{1, 1, 1, 1, 4, 3},
+			{1, 1, 1, 3, 4, 1},
+			{1, 3, 1, 1, 4, 1},
+			{1, 1, 4, 1, 1, 3}, /* 95 */
+			{1, 1, 4, 3, 1, 1},
+			{4, 1, 1, 1, 1, 3},
+			{4, 1, 1, 3, 1, 1},
+			{1, 1, 3, 1, 4, 1},
+			{1, 1, 4, 1, 3, 1}, /* 100 */
+			{3, 1, 1, 1, 4, 1},
+			{4, 1, 1, 1, 3, 1},
+			{2, 1, 1, 4, 1, 2},
+			{2, 1, 1, 2, 1, 4},
+			{2, 1, 1, 2, 3, 2}, /* 105 */
+			{2, 3, 3, 1, 1, 1}
+		};
+
+
+		Code128Reader::Code128Reader(){
+		}
+
+		int* Code128Reader::findStartPattern(Ref<BitArray> row){
+			int width = row->getSize();
+			int rowOffset = 0;
+			while (rowOffset < width) {
+				if (row->get(rowOffset)) {
+					break;
+				}
+				rowOffset++;
+			}
+
+			int counterPosition = 0;
+			int counters[countersLength] = {0,0,0,0,0,0};
+			int patternStart = rowOffset;
+			bool isWhite = false;
+			int patternLength =  sizeof(counters) / sizeof(int);
+
+			for (int i = rowOffset; i < width; i++) {
+				bool pixel = row->get(i);
+				if (pixel ^ isWhite) {
+					counters[counterPosition]++;
+				} else {
+					if (counterPosition == patternLength - 1) {
+						unsigned int bestVariance = MAX_AVG_VARIANCE;
+						int bestMatch = -1;
+						for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
+							unsigned int variance = patternMatchVariance(counters, sizeof(counters) / sizeof(int),
+							    CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
+							if (variance < bestVariance) {
+								bestVariance = variance;
+								bestMatch = startCode;
+							}
+						}
+						if (bestMatch >= 0) {
+							// Look for whitespace before start pattern, >= 50% of width of start pattern
+              if (row->isRange(std::max(0, patternStart - (i - patternStart) / 2), patternStart,
+							    false)) {
+								int* resultValue = new int[3];
+								resultValue[0] = patternStart;
+								resultValue[1] = i;
+								resultValue[2] = bestMatch;
+								return resultValue;
+							}
+						}
+						patternStart += counters[0] + counters[1];
+						for (int y = 2; y < patternLength; y++) {
+							counters[y - 2] = counters[y];
+						}
+						counters[patternLength - 2] = 0;
+						counters[patternLength - 1] = 0;
+						counterPosition--;
+					} else {
+						counterPosition++;
+					}
+					counters[counterPosition] = 1;
+					isWhite = !isWhite;
+				}
+			}
+			throw ReaderException("");
+		}
+
+		int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount,
+		    int rowOffset) {
+		  if (!recordPattern(row, rowOffset, counters, countersCount)) {
+		    throw ReaderException("");
+		  }
+			unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
+			int bestMatch = -1;
+			for (int d = 0; d < CODE_PATTERNS_LENGTH; d++) {
+				int pattern[countersLength];
+
+				for(int ind = 0; ind< countersLength; ind++){
+					pattern[ind] = CODE_PATTERNS[d][ind];
+				}
+//				memcpy(pattern, CODE_PATTERNS[d], countersLength);
+				unsigned int variance = patternMatchVariance(counters, countersCount, pattern,
+				    MAX_INDIVIDUAL_VARIANCE);
+				if (variance < bestVariance) {
+					bestVariance = variance;
+					bestMatch = d;
+				}
+			}
+			// TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.
+			if (bestMatch >= 0) {
+				return bestMatch;
+			} else {
+				throw ReaderException("");
+			}
+		}
+
+		Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row) {
+		  int* startPatternInfo = NULL;
+		  try {
+        startPatternInfo = findStartPattern(row);
+        int startCode = startPatternInfo[2];
+        int codeSet;
+        switch (startCode) {
+          case CODE_START_A:
+            codeSet = CODE_CODE_A;
+            break;
+          case CODE_START_B:
+            codeSet = CODE_CODE_B;
+            break;
+          case CODE_START_C:
+            codeSet = CODE_CODE_C;
+            break;
+          default:
+            throw ReaderException("");
+        }
+
+        bool done = false;
+        bool isNextShifted = false;
+
+        std::string tmpResultString;
+        std::stringstream tmpResultSStr; // used if its Code 128C
+
+        int lastStart = startPatternInfo[0];
+        int nextStart = startPatternInfo[1];
+        int counters[countersLength] = {0,0,0,0,0,0};
+
+        int lastCode = 0;
+        int code = 0;
+        int checksumTotal = startCode;
+        int multiplier = 0;
+        bool lastCharacterWasPrintable = true;
+
+        while (!done) {
+          bool unshift = isNextShifted;
+          isNextShifted = false;
+
+          // Save off last code
+          lastCode = code;
+
+          // Decode another code from image
+          try {
+            code = decodeCode(row, counters, sizeof(counters)/sizeof(int), nextStart);
+          } catch (ReaderException const& re) {
+            throw re;
+          }
+
+          // Remember whether the last code was printable or not (excluding CODE_STOP)
+          if (code != CODE_STOP) {
+            lastCharacterWasPrintable = true;
+          }
+
+          // Add to checksum computation (if not CODE_STOP of course)
+          if (code != CODE_STOP) {
+            multiplier++;
+            checksumTotal += multiplier * code;
+          }
+
+          // Advance to where the next code will to start
+          lastStart = nextStart;
+          int _countersLength = sizeof(counters) / sizeof(int);
+          for (int i = 0; i < _countersLength; i++) {
+            nextStart += counters[i];
+          }
+
+          // Take care of illegal start codes
+          switch (code) {
+            case CODE_START_A:
+            case CODE_START_B:
+            case CODE_START_C:
+              throw ReaderException("");
+          }
+
+          switch (codeSet) {
+
+            case CODE_CODE_A:
+              if (code < 64) {
+                tmpResultString.append(1, (char) (' ' + code));
+              } else if (code < 96) {
+                tmpResultString.append(1, (char) (code - 64));
+              } else {
+                // Don't let CODE_STOP, which always appears, affect whether whether we think the
+                // last code was printable or not.
+                if (code != CODE_STOP) {
+                  lastCharacterWasPrintable = false;
+                }
+                switch (code) {
+                  case CODE_FNC_1:
+                  case CODE_FNC_2:
+                  case CODE_FNC_3:
+                  case CODE_FNC_4_A:
+                    // do nothing?
+                    break;
+                  case CODE_SHIFT:
+                    isNextShifted = true;
+                    codeSet = CODE_CODE_B;
+                    break;
+                  case CODE_CODE_B:
+                    codeSet = CODE_CODE_B;
+                    break;
+                  case CODE_CODE_C:
+                    codeSet = CODE_CODE_C;
+                    break;
+                  case CODE_STOP:
+                    done = true;
+                    break;
+                }
+              }
+              break;
+            case CODE_CODE_B:
+              if (code < 96) {
+                tmpResultString.append(1, (char) (' ' + code));
+              } else {
+                if (code != CODE_STOP) {
+                  lastCharacterWasPrintable = false;
+                }
+                switch (code) {
+                  case CODE_FNC_1:
+                  case CODE_FNC_2:
+                  case CODE_FNC_3:
+                  case CODE_FNC_4_B:
+                    // do nothing?
+                    break;
+                  case CODE_SHIFT:
+                    isNextShifted = true;
+                    codeSet = CODE_CODE_C;
+                    break;
+                  case CODE_CODE_A:
+                    codeSet = CODE_CODE_A;
+                    break;
+                  case CODE_CODE_C:
+                    codeSet = CODE_CODE_C;
+                    break;
+                  case CODE_STOP:
+                    done = true;
+                    break;
+                }
+              }
+              break;
+            case CODE_CODE_C:
+              tmpResultSStr.str(std::string());
+              // the code read in this case is the number encoded directly
+              if (code < 100) {
+                if (code < 10) {
+ 					        tmpResultSStr << '0';
+ 				        }
+                tmpResultSStr << code;
+ 				        tmpResultString.append(tmpResultSStr.str());
+              } else {
+                if (code != CODE_STOP) {
+                  lastCharacterWasPrintable = false;
+                }
+                switch (code) {
+                  case CODE_FNC_1:
+                    // do nothing?
+                    break;
+                  case CODE_CODE_A:
+                    codeSet = CODE_CODE_A;
+                    break;
+                  case CODE_CODE_B:
+                    codeSet = CODE_CODE_B;
+                    break;
+                  case CODE_STOP:
+                    done = true;
+                    break;
+                }
+              }
+              break;
+          }
+
+          // Unshift back to another code set if we were shifted
+          if (unshift) {
+            switch (codeSet) {
+              case CODE_CODE_A:
+                codeSet = CODE_CODE_C;
+                break;
+              case CODE_CODE_B:
+                codeSet = CODE_CODE_A;
+                break;
+              case CODE_CODE_C:
+                codeSet = CODE_CODE_B;
+                break;
+            }
+          }
+
+        }
+
+        // Check for ample whitespace following pattern, but, to do this we first need to remember that
+        // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left
+        // to read off. Would be slightly better to properly read. Here we just skip it:
+        int width = row->getSize();
+        while (nextStart < width && row->get(nextStart)) {
+          nextStart++;
+        }
+        if (!row->isRange(nextStart,
+                          std::min(width, nextStart + (nextStart - lastStart) / 2),
+                          false)) {
+          throw ReaderException("");
+        }
+
+        // Pull out from sum the value of the penultimate check code
+        checksumTotal -= multiplier * lastCode;
+        // lastCode is the checksum then:
+        if (checksumTotal % 103 != lastCode) {
+          throw ReaderException("");
+        }
+
+        // Need to pull out the check digits from string
+        int resultLength = tmpResultString.length();
+        // Only bother if the result had at least one character, and if the checksum digit happened to
+        // be a printable character. If it was just interpreted as a control code, nothing to remove.
+        if (resultLength > 0 && lastCharacterWasPrintable) {
+          if (codeSet == CODE_CODE_C) {
+            tmpResultString.erase(resultLength - 2, resultLength);
+          } else {
+            tmpResultString.erase(resultLength - 1, resultLength);
+          }
+        }
+
+        Ref<String> resultString(new String(tmpResultString));
+        if (tmpResultString.length() == 0) {
+          // Almost surely a false positive
+          throw ReaderException("");
+        }
+
+        float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
+        float right = (float) (nextStart + lastStart) / 2.0f;
+
+        std::vector< Ref<ResultPoint> > resultPoints(2);
+        Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
+        Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
+        resultPoints[0] = resultPoint1;
+        resultPoints[1] = resultPoint2;
+
+        delete [] startPatternInfo;
+        ArrayRef<unsigned char> resultBytes(1);
+        return Ref<Result>(new Result(resultString, resultBytes, resultPoints,
+            BarcodeFormat_CODE_128));
+			} catch (ReaderException const& re) {
+			  delete [] startPatternInfo;
+			  return Ref<Result>();
+			}
+		}
+
+		void Code128Reader::append(char* s, char c){
+			int len = strlen(s);
+			s[len] = c;
+			s[len + 1] = '\0';
+		}
+
+		Code128Reader::~Code128Reader(){
+		}
+	}
+}
+
+// file: zxing/oned/Code39Reader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "Code39Reader.h"
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/ReaderException.h>
+// #include <math.h>
+// #include <limits.h>
+
+namespace zxing {
+namespace oned {
+
+  static const char* ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
+
+
+  /**
+   * These represent the encodings of characters, as patterns of wide and narrow
+   * bars.
+   * The 9 least-significant bits of each int correspond to the pattern of wide
+   * and narrow, with 1s representing "wide" and 0s representing narrow.
+   */
+  const int CHARACTER_ENCODINGS_LEN = 44;
+  static int CHARACTER_ENCODINGS[CHARACTER_ENCODINGS_LEN] = {
+    0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9
+    0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J
+    0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T
+    0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-*
+    0x0A8, 0x0A2, 0x08A, 0x02A // $-%
+  };
+
+  static int ASTERISK_ENCODING = 0x094;
+  static const char* ALPHABET_STRING =
+    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
+
+
+  /**
+   * Creates a reader that assumes all encoded data is data, and does not treat
+   * the final character as a check digit. It will not decoded "extended
+   * Code 39" sequences.
+   */
+  Code39Reader::Code39Reader() : alphabet_string(ALPHABET_STRING),
+                                 usingCheckDigit(false),
+                                 extendedMode(false) {
+  }
+
+  /**
+   * Creates a reader that can be configured to check the last character as a
+   * check digit. It will not decoded "extended Code 39" sequences.
+   *
+   * @param usingCheckDigit if true, treat the last data character as a check
+   * digit, not data, and verify that the checksum passes.
+   */
+  Code39Reader::Code39Reader(bool usingCheckDigit_) :
+    alphabet_string(ALPHABET_STRING),
+    usingCheckDigit(usingCheckDigit_),
+    extendedMode(false) {
+  }
+
+
+  Code39Reader::Code39Reader(bool usingCheckDigit_, bool extendedMode_) :
+    alphabet_string(ALPHABET_STRING),
+    usingCheckDigit(usingCheckDigit_),
+    extendedMode(extendedMode_) {
+  }
+
+  Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row) {
+    int* start = NULL;
+    try {
+      start = findAsteriskPattern(row);
+      int nextStart = start[1];
+      int end = row->getSize();
+
+      // Read off white space
+      while (nextStart < end && !row->get(nextStart)) {
+        nextStart++;
+      }
+
+      std::string tmpResultString;
+
+      const int countersLen = 9;
+      int counters[countersLen];
+      for (int i = 0; i < countersLen; i++) {
+        counters[i] = 0;
+      }
+      char decodedChar;
+      int lastStart;
+      do {
+        if (!recordPattern(row, nextStart, counters, countersLen)) {
+          throw ReaderException("");
+        }
+        int pattern = toNarrowWidePattern(counters, countersLen);
+        if (pattern < 0) {
+          throw ReaderException("pattern < 0");
+        }
+        decodedChar = patternToChar(pattern);
+        tmpResultString.append(1, decodedChar);
+        lastStart = nextStart;
+        for (int i = 0; i < countersLen; i++) {
+          nextStart += counters[i];
+        }
+        // Read off white space
+        while (nextStart < end && !row->get(nextStart)) {
+          nextStart++;
+        }
+      } while (decodedChar != '*');
+      tmpResultString.erase(tmpResultString.length()-1, 1);// remove asterisk
+
+      // Look for whitespace after pattern:
+      int lastPatternSize = 0;
+      for (int i = 0; i < countersLen; i++) {
+        lastPatternSize += counters[i];
+      }
+      int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
+      // If 50% of last pattern size, following last pattern, is not whitespace,
+      // fail (but if it's whitespace to the very end of the image, that's OK)
+      if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) {
+        throw ReaderException("too short end white space");
+      }
+
+      if (usingCheckDigit) {
+        int max = tmpResultString.length() - 1;
+        unsigned int total = 0;
+        for (int i = 0; i < max; i++) {
+          total += alphabet_string.find_first_of(tmpResultString[i], 0);
+        }
+        if (total % 43 != alphabet_string.find_first_of(tmpResultString[max], 0)) {
+          throw ReaderException("");
+        }
+        tmpResultString.erase(max, 1);
+      }
+
+      Ref<String> resultString(new String(tmpResultString));
+      if (extendedMode) {
+        resultString = decodeExtended(tmpResultString);
+      }
+
+      if (tmpResultString.length() == 0) {
+        // Almost surely a false positive
+        throw ReaderException("");
+      }
+
+      float left = (float) (start[1] + start[0]) / 2.0f;
+      float right = (float) (nextStart + lastStart) / 2.0f;
+
+      std::vector< Ref<ResultPoint> > resultPoints(2);
+      Ref<OneDResultPoint> resultPoint1(
+        new OneDResultPoint(left, (float) rowNumber));
+      Ref<OneDResultPoint> resultPoint2(
+        new OneDResultPoint(right, (float) rowNumber));
+      resultPoints[0] = resultPoint1;
+      resultPoints[1] = resultPoint2;
+
+      ArrayRef<unsigned char> resultBytes(1);
+
+      Ref<Result> res(new Result(
+                        resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39));
+
+      delete [] start;
+      return res;
+    } catch (ReaderException const& re) {
+      delete [] start;
+      return Ref<Result>();
+    }
+  }
+
+  int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){
+    int width = row->getSize();
+    int rowOffset = 0;
+    while (rowOffset < width) {
+      if (row->get(rowOffset)) {
+        break;
+      }
+      rowOffset++;
+    }
+
+    int counterPosition = 0;
+    const int countersLen = 9;
+    int counters[countersLen];
+    for (int i = 0; i < countersLen; i++) {
+      counters[i] = 0;
+    }
+    int patternStart = rowOffset;
+    bool isWhite = false;
+    int patternLength = countersLen;
+
+    for (int i = rowOffset; i < width; i++) {
+      bool pixel = row->get(i);
+      if (pixel ^ isWhite) {
+        counters[counterPosition]++;
+      } else {
+        if (counterPosition == patternLength - 1) {
+          if (toNarrowWidePattern(counters, countersLen) == ASTERISK_ENCODING) {
+            // Look for whitespace before start pattern, >= 50% of width of
+            // start pattern.
+            if (row->isRange(std::max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) {
+              int* resultValue = new int[2];
+              resultValue[0] = patternStart;
+              resultValue[1] = i;
+              return resultValue;
+            }
+          }
+          patternStart += counters[0] + counters[1];
+          for (int y = 2; y < patternLength; y++) {
+            counters[y - 2] = counters[y];
+          }
+          counters[patternLength - 2] = 0;
+          counters[patternLength - 1] = 0;
+          counterPosition--;
+        } else {
+          counterPosition++;
+        }
+        counters[counterPosition] = 1;
+        isWhite = !isWhite;
+      }
+    }
+    throw ReaderException("");
+  }
+
+  // For efficiency, returns -1 on failure. Not throwing here saved as many as
+  // 700 exceptions per image when using some of our blackbox images.
+  int Code39Reader::toNarrowWidePattern(int counters[], int countersLen){
+    int numCounters = countersLen;
+    int maxNarrowCounter = 0;
+    int wideCounters;
+    do {
+      int minCounter = INT_MAX;
+      for (int i = 0; i < numCounters; i++) {
+        int counter = counters[i];
+        if (counter < minCounter && counter > maxNarrowCounter) {
+          minCounter = counter;
+        }
+      }
+      maxNarrowCounter = minCounter;
+      wideCounters = 0;
+      int totalWideCountersWidth = 0;
+      int pattern = 0;
+      for (int i = 0; i < numCounters; i++) {
+        int counter = counters[i];
+        if (counters[i] > maxNarrowCounter) {
+          pattern |= 1 << (numCounters - 1 - i);
+          wideCounters++;
+          totalWideCountersWidth += counter;
+        }
+      }
+      if (wideCounters == 3) {
+        // Found 3 wide counters, but are they close enough in width?
+        // We can perform a cheap, conservative check to see if any individual
+        // counter is more than 1.5 times the average:
+        for (int i = 0; i < numCounters && wideCounters > 0; i++) {
+          int counter = counters[i];
+          if (counters[i] > maxNarrowCounter) {
+            wideCounters--;
+            // totalWideCountersWidth = 3 * average, so this checks if
+            // counter >= 3/2 * average.
+            if ((counter << 1) >= totalWideCountersWidth) {
+              return -1;
+            }
+          }
+        }
+        return pattern;
+      }
+    } while (wideCounters > 3);
+    return -1;
+  }
+
+  char Code39Reader::patternToChar(int pattern){
+    for (int i = 0; i < CHARACTER_ENCODINGS_LEN; i++) {
+      if (CHARACTER_ENCODINGS[i] == pattern) {
+        return ALPHABET[i];
+      }
+    }
+    throw ReaderException("");
+  }
+
+  Ref<String> Code39Reader::decodeExtended(std::string encoded){
+    int length = encoded.length();
+    std::string tmpDecoded;
+    for (int i = 0; i < length; i++) {
+      char c = encoded[i];
+      if (c == '+' || c == '$' || c == '%' || c == '/') {
+        char next = encoded[i + 1];
+        char decodedChar = '\0';
+        switch (c) {
+          case '+':
+            // +A to +Z map to a to z
+            if (next >= 'A' && next <= 'Z') {
+              decodedChar = (char) (next + 32);
+            } else {
+              throw ReaderException("");
+            }
+            break;
+          case '$':
+            // $A to $Z map to control codes SH to SB
+            if (next >= 'A' && next <= 'Z') {
+              decodedChar = (char) (next - 64);
+            } else {
+              throw ReaderException("");
+            }
+            break;
+          case '%':
+            // %A to %E map to control codes ESC to US
+            if (next >= 'A' && next <= 'E') {
+              decodedChar = (char) (next - 38);
+            } else if (next >= 'F' && next <= 'W') {
+              decodedChar = (char) (next - 11);
+            } else {
+              throw ReaderException("");
+            }
+            break;
+          case '/':
+            // /A to /O map to ! to , and /Z maps to :
+            if (next >= 'A' && next <= 'O') {
+              decodedChar = (char) (next - 32);
+            } else if (next == 'Z') {
+              decodedChar = ':';
+            } else {
+              throw ReaderException("");
+            }
+            break;
+        }
+        tmpDecoded.append(1, decodedChar);
+        // bump up i again since we read two characters
+        i++;
+      } else {
+        tmpDecoded.append(1, c);
+      }
+    }
+    Ref<String> decoded(new String(tmpDecoded));
+    return decoded;
+  }
+} // namespace oned
+} // namespace zxing
+
+
+// file: zxing/oned/EAN13Reader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "EAN13Reader.h"
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+
+    static const int FIRST_DIGIT_ENCODINGS[10] = {
+      0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
+    };
+
+    EAN13Reader::EAN13Reader() { }
+
+    int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+        std::string& resultString) {
+      (void)startGuardBegin;
+      const int countersLen = 4;
+      int counters[countersLen] = { 0, 0, 0, 0 };
+
+      int end = row->getSize();
+      int rowOffset = startGuardEnd;
+      int lgPatternFound = 0;
+
+      for (int x = 0; x < 6 && rowOffset < end; x++) {
+        int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
+            UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
+        if (bestMatch < 0) {
+          return -1;
+        }
+        resultString.append(1, (char) ('0' + bestMatch % 10));
+        for (int i = 0; i < countersLen; i++) {
+          rowOffset += counters[i];
+        }
+        if (bestMatch >= 10) {
+          lgPatternFound |= 1 << (5 - x);
+        }
+      }
+
+      if (!determineFirstDigit(resultString, lgPatternFound)) {
+        return -1;
+      }
+
+      int middleRangeStart;
+      int middleRangeEnd;
+      if (findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
+            getMIDDLE_PATTERN_LEN(), &middleRangeStart, &middleRangeEnd)) {
+        rowOffset = middleRangeEnd;
+        for (int x = 0; x < 6 && rowOffset < end; x++) {
+          int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
+              UPC_EAN_PATTERNS_L_PATTERNS);
+          if (bestMatch < 0) {
+            return -1;
+          }
+          resultString.append(1, (char) ('0' + bestMatch));
+          for (int i = 0; i < countersLen; i++) {
+            rowOffset += counters[i];
+          }
+        }
+        return rowOffset;
+      }
+      return -1;
+    }
+
+    bool EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound) {
+      for (int d = 0; d < 10; d++) {
+        if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) {
+          resultString.insert(0, 1, (char) ('0' + d));
+          return true;
+        }
+      }
+      return false;
+    }
+
+    BarcodeFormat EAN13Reader::getBarcodeFormat(){
+      return BarcodeFormat_EAN_13;
+    }
+  }
+}
+
+// file: zxing/oned/EAN8Reader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "EAN8Reader.h"
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+
+    EAN8Reader::EAN8Reader(){ }
+
+    int EAN8Reader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+        std::string& resultString){
+      (void)startGuardBegin;
+      const int countersLen = 4;
+      int counters[countersLen] = { 0, 0, 0, 0 };
+
+      int end = row->getSize();
+      int rowOffset = startGuardEnd;
+
+      for (int x = 0; x < 4 && rowOffset < end; x++) {
+        int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
+            UPC_EAN_PATTERNS_L_PATTERNS);
+        if (bestMatch < 0) {
+          return -1;
+        }
+        resultString.append(1, (char) ('0' + bestMatch));
+        for (int i = 0; i < countersLen; i++) {
+          rowOffset += counters[i];
+        }
+      }
+
+      int middleRangeStart;
+      int middleRangeEnd;
+      if (findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
+            getMIDDLE_PATTERN_LEN(), &middleRangeStart, &middleRangeEnd)) {
+        rowOffset = middleRangeEnd;
+        for (int x = 0; x < 4 && rowOffset < end; x++) {
+          int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
+              UPC_EAN_PATTERNS_L_PATTERNS);
+          if (bestMatch < 0) {
+            return -1;
+          }
+          resultString.append(1, (char) ('0' + bestMatch));
+          for (int i = 0; i < countersLen; i++) {
+            rowOffset += counters[i];
+          }
+        }
+        return rowOffset;
+      }
+      return -1;
+    }
+
+    BarcodeFormat EAN8Reader::getBarcodeFormat(){
+      return BarcodeFormat_EAN_8;
+    }
+  }
+}
+
+// file: zxing/oned/ITFReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "ITFReader.h"
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/ReaderException.h>
+// #include <math.h>
+
+namespace zxing {
+  namespace oned {
+
+    static const int W = 3; // Pixel width of a wide line
+    static const int N = 1; // Pixed width of a narrow line
+
+    const int DEFAULT_ALLOWED_LENGTHS_LEN = 10;
+    const int DEFAULT_ALLOWED_LENGTHS[DEFAULT_ALLOWED_LENGTHS_LEN] = { 44, 24, 20, 18, 16, 14, 12, 10, 8, 6 };
+
+    /**
+     * Start/end guard pattern.
+     *
+     * Note: The end pattern is reversed because the row is reversed before
+     * searching for the END_PATTERN
+     */
+    static const int START_PATTERN_LEN = 4;
+    static const int START_PATTERN[START_PATTERN_LEN] = {N, N, N, N};
+
+    static const int END_PATTERN_REVERSED_LEN = 3;
+    static const int END_PATTERN_REVERSED[END_PATTERN_REVERSED_LEN] = {N, N, W};
+
+    /**
+     * Patterns of Wide / Narrow lines to indicate each digit
+     */
+    static const int PATTERNS_LEN = 10;
+    static const int PATTERNS[PATTERNS_LEN][5] = {
+      {N, N, W, W, N}, // 0
+      {W, N, N, N, W}, // 1
+      {N, W, N, N, W}, // 2
+      {W, W, N, N, N}, // 3
+      {N, N, W, N, W}, // 4
+      {W, N, W, N, N}, // 5
+      {N, W, W, N, N}, // 6
+      {N, N, N, W, W}, // 7
+      {W, N, N, W, N}, // 8
+      {N, W, N, W, N}  // 9
+    };
+
+
+    ITFReader::ITFReader() : narrowLineWidth(-1) {
+    }
+
+
+    Ref<Result> ITFReader::decodeRow(int rowNumber, Ref<BitArray> row) {
+      int* startRange = 0;
+      int* endRange = 0;
+      try {
+        // Find out where the Middle section (payload) starts & ends
+        startRange = decodeStart(row);
+        endRange = decodeEnd(row);
+
+        std::string tmpResult;
+        decodeMiddle(row, startRange[1], endRange[0], tmpResult);
+
+        // To avoid false positives with 2D barcodes (and other patterns), make
+        // an assumption that the decoded string must be a known length
+        int length = tmpResult.length();
+        bool lengthOK = false;
+        for (int i = 0; i < DEFAULT_ALLOWED_LENGTHS_LEN; i++) {
+          if (length == DEFAULT_ALLOWED_LENGTHS[i]) {
+            lengthOK = true;
+            break;
+          }
+        }
+        if (!lengthOK) {
+          throw ReaderException("not enough characters count");
+        }
+
+        Ref<String> resultString(new String(tmpResult));
+
+        std::vector< Ref<ResultPoint> > resultPoints(2);
+        Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(startRange[1], (float) rowNumber));
+        Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(endRange[0], (float) rowNumber));
+        resultPoints[0] = resultPoint1;
+        resultPoints[1] = resultPoint2;
+
+        delete [] startRange;
+        delete [] endRange;
+        ArrayRef<unsigned char> resultBytes(1);
+        return Ref<Result>(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF));
+      } catch (ReaderException const& re) {
+        delete [] startRange;
+        delete [] endRange;
+        return Ref<Result>();
+      }
+    }
+
+    /**
+     * @param row          row of black/white values to search
+     * @param payloadStart offset of start pattern
+     * @param resultString {@link StringBuffer} to append decoded chars to
+     * @throws ReaderException if decoding could not complete successfully
+     */
+    void ITFReader::decodeMiddle(Ref<BitArray> row, int payloadStart, int payloadEnd,
+        std::string& resultString) {
+      // Digits are interleaved in pairs - 5 black lines for one digit, and the
+      // 5
+      // interleaved white lines for the second digit.
+      // Therefore, need to scan 10 lines and then
+      // split these into two arrays
+      int counterDigitPairLen = 10;
+      int counterDigitPair[counterDigitPairLen];
+      for (int i=0; i<counterDigitPairLen; i++) {
+        counterDigitPair[i] = 0;
+      }
+
+      int counterBlack[5];
+      int counterWhite[5];
+      for (int i=0; i<5; i++) {
+        counterBlack[i] = 0;
+        counterWhite[i] = 0;
+      }
+
+      while (payloadStart < payloadEnd) {
+        // Get 10 runs of black/white.
+        if (!recordPattern(row, payloadStart, counterDigitPair, counterDigitPairLen)) {
+          throw ReaderException("");
+        }
+        // Split them into each array
+        for (int k = 0; k < 5; k++) {
+          int twoK = k << 1;
+          counterBlack[k] = counterDigitPair[twoK];
+          counterWhite[k] = counterDigitPair[twoK + 1];
+        }
+
+        int bestMatch = decodeDigit(counterBlack, 5);
+        resultString.append(1, (char) ('0' + bestMatch));
+        bestMatch = decodeDigit(counterWhite, 5);
+        resultString.append(1, (char) ('0' + bestMatch));
+
+        for (int i = 0; i < counterDigitPairLen; i++) {
+          payloadStart += counterDigitPair[i];
+        }
+      }
+    }
+
+    /**
+     * Identify where the start of the middle / payload section starts.
+     *
+     * @param row row of black/white values to search
+     * @return Array, containing index of start of 'start block' and end of
+     *         'start block'
+     * @throws ReaderException
+     */
+    int* ITFReader::decodeStart(Ref<BitArray> row) {
+      int endStart = skipWhiteSpace(row);
+      int* startPattern = 0;
+      try {
+          startPattern = findGuardPattern(row, endStart, START_PATTERN, START_PATTERN_LEN);
+
+          // Determine the width of a narrow line in pixels. We can do this by
+          // getting the width of the start pattern and dividing by 4 because its
+          // made up of 4 narrow lines.
+          narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2;
+          validateQuietZone(row, startPattern[0]);
+          return startPattern;
+      } catch (ReaderException const& re) {
+          delete [] startPattern;
+        throw re;
+      }
+    }
+
+    /**
+     * Identify where the end of the middle / payload section ends.
+     *
+     * @param row row of black/white values to search
+     * @return Array, containing index of start of 'end block' and end of 'end
+     *         block'
+     * @throws ReaderException
+     */
+
+    int* ITFReader::decodeEnd(Ref<BitArray> row) {
+      // For convenience, reverse the row and then
+      // search from 'the start' for the end block
+      row->reverse();
+                        int* endPattern = 0;
+      try {
+        int endStart = skipWhiteSpace(row);
+        endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED, END_PATTERN_REVERSED_LEN);
+
+        // The start & end patterns must be pre/post fixed by a quiet zone. This
+        // zone must be at least 10 times the width of a narrow line.
+        // ref: http://www.barcode-1.net/i25code.html
+        validateQuietZone(row, endPattern[0]);
+
+        // Now recalculate the indices of where the 'endblock' starts & stops to
+        // accommodate
+        // the reversed nature of the search
+        int temp = endPattern[0];
+        endPattern[0] = row->getSize() - endPattern[1];
+        endPattern[1] = row->getSize() - temp;
+
+        row->reverse();
+        return endPattern;
+      } catch (ReaderException const& re) {
+                                delete [] endPattern;
+        row->reverse();
+        throw re;
+      }
+    }
+
+    /**
+     * The start & end patterns must be pre/post fixed by a quiet zone. This
+     * zone must be at least 10 times the width of a narrow line.  Scan back until
+     * we either get to the start of the barcode or match the necessary number of
+     * quiet zone pixels.
+     *
+     * Note: Its assumed the row is reversed when using this method to find
+     * quiet zone after the end pattern.
+     *
+     * ref: http://www.barcode-1.net/i25code.html
+     *
+     * @param row bit array representing the scanned barcode.
+     * @param startPattern index into row of the start or end pattern.
+     * @throws ReaderException if the quiet zone cannot be found, a ReaderException is thrown.
+     */
+    void ITFReader::validateQuietZone(Ref<BitArray> row, int startPattern) {
+      (void)row;
+      (void)startPattern;
+//#pragma mark needs some corrections
+//      int quietCount = narrowLineWidth * 10;  // expect to find this many pixels of quiet zone
+//
+//      for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) {
+//        if (row->get(i)) {
+//          break;
+//        }
+//        quietCount--;
+//      }
+//      if (quietCount != 0) {
+//        // Unable to find the necessary number of quiet zone pixels.
+//        throw ReaderException("Unable to find the necessary number of quiet zone pixels");
+//      }
+    }
+
+    /**
+     * Skip all whitespace until we get to the first black line.
+     *
+     * @param row row of black/white values to search
+     * @return index of the first black line.
+     * @throws ReaderException Throws exception if no black lines are found in the row
+     */
+    int ITFReader::skipWhiteSpace(Ref<BitArray> row) {
+      int width = row->getSize();
+      int endStart = 0;
+      while (endStart < width) {
+        if (row->get(endStart)) {
+          break;
+        }
+        endStart++;
+      }
+      if (endStart == width) {
+        throw ReaderException("");
+      }
+      return endStart;
+    }
+
+    /**
+     * @param row       row of black/white values to search
+     * @param rowOffset position to start search
+     * @param pattern   pattern of counts of number of black and white pixels that are
+     *                  being searched for as a pattern
+     * @return start/end horizontal offset of guard pattern, as an array of two
+     *         ints
+     * @throws ReaderException if pattern is not found
+     */
+    int* ITFReader::findGuardPattern(Ref<BitArray> row, int rowOffset, const int pattern[],
+        int patternLen) {
+      // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be
+      // merged to a single method.
+      int patternLength = patternLen;
+      int counters[patternLength];
+      for (int i=0; i<patternLength; i++) {
+        counters[i] = 0;
+      }
+      int width = row->getSize();
+      bool isWhite = false;
+
+      int counterPosition = 0;
+      int patternStart = rowOffset;
+      for (int x = rowOffset; x < width; x++) {
+        bool pixel = row->get(x);
+        if (pixel ^ isWhite) {
+          counters[counterPosition]++;
+        } else {
+          if (counterPosition == patternLength - 1) {
+            if (patternMatchVariance(counters, patternLength, pattern,
+                MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
+              int* resultValue = new int[2];
+              resultValue[0] = patternStart;
+              resultValue[1] = x;
+              return resultValue;
+            }
+            patternStart += counters[0] + counters[1];
+            for (int y = 2; y < patternLength; y++) {
+              counters[y - 2] = counters[y];
+            }
+            counters[patternLength - 2] = 0;
+            counters[patternLength - 1] = 0;
+            counterPosition--;
+          } else {
+            counterPosition++;
+          }
+          counters[counterPosition] = 1;
+          isWhite = !isWhite;
+        }
+      }
+      throw ReaderException("");
+    }
+
+    /**
+     * Attempts to decode a sequence of ITF black/white lines into single
+     * digit.
+     *
+     * @param counters the counts of runs of observed black/white/black/... values
+     * @return The decoded digit
+     * @throws ReaderException if digit cannot be decoded
+     */
+    int ITFReader::decodeDigit(int counters[], int countersLen){
+      unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
+      int bestMatch = -1;
+      int max = PATTERNS_LEN;
+      for (int i = 0; i < max; i++) {
+        int pattern[countersLen];
+        for(int ind = 0; ind<countersLen; ind++){
+          pattern[ind] = PATTERNS[i][ind];
+        }
+        unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
+            MAX_INDIVIDUAL_VARIANCE);
+        if (variance < bestVariance) {
+          bestVariance = variance;
+          bestMatch = i;
+        }
+      }
+      if (bestMatch >= 0) {
+        return bestMatch;
+      } else {
+        throw ReaderException("digit didint found");
+      }
+    }
+
+    ITFReader::~ITFReader(){
+    }
+  }
+}
+
+// file: zxing/oned/MultiFormatOneDReader.cpp
+
+/*
+ *  MultiFormatOneDReader.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "MultiFormatOneDReader.h"
+
+// #include <zxing/oned/MultiFormatUPCEANReader.h>
+// #include <zxing/oned/Code39Reader.h>
+// #include <zxing/oned/Code128Reader.h>
+// #include <zxing/oned/ITFReader.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+    MultiFormatOneDReader::MultiFormatOneDReader(DecodeHints hints) : readers() {
+      if (hints.containsFormat(BarcodeFormat_EAN_13) ||
+          hints.containsFormat(BarcodeFormat_EAN_8) ||
+          hints.containsFormat(BarcodeFormat_UPC_A) ||
+          hints.containsFormat(BarcodeFormat_UPC_E)) {
+        readers.push_back(Ref<OneDReader>(new MultiFormatUPCEANReader(hints)));
+      }
+      if (hints.containsFormat(BarcodeFormat_CODE_39)) {
+        readers.push_back(Ref<OneDReader>(new Code39Reader()));
+      }
+      if (hints.containsFormat(BarcodeFormat_CODE_128)) {
+        readers.push_back(Ref<OneDReader>(new Code128Reader()));
+      }
+      if (hints.containsFormat(BarcodeFormat_ITF)) {
+        readers.push_back(Ref<OneDReader>(new ITFReader()));
+      }
+      if (readers.size() == 0) {
+        readers.push_back(Ref<OneDReader>(new MultiFormatUPCEANReader(hints)));
+        readers.push_back(Ref<OneDReader>(new Code39Reader()));
+        readers.push_back(Ref<OneDReader>(new Code128Reader()));
+        readers.push_back(Ref<OneDReader>(new ITFReader()));
+      }
+    }
+
+    Ref<Result> MultiFormatOneDReader::decodeRow(int rowNumber, Ref<BitArray> row) {
+      int size = readers.size();
+      for (int i = 0; i < size; i++) {
+        OneDReader* reader = readers[i];
+        Ref<Result> result = reader->decodeRow(rowNumber, row);
+        if (!result.empty()) {
+          return result;
+        }
+      }
+      return Ref<Result>();
+    }
+  }
+}
+
+// file: zxing/oned/MultiFormatUPCEANReader.cpp
+
+/*
+ *  MultiFormatUPCEANReader.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// #include "MultiFormatUPCEANReader.h"
+
+// #include <zxing/oned/EAN13Reader.h>
+// #include <zxing/oned/EAN8Reader.h>
+// #include <zxing/oned/UPCEReader.h>
+// #include <zxing/oned/UPCAReader.h>
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/ReaderException.h>
+// #include <math.h>
+
+namespace zxing {
+  namespace oned {
+
+    MultiFormatUPCEANReader::MultiFormatUPCEANReader(DecodeHints hints) : readers() {
+      if (hints.containsFormat(BarcodeFormat_EAN_13)) {
+        readers.push_back(Ref<OneDReader>(new EAN13Reader()));
+      } else if (hints.containsFormat(BarcodeFormat_UPC_A)) {
+        readers.push_back(Ref<OneDReader>(new UPCAReader()));
+      }
+      if (hints.containsFormat(BarcodeFormat_EAN_8)) {
+        readers.push_back(Ref<OneDReader>(new EAN8Reader()));
+      }
+      if (hints.containsFormat(BarcodeFormat_UPC_E)) {
+        readers.push_back(Ref<OneDReader>(new UPCEReader()));
+      }
+      if (readers.size() == 0) {
+        readers.push_back(Ref<OneDReader>(new EAN13Reader()));
+        // UPC-A is covered by EAN-13
+        readers.push_back(Ref<OneDReader>(new EAN8Reader()));
+        readers.push_back(Ref<OneDReader>(new UPCEReader()));
+      }
+    }
+
+    Ref<Result> MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
+      // Compute this location once and reuse it on multiple implementations
+      int size = readers.size();
+      for (int i = 0; i < size; i++) {
+        Ref<OneDReader> reader = readers[i];
+        Ref<Result> result = reader->decodeRow(rowNumber, row);
+        if (result.empty()) {
+          continue;
+        }
+
+        // Special case: a 12-digit code encoded in UPC-A is identical to a "0"
+        // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,
+        // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0".
+        // Individually these are correct and their readers will both read such a code
+        // and correctly call it EAN-13, or UPC-A, respectively.
+        //
+        // In this case, if we've been looking for both types, we'd like to call it
+        // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read
+        // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A
+        // result if appropriate.
+        if (result->getBarcodeFormat() == BarcodeFormat_EAN_13) {
+          const std::string& text = (result->getText())->getText();
+          if (text[0] == '0') {
+            Ref<String> resultString(new String(text.substr(1)));
+            Ref<Result> res(new Result(resultString, result->getRawBytes(),
+                result->getResultPoints(), BarcodeFormat_UPC_A));
+            return res;
+          }
+        }
+        return result;
+      }
+      return Ref<Result>();
+    }
+  }
+}
+
+// file: zxing/oned/OneDReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  OneDReader.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "OneDReader.h"
+// #include <zxing/ReaderException.h>
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <math.h>
+// #include <limits.h>
+
+namespace zxing {
+  namespace oned {
+    using namespace std;
+
+    OneDReader::OneDReader() {
+    }
+
+    Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+      Ref<Result> result = doDecode(image, hints);
+      if (result.empty()) { // && hints.getTryHarder() && image->isRotateSupported()) {
+        Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise());
+        result = doDecode(rotatedImage, hints);
+        if (!result.empty()) {
+          /*
+          // Record that we found it rotated 90 degrees CCW / 270 degrees CW
+          Hashtable metadata = result.getResultMetadata();
+          int orientation = 270;
+          if (metadata != null && metadata.containsKey(ResultMetadataType.ORIENTATION)) {
+            // But if we found it reversed in doDecode(), add in that result here:
+            orientation = (orientation +
+                     ((Integer) metadata.get(ResultMetadataType.ORIENTATION)).intValue()) % 360;
+          }
+          result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(orientation));
+          */
+          // Update result points
+          std::vector<Ref<ResultPoint> >& points (result->getResultPoints());
+          int height = rotatedImage->getHeight();
+          for (size_t i = 0; i < points.size(); i++) {
+            points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX()));
+          }
+        }
+      }
+      if (result.empty()) {
+        throw ReaderException("");
+      }
+      return result;
+    }
+
+    Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) {
+      int width = image->getWidth();
+      int height = image->getHeight();
+      Ref<BitArray> row(new BitArray(width));
+      int middle = height >> 1;
+      bool tryHarder = hints.getTryHarder();
+      int rowStep = (int)fmax(1, height >> (tryHarder ? 8 : 5));
+      int maxLines;
+      if (tryHarder) {
+        maxLines = height; // Look at the whole image, not just the center
+      } else {
+        maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image
+      }
+
+      for (int x = 0; x < maxLines; x++) {
+        // Scanning from the middle out. Determine which row we're looking at next:
+        int rowStepsAboveOrBelow = (x + 1) >> 1;
+        bool isAbove = (x & 0x01) == 0; // i.e. is x even?
+        int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
+        if (rowNumber < 0 || rowNumber >= height) {
+          // Oops, if we run off the top or bottom, stop
+          break;
+        }
+
+        // Estimate black point for this row and load it:
+        try {
+          row = image->getBlackRow(rowNumber, row);
+        } catch (ReaderException const& re) {
+          continue;
+        } catch (IllegalArgumentException const& re) {
+          continue;
+        }
+
+        // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
+        // handle decoding upside down barcodes.
+        for (int attempt = 0; attempt < 2; attempt++) {
+          if (attempt == 1) {
+            row->reverse(); // reverse the row and continue
+          }
+
+          // Look for a barcode
+          Ref<Result> result = decodeRow(rowNumber, row);
+          // We found our barcode
+          if (!result.empty()) {
+            if (attempt == 1) {
+              // But it was upside down, so note that
+              // result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
+              // And remember to flip the result points horizontally.
+              std::vector<Ref<ResultPoint> > points(result->getResultPoints());
+              // if there's exactly two points (which there should be), flip the x coordinate
+              // if there's not exactly 2, I don't know what do do with it
+              if (points.size() == 2) {
+                Ref<ResultPoint> pointZero(new OneDResultPoint(width - points[0]->getX() - 1,
+                    points[0]->getY()));
+                points[0] = pointZero;
+
+                Ref<ResultPoint> pointOne(new OneDResultPoint(width - points[1]->getX() - 1,
+                    points[1]->getY()));
+                points[1] = pointOne;
+
+                result.reset(new Result(result->getText(), result->getRawBytes(), points,
+                    result->getBarcodeFormat()));
+              }
+            }
+            return result;
+          }
+        }
+      }
+      return Ref<Result>();
+    }
+
+    unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize,
+        const int pattern[], int maxIndividualVariance) {
+      int numCounters = countersSize;
+      unsigned int total = 0;
+      unsigned int patternLength = 0;
+      for (int i = 0; i < numCounters; i++) {
+        total += counters[i];
+        patternLength += pattern[i];
+      }
+      if (total < patternLength) {
+        // If we don't even have one pixel per unit of bar width, assume this is too small
+        // to reliably match, so fail:
+        return INT_MAX;
+      }
+      // We're going to fake floating-point math in integers. We just need to use more bits.
+      // Scale up patternLength so that intermediate values below like scaledCounter will have
+      // more "significant digits"
+      unsigned int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
+      maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;
+
+      unsigned int totalVariance = 0;
+      for (int x = 0; x < numCounters; x++) {
+        int counter = counters[x] << INTEGER_MATH_SHIFT;
+        int scaledPattern = pattern[x] * unitBarWidth;
+        int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;
+        if (variance > maxIndividualVariance) {
+          return INT_MAX;
+        }
+        totalVariance += variance;
+      }
+      return totalVariance / total;
+    }
+
+    bool OneDReader::recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount) {
+      int numCounters = countersCount;//sizeof(counters) / sizeof(int);
+      for (int i = 0; i < numCounters; i++) {
+        counters[i] = 0;
+      }
+      int end = row->getSize();
+      if (start >= end) {
+        return false;
+      }
+      bool isWhite = !row->get(start);
+      int counterPosition = 0;
+      int i = start;
+      while (i < end) {
+        bool pixel = row->get(i);
+        if (pixel ^ isWhite) { // that is, exactly one is true
+          counters[counterPosition]++;
+        } else {
+          counterPosition++;
+          if (counterPosition == numCounters) {
+            break;
+          } else {
+            counters[counterPosition] = 1;
+            isWhite ^= true; // isWhite = !isWhite;
+          }
+        }
+        i++;
+      }
+      // If we read fully the last section of pixels and filled up our counters -- or filled
+      // the last counter but ran off the side of the image, OK. Otherwise, a problem.
+      if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) {
+        return false;
+      }
+      return true;
+    }
+
+    OneDReader::~OneDReader() {
+    }
+  }
+}
+
+// file: zxing/oned/OneDResultPoint.cpp
+
+/*
+ *  OneDResultPoint.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "OneDResultPoint.h"
+
+namespace zxing {
+	namespace oned {
+
+		OneDResultPoint::OneDResultPoint(float posX, float posY) : ResultPoint(posX,posY) {
+		}
+	}
+}
+
+// file: zxing/oned/UPCAReader.cpp
+
+/*
+ *  UPCAReader.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "UPCAReader.h"
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+    UPCAReader::UPCAReader() : ean13Reader() {
+    }
+
+    Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row) {
+      return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row));
+    }
+
+    Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+        int startGuardEnd) {
+      return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardBegin,
+          startGuardEnd));
+    }
+
+    Ref<Result> UPCAReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+      return maybeReturnResult(ean13Reader.decode(image, hints));
+    }
+
+    int UPCAReader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+        std::string& resultString) {
+      return ean13Reader.decodeMiddle(row, startGuardBegin, startGuardEnd, resultString);
+    }
+
+    Ref<Result> UPCAReader::maybeReturnResult(Ref<Result> result) {
+      if (result.empty()) {
+        return result;
+      }
+      const std::string& text = (result->getText())->getText();
+      if (text[0] == '0') {
+        Ref<String> resultString(new String(text.substr(1)));
+        Ref<Result> res(new Result(resultString, result->getRawBytes(), result->getResultPoints(),
+            BarcodeFormat_UPC_A));
+        return res;
+      }
+      return Ref<Result>();
+    }
+
+    BarcodeFormat UPCAReader::getBarcodeFormat(){
+      return BarcodeFormat_UPC_A;
+    }
+  }
+}
+
+// file: zxing/oned/UPCEANReader.cpp
+
+/*
+ *  UPCEANReader.cpp
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "UPCEANReader.h"
+// #include <zxing/oned/OneDResultPoint.h>
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+
+    /**
+     * Start/end guard pattern.
+     */
+    static const int START_END_PATTERN[3] = {1, 1, 1};
+
+    /**
+     * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.
+     */
+    static const int MIDDLE_PATTERN_LEN = 5;
+    static const int MIDDLE_PATTERN[MIDDLE_PATTERN_LEN] = {1, 1, 1, 1, 1};
+
+    /**
+     * "Odd", or "L" patterns used to encode UPC/EAN digits.
+     */
+    const int L_PATTERNS_LEN = 10;
+    const int L_PATTERNS_SUB_LEN = 4;
+    const int L_PATTERNS[L_PATTERNS_LEN][L_PATTERNS_SUB_LEN] = {
+      {3, 2, 1, 1}, // 0
+      {2, 2, 2, 1}, // 1
+      {2, 1, 2, 2}, // 2
+      {1, 4, 1, 1}, // 3
+      {1, 1, 3, 2}, // 4
+      {1, 2, 3, 1}, // 5
+      {1, 1, 1, 4}, // 6
+      {1, 3, 1, 2}, // 7
+      {1, 2, 1, 3}, // 8
+      {3, 1, 1, 2}  // 9
+    };
+
+    /**
+     * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
+     */
+    const int L_AND_G_PATTERNS_LEN = 20;
+    const int L_AND_G_PATTERNS_SUB_LEN = 4;
+    const int L_AND_G_PATTERNS[L_AND_G_PATTERNS_LEN][L_AND_G_PATTERNS_SUB_LEN] = {
+      {3, 2, 1, 1}, // 0
+      {2, 2, 2, 1}, // 1
+      {2, 1, 2, 2}, // 2
+      {1, 4, 1, 1}, // 3
+      {1, 1, 3, 2}, // 4
+      {1, 2, 3, 1}, // 5
+      {1, 1, 1, 4}, // 6
+      {1, 3, 1, 2}, // 7
+      {1, 2, 1, 3}, // 8
+      {3, 1, 1, 2}, // 9
+      {1, 1, 2, 3}, // 10 reversed 0
+      {1, 2, 2, 2}, // 11 reversed 1
+      {2, 2, 1, 2}, // 12 reversed 2
+      {1, 1, 4, 1}, // 13 reversed 3
+      {2, 3, 1, 1}, // 14 reversed 4
+      {1, 3, 2, 1}, // 15 reversed 5
+      {4, 1, 1, 1}, // 16 reversed 6
+      {2, 1, 3, 1}, // 17 reversed 7
+      {3, 1, 2, 1}, // 18 reversed 8
+      {2, 1, 1, 3}  // 19 reversed 9
+    };
+
+
+    int UPCEANReader::getMIDDLE_PATTERN_LEN() {
+      return MIDDLE_PATTERN_LEN;
+    }
+
+    const int* UPCEANReader::getMIDDLE_PATTERN() {
+      return MIDDLE_PATTERN;
+    }
+
+    UPCEANReader::UPCEANReader() {
+    }
+
+
+    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
+      int rangeStart;
+      int rangeEnd;
+			if (findStartGuardPattern(row, &rangeStart, &rangeEnd)) {
+        try {
+          return decodeRow(rowNumber, row, rangeStart, rangeEnd);
+        } catch (ReaderException const& re) {
+        }
+			}
+			return Ref<Result>();
+    }
+
+    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+        int startGuardEnd) {
+      std::string tmpResultString;
+      std::string& tmpResultStringRef = tmpResultString;
+      int endStart = decodeMiddle(row, startGuardBegin, startGuardEnd, tmpResultStringRef);
+      if (endStart < 0) {
+        return Ref<Result>();
+      }
+
+      int endGuardBegin;
+      int endGuardEnd;
+      if (!decodeEnd(row, endStart, &endGuardBegin, &endGuardEnd)) {
+        return Ref<Result>();
+      }
+
+      // Make sure there is a quiet zone at least as big as the end pattern after the barcode.
+      // The spec might want more whitespace, but in practice this is the maximum we can count on.
+      size_t quietEnd = endGuardEnd + (endGuardEnd - endGuardBegin);
+      if (quietEnd >= row->getSize() || !row->isRange(endGuardEnd, quietEnd, false)) {
+        return Ref<Result>();
+      }
+
+      if (!checkChecksum(tmpResultString)) {
+        return Ref<Result>();
+      }
+
+      Ref<String> resultString(new String(tmpResultString));
+      float left = (float) (startGuardBegin + startGuardEnd) / 2.0f;
+      float right = (float) (endGuardBegin + endGuardEnd) / 2.0f;
+
+      std::vector< Ref<ResultPoint> > resultPoints(2);
+      Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
+      Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
+      resultPoints[0] = resultPoint1;
+      resultPoints[1] = resultPoint2;
+
+      ArrayRef<unsigned char> resultBytes(1);
+      return Ref<Result>(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
+    }
+
+    bool UPCEANReader::findStartGuardPattern(Ref<BitArray> row, int* rangeStart, int* rangeEnd) {
+      int nextStart = 0;
+      while (findGuardPattern(row, nextStart, false, START_END_PATTERN,
+          sizeof(START_END_PATTERN) / sizeof(int), rangeStart, rangeEnd)) {
+        int start = *rangeStart;
+        nextStart = *rangeEnd;
+        // Make sure there is a quiet zone at least as big as the start pattern before the barcode.
+        // If this check would run off the left edge of the image, do not accept this barcode,
+        // as it is very likely to be a false positive.
+        int quietStart = start - (nextStart - start);
+        if (quietStart >= 0 && row->isRange(quietStart, start, false)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    bool UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
+        const int pattern[], int patternLen, int* start, int* end) {
+      int patternLength = patternLen;
+      int counters[patternLength];
+      int countersCount = sizeof(counters) / sizeof(int);
+      for (int i = 0; i < countersCount; i++) {
+        counters[i] = 0;
+      }
+      int width = row->getSize();
+      bool isWhite = false;
+      while (rowOffset < width) {
+        isWhite = !row->get(rowOffset);
+        if (whiteFirst == isWhite) {
+          break;
+        }
+        rowOffset++;
+      }
+
+      int counterPosition = 0;
+      int patternStart = rowOffset;
+      for (int x = rowOffset; x < width; x++) {
+        bool pixel = row->get(x);
+        if (pixel ^ isWhite) {
+          counters[counterPosition]++;
+        } else {
+          if (counterPosition == patternLength - 1) {
+            if (patternMatchVariance(counters, countersCount, pattern,
+                MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
+              *start = patternStart;
+              *end = x;
+              return true;
+            }
+            patternStart += counters[0] + counters[1];
+            for (int y = 2; y < patternLength; y++) {
+              counters[y - 2] = counters[y];
+            }
+            counters[patternLength - 2] = 0;
+            counters[patternLength - 1] = 0;
+            counterPosition--;
+          } else {
+            counterPosition++;
+          }
+          counters[counterPosition] = 1;
+          isWhite = !isWhite;
+        }
+      }
+      return false;
+    }
+
+    bool UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin,
+        int* endGuardEnd) {
+      return findGuardPattern(row, endStart, false, START_END_PATTERN,
+          sizeof(START_END_PATTERN) / sizeof(int), endGuardBegin, endGuardEnd);
+    }
+
+    int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
+        UPC_EAN_PATTERNS patternType) {
+      if (!recordPattern(row, rowOffset, counters, countersLen)) {
+        return -1;
+      }
+      unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
+      int bestMatch = -1;
+
+      int max = 0;
+      switch (patternType) {
+        case UPC_EAN_PATTERNS_L_PATTERNS:
+          max = L_PATTERNS_LEN;
+          for (int i = 0; i < max; i++) {
+            int pattern[countersLen];
+            for(int j = 0; j< countersLen; j++){
+              pattern[j] = L_PATTERNS[i][j];
+            }
+
+            unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
+                MAX_INDIVIDUAL_VARIANCE);
+            if (variance < bestVariance) {
+              bestVariance = variance;
+              bestMatch = i;
+            }
+          }
+          break;
+        case UPC_EAN_PATTERNS_L_AND_G_PATTERNS:
+          max = L_AND_G_PATTERNS_LEN;
+          for (int i = 0; i < max; i++) {
+            int pattern[countersLen];
+            for(int j = 0; j< countersLen; j++){
+              pattern[j] = L_AND_G_PATTERNS[i][j];
+            }
+
+            unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
+                MAX_INDIVIDUAL_VARIANCE);
+            if (variance < bestVariance) {
+              bestVariance = variance;
+              bestMatch = i;
+            }
+          }
+          break;
+        default:
+          break;
+      }
+      return bestMatch;
+    }
+
+    /**
+     * @return {@link #checkStandardUPCEANChecksum(String)}
+     */
+    bool UPCEANReader::checkChecksum(std::string s) {
+      return checkStandardUPCEANChecksum(s);
+    }
+
+    /**
+     * Computes the UPC/EAN checksum on a string of digits, and reports
+     * whether the checksum is correct or not.
+     *
+     * @param s string of digits to check
+     * @return true iff string of digits passes the UPC/EAN checksum algorithm
+     */
+    bool UPCEANReader::checkStandardUPCEANChecksum(std::string s) {
+      int length = s.length();
+      if (length == 0) {
+        return false;
+      }
+
+      int sum = 0;
+      for (int i = length - 2; i >= 0; i -= 2) {
+        int digit = (int) s[i] - (int) '0';
+        if (digit < 0 || digit > 9) {
+          return false;
+        }
+        sum += digit;
+      }
+      sum *= 3;
+      for (int i = length - 1; i >= 0; i -= 2) {
+        int digit = (int) s[i] - (int) '0';
+        if (digit < 0 || digit > 9) {
+          return false;
+        }
+        sum += digit;
+      }
+      return sum % 10 == 0;
+    }
+
+    UPCEANReader::~UPCEANReader() {
+    }
+  }
+}
+
+// file: zxing/oned/UPCEReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "UPCEReader.h"
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+  namespace oned {
+
+    /**
+     * The pattern that marks the middle, and end, of a UPC-E pattern.
+     * There is no "second half" to a UPC-E barcode.
+     */
+    static const int MIDDLE_END_PATTERN[6] = {1, 1, 1, 1, 1, 1};
+
+    /**
+     * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of
+     * even-odd parity encodings of digits that imply both the number system (0 or 1)
+     * used, and the check digit.
+     */
+    static const int NUMSYS_AND_CHECK_DIGIT_PATTERNS[2][10] = {
+      {0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25},
+      {0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}
+    };
+
+    UPCEReader::UPCEReader() {
+    }
+
+    int UPCEReader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+        std::string& resultString) {
+      (void)startGuardBegin;
+      const int countersLen = 4;
+      int counters[countersLen] = { 0, 0, 0, 0 };
+
+      int end = row->getSize();
+      int rowOffset = startGuardEnd;
+      int lgPatternFound = 0;
+
+      for (int x = 0; x < 6 && rowOffset < end; x++) {
+        int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
+            UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
+        if (bestMatch < 0) {
+          return -1;
+        }
+        resultString.append(1, (char) ('0' + bestMatch % 10));
+        for (int i = 0; i < countersLen; i++) {
+          rowOffset += counters[i];
+        }
+        if (bestMatch >= 10) {
+          lgPatternFound |= 1 << (5 - x);
+        }
+      }
+
+      if (!determineNumSysAndCheckDigit(resultString, lgPatternFound)) {
+        return -1;
+      }
+      return rowOffset;
+    }
+
+    bool UPCEReader::decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin,
+        int* endGuardEnd) {
+      return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN,
+          sizeof(MIDDLE_END_PATTERN) / sizeof(int), endGuardBegin, endGuardEnd);
+    }
+
+    bool UPCEReader::checkChecksum(std::string s){
+      return UPCEANReader::checkChecksum(convertUPCEtoUPCA(s));
+    }
+
+
+    bool UPCEReader::determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound) {
+      for (int numSys = 0; numSys <= 1; numSys++) {
+        for (int d = 0; d < 10; d++) {
+          if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {
+            resultString.insert(0, 1, (char) ('0' + numSys));
+            resultString.append(1, (char) ('0' + d));
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+
+    /**
+     * Expands a UPC-E value back into its full, equivalent UPC-A code value.
+     *
+     * @param upce UPC-E code as string of digits
+     * @return equivalent UPC-A code as string of digits
+     */
+    std::string UPCEReader::convertUPCEtoUPCA(std::string upce) {
+      std::string result;
+      result.append(1, upce[0]);
+      char lastChar = upce[6];
+      switch (lastChar) {
+        case '0':
+        case '1':
+        case '2':
+          result.append(upce.substr(1,2));
+          result.append(1, lastChar);
+          result.append("0000");
+          result.append(upce.substr(3,3));
+          break;
+        case '3':
+          result.append(upce.substr(1,3));
+          result.append("00000");
+          result.append(upce.substr(4,2));
+          break;
+        case '4':
+          result.append(upce.substr(1,4));
+          result.append("00000");
+          result.append(1, upce[5]);
+          break;
+        default:
+          result.append(upce.substr(1,5));
+          result.append("0000");
+          result.append(1, lastChar);
+          break;
+      }
+      result.append(1, upce[7]);
+      return result;
+    }
+
+
+    BarcodeFormat UPCEReader::getBarcodeFormat() {
+      return BarcodeFormat_UPC_E;
+    }
+  }
+}
+
+// file: zxing/qrcode/ErrorCorrectionLevel.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  ErrorCorrectionLevel.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 15/05/2008.
+ *  Copyright 2008-2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/ErrorCorrectionLevel.h>
+
+using std::string;
+
+namespace zxing {
+namespace qrcode {
+
+ErrorCorrectionLevel::ErrorCorrectionLevel(int inOrdinal,
+                                           int bits,
+                                           char const* name) :
+  ordinal_(inOrdinal), bits_(bits), name_(name) {}
+
+int ErrorCorrectionLevel::ordinal() const {
+  return ordinal_;
+}
+
+int ErrorCorrectionLevel::bits() const {
+  return bits_;
+}
+
+string const& ErrorCorrectionLevel::name() const {
+  return name_;
+}
+
+ErrorCorrectionLevel::operator string const& () const {
+  return name_;
+}
+
+ErrorCorrectionLevel& ErrorCorrectionLevel::forBits(int bits) {
+  if (bits < 0 || bits >= N_LEVELS) {
+    throw ReaderException("Ellegal error correction level bits");
+  }
+  return *FOR_BITS[bits];
+}
+
+  ErrorCorrectionLevel ErrorCorrectionLevel::L(0, 0x01, "L");
+  ErrorCorrectionLevel ErrorCorrectionLevel::M(1, 0x00, "M");
+  ErrorCorrectionLevel ErrorCorrectionLevel::Q(2, 0x03, "Q");
+  ErrorCorrectionLevel ErrorCorrectionLevel::H(3, 0x02, "H");
+ErrorCorrectionLevel *ErrorCorrectionLevel::FOR_BITS[] = { &M, &L, &H, &Q };
+int ErrorCorrectionLevel::N_LEVELS = 4;
+
+}
+}
+
+// file: zxing/qrcode/FormatInformation.cpp
+
+/*
+ *  FormatInformation.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 18/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/FormatInformation.h>
+// #include <limits>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+int FormatInformation::FORMAT_INFO_MASK_QR = 0x5412;
+int FormatInformation::FORMAT_INFO_DECODE_LOOKUP[][2] = { { 0x5412, 0x00 }, { 0x5125, 0x01 }, { 0x5E7C, 0x02 }, {
+    0x5B4B, 0x03 }, { 0x45F9, 0x04 }, { 0x40CE, 0x05 }, { 0x4F97, 0x06 }, { 0x4AA0, 0x07 }, { 0x77C4, 0x08 }, {
+    0x72F3, 0x09 }, { 0x7DAA, 0x0A }, { 0x789D, 0x0B }, { 0x662F, 0x0C }, { 0x6318, 0x0D }, { 0x6C41, 0x0E }, {
+    0x6976, 0x0F }, { 0x1689, 0x10 }, { 0x13BE, 0x11 }, { 0x1CE7, 0x12 }, { 0x19D0, 0x13 }, { 0x0762, 0x14 }, {
+    0x0255, 0x15 }, { 0x0D0C, 0x16 }, { 0x083B, 0x17 }, { 0x355F, 0x18 }, { 0x3068, 0x19 }, { 0x3F31, 0x1A }, {
+    0x3A06, 0x1B }, { 0x24B4, 0x1C }, { 0x2183, 0x1D }, { 0x2EDA, 0x1E }, { 0x2BED, 0x1F },
+};
+int FormatInformation::N_FORMAT_INFO_DECODE_LOOKUPS = 32;
+
+int FormatInformation::BITS_SET_IN_HALF_BYTE[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+FormatInformation::FormatInformation(int formatInfo) :
+    errorCorrectionLevel_(ErrorCorrectionLevel::forBits((formatInfo >> 3) & 0x03)), dataMask_(
+      (unsigned char)(formatInfo & 0x07)) {
+}
+
+ErrorCorrectionLevel& FormatInformation::getErrorCorrectionLevel() {
+  return errorCorrectionLevel_;
+}
+
+unsigned char FormatInformation::getDataMask() {
+  return dataMask_;
+}
+
+int FormatInformation::numBitsDiffering(unsigned int a, unsigned int b) {
+  a ^= b;
+  return BITS_SET_IN_HALF_BYTE[a & 0x0F] + BITS_SET_IN_HALF_BYTE[(a >> 4 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 8
+         & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 12 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 16 & 0x0F)]
+         + BITS_SET_IN_HALF_BYTE[(a >> 20 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 24 & 0x0F)]
+         + BITS_SET_IN_HALF_BYTE[(a >> 28 & 0x0F)];
+}
+
+Ref<FormatInformation> FormatInformation::decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
+  Ref<FormatInformation> result(doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2));
+  if (result != 0) {
+    return result;
+  }
+  // Should return null, but, some QR codes apparently
+  // do not mask this info. Try again by actually masking the pattern
+  // first
+  return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR,
+                                   maskedFormatInfo2  ^ FORMAT_INFO_MASK_QR);
+}
+Ref<FormatInformation> FormatInformation::doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
+  // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
+  int bestDifference = numeric_limits<int>::max();
+  int bestFormatInfo = 0;
+  for (int i = 0; i < N_FORMAT_INFO_DECODE_LOOKUPS; i++) {
+    int* decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
+    int targetInfo = decodeInfo[0];
+    if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) {
+      // Found an exact match
+      Ref<FormatInformation> result(new FormatInformation(decodeInfo[1]));
+      return result;
+    }
+    int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo);
+    if (bitsDifference < bestDifference) {
+      bestFormatInfo = decodeInfo[1];
+      bestDifference = bitsDifference;
+    }
+    if (maskedFormatInfo1 != maskedFormatInfo2) {
+        // also try the other option
+        bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo);
+        if (bitsDifference < bestDifference) {
+            bestFormatInfo = decodeInfo[1];
+          bestDifference = bitsDifference;
+        }
+      }
+  }
+  if (bestDifference <= 3) {
+    Ref<FormatInformation> result(new FormatInformation(bestFormatInfo));
+    return result;
+  }
+  Ref<FormatInformation> result;
+  return result;
+}
+
+bool operator==(const FormatInformation &a, const FormatInformation &b) {
+  return &(a.errorCorrectionLevel_) == &(b.errorCorrectionLevel_) && a.dataMask_ == b.dataMask_;
+}
+
+ostream& operator<<(ostream& out, const FormatInformation& fi) {
+  const FormatInformation *fip = &fi;
+  out << "FormatInformation @ " << fip;
+  return out;
+}
+
+}
+}
+
+// file: zxing/qrcode/QRCodeReader.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  QRCodeReader.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/QRCodeReader.h>
+// #include <zxing/qrcode/detector/Detector.h>
+
+// #include <iostream>
+
+namespace zxing {
+	namespace qrcode {
+
+		using namespace std;
+
+		QRCodeReader::QRCodeReader() :decoder_() {
+		}
+		//TODO: see if any of the other files in the qrcode tree need tryHarder
+		Ref<Result> QRCodeReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+#ifdef DEBUG
+			cout << "decoding image " << image.object_ << ":\n" << flush;
+#endif
+
+			Detector detector(image->getBlackMatrix());
+
+
+#ifdef DEBUG
+			cout << "(1) created detector " << &detector << "\n" << flush;
+#endif
+
+			Ref<DetectorResult> detectorResult(detector.detect(hints));
+#ifdef DEBUG
+			cout << "(2) detected, have detectorResult " << detectorResult.object_ << "\n" << flush;
+#endif
+
+			std::vector<Ref<ResultPoint> > points(detectorResult->getPoints());
+
+
+#ifdef DEBUG
+			cout << "(3) extracted points " << &points << "\n" << flush;
+			cout << "found " << points.size() << " points:\n";
+			for (size_t i = 0; i < points.size(); i++) {
+				cout << "   " << points[i]->getX() << "," << points[i]->getY() << "\n";
+			}
+			cout << "bits:\n";
+			cout << *(detectorResult->getBits()) << "\n";
+#endif
+
+			Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult->getBits()));
+#ifdef DEBUG
+			cout << "(4) decoded, have decoderResult " << decoderResult.object_ << "\n" << flush;
+#endif
+
+			Ref<Result> result(
+							   new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_QR_CODE));
+#ifdef DEBUG
+			cout << "(5) created result " << result.object_ << ", returning\n" << flush;
+#endif
+
+			return result;
+		}
+
+		QRCodeReader::~QRCodeReader() {
+		}
+
+    Decoder& QRCodeReader::getDecoder() {
+        return decoder_;
+    }
+	}
+}
+
+// file: zxing/qrcode/Version.cpp
+
+/*
+ *  Version.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 14/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/Version.h>
+// #include <zxing/qrcode/FormatInformation.h>
+// #include <limits>
+// #include <iostream>
+// #include <cstdarg>
+
+namespace zxing {
+namespace qrcode {
+using namespace std;
+
+ECB::ECB(int count, int dataCodewords) :
+    count_(count), dataCodewords_(dataCodewords) {
+}
+
+int ECB::getCount() {
+  return count_;
+}
+
+int ECB::getDataCodewords() {
+  return dataCodewords_;
+}
+
+ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks) :
+    ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks) {
+}
+
+ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2) :
+    ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks1) {
+  ecBlocks_.push_back(ecBlocks2);
+}
+
+int ECBlocks::getECCodewords() {
+  return ecCodewords_;
+}
+
+std::vector<ECB*>& ECBlocks::getECBlocks() {
+  return ecBlocks_;
+}
+
+ECBlocks::~ECBlocks() {
+  for (size_t i = 0; i < ecBlocks_.size(); i++) {
+    delete ecBlocks_[i];
+  }
+}
+
+unsigned int Version::VERSION_DECODE_INFO[] = { 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D,
+    0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
+    0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64,
+    0x27541, 0x28C69
+                                              };
+int Version::N_VERSION_DECODE_INFOS = 34;
+vector<Ref<Version> > Version::VERSIONS;
+static int N_VERSIONS = Version::buildVersions();
+
+int Version::getVersionNumber() {
+  return versionNumber_;
+}
+
+vector<int> &Version::getAlignmentPatternCenters() {
+  return alignmentPatternCenters_;
+}
+
+int Version::getTotalCodewords() {
+  return totalCodewords_;
+}
+
+int Version::getDimensionForVersion() {
+  return 17 + 4 * versionNumber_;
+}
+
+ECBlocks& Version::getECBlocksForLevel(ErrorCorrectionLevel &ecLevel) {
+  return *ecBlocks_[ecLevel.ordinal()];
+}
+
+Version *Version::getProvisionalVersionForDimension(int dimension) {
+  if (dimension % 4 != 1) {
+    throw ReaderException("Dimension must be 1 mod 4");
+  }
+  return Version::getVersionForNumber((dimension - 17) >> 2);
+}
+
+Version *Version::getVersionForNumber(int versionNumber) {
+  if (versionNumber < 1 || versionNumber > N_VERSIONS) {
+    throw ReaderException("versionNumber must be between 1 and 40");
+  }
+
+  return VERSIONS[versionNumber - 1];
+}
+
+Version::Version(int versionNumber, vector<int> *alignmentPatternCenters, ECBlocks *ecBlocks1, ECBlocks *ecBlocks2,
+                 ECBlocks *ecBlocks3, ECBlocks *ecBlocks4) :
+    versionNumber_(versionNumber), alignmentPatternCenters_(*alignmentPatternCenters), ecBlocks_(4), totalCodewords_(0) {
+  ecBlocks_[0] = ecBlocks1;
+  ecBlocks_[1] = ecBlocks2;
+  ecBlocks_[2] = ecBlocks3;
+  ecBlocks_[3] = ecBlocks4;
+
+  int total = 0;
+  int ecCodewords = ecBlocks1->getECCodewords();
+  vector<ECB*> &ecbArray = ecBlocks1->getECBlocks();
+  for (size_t i = 0; i < ecbArray.size(); i++) {
+    ECB *ecBlock = ecbArray[i];
+    total += ecBlock->getCount() * (ecBlock->getDataCodewords() + ecCodewords);
+  }
+  totalCodewords_ = total;
+}
+
+Version::~Version() {
+  delete &alignmentPatternCenters_;
+  for (size_t i = 0; i < ecBlocks_.size(); i++) {
+    delete ecBlocks_[i];
+  }
+}
+
+Version *Version::decodeVersionInformation(unsigned int versionBits) {
+  int bestDifference = numeric_limits<int>::max();
+  size_t bestVersion = 0;
+  for (int i = 0; i < N_VERSION_DECODE_INFOS; i++) {
+    unsigned targetVersion = VERSION_DECODE_INFO[i];
+    // Do the version info bits match exactly? done.
+    if (targetVersion == versionBits) {
+      return getVersionForNumber(i + 7);
+    }
+    // Otherwise see if this is the closest to a real version info bit
+    // string we have seen so far
+    int bitsDifference = FormatInformation::numBitsDiffering(versionBits, targetVersion);
+    if (bitsDifference < bestDifference) {
+      bestVersion = i + 7;
+      bestDifference = bitsDifference;
+    }
+  }
+  // We can tolerate up to 3 bits of error since no two version info codewords will
+  // differ in less than 4 bits.
+  if (bestDifference <= 3) {
+    return getVersionForNumber(bestVersion);
+  }
+  // If we didn't find a close enough match, fail
+  return 0;
+}
+
+Ref<BitMatrix> Version::buildFunctionPattern() {
+  int dimension = getDimensionForVersion();
+  Ref<BitMatrix> functionPattern(new BitMatrix(dimension));
+
+
+  // Top left finder pattern + separator + format
+  functionPattern->setRegion(0, 0, 9, 9);
+  // Top right finder pattern + separator + format
+  functionPattern->setRegion(dimension - 8, 0, 8, 9);
+  // Bottom left finder pattern + separator + format
+  functionPattern->setRegion(0, dimension - 8, 9, 8);
+
+
+  // Alignment patterns
+  size_t max = alignmentPatternCenters_.size();
+  for (size_t x = 0; x < max; x++) {
+    int i = alignmentPatternCenters_[x] - 2;
+    for (size_t y = 0; y < max; y++) {
+      if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
+        // No alignment patterns near the three finder patterns
+        continue;
+      }
+      functionPattern->setRegion(alignmentPatternCenters_[y] - 2, i, 5, 5);
+    }
+  }
+
+  // Vertical timing pattern
+  functionPattern->setRegion(6, 9, 1, dimension - 17);
+  // Horizontal timing pattern
+  functionPattern->setRegion(9, 6, dimension - 17, 1);
+
+  if (versionNumber_ > 6) {
+    // Version info, top right
+    functionPattern->setRegion(dimension - 11, 0, 3, 6);
+    // Version info, bottom left
+    functionPattern->setRegion(0, dimension - 11, 6, 3);
+  }
+
+
+  //#ifdef DEBUG
+  //	cout << "version " << versionNumber_ << " built function pattern:\n";
+  //	cout << *functionPattern;
+  //#endif
+
+  return functionPattern;
+}
+
+static vector<int> *intArray(size_t n...) {
+  va_list ap;
+  va_start(ap, n);
+  vector<int> *result = new vector<int>(n);
+  for (size_t i = 0; i < n; i++) {
+    (*result)[i] = va_arg(ap, int);
+  }
+  va_end(ap);
+  return result;
+}
+
+int Version::buildVersions() {
+  VERSIONS.push_back(Ref<Version>(new Version(1, intArray(0),
+                                  new ECBlocks(7, new ECB(1, 19)),
+                                  new ECBlocks(10, new ECB(1, 16)),
+                                  new ECBlocks(13, new ECB(1, 13)),
+                                  new ECBlocks(17, new ECB(1, 9)))));
+  VERSIONS.push_back(Ref<Version>(new Version(2, intArray(2, 6, 18),
+                                  new ECBlocks(10, new ECB(1, 34)),
+                                  new ECBlocks(16, new ECB(1, 28)),
+                                  new ECBlocks(22, new ECB(1, 22)),
+                                  new ECBlocks(28, new ECB(1, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(3, intArray(2, 6, 22),
+                                  new ECBlocks(15, new ECB(1, 55)),
+                                  new ECBlocks(26, new ECB(1, 44)),
+                                  new ECBlocks(18, new ECB(2, 17)),
+                                  new ECBlocks(22, new ECB(2, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(4, intArray(2, 6, 26),
+                                  new ECBlocks(20, new ECB(1, 80)),
+                                  new ECBlocks(18, new ECB(2, 32)),
+                                  new ECBlocks(26, new ECB(2, 24)),
+                                  new ECBlocks(16, new ECB(4, 9)))));
+  VERSIONS.push_back(Ref<Version>(new Version(5, intArray(2, 6, 30),
+                                  new ECBlocks(26, new ECB(1, 108)),
+                                  new ECBlocks(24, new ECB(2, 43)),
+                                  new ECBlocks(18, new ECB(2, 15),
+                                               new ECB(2, 16)),
+                                  new ECBlocks(22, new ECB(2, 11),
+                                               new ECB(2, 12)))));
+  VERSIONS.push_back(Ref<Version>(new Version(6, intArray(2, 6, 34),
+                                  new ECBlocks(18, new ECB(2, 68)),
+                                  new ECBlocks(16, new ECB(4, 27)),
+                                  new ECBlocks(24, new ECB(4, 19)),
+                                  new ECBlocks(28, new ECB(4, 15)))));
+  VERSIONS.push_back(Ref<Version>(new Version(7, intArray(3, 6, 22, 38),
+                                  new ECBlocks(20, new ECB(2, 78)),
+                                  new ECBlocks(18, new ECB(4, 31)),
+                                  new ECBlocks(18, new ECB(2, 14),
+                                               new ECB(4, 15)),
+                                  new ECBlocks(26, new ECB(4, 13),
+                                               new ECB(1, 14)))));
+  VERSIONS.push_back(Ref<Version>(new Version(8, intArray(3, 6, 24, 42),
+                                  new ECBlocks(24, new ECB(2, 97)),
+                                  new ECBlocks(22, new ECB(2, 38),
+                                               new ECB(2, 39)),
+                                  new ECBlocks(22, new ECB(4, 18),
+                                               new ECB(2, 19)),
+                                  new ECBlocks(26, new ECB(4, 14),
+                                               new ECB(2, 15)))));
+  VERSIONS.push_back(Ref<Version>(new Version(9, intArray(3, 6, 26, 46),
+                                  new ECBlocks(30, new ECB(2, 116)),
+                                  new ECBlocks(22, new ECB(3, 36),
+                                               new ECB(2, 37)),
+                                  new ECBlocks(20, new ECB(4, 16),
+                                               new ECB(4, 17)),
+                                  new ECBlocks(24, new ECB(4, 12),
+                                               new ECB(4, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(10, intArray(3, 6, 28, 50),
+                                  new ECBlocks(18, new ECB(2, 68),
+                                               new ECB(2, 69)),
+                                  new ECBlocks(26, new ECB(4, 43),
+                                               new ECB(1, 44)),
+                                  new ECBlocks(24, new ECB(6, 19),
+                                               new ECB(2, 20)),
+                                  new ECBlocks(28, new ECB(6, 15),
+                                               new ECB(2, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(11, intArray(3, 6, 30, 54),
+                                  new ECBlocks(20, new ECB(4, 81)),
+                                  new ECBlocks(30, new ECB(1, 50),
+                                               new ECB(4, 51)),
+                                  new ECBlocks(28, new ECB(4, 22),
+                                               new ECB(4, 23)),
+                                  new ECBlocks(24, new ECB(3, 12),
+                                               new ECB(8, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(12, intArray(3, 6, 32, 58),
+                                  new ECBlocks(24, new ECB(2, 92),
+                                               new ECB(2, 93)),
+                                  new ECBlocks(22, new ECB(6, 36),
+                                               new ECB(2, 37)),
+                                  new ECBlocks(26, new ECB(4, 20),
+                                               new ECB(6, 21)),
+                                  new ECBlocks(28, new ECB(7, 14),
+                                               new ECB(4, 15)))));
+  VERSIONS.push_back(Ref<Version>(new Version(13, intArray(3, 6, 34, 62),
+                                  new ECBlocks(26, new ECB(4, 107)),
+                                  new ECBlocks(22, new ECB(8, 37),
+                                               new ECB(1, 38)),
+                                  new ECBlocks(24, new ECB(8, 20),
+                                               new ECB(4, 21)),
+                                  new ECBlocks(22, new ECB(12, 11),
+                                               new ECB(4, 12)))));
+  VERSIONS.push_back(Ref<Version>(new Version(14, intArray(4, 6, 26, 46, 66),
+                                  new ECBlocks(30, new ECB(3, 115),
+                                               new ECB(1, 116)),
+                                  new ECBlocks(24, new ECB(4, 40),
+                                               new ECB(5, 41)),
+                                  new ECBlocks(20, new ECB(11, 16),
+                                               new ECB(5, 17)),
+                                  new ECBlocks(24, new ECB(11, 12),
+                                               new ECB(5, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(15, intArray(4, 6, 26, 48, 70),
+                                  new ECBlocks(22, new ECB(5, 87),
+                                               new ECB(1, 88)),
+                                  new ECBlocks(24, new ECB(5, 41),
+                                               new ECB(5, 42)),
+                                  new ECBlocks(30, new ECB(5, 24),
+                                               new ECB(7, 25)),
+                                  new ECBlocks(24, new ECB(11, 12),
+                                               new ECB(7, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(16, intArray(4, 6, 26, 50, 74),
+                                  new ECBlocks(24, new ECB(5, 98),
+                                               new ECB(1, 99)),
+                                  new ECBlocks(28, new ECB(7, 45),
+                                               new ECB(3, 46)),
+                                  new ECBlocks(24, new ECB(15, 19),
+                                               new ECB(2, 20)),
+                                  new ECBlocks(30, new ECB(3, 15),
+                                               new ECB(13, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(17, intArray(4, 6, 30, 54, 78),
+                                  new ECBlocks(28, new ECB(1, 107),
+                                               new ECB(5, 108)),
+                                  new ECBlocks(28, new ECB(10, 46),
+                                               new ECB(1, 47)),
+                                  new ECBlocks(28, new ECB(1, 22),
+                                               new ECB(15, 23)),
+                                  new ECBlocks(28, new ECB(2, 14),
+                                               new ECB(17, 15)))));
+  VERSIONS.push_back(Ref<Version>(new Version(18, intArray(4, 6, 30, 56, 82),
+                                  new ECBlocks(30, new ECB(5, 120),
+                                               new ECB(1, 121)),
+                                  new ECBlocks(26, new ECB(9, 43),
+                                               new ECB(4, 44)),
+                                  new ECBlocks(28, new ECB(17, 22),
+                                               new ECB(1, 23)),
+                                  new ECBlocks(28, new ECB(2, 14),
+                                               new ECB(19, 15)))));
+  VERSIONS.push_back(Ref<Version>(new Version(19, intArray(4, 6, 30, 58, 86),
+                                  new ECBlocks(28, new ECB(3, 113),
+                                               new ECB(4, 114)),
+                                  new ECBlocks(26, new ECB(3, 44),
+                                               new ECB(11, 45)),
+                                  new ECBlocks(26, new ECB(17, 21),
+                                               new ECB(4, 22)),
+                                  new ECBlocks(26, new ECB(9, 13),
+                                               new ECB(16, 14)))));
+  VERSIONS.push_back(Ref<Version>(new Version(20, intArray(4, 6, 34, 62, 90),
+                                  new ECBlocks(28, new ECB(3, 107),
+                                               new ECB(5, 108)),
+                                  new ECBlocks(26, new ECB(3, 41),
+                                               new ECB(13, 42)),
+                                  new ECBlocks(30, new ECB(15, 24),
+                                               new ECB(5, 25)),
+                                  new ECBlocks(28, new ECB(15, 15),
+                                               new ECB(10, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(21, intArray(5, 6, 28, 50, 72, 94),
+                                  new ECBlocks(28, new ECB(4, 116),
+                                               new ECB(4, 117)),
+                                  new ECBlocks(26, new ECB(17, 42)),
+                                  new ECBlocks(28, new ECB(17, 22),
+                                               new ECB(6, 23)),
+                                  new ECBlocks(30, new ECB(19, 16),
+                                               new ECB(6, 17)))));
+  VERSIONS.push_back(Ref<Version>(new Version(22, intArray(5, 6, 26, 50, 74, 98),
+                                  new ECBlocks(28, new ECB(2, 111),
+                                               new ECB(7, 112)),
+                                  new ECBlocks(28, new ECB(17, 46)),
+                                  new ECBlocks(30, new ECB(7, 24),
+                                               new ECB(16, 25)),
+                                  new ECBlocks(24, new ECB(34, 13)))));
+  VERSIONS.push_back(Ref<Version>(new Version(23, intArray(5, 6, 30, 54, 78, 102),
+                                  new ECBlocks(30, new ECB(4, 121),
+                                               new ECB(5, 122)),
+                                  new ECBlocks(28, new ECB(4, 47),
+                                               new ECB(14, 48)),
+                                  new ECBlocks(30, new ECB(11, 24),
+                                               new ECB(14, 25)),
+                                  new ECBlocks(30, new ECB(16, 15),
+                                               new ECB(14, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(24, intArray(5, 6, 28, 54, 80, 106),
+                                  new ECBlocks(30, new ECB(6, 117),
+                                               new ECB(4, 118)),
+                                  new ECBlocks(28, new ECB(6, 45),
+                                               new ECB(14, 46)),
+                                  new ECBlocks(30, new ECB(11, 24),
+                                               new ECB(16, 25)),
+                                  new ECBlocks(30, new ECB(30, 16),
+                                               new ECB(2, 17)))));
+  VERSIONS.push_back(Ref<Version>(new Version(25, intArray(5, 6, 32, 58, 84, 110),
+                                  new ECBlocks(26, new ECB(8, 106),
+                                               new ECB(4, 107)),
+                                  new ECBlocks(28, new ECB(8, 47),
+                                               new ECB(13, 48)),
+                                  new ECBlocks(30, new ECB(7, 24),
+                                               new ECB(22, 25)),
+                                  new ECBlocks(30, new ECB(22, 15),
+                                               new ECB(13, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(26, intArray(5, 6, 30, 58, 86, 114),
+                                  new ECBlocks(28, new ECB(10, 114),
+                                               new ECB(2, 115)),
+                                  new ECBlocks(28, new ECB(19, 46),
+                                               new ECB(4, 47)),
+                                  new ECBlocks(28, new ECB(28, 22),
+                                               new ECB(6, 23)),
+                                  new ECBlocks(30, new ECB(33, 16),
+                                               new ECB(4, 17)))));
+  VERSIONS.push_back(Ref<Version>(new Version(27, intArray(5, 6, 34, 62, 90, 118),
+                                  new ECBlocks(30, new ECB(8, 122),
+                                               new ECB(4, 123)),
+                                  new ECBlocks(28, new ECB(22, 45),
+                                               new ECB(3, 46)),
+                                  new ECBlocks(30, new ECB(8, 23),
+                                               new ECB(26, 24)),
+                                  new ECBlocks(30, new ECB(12, 15),
+                                               new ECB(28, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(28, intArray(6, 6, 26, 50, 74, 98, 122),
+                                  new ECBlocks(30, new ECB(3, 117),
+                                               new ECB(10, 118)),
+                                  new ECBlocks(28, new ECB(3, 45),
+                                               new ECB(23, 46)),
+                                  new ECBlocks(30, new ECB(4, 24),
+                                               new ECB(31, 25)),
+                                  new ECBlocks(30, new ECB(11, 15),
+                                               new ECB(31, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(29, intArray(6, 6, 30, 54, 78, 102, 126),
+                                  new ECBlocks(30, new ECB(7, 116),
+                                               new ECB(7, 117)),
+                                  new ECBlocks(28, new ECB(21, 45),
+                                               new ECB(7, 46)),
+                                  new ECBlocks(30, new ECB(1, 23),
+                                               new ECB(37, 24)),
+                                  new ECBlocks(30, new ECB(19, 15),
+                                               new ECB(26, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(30, intArray(6, 6, 26, 52, 78, 104, 130),
+                                  new ECBlocks(30, new ECB(5, 115),
+                                               new ECB(10, 116)),
+                                  new ECBlocks(28, new ECB(19, 47),
+                                               new ECB(10, 48)),
+                                  new ECBlocks(30, new ECB(15, 24),
+                                               new ECB(25, 25)),
+                                  new ECBlocks(30, new ECB(23, 15),
+                                               new ECB(25, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(31, intArray(6, 6, 30, 56, 82, 108, 134),
+                                  new ECBlocks(30, new ECB(13, 115),
+                                               new ECB(3, 116)),
+                                  new ECBlocks(28, new ECB(2, 46),
+                                               new ECB(29, 47)),
+                                  new ECBlocks(30, new ECB(42, 24),
+                                               new ECB(1, 25)),
+                                  new ECBlocks(30, new ECB(23, 15),
+                                               new ECB(28, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(32, intArray(6, 6, 34, 60, 86, 112, 138),
+                                  new ECBlocks(30, new ECB(17, 115)),
+                                  new ECBlocks(28, new ECB(10, 46),
+                                               new ECB(23, 47)),
+                                  new ECBlocks(30, new ECB(10, 24),
+                                               new ECB(35, 25)),
+                                  new ECBlocks(30, new ECB(19, 15),
+                                               new ECB(35, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(33, intArray(6, 6, 30, 58, 86, 114, 142),
+                                  new ECBlocks(30, new ECB(17, 115),
+                                               new ECB(1, 116)),
+                                  new ECBlocks(28, new ECB(14, 46),
+                                               new ECB(21, 47)),
+                                  new ECBlocks(30, new ECB(29, 24),
+                                               new ECB(19, 25)),
+                                  new ECBlocks(30, new ECB(11, 15),
+                                               new ECB(46, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(34, intArray(6, 6, 34, 62, 90, 118, 146),
+                                  new ECBlocks(30, new ECB(13, 115),
+                                               new ECB(6, 116)),
+                                  new ECBlocks(28, new ECB(14, 46),
+                                               new ECB(23, 47)),
+                                  new ECBlocks(30, new ECB(44, 24),
+                                               new ECB(7, 25)),
+                                  new ECBlocks(30, new ECB(59, 16),
+                                               new ECB(1, 17)))));
+  VERSIONS.push_back(Ref<Version>(new Version(35, intArray(7, 6, 30, 54, 78,
+                                  102, 126, 150),
+                                  new ECBlocks(30, new ECB(12, 121),
+                                               new ECB(7, 122)),
+                                  new ECBlocks(28, new ECB(12, 47),
+                                               new ECB(26, 48)),
+                                  new ECBlocks(30, new ECB(39, 24),
+                                               new ECB(14, 25)),
+                                  new ECBlocks(30, new ECB(22, 15),
+                                               new ECB(41, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(36, intArray(7, 6, 24, 50, 76,
+                                  102, 128, 154),
+                                  new ECBlocks(30, new ECB(6, 121),
+                                               new ECB(14, 122)),
+                                  new ECBlocks(28, new ECB(6, 47),
+                                               new ECB(34, 48)),
+                                  new ECBlocks(30, new ECB(46, 24),
+                                               new ECB(10, 25)),
+                                  new ECBlocks(30, new ECB(2, 15),
+                                               new ECB(64, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(37, intArray(7, 6, 28, 54, 80,
+                                  106, 132, 158),
+                                  new ECBlocks(30, new ECB(17, 122),
+                                               new ECB(4, 123)),
+                                  new ECBlocks(28, new ECB(29, 46),
+                                               new ECB(14, 47)),
+                                  new ECBlocks(30, new ECB(49, 24),
+                                               new ECB(10, 25)),
+                                  new ECBlocks(30, new ECB(24, 15),
+                                               new ECB(46, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(38, intArray(7, 6, 32, 58, 84,
+                                  110, 136, 162),
+                                  new ECBlocks(30, new ECB(4, 122),
+                                               new ECB(18, 123)),
+                                  new ECBlocks(28, new ECB(13, 46),
+                                               new ECB(32, 47)),
+                                  new ECBlocks(30, new ECB(48, 24),
+                                               new ECB(14, 25)),
+                                  new ECBlocks(30, new ECB(42, 15),
+                                               new ECB(32, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(39, intArray(7, 6, 26, 54, 82,
+                                  110, 138, 166),
+                                  new ECBlocks(30, new ECB(20, 117),
+                                               new ECB(4, 118)),
+                                  new ECBlocks(28, new ECB(40, 47),
+                                               new ECB(7, 48)),
+                                  new ECBlocks(30, new ECB(43, 24),
+                                               new ECB(22, 25)),
+                                  new ECBlocks(30, new ECB(10, 15),
+                                               new ECB(67, 16)))));
+  VERSIONS.push_back(Ref<Version>(new Version(40, intArray(7, 6, 30, 58, 86,
+                                  114, 142, 170),
+                                  new ECBlocks(30, new ECB(19, 118),
+                                               new ECB(6, 119)),
+                                  new ECBlocks(28, new ECB(18, 47),
+                                               new ECB(31, 48)),
+                                  new ECBlocks(30, new ECB(34, 24),
+                                               new ECB(34, 25)),
+                                  new ECBlocks(30, new ECB(20, 15),
+                                               new ECB(61, 16)))));
+  return VERSIONS.size();
+}
+}
+}
+
+// file: zxing/qrcode/decoder/BitMatrixParser.cpp
+
+/*
+ *  BitMatrixParser.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/BitMatrixParser.h>
+// #include <zxing/qrcode/decoder/DataMask.h>
+
+
+namespace zxing {
+namespace qrcode {
+
+int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) {
+  return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1;
+}
+
+BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) :
+    bitMatrix_(bitMatrix), parsedVersion_(0), parsedFormatInfo_() {
+  size_t dimension = bitMatrix->getDimension();
+  if ((dimension < 21) || (dimension & 0x03) != 1) {
+    throw ReaderException("Dimension must be 1 mod 4 and >= 21");
+  }
+}
+
+Ref<FormatInformation> BitMatrixParser::readFormatInformation() {
+  if (parsedFormatInfo_ != 0) {
+    return parsedFormatInfo_;
+  }
+
+  // Read top-left format info bits
+  int formatInfoBits1 = 0;
+  for (int i = 0; i < 6; i++) {
+    formatInfoBits1 = copyBit(i, 8, formatInfoBits1);
+  }
+  // .. and skip a bit in the timing pattern ...
+  formatInfoBits1 = copyBit(7, 8, formatInfoBits1);
+  formatInfoBits1 = copyBit(8, 8, formatInfoBits1);
+  formatInfoBits1 = copyBit(8, 7, formatInfoBits1);
+  // .. and skip a bit in the timing pattern ...
+  for (int j = 5; j >= 0; j--) {
+    formatInfoBits1 = copyBit(8, j, formatInfoBits1);
+  }
+
+  // Read the top-right/bottom-left pattern
+  int dimension = bitMatrix_->getDimension();
+  int formatInfoBits2 = 0;
+  int jMin = dimension - 7;
+  for (int j = dimension - 1; j >= jMin; j--) {
+    formatInfoBits2 = copyBit(8, j, formatInfoBits2);
+  }
+  for (int i = dimension - 8; i < dimension; i++) {
+    formatInfoBits2 = copyBit(i, 8, formatInfoBits2);
+  }
+
+  parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits1,formatInfoBits2);
+  if (parsedFormatInfo_ != 0) {
+    return parsedFormatInfo_;
+  }
+  throw ReaderException("Could not decode format information");
+}
+
+Version *BitMatrixParser::readVersion() {
+  if (parsedVersion_ != 0) {
+    return parsedVersion_;
+  }
+
+  int dimension = bitMatrix_->getDimension();
+
+  int provisionalVersion = (dimension - 17) >> 2;
+  if (provisionalVersion <= 6) {
+    return Version::getVersionForNumber(provisionalVersion);
+  }
+
+  // Read top-right version info: 3 wide by 6 tall
+  int versionBits = 0;
+  for (int y = 5; y >= 0; y--) {
+    int xMin = dimension - 11;
+    for (int x = dimension - 9; x >= xMin; x--) {
+      versionBits = copyBit(x, y, versionBits);
+    }
+  }
+
+  parsedVersion_ = Version::decodeVersionInformation(versionBits);
+  if (parsedVersion_ != 0 && parsedVersion_->getDimensionForVersion() == dimension) {
+    return parsedVersion_;
+  }
+
+  // Hmm, failed. Try bottom left: 6 wide by 3 tall
+  versionBits = 0;
+  for (int x = 5; x >= 0; x--) {
+    int yMin = dimension - 11;
+    for (int y = dimension - 9; y >= yMin; y--) {
+      versionBits = copyBit(x, y, versionBits);
+    }
+  }
+
+  parsedVersion_ = Version::decodeVersionInformation(versionBits);
+  if (parsedVersion_ != 0 && parsedVersion_->getDimensionForVersion() == dimension) {
+    return parsedVersion_;
+  }
+  throw ReaderException("Could not decode version");
+}
+
+ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
+  Ref<FormatInformation> formatInfo = readFormatInformation();
+  Version *version = readVersion();
+
+
+  //	cerr << *bitMatrix_ << endl;
+  //	cerr << bitMatrix_->getDimension() << endl;
+
+  // Get the data mask for the format used in this QR Code. This will exclude
+  // some bits from reading as we wind through the bit matrix.
+  DataMask &dataMask = DataMask::forReference((int)formatInfo->getDataMask());
+  //	cout << (int)formatInfo->getDataMask() << endl;
+  int dimension = bitMatrix_->getDimension();
+  dataMask.unmaskBitMatrix(*bitMatrix_, dimension);
+
+
+  //		cerr << *bitMatrix_ << endl;
+  //	cerr << version->getTotalCodewords() << endl;
+
+  Ref<BitMatrix> functionPattern = version->buildFunctionPattern();
+
+
+  //	cout << *functionPattern << endl;
+
+  bool readingUp = true;
+  ArrayRef<unsigned char> result(version->getTotalCodewords());
+  int resultOffset = 0;
+  int currentByte = 0;
+  int bitsRead = 0;
+  // Read columns in pairs, from right to left
+  for (int x = dimension - 1; x > 0; x -= 2) {
+    if (x == 6) {
+      // Skip whole column with vertical alignment pattern;
+      // saves time and makes the other code proceed more cleanly
+      x--;
+    }
+    // Read alternatingly from bottom to top then top to bottom
+    for (int counter = 0; counter < dimension; counter++) {
+      int y = readingUp ? dimension - 1 - counter : counter;
+      for (int col = 0; col < 2; col++) {
+        // Ignore bits covered by the function pattern
+        if (!functionPattern->get(x - col, y)) {
+          // Read a bit
+          bitsRead++;
+          currentByte <<= 1;
+          if (bitMatrix_->get(x - col, y)) {
+            currentByte |= 1;
+          }
+          // If we've made a whole byte, save it off
+          if (bitsRead == 8) {
+            result[resultOffset++] = (unsigned char)currentByte;
+            bitsRead = 0;
+            currentByte = 0;
+          }
+        }
+      }
+    }
+    readingUp = !readingUp; // switch directions
+  }
+
+  if (resultOffset != version->getTotalCodewords()) {
+    throw ReaderException("Did not read all codewords");
+  }
+  return result;
+}
+
+}
+}
+
+// file: zxing/qrcode/decoder/DataBlock.cpp
+
+/*
+ *  DataBlock.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 19/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/DataBlock.h>
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+DataBlock::DataBlock(int numDataCodewords, ArrayRef<unsigned char> codewords) :
+    numDataCodewords_(numDataCodewords), codewords_(codewords) {
+}
+
+int DataBlock::getNumDataCodewords() {
+  return numDataCodewords_;
+}
+
+ArrayRef<unsigned char> DataBlock::getCodewords() {
+  return codewords_;
+}
+
+
+std::vector<Ref<DataBlock> > DataBlock::getDataBlocks(ArrayRef<unsigned char> rawCodewords, Version *version,
+    ErrorCorrectionLevel &ecLevel) {
+
+
+  // Figure out the number and size of data blocks used by this version and
+  // error correction level
+  ECBlocks &ecBlocks = version->getECBlocksForLevel(ecLevel);
+
+
+  // First count the total number of data blocks
+  int totalBlocks = 0;
+  vector<ECB*> ecBlockArray = ecBlocks.getECBlocks();
+  for (size_t i = 0; i < ecBlockArray.size(); i++) {
+    totalBlocks += ecBlockArray[i]->getCount();
+  }
+
+  // Now establish DataBlocks of the appropriate size and number of data codewords
+  std::vector<Ref<DataBlock> > result(totalBlocks);
+  int numResultBlocks = 0;
+  for (size_t j = 0; j < ecBlockArray.size(); j++) {
+    ECB *ecBlock = ecBlockArray[j];
+    for (int i = 0; i < ecBlock->getCount(); i++) {
+      int numDataCodewords = ecBlock->getDataCodewords();
+      int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;
+      ArrayRef<unsigned char> buffer(numBlockCodewords);
+      Ref<DataBlock> blockRef(new DataBlock(numDataCodewords, buffer));
+      result[numResultBlocks++] = blockRef;
+    }
+  }
+
+  // All blocks have the same amount of data, except that the last n
+  // (where n may be 0) have 1 more byte. Figure out where these start.
+  int shorterBlocksTotalCodewords = result[0]->codewords_.size();
+  int longerBlocksStartAt = result.size() - 1;
+  while (longerBlocksStartAt >= 0) {
+    int numCodewords = result[longerBlocksStartAt]->codewords_.size();
+    if (numCodewords == shorterBlocksTotalCodewords) {
+      break;
+    }
+    if (numCodewords != shorterBlocksTotalCodewords + 1) {
+      throw IllegalArgumentException("Data block sizes differ by more than 1");
+    }
+    longerBlocksStartAt--;
+  }
+  longerBlocksStartAt++;
+
+  int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewords();
+  // The last elements of result may be 1 element longer;
+  // first fill out as many elements as all of them have
+  int rawCodewordsOffset = 0;
+  for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
+    for (int j = 0; j < numResultBlocks; j++) {
+      result[j]->codewords_[i] = rawCodewords[rawCodewordsOffset++];
+    }
+  }
+  // Fill out the last data block in the longer ones
+  for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {
+    result[j]->codewords_[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
+  }
+  // Now add in error correction blocks
+  int max = result[0]->codewords_.size();
+  for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
+    for (int j = 0; j < numResultBlocks; j++) {
+      int iOffset = j < longerBlocksStartAt ? i : i + 1;
+      result[j]->codewords_[iOffset] = rawCodewords[rawCodewordsOffset++];
+    }
+  }
+
+  if ((size_t)rawCodewordsOffset != rawCodewords.size()) {
+    throw IllegalArgumentException("rawCodewordsOffset != rawCodewords.length");
+  }
+
+  return result;
+}
+
+}
+}
+
+// file: zxing/qrcode/decoder/DataMask.cpp
+
+/*
+ *  DataMask.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 19/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/DataMask.h>
+
+// #include <zxing/common/IllegalArgumentException.h>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+DataMask::DataMask() {
+}
+
+DataMask::~DataMask() {
+}
+
+vector<Ref<DataMask> > DataMask::DATA_MASKS;
+static int N_DATA_MASKS = DataMask::buildDataMasks();
+
+DataMask &DataMask::forReference(int reference) {
+  if (reference < 0 || reference > 7) {
+    throw IllegalArgumentException("reference must be between 0 and 7");
+  }
+  return *DATA_MASKS[reference];
+}
+
+void DataMask::unmaskBitMatrix(BitMatrix& bits, size_t dimension) {
+  for (size_t y = 0; y < dimension; y++) {
+    for (size_t x = 0; x < dimension; x++) {
+      // TODO: check why the coordinates have to be swapped
+      if (isMasked(y, x)) {
+        bits.flip(x, y);
+      }
+    }
+  }
+}
+
+/**
+ * 000: mask bits for which (x + y) mod 2 == 0
+ */
+class DataMask000 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    //		return ((x + y) & 0x01) == 0;
+    return ((x + y) % 2) == 0;
+  }
+};
+
+/**
+ * 001: mask bits for which x mod 2 == 0
+ */
+class DataMask001 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t) {
+    //		return (x & 0x01) == 0;
+    return (x % 2) == 0;
+  }
+};
+
+/**
+ * 010: mask bits for which y mod 3 == 0
+ */
+class DataMask010 : public DataMask {
+public:
+  bool isMasked(size_t, size_t y) {
+    return y % 3 == 0;
+  }
+};
+
+/**
+ * 011: mask bits for which (x + y) mod 3 == 0
+ */
+class DataMask011 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    return (x + y) % 3 == 0;
+  }
+};
+
+/**
+ * 100: mask bits for which (x/2 + y/3) mod 2 == 0
+ */
+class DataMask100 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    //		return (((x >> 1) + (y / 3)) & 0x01) == 0;
+    return (((x >> 1) + (y / 3)) % 2) == 0;
+  }
+};
+
+/**
+ * 101: mask bits for which xy mod 2 + xy mod 3 == 0
+ */
+class DataMask101 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    size_t temp = x * y;
+    //		return (temp & 0x01) + (temp % 3) == 0;
+    return (temp % 2) + (temp % 3) == 0;
+
+  }
+};
+
+/**
+ * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
+ */
+class DataMask110 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    size_t temp = x * y;
+    //		return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
+    return (((temp % 2) + (temp % 3)) % 2) == 0;
+  }
+};
+
+/**
+ * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
+ */
+class DataMask111 : public DataMask {
+public:
+  bool isMasked(size_t x, size_t y) {
+    //		return ((((x + y) & 0x01) + ((x * y) % 3)) & 0x01) == 0;
+    return ((((x + y) % 2) + ((x * y) % 3)) % 2) == 0;
+  }
+};
+
+int DataMask::buildDataMasks() {
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask000()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask001()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask010()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask011()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask100()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask101()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask110()));
+  DATA_MASKS.push_back(Ref<DataMask> (new DataMask111()));
+  return DATA_MASKS.size();
+}
+
+}
+}
+
+// file: zxing/qrcode/decoder/DecodedBitStreamParser.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  DecodedBitStreamParser.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/DecodedBitStreamParser.h>
+// #include <zxing/common/CharacterSetECI.h>
+// #include <zxing/FormatException.h>
+// #include <zxing/common/StringUtils.h>
+// #include <iostream>
+#ifndef NO_ICONV
+// #include <iconv.h>
+#endif
+
+// Required for compatibility. TODO: test on Symbian
+#ifdef ZXING_ICONV_CONST
+#undef ICONV_CONST
+#define ICONV_CONST const
+#endif
+
+#ifndef ICONV_CONST
+#define ICONV_CONST /**/
+#endif
+
+using namespace std;
+using namespace zxing;
+using namespace zxing::qrcode;
+using namespace zxing::common;
+
+const char DecodedBitStreamParser::ALPHANUMERIC_CHARS[] =
+{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
+  'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+  'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+  'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'
+};
+
+namespace {int GB2312_SUBSET = 1;}
+
+void DecodedBitStreamParser::append(std::string &result,
+                                    string const& in,
+                                    const char *src) {
+  append(result, (unsigned char const*)in.c_str(), in.length(), src);
+}
+
+void DecodedBitStreamParser::append(std::string &result,
+                                    const unsigned char *bufIn,
+                                    size_t nIn,
+                                    const char *src) {
+#ifndef NO_ICONV
+  if (nIn == 0) {
+    return;
+  }
+
+  iconv_t cd = iconv_open(StringUtils::UTF8, src);
+  if (cd == (iconv_t)-1) {
+    result.append((const char *)bufIn, nIn);
+    return;
+  }
+
+  const int maxOut = 4 * nIn + 1;
+  unsigned char* bufOut = new unsigned char[maxOut];
+
+  ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn;
+  size_t nFrom = nIn;
+  char *toPtr = (char *)bufOut;
+  size_t nTo = maxOut;
+
+  while (nFrom > 0) {
+    size_t oneway = iconv(cd, &fromPtr, &nFrom, &toPtr, &nTo);
+    if (oneway == (size_t)(-1)) {
+      iconv_close(cd);
+      delete[] bufOut;
+      throw ReaderException("error converting characters");
+    }
+  }
+  iconv_close(cd);
+
+  int nResult = maxOut - nTo;
+  bufOut[nResult] = '\0';
+  result.append((const char *)bufOut);
+  delete[] bufOut;
+#else
+  result.append((const char *)bufIn, nIn);
+#endif
+}
+
+void DecodedBitStreamParser::decodeHanziSegment(Ref<BitSource> bits_,
+                                                string& result,
+                                                int count) {
+    BitSource& bits (*bits_);
+    // Don't crash trying to read more bits than we have available.
+    if (count * 13 > bits.available()) {
+      throw FormatException();
+    }
+
+    // Each character will require 2 bytes. Read the characters as 2-byte pairs
+    // and decode as GB2312 afterwards
+    size_t nBytes = 2 * count;
+    unsigned char* buffer = new unsigned char[nBytes];
+    int offset = 0;
+    while (count > 0) {
+      // Each 13 bits encodes a 2-byte character
+      int twoBytes = bits.readBits(13);
+      int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
+      if (assembledTwoBytes < 0x003BF) {
+        // In the 0xA1A1 to 0xAAFE range
+        assembledTwoBytes += 0x0A1A1;
+      } else {
+        // In the 0xB0A1 to 0xFAFE range
+        assembledTwoBytes += 0x0A6A1;
+      }
+      buffer[offset] = (unsigned char) ((assembledTwoBytes >> 8) & 0xFF);
+      buffer[offset + 1] = (unsigned char) (assembledTwoBytes & 0xFF);
+      offset += 2;
+      count--;
+    }
+
+    try {
+      append(result, buffer, nBytes, StringUtils::GB2312);
+    } catch (ReaderException const& re) {
+      delete [] buffer;
+      throw FormatException();
+    }
+
+    delete [] buffer;
+  }
+
+void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, std::string &result, int count) {
+  // Each character will require 2 bytes. Read the characters as 2-byte pairs
+  // and decode as Shift_JIS afterwards
+  size_t nBytes = 2 * count;
+  unsigned char* buffer = new unsigned char[nBytes];
+  int offset = 0;
+  while (count > 0) {
+    // Each 13 bits encodes a 2-byte character
+
+    int twoBytes = bits->readBits(13);
+    int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
+    if (assembledTwoBytes < 0x01F00) {
+      // In the 0x8140 to 0x9FFC range
+      assembledTwoBytes += 0x08140;
+    } else {
+      // In the 0xE040 to 0xEBBF range
+      assembledTwoBytes += 0x0C140;
+    }
+    buffer[offset] = (unsigned char)(assembledTwoBytes >> 8);
+    buffer[offset + 1] = (unsigned char)assembledTwoBytes;
+    offset += 2;
+    count--;
+  }
+
+  append(result, buffer, nBytes, StringUtils::SHIFT_JIS);
+  delete[] buffer;
+}
+
+void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_,
+                                               string& result,
+                                               int count,
+                                               CharacterSetECI* currentCharacterSetECI,
+                                               ArrayRef< ArrayRef<unsigned char> >& byteSegments,
+                                               Hashtable const& hints) {
+  int nBytes = count;
+  BitSource& bits (*bits_);
+  // Don't crash trying to read more bits than we have available.
+  if (count << 3 > bits.available()) {
+    throw FormatException();
+  }
+
+  ArrayRef<unsigned char> bytes_ (count);
+  unsigned char* readBytes = &(*bytes_)[0];
+  for (int i = 0; i < count; i++) {
+    readBytes[i] = (unsigned char) bits.readBits(8);
+  }
+  string encoding;
+  if (currentCharacterSetECI == 0) {
+    // The spec isn't clear on this mode; see
+    // section 6.4.5: t does not say which encoding to assuming
+    // upon decoding. I have seen ISO-8859-1 used as well as
+    // Shift_JIS -- without anything like an ECI designator to
+    // give a hint.
+    encoding = StringUtils::guessEncoding(readBytes, count, hints);
+  } else {
+    encoding = currentCharacterSetECI->getEncodingName();
+  }
+  try {
+    append(result, readBytes, nBytes, encoding.c_str());
+  } catch (ReaderException const& re) {
+    throw FormatException();
+  }
+  byteSegments->values().push_back(bytes_);
+}
+
+void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, std::string &result, int count) {
+  int nBytes = count;
+  unsigned char* bytes = new unsigned char[nBytes];
+  int i = 0;
+  // Read three digits at a time
+  while (count >= 3) {
+    // Each 10 bits encodes three digits
+    if (bits->available() < 10) {
+      throw ReaderException("format exception");
+    }
+    int threeDigitsBits = bits->readBits(10);
+    if (threeDigitsBits >= 1000) {
+      ostringstream s;
+      s << "Illegal value for 3-digit unit: " << threeDigitsBits;
+      delete[] bytes;
+      throw ReaderException(s.str().c_str());
+    }
+    bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100];
+    bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10];
+    bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10];
+    count -= 3;
+  }
+  if (count == 2) {
+    if (bits->available() < 7) {
+      throw ReaderException("format exception");
+    }
+    // Two digits left over to read, encoded in 7 bits
+    int twoDigitsBits = bits->readBits(7);
+    if (twoDigitsBits >= 100) {
+      ostringstream s;
+      s << "Illegal value for 2-digit unit: " << twoDigitsBits;
+      delete[] bytes;
+      throw ReaderException(s.str().c_str());
+    }
+    bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10];
+    bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10];
+  } else if (count == 1) {
+    if (bits->available() < 4) {
+      throw ReaderException("format exception");
+    }
+    // One digit left over to read
+    int digitBits = bits->readBits(4);
+    if (digitBits >= 10) {
+      ostringstream s;
+      s << "Illegal value for digit unit: " << digitBits;
+      delete[] bytes;
+      throw ReaderException(s.str().c_str());
+    }
+    bytes[i++] = ALPHANUMERIC_CHARS[digitBits];
+  }
+  append(result, bytes, nBytes, StringUtils::ASCII);
+  delete[] bytes;
+}
+
+char DecodedBitStreamParser::toAlphaNumericChar(size_t value) {
+  if (value >= sizeof(DecodedBitStreamParser::ALPHANUMERIC_CHARS)) {
+    throw FormatException();
+  }
+  return ALPHANUMERIC_CHARS[value];
+}
+
+void DecodedBitStreamParser::decodeAlphanumericSegment(Ref<BitSource> bits_,
+                                                       string& result,
+                                                       int count,
+                                                       bool fc1InEffect) {
+  BitSource& bits (*bits_);
+  ostringstream bytes;
+  // Read two characters at a time
+  while (count > 1) {
+    int nextTwoCharsBits = bits.readBits(11);
+    bytes << toAlphaNumericChar(nextTwoCharsBits / 45);
+    bytes << toAlphaNumericChar(nextTwoCharsBits % 45);
+    count -= 2;
+  }
+  if (count == 1) {
+    // special case: one character left
+    bytes << toAlphaNumericChar(bits.readBits(6));
+  }
+  // See section 6.4.8.1, 6.4.8.2
+  string s = bytes.str();
+  if (fc1InEffect) {
+    // We need to massage the result a bit if in an FNC1 mode:
+    ostringstream r;
+    for (size_t i = 0; i < s.length(); i++) {
+      if (s[i] != '%') {
+        r << s[i];
+      } else {
+        if (i < s.length() - 1 && s[i + 1] == '%') {
+          // %% is rendered as %
+          r << s[i++];
+        } else {
+          // In alpha mode, % should be converted to FNC1 separator 0x1D
+          r << (char)0x1D;
+        }
+      }
+    }
+    s = r.str();
+  }
+  append(result, s, StringUtils::ASCII);
+}
+
+namespace {
+  int parseECIValue(BitSource bits) {
+    int firstByte = bits.readBits(8);
+    if ((firstByte & 0x80) == 0) {
+      // just one byte
+      return firstByte & 0x7F;
+    }
+    if ((firstByte & 0xC0) == 0x80) {
+      // two bytes
+      int secondByte = bits.readBits(8);
+      return ((firstByte & 0x3F) << 8) | secondByte;
+    }
+    if ((firstByte & 0xE0) == 0xC0) {
+      // three bytes
+      int secondThirdBytes = bits.readBits(16);
+      return ((firstByte & 0x1F) << 16) | secondThirdBytes;
+    }
+    throw IllegalArgumentException("Bad ECI bits starting with byte ");
+  }
+}
+
+Ref<DecoderResult>
+DecodedBitStreamParser::decode(ArrayRef<unsigned char> bytes,
+                               Version* version,
+                               ErrorCorrectionLevel const& ecLevel,
+                               Hashtable const& hints) {
+  Ref<BitSource> bits_ (new BitSource(bytes));
+  BitSource& bits (*bits_);
+  string result;
+  CharacterSetECI* currentCharacterSetECI = 0;
+  bool fc1InEffect = false;
+  ArrayRef< ArrayRef<unsigned char> > byteSegments (size_t(0));
+  Mode* mode = 0;
+  do {
+    // While still another segment to read...
+    if (bits.available() < 4) {
+      // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
+      mode = &Mode::TERMINATOR;
+    } else {
+      try {
+        mode = &Mode::forBits(bits.readBits(4)); // mode is encoded by 4 bits
+      } catch (IllegalArgumentException const& iae) {
+        throw iae;
+        // throw FormatException.getFormatInstance();
+      }
+    }
+    if (mode != &Mode::TERMINATOR) {
+      if ((mode == &Mode::FNC1_FIRST_POSITION) || (mode == &Mode::FNC1_SECOND_POSITION)) {
+        // We do little with FNC1 except alter the parsed result a bit according to the spec
+        fc1InEffect = true;
+      } else if (mode == &Mode::STRUCTURED_APPEND) {
+        // not really supported; all we do is ignore it
+        // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
+        bits.readBits(16);
+      } else if (mode == &Mode::ECI) {
+        // Count doesn't apply to ECI
+        int value = parseECIValue(bits);
+        currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value);
+        if (currentCharacterSetECI == 0) {
+          throw FormatException();
+        }
+      } else {
+        // First handle Hanzi mode which does not start with character count
+        if (mode == &Mode::HANZI) {
+          //chinese mode contains a sub set indicator right after mode indicator
+          int subset = bits.readBits(4);
+          int countHanzi = bits.readBits(mode->getCharacterCountBits(version));
+          if (subset == GB2312_SUBSET) {
+            decodeHanziSegment(bits_, result, countHanzi);
+          }
+        } else {
+          // "Normal" QR code modes:
+          // How many characters will follow, encoded in this mode?
+          int count = bits.readBits(mode->getCharacterCountBits(version));
+          if (mode == &Mode::NUMERIC) {
+            decodeNumericSegment(bits_, result, count);
+          } else if (mode == &Mode::ALPHANUMERIC) {
+            decodeAlphanumericSegment(bits_, result, count, fc1InEffect);
+          } else if (mode == &Mode::BYTE) {
+            decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints);
+          } else if (mode == &Mode::KANJI) {
+            decodeKanjiSegment(bits_, result, count);
+          } else {
+            throw FormatException();
+          }
+        }
+      }
+    }
+  } while (mode != &Mode::TERMINATOR);
+
+  return Ref<DecoderResult>(new DecoderResult(bytes, Ref<String>(new String(result)), byteSegments, (string)ecLevel));
+}
+
+
+// file: zxing/qrcode/decoder/Decoder.cpp
+
+/*
+ *  Decoder.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 20/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/Decoder.h>
+// #include <zxing/qrcode/decoder/BitMatrixParser.h>
+// #include <zxing/qrcode/ErrorCorrectionLevel.h>
+// #include <zxing/qrcode/Version.h>
+// #include <zxing/qrcode/decoder/DataBlock.h>
+// #include <zxing/qrcode/decoder/DecodedBitStreamParser.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/reedsolomon/ReedSolomonException.h>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+Decoder::Decoder() :
+    rsDecoder_(GF256::QR_CODE_FIELD) {
+}
+
+void Decoder::correctErrors(ArrayRef<unsigned char> codewordBytes, int numDataCodewords) {
+  int numCodewords = codewordBytes->size();
+  ArrayRef<int> codewordInts(numCodewords);
+  for (int i = 0; i < numCodewords; i++) {
+    codewordInts[i] = codewordBytes[i] & 0xff;
+  }
+  int numECCodewords = numCodewords - numDataCodewords;
+
+  try {
+    rsDecoder_.decode(codewordInts, numECCodewords);
+  } catch (ReedSolomonException const& ex) {
+    ReaderException rex(ex.what());
+    throw rex;
+  }
+
+  for (int i = 0; i < numDataCodewords; i++) {
+    codewordBytes[i] = (unsigned char)codewordInts[i];
+  }
+}
+
+Ref<DecoderResult> Decoder::decode(Ref<BitMatrix> bits) {
+  // Construct a parser and read version, error-correction level
+  BitMatrixParser parser(bits);
+
+  Version *version = parser.readVersion();
+  ErrorCorrectionLevel &ecLevel = parser.readFormatInformation()->getErrorCorrectionLevel();
+
+
+  // Read codewords
+  ArrayRef<unsigned char> codewords(parser.readCodewords());
+
+
+  // Separate into data blocks
+  std::vector<Ref<DataBlock> > dataBlocks(DataBlock::getDataBlocks(codewords, version, ecLevel));
+
+
+  // Count total number of data bytes
+  int totalBytes = 0;
+  for (size_t i = 0; i < dataBlocks.size(); i++) {
+    totalBytes += dataBlocks[i]->getNumDataCodewords();
+  }
+  ArrayRef<unsigned char> resultBytes(totalBytes);
+  int resultOffset = 0;
+
+
+  // Error-correct and copy data blocks together into a stream of bytes
+  for (size_t j = 0; j < dataBlocks.size(); j++) {
+    Ref<DataBlock> dataBlock(dataBlocks[j]);
+    ArrayRef<unsigned char> codewordBytes = dataBlock->getCodewords();
+    int numDataCodewords = dataBlock->getNumDataCodewords();
+    correctErrors(codewordBytes, numDataCodewords);
+    for (int i = 0; i < numDataCodewords; i++) {
+      resultBytes[resultOffset++] = codewordBytes[i];
+    }
+  }
+
+  return DecodedBitStreamParser::decode(resultBytes,
+                                        version,
+                                        ecLevel,
+                                        DecodedBitStreamParser::Hashtable());
+}
+
+}
+}
+
+// file: zxing/qrcode/decoder/Mode.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Mode.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 19/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/decoder/Mode.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/qrcode/Version.h>
+// #include <sstream>
+
+using zxing::qrcode::Mode;
+using std::ostringstream;
+
+Mode Mode::TERMINATOR(0, 0, 0, 0x00, "TERMINATOR");
+Mode Mode::NUMERIC(10, 12, 14, 0x01, "NUMERIC");
+Mode Mode::ALPHANUMERIC(9, 11, 13, 0x02, "ALPHANUMERIC");
+Mode Mode::STRUCTURED_APPEND(0, 0, 0, 0x03, "STRUCTURED_APPEND");
+Mode Mode::BYTE(8, 16, 16, 0x04, "BYTE");
+Mode Mode::ECI(0, 0, 0, 0x07, "ECI");
+Mode Mode::KANJI(8, 10, 12, 0x08, "KANJI");
+Mode Mode::FNC1_FIRST_POSITION(0, 0, 0, 0x05, "FNC1_FIRST_POSITION");
+Mode Mode::FNC1_SECOND_POSITION(0, 0, 0, 0x09, "FNC1_SECOND_POSITION");
+Mode Mode::HANZI(8, 10, 12, 0x0D, "HANZI");
+
+Mode::Mode(int cbv0_9, int cbv10_26, int cbv27, int bits, char const* name) :
+    characterCountBitsForVersions0To9_(cbv0_9), characterCountBitsForVersions10To26_(cbv10_26),
+    characterCountBitsForVersions27AndHigher_(cbv27), bits_(bits), name_(name) {
+}
+
+Mode& Mode::forBits(int bits) {
+    switch (bits) {
+    case 0x0:
+        return TERMINATOR;
+    case 0x1:
+        return NUMERIC;
+    case 0x2:
+        return ALPHANUMERIC;
+    case 0x3:
+        return STRUCTURED_APPEND;
+    case 0x4:
+        return BYTE;
+    case 0x5:
+        return FNC1_FIRST_POSITION;
+    case 0x7:
+        return ECI;
+    case 0x8:
+        return KANJI;
+    case 0x9:
+        return FNC1_SECOND_POSITION;
+    case 0xD:
+        // 0xD is defined in GBT 18284-2000, may not be supported in foreign country
+        return HANZI;
+    default:
+        ostringstream s;
+        s << "Illegal mode bits: " << bits;
+        throw ReaderException(s.str().c_str());
+    }
+}
+
+int Mode::getCharacterCountBits(Version *version) {
+  int number = version->getVersionNumber();
+  if (number <= 9) {
+    return characterCountBitsForVersions0To9_;
+  } else if (number <= 26) {
+    return characterCountBitsForVersions10To26_;
+  } else {
+    return characterCountBitsForVersions27AndHigher_;
+  }
+}
+
+// file: zxing/qrcode/detector/AlignmentPattern.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  AlignmentPattern.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/AlignmentPattern.h>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+AlignmentPattern::AlignmentPattern(float posX, float posY, float estimatedModuleSize) :
+    ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize) {
+}
+
+bool AlignmentPattern::aboutEquals(float moduleSize, float i, float j) const {
+  if (abs(i - getY()) <= moduleSize && abs(j - getX()) <= moduleSize) {
+    float moduleSizeDiff = abs(moduleSize - estimatedModuleSize_);
+    return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize_;
+  }
+  return false;
+}
+
+Ref<AlignmentPattern> AlignmentPattern::combineEstimate(float i, float j, float newModuleSize) const {
+  float combinedX = (getX() + j) / 2.0f;
+  float combinedY = (getY() + i) / 2.0f;
+  float combinedModuleSize = (estimatedModuleSize_ + newModuleSize) / 2.0f;
+  Ref<AlignmentPattern> result
+    (new AlignmentPattern(combinedX, combinedY, combinedModuleSize));
+  return result;
+}
+
+}
+}
+
+// file: zxing/qrcode/detector/AlignmentPatternFinder.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  AlignmentPatternFinder.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 14/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "AlignmentPatternFinder.h"
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/BitArray.h>
+// #include <vector>
+// #include <cmath>
+// #include <cstdlib>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+float AlignmentPatternFinder::centerFromEnd(vector<int> &stateCount, int end) {
+  return (float)(end - stateCount[2]) - stateCount[1] / 2.0f;
+}
+
+bool AlignmentPatternFinder::foundPatternCross(vector<int> &stateCount) {
+  float maxVariance = moduleSize_ / 2.0f;
+  for (size_t i = 0; i < 3; i++) {
+    if (abs(moduleSize_ - stateCount[i]) >= maxVariance) {
+      return false;
+    }
+  }
+  return true;
+}
+
+float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount,
+    int originalStateCountTotal) {
+  int maxI = image_->getHeight();
+  vector<int> stateCount(3, 0);
+
+
+  // Start counting up from center
+  int i = startI;
+  while (i >= 0 && image_->get(centerJ, i) && stateCount[1] <= maxCount) {
+    stateCount[1]++;
+    i--;
+  }
+  // If already too many modules in this state or ran off the edge:
+  if (i < 0 || stateCount[1] > maxCount) {
+    return NAN;
+  }
+  while (i >= 0 && !image_->get(centerJ, i) && stateCount[0] <= maxCount) {
+    stateCount[0]++;
+    i--;
+  }
+  if (stateCount[0] > maxCount) {
+    return NAN;
+  }
+
+  // Now also count down from center
+  i = startI + 1;
+  while (i < maxI && image_->get(centerJ, i) && stateCount[1] <= maxCount) {
+    stateCount[1]++;
+    i++;
+  }
+  if (i == maxI || stateCount[1] > maxCount) {
+    return NAN;
+  }
+  while (i < maxI && !image_->get(centerJ, i) && stateCount[2] <= maxCount) {
+    stateCount[2]++;
+    i++;
+  }
+  if (stateCount[2] > maxCount) {
+    return NAN;
+  }
+
+  int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
+  if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
+    return NAN;
+  }
+
+  return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN;
+}
+
+Ref<AlignmentPattern> AlignmentPatternFinder::handlePossibleCenter(vector<int> &stateCount, size_t i, size_t j) {
+  int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
+  float centerJ = centerFromEnd(stateCount, j);
+  float centerI = crossCheckVertical(i, (int)centerJ, 2 * stateCount[1], stateCountTotal);
+  if (!isnan(centerI)) {
+    float estimatedModuleSize = (float)(stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
+    int max = possibleCenters_->size();
+    for (int index = 0; index < max; index++) {
+      Ref<AlignmentPattern> center((*possibleCenters_)[index]);
+      // Look for about the same center and module size:
+      if (center->aboutEquals(estimatedModuleSize, centerI, centerJ)) {
+        return center->combineEstimate(centerI, centerJ, estimatedModuleSize);
+      }
+    }
+    AlignmentPattern *tmp = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
+    // Hadn't found this before; save it
+    tmp->retain();
+    possibleCenters_->push_back(tmp);
+    if (callback_ != 0) {
+      callback_->foundPossibleResultPoint(*tmp);
+    }
+  }
+  Ref<AlignmentPattern> result;
+  return result;
+}
+
+AlignmentPatternFinder::AlignmentPatternFinder(Ref<BitMatrix> image, size_t startX, size_t startY, size_t width,
+                                               size_t height, float moduleSize,
+                                               Ref<ResultPointCallback>const& callback) :
+    image_(image), possibleCenters_(new vector<AlignmentPattern *> ()), startX_(startX), startY_(startY),
+    width_(width), height_(height), moduleSize_(moduleSize), callback_(callback) {
+}
+
+AlignmentPatternFinder::~AlignmentPatternFinder() {
+  for (size_t i = 0; i < possibleCenters_->size(); i++) {
+    (*possibleCenters_)[i]->release();
+    (*possibleCenters_)[i] = 0;
+  }
+  delete possibleCenters_;
+}
+
+Ref<AlignmentPattern> AlignmentPatternFinder::find() {
+  size_t maxJ = startX_ + width_;
+  size_t middleI = startY_ + (height_ >> 1);
+  //      Ref<BitArray> luminanceRow(new BitArray(width_));
+  // We are looking for black/white/black modules in 1:1:1 ratio;
+  // this tracks the number of black/white/black modules seen so far
+  vector<int> stateCount(3, 0);
+  for (size_t iGen = 0; iGen < height_; iGen++) {
+    // Search from middle outwards
+    size_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));
+    //        image_->getBlackRow(i, luminanceRow, startX_, width_);
+    stateCount[0] = 0;
+    stateCount[1] = 0;
+    stateCount[2] = 0;
+    size_t j = startX_;
+    // Burn off leading white pixels before anything else; if we start in the middle of
+    // a white run, it doesn't make sense to count its length, since we don't know if the
+    // white run continued to the left of the start point
+    while (j < maxJ && !image_->get(j, i)) {
+      j++;
+    }
+    int currentState = 0;
+    while (j < maxJ) {
+      if (image_->get(j, i)) {
+        // Black pixel
+        if (currentState == 1) { // Counting black pixels
+          stateCount[currentState]++;
+        } else { // Counting white pixels
+          if (currentState == 2) { // A winner?
+            if (foundPatternCross(stateCount)) { // Yes
+              Ref<AlignmentPattern> confirmed(handlePossibleCenter(stateCount, i, j));
+              if (confirmed != 0) {
+                return confirmed;
+              }
+            }
+            stateCount[0] = stateCount[2];
+            stateCount[1] = 1;
+            stateCount[2] = 0;
+            currentState = 1;
+          } else {
+            stateCount[++currentState]++;
+          }
+        }
+      } else { // White pixel
+        if (currentState == 1) { // Counting black pixels
+          currentState++;
+        }
+        stateCount[currentState]++;
+      }
+      j++;
+    }
+    if (foundPatternCross(stateCount)) {
+      Ref<AlignmentPattern> confirmed(handlePossibleCenter(stateCount, i, maxJ));
+      if (confirmed != 0) {
+        return confirmed;
+      }
+    }
+
+  }
+
+  // Hmm, nothing we saw was observed and confirmed twice. If we had
+  // any guess at all, return it.
+  if (possibleCenters_->size() > 0) {
+    Ref<AlignmentPattern> center((*possibleCenters_)[0]);
+    return center;
+  }
+
+  throw zxing::ReaderException("Could not find alignment pattern");
+}
+
+}
+}
+
+// file: zxing/qrcode/detector/Detector.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Detector.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 14/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/Detector.h>
+// #include <zxing/qrcode/detector/FinderPatternFinder.h>
+// #include <zxing/qrcode/detector/FinderPattern.h>
+// #include <zxing/qrcode/detector/AlignmentPattern.h>
+// #include <zxing/qrcode/detector/AlignmentPatternFinder.h>
+// #include <zxing/qrcode/Version.h>
+// #include <zxing/common/GridSampler.h>
+// #include <zxing/DecodeHints.h>
+// #include <cmath>
+// #include <sstream>
+// #include <cstdlib>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+Detector::Detector(Ref<BitMatrix> image) :
+    image_(image) {
+}
+
+Ref<BitMatrix> Detector::getImage() {
+   return image_;
+}
+
+Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
+  callback_ = hints.getResultPointCallback();
+  FinderPatternFinder finder(image_, hints.getResultPointCallback());
+  Ref<FinderPatternInfo> info(finder.find(hints));
+  return processFinderPatternInfo(info);
+}
+
+Ref<DetectorResult> Detector::processFinderPatternInfo(Ref<FinderPatternInfo> info){
+  Ref<FinderPattern> topLeft(info->getTopLeft());
+  Ref<FinderPattern> topRight(info->getTopRight());
+  Ref<FinderPattern> bottomLeft(info->getBottomLeft());
+
+  float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
+  if (moduleSize < 1.0f) {
+    throw zxing::ReaderException("bad module size");
+  }
+  int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
+  Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
+  int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
+
+  Ref<AlignmentPattern> alignmentPattern;
+  // Anything above version 1 has an alignment pattern
+  if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
+
+
+    // Guess where a "bottom right" finder pattern would have been
+    float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
+    float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY();
+
+
+    // Estimate that alignment pattern is closer by 3 modules
+    // from "bottom right" to known top left location
+    float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
+    int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
+    int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
+
+
+    // Kind of arbitrary -- expand search radius before giving up
+    for (int i = 4; i <= 16; i <<= 1) {
+      try {
+        alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
+        break;
+      } catch (zxing::ReaderException const& re) {
+        // try next round
+      }
+    }
+    if (alignmentPattern == 0) {
+      // Try anyway
+    }
+
+  }
+
+  Ref<PerspectiveTransform> transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
+  Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform));
+  std::vector<Ref<ResultPoint> > points(alignmentPattern == 0 ? 3 : 4);
+  points[0].reset(bottomLeft);
+  points[1].reset(topLeft);
+  points[2].reset(topRight);
+  if (alignmentPattern != 0) {
+    points[3].reset(alignmentPattern);
+  }
+
+  Ref<DetectorResult> result(new DetectorResult(bits, points, transform));
+  return result;
+}
+
+Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+    ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
+
+  float dimMinusThree = (float)dimension - 3.5f;
+  float bottomRightX;
+  float bottomRightY;
+  float sourceBottomRightX;
+  float sourceBottomRightY;
+  if (alignmentPattern != 0) {
+    bottomRightX = alignmentPattern->getX();
+    bottomRightY = alignmentPattern->getY();
+    sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
+  } else {
+    // Don't have an alignment pattern, just make up the bottom-right point
+    bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX();
+    bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY();
+    sourceBottomRightX = sourceBottomRightY = dimMinusThree;
+  }
+
+  Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX,
+                                      sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(),
+                                      topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY()));
+
+  return transform;
+}
+
+Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
+  GridSampler &sampler = GridSampler::getInstance();
+  return sampler.sampleGrid(image, dimension, transform);
+}
+
+int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
+                               float moduleSize) {
+  int tltrCentersDimension = int(FinderPatternFinder::distance(topLeft, topRight) / moduleSize + 0.5f);
+  int tlblCentersDimension = int(FinderPatternFinder::distance(topLeft, bottomLeft) / moduleSize + 0.5f);
+  int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
+  switch (dimension & 0x03) { // mod 4
+  case 0:
+    dimension++;
+    break;
+    // 1? do nothing
+  case 2:
+    dimension--;
+    break;
+  case 3:
+    ostringstream s;
+    s << "Bad dimension: " << dimension;
+    throw zxing::ReaderException(s.str().c_str());
+  }
+  return dimension;
+}
+
+float Detector::calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft) {
+  // Take the average
+  return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
+}
+
+float Detector::calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern) {
+  float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(),
+                         (int)otherPattern->getX(), (int)otherPattern->getY());
+  float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(),
+                         (int)pattern->getX(), (int)pattern->getY());
+  if (isnan(moduleSizeEst1)) {
+    return moduleSizeEst2;
+  }
+  if (isnan(moduleSizeEst2)) {
+    return moduleSizeEst1;
+  }
+  // Average them, and divide by 7 since we've counted the width of 3 black modules,
+  // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
+  return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
+}
+
+float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
+
+    float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
+
+    // Now count other way -- don't run off image though of course
+    float scale = 1.0f;
+    int otherToX = fromX - (toX - fromX);
+    if (otherToX < 0) {
+      scale = (float) fromX / (float) (fromX - otherToX);
+      otherToX = 0;
+    } else if (otherToX >= (int)image_->getWidth()) {
+      scale = (float) (image_->getWidth() - 1 - fromX) / (float) (otherToX - fromX);
+      otherToX = image_->getWidth() - 1;
+    }
+    int otherToY = (int) (fromY - (toY - fromY) * scale);
+
+    scale = 1.0f;
+    if (otherToY < 0) {
+      scale = (float) fromY / (float) (fromY - otherToY);
+      otherToY = 0;
+    } else if (otherToY >= (int)image_->getHeight()) {
+      scale = (float) (image_->getHeight() - 1 - fromY) / (float) (otherToY - fromY);
+      otherToY = image_->getHeight() - 1;
+    }
+    otherToX = (int) (fromX + (otherToX - fromX) * scale);
+
+    result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
+
+    // Middle pixel is double-counted this way; subtract 1
+    return result - 1.0f;
+}
+
+float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
+    // Mild variant of Bresenham's algorithm;
+    // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
+    bool steep = abs(toY - fromY) > abs(toX - fromX);
+    if (steep) {
+      int temp = fromX;
+      fromX = fromY;
+      fromY = temp;
+      temp = toX;
+      toX = toY;
+      toY = temp;
+    }
+
+    int dx = abs(toX - fromX);
+    int dy = abs(toY - fromY);
+    int error = -dx >> 1;
+    int xstep = fromX < toX ? 1 : -1;
+    int ystep = fromY < toY ? 1 : -1;
+
+    // In black pixels, looking for white, first or second time.
+    int state = 0;
+    // Loop up until x == toX, but not beyond
+    int xLimit = toX + xstep;
+    for (int x = fromX, y = fromY; x != xLimit; x += xstep) {
+      int realX = steep ? y : x;
+      int realY = steep ? x : y;
+
+      // Does current pixel mean we have moved white to black or vice versa?
+      if (!((state == 1) ^ image_->get(realX, realY))) {
+        if (state == 2) {
+          int diffX = x - fromX;
+          int diffY = y - fromY;
+          return (float) sqrt((double) (diffX * diffX + diffY * diffY));
+        }
+        state++;
+      }
+
+      error += dy;
+      if (error > 0) {
+        if (y == toY) {
+          break;
+        }
+        y += ystep;
+        error -= dx;
+      }
+    }
+    // Found black-white-black; give the benefit of the doubt that the next pixel outside the image
+    // is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
+    // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
+    if (state == 2) {
+      int diffX = toX + xstep - fromX;
+      int diffY = toY - fromY;
+      return (float) sqrt((double) (diffX * diffX + diffY * diffY));
+    }
+    // else we didn't find even black-white-black; no estimate is really possible
+    return NAN;
+}
+
+Ref<AlignmentPattern> Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
+    float allowanceFactor) {
+  // Look for an alignment pattern (3 modules in size) around where it
+  // should be
+  int allowance = (int)(allowanceFactor * overallEstModuleSize);
+  int alignmentAreaLeftX = max(0, estAlignmentX - allowance);
+  int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance);
+  if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {
+      throw zxing::ReaderException("region too small to hold alignment pattern");
+  }
+  int alignmentAreaTopY = max(0, estAlignmentY - allowance);
+  int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
+  if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {
+      throw zxing::ReaderException("region too small to hold alignment pattern");
+  }
+
+  AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
+                                         - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, callback_);
+  return alignmentFinder.find();
+}
+
+}
+}
+
+// file: zxing/qrcode/detector/FinderPattern.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  FinderPattern.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPattern.h>
+
+namespace zxing {
+	namespace qrcode {
+
+		using namespace std;
+
+		FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize) :
+		ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(1) {
+		}
+
+		FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize, int count) :
+		ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(count) {
+		}
+
+		int FinderPattern::getCount() const {
+			return count_;
+		}
+
+		float FinderPattern::getEstimatedModuleSize() const {
+			return estimatedModuleSize_;
+		}
+
+		void FinderPattern::incrementCount() {
+			count_++;
+		}
+
+/*
+		bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const {
+			return abs(i - posY_) <= moduleSize && abs(j - posX_) <= moduleSize && (abs(moduleSize - estimatedModuleSize_)
+																					<= 1.0f || abs(moduleSize - estimatedModuleSize_) / estimatedModuleSize_ <= 0.1f);
+		}
+*/
+    bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const {
+      if (abs(i - getY()) <= moduleSize && abs(j - getX()) <= moduleSize) {
+        float moduleSizeDiff = abs(moduleSize - estimatedModuleSize_);
+        return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize_;
+      }
+      return false;
+    }
+
+    Ref<FinderPattern> FinderPattern::combineEstimate(float i, float j, float newModuleSize) const {
+      int combinedCount = count_ + 1;
+      float combinedX = (count_ * getX() + j) / combinedCount;
+      float combinedY = (count_ * getY() + i) / combinedCount;
+      float combinedModuleSize = (count_ * getEstimatedModuleSize() + newModuleSize) / combinedCount;
+      return Ref<FinderPattern>(new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount));
+    }
+	}
+}
+
+// file: zxing/qrcode/detector/FinderPatternFinder.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  FinderPatternFinder.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPatternFinder.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/DecodeHints.h>
+// #include <vector>
+// #include <cmath>
+// #include <cstdlib>
+// #include <algorithm>
+
+namespace zxing {
+namespace qrcode {
+
+using namespace std;
+
+class FurthestFromAverageComparator {
+private:
+  const float averageModuleSize_;
+public:
+  FurthestFromAverageComparator(float averageModuleSize) :
+    averageModuleSize_(averageModuleSize) {
+  }
+  bool operator()(Ref<FinderPattern> a, Ref<FinderPattern> b) {
+    float dA = abs(a->getEstimatedModuleSize() - averageModuleSize_);
+    float dB = abs(b->getEstimatedModuleSize() - averageModuleSize_);
+    return dA > dB;
+  }
+};
+
+class CenterComparator {
+  const float averageModuleSize_;
+public:
+  CenterComparator(float averageModuleSize) :
+    averageModuleSize_(averageModuleSize) {
+  }
+  bool operator()(Ref<FinderPattern> a, Ref<FinderPattern> b) {
+    // N.B.: we want the result in descending order ...
+    if (a->getCount() != b->getCount()) {
+      return a->getCount() > b->getCount();
+    } else {
+      float dA = abs(a->getEstimatedModuleSize() - averageModuleSize_);
+      float dB = abs(b->getEstimatedModuleSize() - averageModuleSize_);
+      return dA < dB;
+    }
+  }
+};
+
+int FinderPatternFinder::CENTER_QUORUM = 2;
+int FinderPatternFinder::MIN_SKIP = 3;
+int FinderPatternFinder::MAX_MODULES = 57;
+
+float FinderPatternFinder::centerFromEnd(int* stateCount, int end) {
+  return (float)(end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f;
+}
+
+bool FinderPatternFinder::foundPatternCross(int* stateCount) {
+  int totalModuleSize = 0;
+  for (int i = 0; i < 5; i++) {
+    if (stateCount[i] == 0) {
+      return false;
+    }
+    totalModuleSize += stateCount[i];
+  }
+  if (totalModuleSize < 7) {
+    return false;
+  }
+  float moduleSize = (float)totalModuleSize / 7.0f;
+  float maxVariance = moduleSize / 2.0f;
+  // Allow less than 50% variance from 1-1-3-1-1 proportions
+  return abs(moduleSize - stateCount[0]) < maxVariance && abs(moduleSize - stateCount[1]) < maxVariance && abs(3.0f
+         * moduleSize - stateCount[2]) < 3.0f * maxVariance && abs(moduleSize - stateCount[3]) < maxVariance && abs(
+           moduleSize - stateCount[4]) < maxVariance;
+}
+
+float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal) {
+
+  int maxI = image_->getHeight();
+  int stateCount[5];
+  for (int i = 0; i < 5; i++)
+    stateCount[i] = 0;
+
+
+  // Start counting up from center
+  int i = startI;
+  while (i >= 0 && image_->get(centerJ, i)) {
+    stateCount[2]++;
+    i--;
+  }
+  if (i < 0) {
+    return NAN;
+  }
+  while (i >= 0 && !image_->get(centerJ, i) && stateCount[1] <= maxCount) {
+    stateCount[1]++;
+    i--;
+  }
+  // If already too many modules in this state or ran off the edge:
+  if (i < 0 || stateCount[1] > maxCount) {
+    return NAN;
+  }
+  while (i >= 0 && image_->get(centerJ, i) && stateCount[0] <= maxCount) {
+    stateCount[0]++;
+    i--;
+  }
+  if (stateCount[0] > maxCount) {
+    return NAN;
+  }
+
+  // Now also count down from center
+  i = startI + 1;
+  while (i < maxI && image_->get(centerJ, i)) {
+    stateCount[2]++;
+    i++;
+  }
+  if (i == maxI) {
+    return NAN;
+  }
+  while (i < maxI && !image_->get(centerJ, i) && stateCount[3] < maxCount) {
+    stateCount[3]++;
+    i++;
+  }
+  if (i == maxI || stateCount[3] >= maxCount) {
+    return NAN;
+  }
+  while (i < maxI && image_->get(centerJ, i) && stateCount[4] < maxCount) {
+    stateCount[4]++;
+    i++;
+  }
+  if (stateCount[4] >= maxCount) {
+    return NAN;
+  }
+
+  // If we found a finder-pattern-like section, but its size is more than 40% different than
+  // the original, assume it's a false positive
+  int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
+  if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
+    return NAN;
+  }
+
+  return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN;
+}
+
+float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount,
+    int originalStateCountTotal) {
+
+  int maxJ = image_->getWidth();
+  int stateCount[5];
+  for (int i = 0; i < 5; i++)
+    stateCount[i] = 0;
+
+  int j = startJ;
+  while (j >= 0 && image_->get(j, centerI)) {
+    stateCount[2]++;
+    j--;
+  }
+  if (j < 0) {
+    return NAN;
+  }
+  while (j >= 0 && !image_->get(j, centerI) && stateCount[1] <= maxCount) {
+    stateCount[1]++;
+    j--;
+  }
+  if (j < 0 || stateCount[1] > maxCount) {
+    return NAN;
+  }
+  while (j >= 0 && image_->get(j, centerI) && stateCount[0] <= maxCount) {
+    stateCount[0]++;
+    j--;
+  }
+  if (stateCount[0] > maxCount) {
+    return NAN;
+  }
+
+  j = startJ + 1;
+  while (j < maxJ && image_->get(j, centerI)) {
+    stateCount[2]++;
+    j++;
+  }
+  if (j == maxJ) {
+    return NAN;
+  }
+  while (j < maxJ && !image_->get(j, centerI) && stateCount[3] < maxCount) {
+    stateCount[3]++;
+    j++;
+  }
+  if (j == maxJ || stateCount[3] >= maxCount) {
+    return NAN;
+  }
+  while (j < maxJ && image_->get(j, centerI) && stateCount[4] < maxCount) {
+    stateCount[4]++;
+    j++;
+  }
+  if (stateCount[4] >= maxCount) {
+    return NAN;
+  }
+
+  // If we found a finder-pattern-like section, but its size is significantly different than
+  // the original, assume it's a false positive
+  int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
+  if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
+    return NAN;
+  }
+
+  return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : NAN;
+}
+
+bool FinderPatternFinder::handlePossibleCenter(int* stateCount, size_t i, size_t j) {
+  int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
+  float centerJ = centerFromEnd(stateCount, j);
+  float centerI = crossCheckVertical(i, (size_t)centerJ, stateCount[2], stateCountTotal);
+  if (!isnan(centerI)) {
+    // Re-cross check
+    centerJ = crossCheckHorizontal((size_t)centerJ, (size_t)centerI, stateCount[2], stateCountTotal);
+    if (!isnan(centerJ)) {
+      float estimatedModuleSize = (float)stateCountTotal / 7.0f;
+      bool found = false;
+      size_t max = possibleCenters_.size();
+      for (size_t index = 0; index < max; index++) {
+        Ref<FinderPattern> center = possibleCenters_[index];
+        // Look for about the same center and module size:
+        if (center->aboutEquals(estimatedModuleSize, centerI, centerJ)) {
+          possibleCenters_[index] = center->combineEstimate(centerI, centerJ, estimatedModuleSize);
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        Ref<FinderPattern> newPattern(new FinderPattern(centerJ, centerI, estimatedModuleSize));
+        possibleCenters_.push_back(newPattern);
+        if (callback_ != 0) {
+          callback_->foundPossibleResultPoint(*newPattern);
+        }
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+int FinderPatternFinder::findRowSkip() {
+  size_t max = possibleCenters_.size();
+  if (max <= 1) {
+    return 0;
+  }
+  Ref<FinderPattern> firstConfirmedCenter;
+  for (size_t i = 0; i < max; i++) {
+    Ref<FinderPattern> center = possibleCenters_[i];
+    if (center->getCount() >= CENTER_QUORUM) {
+      if (firstConfirmedCenter == 0) {
+        firstConfirmedCenter = center;
+      } else {
+        // We have two confirmed centers
+        // How far down can we skip before resuming looking for the next
+        // pattern? In the worst case, only the difference between the
+        // difference in the x / y coordinates of the two centers.
+        // This is the case where you find top left first. Draw it out.
+        hasSkipped_ = true;
+        return (int)(abs(firstConfirmedCenter->getX() - center->getX()) - abs(firstConfirmedCenter->getY()
+                     - center->getY()))/2;
+      }
+    }
+  }
+  return 0;
+}
+
+bool FinderPatternFinder::haveMultiplyConfirmedCenters() {
+  int confirmedCount = 0;
+  float totalModuleSize = 0.0f;
+  size_t max = possibleCenters_.size();
+  for (size_t i = 0; i < max; i++) {
+    Ref<FinderPattern> pattern = possibleCenters_[i];
+    if (pattern->getCount() >= CENTER_QUORUM) {
+      confirmedCount++;
+      totalModuleSize += pattern->getEstimatedModuleSize();
+    }
+  }
+  if (confirmedCount < 3) {
+    return false;
+  }
+  // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive"
+  // and that we need to keep looking. We detect this by asking if the estimated module sizes
+  // vary too much. We arbitrarily say that when the total deviation from average exceeds
+  // 5% of the total module size estimates, it's too much.
+  float average = totalModuleSize / max;
+  float totalDeviation = 0.0f;
+  for (size_t i = 0; i < max; i++) {
+    Ref<FinderPattern> pattern = possibleCenters_[i];
+    totalDeviation += abs(pattern->getEstimatedModuleSize() - average);
+  }
+  return totalDeviation <= 0.05f * totalModuleSize;
+}
+
+vector<Ref<FinderPattern> > FinderPatternFinder::selectBestPatterns() {
+  size_t startSize = possibleCenters_.size();
+
+  if (startSize < 3) {
+    // Couldn't find enough finder patterns
+    throw zxing::ReaderException("Could not find three finder patterns");
+  }
+
+  // Filter outlier possibilities whose module size is too different
+  if (startSize > 3) {
+    // But we can only afford to do so if we have at least 4 possibilities to choose from
+    float totalModuleSize = 0.0f;
+    float square = 0.0f;
+    for (size_t i = 0; i < startSize; i++) {
+      float size = possibleCenters_[i]->getEstimatedModuleSize();
+      totalModuleSize += size;
+      square += size * size;
+    }
+    float average = totalModuleSize / (float) startSize;
+    float stdDev = (float)sqrt(square / startSize - average * average);
+
+    sort(possibleCenters_.begin(), possibleCenters_.end(), FurthestFromAverageComparator(average));
+
+    float limit = max(0.2f * average, stdDev);
+
+    for (size_t i = 0; i < possibleCenters_.size() && possibleCenters_.size() > 3; i++) {
+      if (abs(possibleCenters_[i]->getEstimatedModuleSize() - average) > limit) {
+        possibleCenters_.erase(possibleCenters_.begin()+i);
+        i--;
+      }
+    }
+  }
+
+  if (possibleCenters_.size() > 3) {
+    // Throw away all but those first size candidate points we found.
+    float totalModuleSize = 0.0f;
+    for (size_t i = 0; i < possibleCenters_.size(); i++) {
+      float size = possibleCenters_[i]->getEstimatedModuleSize();
+      totalModuleSize += size;
+    }
+    float average = totalModuleSize / (float) possibleCenters_.size();
+    sort(possibleCenters_.begin(), possibleCenters_.end(), CenterComparator(average));
+  }
+
+  if (possibleCenters_.size() > 3) {
+    possibleCenters_.erase(possibleCenters_.begin()+3,possibleCenters_.end());
+  }
+
+  vector<Ref<FinderPattern> > result(3);
+  result[0] = possibleCenters_[0];
+  result[1] = possibleCenters_[1];
+  result[2] = possibleCenters_[2];
+  return result;
+}
+
+vector<Ref<FinderPattern> > FinderPatternFinder::orderBestPatterns(vector<Ref<FinderPattern> > patterns) {
+  // Find distances between pattern centers
+  float abDistance = distance(patterns[0], patterns[1]);
+  float bcDistance = distance(patterns[1], patterns[2]);
+  float acDistance = distance(patterns[0], patterns[2]);
+
+  Ref<FinderPattern> topLeft;
+  Ref<FinderPattern> topRight;
+  Ref<FinderPattern> bottomLeft;
+  // Assume one closest to other two is top left;
+  // topRight and bottomLeft will just be guesses below at first
+  if (bcDistance >= abDistance && bcDistance >= acDistance) {
+    topLeft = patterns[0];
+    topRight = patterns[1];
+    bottomLeft = patterns[2];
+  } else if (acDistance >= bcDistance && acDistance >= abDistance) {
+    topLeft = patterns[1];
+    topRight = patterns[0];
+    bottomLeft = patterns[2];
+  } else {
+    topLeft = patterns[2];
+    topRight = patterns[0];
+    bottomLeft = patterns[1];
+  }
+
+  // Use cross product to figure out which of other1/2 is the bottom left
+  // pattern. The vector "top-left -> bottom-left" x "top-left -> top-right"
+  // should yield a vector with positive z component
+  if ((bottomLeft->getY() - topLeft->getY()) * (topRight->getX() - topLeft->getX()) < (bottomLeft->getX()
+      - topLeft->getX()) * (topRight->getY() - topLeft->getY())) {
+    Ref<FinderPattern> temp = topRight;
+    topRight = bottomLeft;
+    bottomLeft = temp;
+  }
+
+  vector<Ref<FinderPattern> > results(3);
+  results[0] = bottomLeft;
+  results[1] = topLeft;
+  results[2] = topRight;
+  return results;
+}
+
+float FinderPatternFinder::distance(Ref<ResultPoint> p1, Ref<ResultPoint> p2) {
+  float dx = p1->getX() - p2->getX();
+  float dy = p1->getY() - p2->getY();
+  return (float)sqrt(dx * dx + dy * dy);
+}
+
+FinderPatternFinder::FinderPatternFinder(Ref<BitMatrix> image,
+                                           Ref<ResultPointCallback>const& callback) :
+    image_(image), possibleCenters_(), hasSkipped_(false), callback_(callback) {
+}
+
+Ref<FinderPatternInfo> FinderPatternFinder::find(DecodeHints const& hints) {
+  bool tryHarder = hints.getTryHarder();
+
+  size_t maxI = image_->getHeight();
+  size_t maxJ = image_->getWidth();
+
+
+  // We are looking for black/white/black/white/black modules in
+  // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far
+
+  // As this is used often, we use an integer array instead of vector
+  int stateCount[5];
+  bool done = false;
+
+
+  // Let's assume that the maximum version QR Code we support takes up 1/4
+  // the height of the image, and then account for the center being 3
+  // modules in size. This gives the smallest number of pixels the center
+  // could be, so skip this often. When trying harder, look for all
+  // QR versions regardless of how dense they are.
+  int iSkip = (3 * maxI) / (4 * MAX_MODULES);
+  if (iSkip < MIN_SKIP || tryHarder) {
+      iSkip = MIN_SKIP;
+  }
+
+  // This is slightly faster than using the Ref. Efficiency is important here
+  BitMatrix& matrix = *image_;
+
+  for (size_t i = iSkip - 1; i < maxI && !done; i += iSkip) {
+    // Get a row of black/white values
+
+    stateCount[0] = 0;
+    stateCount[1] = 0;
+    stateCount[2] = 0;
+    stateCount[3] = 0;
+    stateCount[4] = 0;
+    int currentState = 0;
+    for (size_t j = 0; j < maxJ; j++) {
+      if (matrix.get(j, i)) {
+        // Black pixel
+        if ((currentState & 1) == 1) { // Counting white pixels
+          currentState++;
+        }
+        stateCount[currentState]++;
+      } else { // White pixel
+        if ((currentState & 1) == 0) { // Counting black pixels
+          if (currentState == 4) { // A winner?
+            if (foundPatternCross(stateCount)) { // Yes
+              bool confirmed = handlePossibleCenter(stateCount, i, j);
+              if (confirmed) {
+                // Start examining every other line. Checking each line turned out to be too
+                // expensive and didn't improve performance.
+                iSkip = 2;
+                if (hasSkipped_) {
+                  done = haveMultiplyConfirmedCenters();
+                } else {
+                  int rowSkip = findRowSkip();
+                  if (rowSkip > stateCount[2]) {
+                    // Skip rows between row of lower confirmed center
+                    // and top of presumed third confirmed center
+                    // but back up a bit to get a full chance of detecting
+                    // it, entire width of center of finder pattern
+
+                    // Skip by rowSkip, but back off by stateCount[2] (size
+                    // of last center of pattern we saw) to be conservative,
+                    // and also back off by iSkip which is about to be
+                    // re-added
+                    i += rowSkip - stateCount[2] - iSkip;
+                    j = maxJ - 1;
+                  }
+                }
+              } else {
+                stateCount[0] = stateCount[2];
+                stateCount[1] = stateCount[3];
+                stateCount[2] = stateCount[4];
+                stateCount[3] = 1;
+                stateCount[4] = 0;
+                currentState = 3;
+                continue;
+              }
+              // Clear state to start looking again
+              currentState = 0;
+              stateCount[0] = 0;
+              stateCount[1] = 0;
+              stateCount[2] = 0;
+              stateCount[3] = 0;
+              stateCount[4] = 0;
+            } else { // No, shift counts back by two
+              stateCount[0] = stateCount[2];
+              stateCount[1] = stateCount[3];
+              stateCount[2] = stateCount[4];
+              stateCount[3] = 1;
+              stateCount[4] = 0;
+              currentState = 3;
+            }
+          } else {
+            stateCount[++currentState]++;
+          }
+        } else { // Counting white pixels
+          stateCount[currentState]++;
+        }
+      }
+    }
+    if (foundPatternCross(stateCount)) {
+      bool confirmed = handlePossibleCenter(stateCount, i, maxJ);
+      if (confirmed) {
+        iSkip = stateCount[0];
+        if (hasSkipped_) {
+          // Found a third one
+          done = haveMultiplyConfirmedCenters();
+        }
+      }
+    }
+  }
+
+  vector<Ref<FinderPattern> > patternInfo = selectBestPatterns();
+  patternInfo = orderBestPatterns(patternInfo);
+
+  Ref<FinderPatternInfo> result(new FinderPatternInfo(patternInfo));
+  return result;
+}
+}
+}
+
+// file: zxing/qrcode/detector/FinderPatternInfo.cpp
+
+/*
+ *  FinderPatternInfo.cpp
+ *  zxing
+ *
+ *  Created by Christian Brunschen on 13/05/2008.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPatternInfo.h>
+
+namespace zxing {
+namespace qrcode {
+
+FinderPatternInfo::FinderPatternInfo(std::vector<Ref<FinderPattern> > patternCenters) :
+    bottomLeft_(patternCenters[0]), topLeft_(patternCenters[1]), topRight_(patternCenters[2]) {
+}
+
+Ref<FinderPattern> FinderPatternInfo::getBottomLeft() {
+  return bottomLeft_;
+}
+Ref<FinderPattern> FinderPatternInfo::getTopLeft() {
+  return topLeft_;
+}
+Ref<FinderPattern> FinderPatternInfo::getTopRight() {
+  return topRight_;
+}
+
+}
+}
+
+// file: zxing/qrcode/detector/QREdgeDetector.cpp
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+/*
+ *  Created by Ralf Kistner on 7/12/2009.
+ *  Copyright 2008 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/QREdgeDetector.h>
+// #include <zxing/common/EdgeDetector.h>
+// #include <cstdlib>
+
+using namespace std;
+
+namespace zxing {
+namespace qrcode {
+
+static const float patternEdgeThreshold = 2;
+static const int patternEdgeWidth = 3;
+static const float patternEdgeSearchRatio = 1.1;
+static const int patternEdgeSkip = 2;
+
+static const float accurateEdgeThreshold = 3.3;
+static const int accurateEdgeWidth = 7;
+static const int accurateEdgeSkip = 2;
+
+static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) {
+  return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y);
+}
+
+static Point rp(Ref<ResultPoint> rp) {
+  return Point(rp->getX(), rp->getY());
+}
+
+QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { }
+
+Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+      ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
+
+  if(alignmentPattern == NULL) {
+    Point corner = findCorner(*Detector::getImage(), rp(topLeft), rp(topRight), rp(bottomLeft), dimension);
+    return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension);
+  } else {
+    return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
+  }
+}
+
+
+
+
+Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) {
+  (void)dimension;
+  Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft);
+
+  Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false);
+  Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true);
+
+  //return EdgeDetector::intersection(bottomEst, rightEst);
+
+  Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
+  Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
+
+
+  return EdgeDetector::intersection(bottom, right);
+}
+
+Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) {
+  Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite);
+
+  float dx = pattern.x - start.x;
+  float dy = pattern.y - start.y;
+  float dist = sqrt(dx*dx + dy*dy);
+
+  float dirX = direction.x - pattern.x;
+  float dirY = direction.y - pattern.y;
+  float dirSize = sqrt(dirX*dirX + dirY*dirY);
+
+  float nx = dirX/dirSize;
+  float ny = dirY/dirSize;
+
+  float search = dist * patternEdgeSearchRatio;
+  Point a(start.x + nx*search, start.y + ny*search);
+  Point b(start.x - nx*search, start.y - ny*search);
+
+  return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip);
+}
+
+
+Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) {
+  float dimMinusThree = (float) dimension - 3.5f;
+
+  Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension,
+                                      dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x,
+                                      topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y));
+
+  return transform;
+}
+
+// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector
+Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) {
+  int fromX = (int)from.x;
+  int fromY = (int)from.y;
+  int toX = (int)to.x;
+  int toY = (int)to.y;
+
+  bool steep = abs(toY - fromY) > abs(toX - fromX);
+  if (steep) {
+    int temp = fromX;
+    fromX = fromY;
+    fromY = temp;
+    temp = toX;
+    toX = toY;
+    toY = temp;
+  }
+
+  int dx = abs(toX - fromX);
+  int dy = abs(toY - fromY);
+  int error = -dx >> 1;
+  int ystep = fromY < toY ? -1 : 1;
+  int xstep = fromX < toX ? -1 : 1;
+  int state = 0; // In black pixels, looking for white, first or second time
+
+  // In case there are no points, prepopulate to from
+  int realX = fromX;
+  int realY = fromY;
+  for (int x = fromX, y = fromY; x != toX; x += xstep) {
+    realX = steep ? y : x;
+    realY = steep ? x : y;
+
+    if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight())
+      break;
+
+    if (state == 1) { // In white pixels, looking for black
+      if (image.get(realX, realY)) {
+        state++;
+      }
+    } else {
+      if (!image.get(realX, realY)) {
+        state++;
+      }
+    }
+
+    if (state == 3) { // Found black, white, black, and stumbled back onto white; done
+      return Point(realX, realY);
+    }
+    error += dy;
+    if (error > 0) {
+      y += ystep;
+      error -= dx;
+    }
+  }
+
+  // B-W-B run not found, return the last point visited.
+  return Point(realX, realY);
+}
+
+} // namespace qrcode
+} // namespace zxing
+

+ 5007 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/ios/zxing-all-in-one.h

xqd
@@ -0,0 +1,5007 @@
+#include <map>
+#include <exception>
+#include <algorithm>
+#include <typeinfo>
+#include <string>
+#include <limits>
+#include <limits.h>
+#include <sstream>
+#include <cstdarg>
+#include <math.h>
+#include <vector>
+#include <cmath>
+#include <string.h>
+#include <memory>
+#include <cstdlib>
+#include <iostream>
+#include <stdlib.h>
+#include <iconv.h>
+
+// file: zxing/Exception.h
+
+#ifndef __EXCEPTION_H__
+// #define __EXCEPTION_H__
+
+/*
+ *  Exception.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <exception>
+
+namespace zxing {
+
+class Exception : public std::exception {
+private:
+  std::string message;
+
+public:
+  Exception();
+  Exception(const char *msg);
+  virtual const char* what() const throw();
+  virtual ~Exception() throw();
+};
+
+}
+#endif // __EXCEPTION_H__
+
+// file: zxing/common/IllegalArgumentException.h
+
+#ifndef __ILLEGAL_ARGUMENT_EXCEPTION_H__
+// #define __ILLEGAL_ARGUMENT_EXCEPTION_H__
+
+/*
+ *  IllegalArgumentException.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Exception.h>
+
+namespace zxing {
+class IllegalArgumentException : public zxing::Exception {
+public:
+  IllegalArgumentException(const char *msg);
+  ~IllegalArgumentException() throw();
+};
+}
+
+#endif // __ILLEGAL_ARGUMENT_EXCEPTION_H__
+
+// file: zxing/common/Counted.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __COUNTED_H__
+// #define __COUNTED_H__
+
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define DEBUG_COUNTING
+
+// #include <iostream>
+
+#ifdef DEBUG_COUNTING
+// #include <typeinfo>
+#endif
+
+namespace zxing {
+
+/* base class for reference-counted objects */
+class Counted {
+private:
+  unsigned int count_;
+public:
+  Counted() :
+      count_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating " << typeid(*this).name() << " " << this <<
+         " @ " << count_ << "\n";
+#endif
+  }
+  virtual ~Counted() {
+  }
+  Counted *retain() {
+#ifdef DEBUG_COUNTING
+    cout << "retaining " << typeid(*this).name() << " " << this <<
+         " @ " << count_;
+#endif
+    count_++;
+#ifdef DEBUG_COUNTING
+    cout << "->" << count_ << "\n";
+#endif
+    return this;
+  }
+  void release() {
+#ifdef DEBUG_COUNTING
+    cout << "releasing " << typeid(*this).name() << " " << this <<
+         " @ " << count_;
+#endif
+    if (count_ == 0 || count_ == 54321) {
+#ifdef DEBUG_COUNTING
+      cout << "\nOverreleasing already-deleted object " << this << "!!!\n";
+#endif
+      throw 4711;
+    }
+    count_--;
+#ifdef DEBUG_COUNTING
+    cout << "->" << count_ << "\n";
+#endif
+    if (count_ == 0) {
+#ifdef DEBUG_COUNTING
+      cout << "deleting " << typeid(*this).name() << " " << this << "\n";
+#endif
+      count_ = 0xDEADF001;
+      delete this;
+    }
+  }
+
+
+  /* return the current count for denugging purposes or similar */
+  int count() const {
+    return count_;
+  }
+};
+
+/* counting reference to reference-counted objects */
+template<typename T> class Ref {
+private:
+public:
+  T *object_;
+  explicit Ref(T *o = 0) :
+      object_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating Ref " << this << " from pointer" << o << "\n";
+#endif
+    reset(o);
+  }
+
+  explicit Ref(const T &o) :
+      object_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating Ref " << this << " from reference\n";
+#endif
+    reset(const_cast<T *>(&o));
+  }
+
+  Ref(const Ref &other) :
+      object_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating Ref " << this << " from Ref " << &other << "\n";
+#endif
+    reset(other.object_);
+  }
+
+  template<class Y>
+  Ref(const Ref<Y> &other) :
+      object_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating Ref " << this << " from reference\n";
+#endif
+    reset(other.object_);
+  }
+
+  ~Ref() {
+#ifdef DEBUG_COUNTING
+    cout << "destroying Ref " << this << " with " <<
+         (object_ ? typeid(*object_).name() : "NULL") << " " << object_ << "\n";
+#endif
+    if (object_) {
+      object_->release();
+    }
+  }
+
+  void reset(T *o) {
+#ifdef DEBUG_COUNTING
+    cout << "resetting Ref " << this << " from " <<
+         (object_ ? typeid(*object_).name() : "NULL") << " " << object_ <<
+         " to " << (o ? typeid(*o).name() : "NULL") << " " << o << "\n";
+#endif
+    if (o) {
+      o->retain();
+    }
+    if (object_ != 0) {
+      object_->release();
+    }
+    object_ = o;
+  }
+  Ref& operator=(const Ref &other) {
+    reset(other.object_);
+    return *this;
+  }
+  template<class Y>
+  Ref& operator=(const Ref<Y> &other) {
+    reset(other.object_);
+    return *this;
+  }
+  Ref& operator=(T* o) {
+    reset(o);
+    return *this;
+  }
+  template<class Y>
+  Ref& operator=(Y* o) {
+    reset(o);
+    return *this;
+  }
+
+  T& operator*() {
+    return *object_;
+  }
+  T* operator->() const {
+    return object_;
+  }
+  operator T*() const {
+    return object_;
+  }
+
+  bool operator==(const T* that) {
+    return object_ == that;
+  }
+  bool operator==(const Ref &other) const {
+    return object_ == other.object_ || *object_ == *(other.object_);
+  }
+  template<class Y>
+  bool operator==(const Ref<Y> &other) const {
+    return object_ == other.object_ || *object_ == *(other.object_);
+  }
+
+  bool operator!=(const T* that) {
+    return !(*this == that);
+  }
+
+  bool empty() const {
+    return object_ == 0;
+  }
+
+  template<class Y>
+  friend std::ostream& operator<<(std::ostream &out, Ref<Y>& ref);
+};
+}
+
+#endif // __COUNTED_H__
+
+// file: zxing/common/BitArray.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __BIT_ARRAY_H__
+// #define __BIT_ARRAY_H__
+
+/*
+ *  Copyright 2010 ZXing authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/IllegalArgumentException.h>
+// #include <vector>
+// #include <limits>
+
+namespace zxing {
+
+#define ZX_LOG_DIGITS(digits) \
+    ((digits == 8) ? 3 : \
+     ((digits == 16) ? 4 : \
+      ((digits == 32) ? 5 : \
+       ((digits == 64) ? 6 : \
+        ((digits == 128) ? 7 : \
+         (-1))))))
+
+class BitArray : public Counted {
+private:
+  size_t size_;
+  std::vector<unsigned int> bits_;
+  static const unsigned int bitsPerWord_ =
+    std::numeric_limits<unsigned int>::digits;
+  static const unsigned int logBits_ = ZX_LOG_DIGITS(bitsPerWord_);
+  static const unsigned int bitsMask_ = (1 << logBits_) - 1;
+  static size_t wordsForBits(size_t bits);
+  explicit BitArray();
+
+public:
+  BitArray(size_t size);
+  ~BitArray();
+  size_t getSize();
+
+  bool get(size_t i) {
+    return (bits_[i >> logBits_] & (1 << (i & bitsMask_))) != 0;
+  }
+
+  void set(size_t i) {
+    bits_[i >> logBits_] |= 1 << (i & bitsMask_);
+  }
+
+  void setBulk(size_t i, unsigned int newBits);
+  void setRange(int start, int end);
+  void clear();
+  bool isRange(size_t start, size_t end, bool value);
+  std::vector<unsigned int>& getBitArray();
+  void reverse();
+};
+
+}
+
+#endif // __BIT_ARRAY_H__
+
+// file: zxing/common/BitMatrix.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __BIT_MATRIX_H__
+// #define __BIT_MATRIX_H__
+
+/*
+ *  BitMatrix.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitArray.h>
+// #include <limits>
+
+namespace zxing {
+
+class BitMatrix : public Counted {
+private:
+  size_t width_;
+  size_t height_;
+  size_t words_;
+  unsigned int* bits_;
+
+#define ZX_LOG_DIGITS(digits) \
+    ((digits == 8) ? 3 : \
+     ((digits == 16) ? 4 : \
+      ((digits == 32) ? 5 : \
+       ((digits == 64) ? 6 : \
+        ((digits == 128) ? 7 : \
+         (-1))))))
+
+  static const unsigned int bitsPerWord =
+    std::numeric_limits<unsigned int>::digits;
+  static const unsigned int logBits = ZX_LOG_DIGITS(bitsPerWord);
+  static const unsigned int bitsMask = (1 << logBits) - 1;
+
+public:
+  BitMatrix(size_t dimension);
+  BitMatrix(size_t width, size_t height);
+
+  ~BitMatrix();
+
+  bool get(size_t x, size_t y) const {
+    size_t offset = x + width_ * y;
+    return ((bits_[offset >> logBits] >> (offset & bitsMask)) & 0x01) != 0;
+  }
+
+  void set(size_t x, size_t y) {
+    size_t offset = x + width_ * y;
+    bits_[offset >> logBits] |= 1 << (offset & bitsMask);
+  }
+
+  void flip(size_t x, size_t y);
+  void clear();
+  void setRegion(size_t left, size_t top, size_t width, size_t height);
+  Ref<BitArray> getRow(int y, Ref<BitArray> row);
+
+  size_t getDimension() const;
+  size_t getWidth() const;
+  size_t getHeight() const;
+
+  unsigned int* getBits() const;
+
+  friend std::ostream& operator<<(std::ostream &out, const BitMatrix &bm);
+  const char *description();
+
+private:
+  BitMatrix(const BitMatrix&);
+  BitMatrix& operator =(const BitMatrix&);
+};
+
+}
+
+#endif // __BIT_MATRIX_H__
+
+// file: zxing/common/Array.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __ARRAY_H__
+// #define __ARRAY_H__
+
+/*
+ *  Array.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+
+#ifdef DEBUG_COUNTING
+// #include <iostream>
+// #include <typeinfo>
+#endif
+
+// #include <zxing/common/Counted.h>
+
+
+namespace zxing {
+
+template<typename T> class Array : public Counted {
+protected:
+public:
+  std::vector<T> values_;
+  Array(size_t n) :
+      Counted(), values_(n, T()) {
+  }
+  Array(T *ts, size_t n) :
+      Counted(), values_(ts, ts+n) {
+  }
+  Array(T v, size_t n) :
+      Counted(), values_(n, v) {
+  }
+  Array(std::vector<T> &v) :
+      Counted(), values_(v) {
+  }
+  Array(Array<T> &other) :
+      Counted(), values_(other.values_) {
+  }
+  Array(Array<T> *other) :
+      Counted(), values_(other->values_) {
+  }
+  virtual ~Array() {
+  }
+  Array<T>& operator=(const Array<T> &other) {
+#ifdef DEBUG_COUNTING
+    cout << "assigning values from Array " << &other << " to this Array " << this << ", ";
+#endif
+    values_ = other.values_;
+#ifdef DEBUG_COUNTING
+    cout << "new size = " << values_.size() << "\n";
+#endif
+    return *this;
+  }
+  Array<T>& operator=(const std::vector<T> &array) {
+#ifdef DEBUG_COUNTING
+    cout << "assigning values from Array " << &array << " to this Array " << this << ", ";
+#endif
+    values_ = array;
+#ifdef DEBUG_COUNTING
+    cout << "new size = " << values_.size() << "\n";
+#endif
+    return *this;
+  }
+  T operator[](size_t i) const {
+    return values_[i];
+  }
+  T& operator[](size_t i) {
+    return values_[i];
+  }
+  size_t size() const {
+    return values_.size();
+  }
+  std::vector<T> values() const {
+    return values_;
+  }
+  std::vector<T>& values() {
+    return values_;
+  }
+};
+
+template<typename T> class ArrayRef : public Counted {
+private:
+public:
+  Array<T> *array_;
+  ArrayRef() :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating empty ArrayRef " << this << "\n";
+#endif
+  }
+  ArrayRef(size_t n) :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << "with size " << n << "\n";
+#endif
+    reset(new Array<T> (n));
+  }
+  ArrayRef(T *ts, size_t n) :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n";
+#endif
+    reset(new Array<T> (ts, n));
+  }
+  ArrayRef(Array<T> *a) :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << " from pointer:\n";
+#endif
+    reset(a);
+  }
+  ArrayRef(const Array<T> &a) :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n";
+#endif
+    reset(const_cast<Array<T> *>(&a));
+  }
+  ArrayRef(const ArrayRef &other) :
+      Counted(), array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
+#endif
+    reset(other.array_);
+  }
+
+  template<class Y>
+  ArrayRef(const ArrayRef<Y> &other) :
+      array_(0) {
+#ifdef DEBUG_COUNTING
+    cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
+#endif
+    reset(static_cast<const Array<T> *>(other.array_));
+  }
+
+  ~ArrayRef() {
+#ifdef DEBUG_COUNTING
+    cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " "
+         << array_ << "\n";
+#endif
+    if (array_) {
+      array_->release();
+    }
+    array_ = 0;
+  }
+
+  T operator[](size_t i) const {
+    return (*array_)[i];
+  }
+  T& operator[](size_t i) {
+    return (*array_)[i];
+  }
+  size_t size() const {
+    return array_->size();
+  }
+
+  void reset(Array<T> *a) {
+#ifdef DEBUG_COUNTING
+    cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " "
+         << array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n";
+#endif
+    if (a) {
+      a->retain();
+    }
+    if (array_) {
+      array_->release();
+    }
+    array_ = a;
+  }
+  void reset(const ArrayRef<T> &other) {
+    reset(other.array_);
+  }
+  ArrayRef<T>& operator=(const ArrayRef<T> &other) {
+    reset(other);
+    return *this;
+  }
+  ArrayRef<T>& operator=(Array<T> *a) {
+    reset(a);
+    return *this;
+  }
+
+  Array<T>& operator*() {
+    return *array_;
+  }
+  Array<T>* operator->() {
+    return array_;
+  }
+};
+
+} // namespace zxing
+
+#endif // __ARRAY_H__
+
+// file: zxing/common/Str.h
+
+#ifndef __STR_H__
+// #define __STR_H__
+
+/*
+ *  Str.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <iostream>
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+
+class String : public Counted {
+private:
+  std::string text_;
+public:
+  String(const std::string &text);
+  const std::string &getText() const;
+  friend std::ostream &operator<<(std::ostream &out, const String &s);
+};
+
+}
+
+#endif // __COMMON__STRING_H__
+
+// file: zxing/common/BitSource.h
+
+#ifndef __BIT_SOURCE_H__
+// #define __BIT_SOURCE_H__
+
+/*
+ *  BitSource.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Array.h>
+
+namespace zxing {
+/**
+ * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
+ * number of bits read is not often a multiple of 8.</p>
+ *
+ * <p>This class is not thread-safe.</p>
+ *
+ * @author srowen@google.com (Sean Owen)
+ * @author christian.brunschen@gmail.com (Christian Brunschen)
+ */
+class BitSource : public Counted {
+  typedef unsigned char byte;
+private:
+  ArrayRef<byte> bytes_;
+  int byteOffset_;
+  int bitOffset_;
+public:
+  /**
+   * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.
+   * Bits are read within a byte from most-significant to least-significant bit.
+   */
+  BitSource(ArrayRef<byte> &bytes) :
+      bytes_(bytes), byteOffset_(0), bitOffset_(0) {
+  }
+
+  int getByteOffset() {
+    return byteOffset_;
+  }
+
+  /**
+   * @param numBits number of bits to read
+   * @return int representing the bits read. The bits will appear as the least-significant
+   *         bits of the int
+   * @throws IllegalArgumentException if numBits isn't in [1,32]
+   */
+  int readBits(int numBits);
+
+  /**
+   * @return number of bits that can be read successfully
+   */
+  int available();
+};
+
+}
+
+#endif // __BIT_SOURCE_H__
+
+// file: zxing/common/DecoderResult.h
+
+#ifndef __DECODER_RESULT_H__
+// #define __DECODER_RESULT_H__
+
+/*
+ *  DecoderResult.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <string>
+// #include <zxing/common/Str.h>
+
+namespace zxing {
+
+class DecoderResult : public Counted {
+private:
+  ArrayRef<unsigned char> rawBytes_;
+  Ref<String> text_;
+  ArrayRef< ArrayRef<unsigned char> > byteSegments_;
+  std::string ecLevel_;
+
+public:
+  DecoderResult(ArrayRef<unsigned char> rawBytes,
+                Ref<String> text,
+                ArrayRef< ArrayRef<unsigned char> >& byteSegments,
+                std::string const& ecLevel);
+
+  DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text);
+
+  ArrayRef<unsigned char> getRawBytes();
+  Ref<String> getText();
+};
+
+}
+
+#endif // __DECODER_RESULT_H__
+
+// file: zxing/common/PerspectiveTransform.h
+
+#ifndef __PERSPECTIVE_TANSFORM_H__
+// #define __PERSPECTIVE_TANSFORM_H__
+
+/*
+ *  PerspectiveTransform.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <vector>
+
+namespace zxing {
+class PerspectiveTransform : public Counted {
+private:
+  float a11, a12, a13, a21, a22, a23, a31, a32, a33;
+  PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, float a23,
+                       float a33);
+
+public:
+  static Ref<PerspectiveTransform>
+  quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3,
+                               float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p);
+  static Ref<PerspectiveTransform> squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2,
+      float x3, float y3);
+  static Ref<PerspectiveTransform> quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, float y2,
+      float x3, float y3);
+  Ref<PerspectiveTransform> buildAdjoint();
+  Ref<PerspectiveTransform> times(Ref<PerspectiveTransform> other);
+  void transformPoints(std::vector<float> &points);
+
+  friend std::ostream& operator<<(std::ostream& out, const PerspectiveTransform &pt);
+};
+}
+
+#endif // __PERSPECTIVE_TANSFORM_H__
+
+// file: zxing/ResultPoint.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __RESULT_POINT_H__
+// #define __RESULT_POINT_H__
+
+/*
+ *  ResultPoint.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <vector>
+
+namespace zxing {
+
+class ResultPoint : public Counted {
+protected:
+  float posX_;
+  float posY_;
+
+public:
+  ResultPoint();
+  ResultPoint(float x, float y);
+  virtual ~ResultPoint();
+
+  virtual float getX() const;
+  virtual float getY() const;
+
+  bool equals(Ref<ResultPoint> other);
+
+  static void orderBestPatterns(std::vector<Ref<ResultPoint> > &patterns);
+  static float distance(Ref<ResultPoint> point1, Ref<ResultPoint> point2);
+  static float distance(float x1, float x2, float y1, float y2);
+
+private:
+  static float crossProductZ(Ref<ResultPoint> pointA, Ref<ResultPoint> pointB, Ref<ResultPoint> pointC);
+};
+
+}
+
+#endif // __RESULT_POINT_H__
+
+// file: zxing/common/DetectorResult.h
+
+#ifndef __DETECTOR_RESULT_H__
+// #define __DETECTOR_RESULT_H__
+
+/*
+ *  DetectorResult.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/ResultPoint.h>
+// #include <zxing/common/PerspectiveTransform.h>
+
+namespace zxing {
+
+class DetectorResult : public Counted {
+private:
+  Ref<BitMatrix> bits_;
+  std::vector<Ref<ResultPoint> > points_;
+  Ref<PerspectiveTransform> transform_;
+
+public:
+  DetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points, Ref<PerspectiveTransform> transform);
+  Ref<BitMatrix> getBits();
+  std::vector<Ref<ResultPoint> > getPoints();
+  Ref<PerspectiveTransform> getTransform();
+};
+}
+
+#endif // __DETECTOR_RESULT_H__
+
+// file: zxing/common/Point.h
+
+#ifndef __POINT_H__
+// #define __POINT_H__
+
+/*
+ *  Point.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace zxing {
+class PointI {
+public:
+  int x;
+  int y;
+};
+
+class Point {
+public:
+  Point() : x(0.0f), y(0.0f) {};
+  Point(float x_, float y_) : x(x_), y(y_) {};
+
+  float x;
+  float y;
+};
+
+class Line {
+public:
+  Line(Point start_, Point end_) : start(start_), end(end_) {};
+
+  Point start;
+  Point end;
+};
+}
+#endif // POINT_H_
+
+// file: zxing/common/EdgeDetector.h
+
+#ifndef __EDGEDETECTOR_H__
+// #define __EDGEDETECTOR_H__
+/*
+ *  EdgeDetector.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+// #include <vector>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Point.h>
+
+namespace zxing {
+namespace EdgeDetector {
+
+void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation);
+Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip);
+
+Point intersection(Line a, Line b);
+
+}
+}
+#endif /* EDGEDETECTOR_H_ */
+
+// file: zxing/LuminanceSource.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __LUMINANCESOURCE_H__
+// #define __LUMINANCESOURCE_H__
+/*
+ *  LuminanceSource.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <string.h>
+
+namespace zxing {
+
+class LuminanceSource : public Counted {
+public:
+  LuminanceSource();
+  virtual ~LuminanceSource();
+
+  virtual int getWidth() const = 0;
+  virtual int getHeight() const = 0;
+
+  // Callers take ownership of the returned memory and must call delete [] on it themselves.
+  virtual unsigned char* getRow(int y, unsigned char* row) = 0;
+  virtual unsigned char* getMatrix() = 0;
+
+  virtual bool isCropSupported() const;
+  virtual Ref<LuminanceSource> crop(int left, int top, int width, int height);
+
+  virtual bool isRotateSupported() const;
+  virtual Ref<LuminanceSource> rotateCounterClockwise();
+
+  operator std::string (); // should be const but don't want to make sure a
+                           // large breaking change right now
+};
+
+}
+
+#endif /* LUMINANCESOURCE_H_ */
+
+// file: zxing/Binarizer.h
+
+#ifndef BINARIZER_H_
+#define BINARIZER_H_
+
+/*
+ *  Binarizer.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/LuminanceSource.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+
+class Binarizer : public Counted {
+ private:
+  Ref<LuminanceSource> source_;
+
+ public:
+  Binarizer(Ref<LuminanceSource> source);
+  virtual ~Binarizer();
+
+  virtual Ref<BitArray> getBlackRow(int y, Ref<BitArray> row) = 0;
+  virtual Ref<BitMatrix> getBlackMatrix() = 0;
+
+  Ref<LuminanceSource> getLuminanceSource() const ;
+  virtual Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source) = 0;
+};
+
+}
+#endif /* BINARIZER_H_ */
+
+// file: zxing/common/GlobalHistogramBinarizer.h
+
+#ifndef __GLOBALHISTOGRAMBINARIZER_H__
+// #define __GLOBALHISTOGRAMBINARIZER_H__
+/*
+ *  GlobalHistogramBinarizer.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/Binarizer.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/common/BitMatrix.h>
+
+namespace zxing {
+
+	class GlobalHistogramBinarizer : public Binarizer {
+	 private:
+    Ref<BitMatrix> cached_matrix_;
+	  Ref<BitArray> cached_row_;
+	  int cached_row_num_;
+
+	public:
+		GlobalHistogramBinarizer(Ref<LuminanceSource> source);
+		virtual ~GlobalHistogramBinarizer();
+
+		virtual Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
+		virtual Ref<BitMatrix> getBlackMatrix();
+		static int estimate(std::vector<int> &histogram);
+		Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source);
+	};
+
+}
+
+#endif /* GLOBALHISTOGRAMBINARIZER_H_ */
+
+// file: zxing/common/GreyscaleLuminanceSource.h
+
+#ifndef __GREYSCALE_LUMINANCE_SOURCE__
+#define __GREYSCALE_LUMINANCE_SOURCE__
+/*
+ *  GreyscaleLuminanceSource.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/LuminanceSource.h>
+
+namespace zxing {
+
+class GreyscaleLuminanceSource : public LuminanceSource {
+
+ private:
+  unsigned char* greyData_;
+  int dataWidth_;
+  int dataHeight_;
+  int left_;
+  int top_;
+  int width_;
+  int height_;
+
+ public:
+  GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth, int dataHeight, int left,
+      int top, int width, int height);
+
+  unsigned char* getRow(int y, unsigned char* row);
+  unsigned char* getMatrix();
+
+  bool isRotateSupported() const {
+    return true;
+  }
+
+  int getWidth() const {
+    return width_;
+  }
+
+  int getHeight() const {
+    return height_;
+  }
+
+  Ref<LuminanceSource> rotateCounterClockwise();
+
+};
+
+} /* namespace */
+
+#endif
+
+// file: zxing/common/GreyscaleRotatedLuminanceSource.h
+
+#ifndef __GREYSCALE_ROTATED_LUMINANCE_SOURCE__
+#define __GREYSCALE_ROTATED_LUMINANCE_SOURCE__
+/*
+ *  GreyscaleRotatedLuminanceSource.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// #include <zxing/LuminanceSource.h>
+
+namespace zxing {
+
+class GreyscaleRotatedLuminanceSource : public LuminanceSource {
+ private:
+  unsigned char* greyData_;
+  int dataWidth_;
+  int dataHeight_;
+  int left_;
+  int top_;
+  int width_;
+  int height_;
+
+public:
+  GreyscaleRotatedLuminanceSource(unsigned char* greyData, int dataWidth, int dataHeight,
+      int left, int top, int width, int height);
+
+  unsigned char* getRow(int y, unsigned char* row);
+  unsigned char* getMatrix();
+
+  bool isRotateSupported() const {
+    return false;
+  }
+
+  int getWidth() const {
+    return width_;
+  }
+
+  int getHeight() const {
+    return height_;
+  }
+
+};
+
+} /* namespace */
+
+#endif
+
+// file: zxing/common/GridSampler.h
+
+#ifndef __GRID_SAMPLER_H__
+// #define __GRID_SAMPLER_H__
+
+/*
+ *  GridSampler.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/PerspectiveTransform.h>
+
+namespace zxing {
+class GridSampler {
+private:
+  static GridSampler gridSampler;
+  GridSampler();
+
+public:
+  Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform);
+  Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimensionX, int dimensionY, Ref<PerspectiveTransform> transform);
+
+  Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, float p1ToX, float p1ToY, float p2ToX, float p2ToY,
+                            float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX,
+                            float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY);
+  static void checkAndNudgePoints(Ref<BitMatrix> image, std::vector<float> &points);
+  static GridSampler &getInstance();
+};
+}
+
+#endif // __GRID_SAMPLER_H__
+
+// file: zxing/common/HybridBinarizer.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __HYBRIDBINARIZER_H__
+// #define __HYBRIDBINARIZER_H__
+/*
+ *  HybridBinarizer.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/Binarizer.h>
+// #include <zxing/common/GlobalHistogramBinarizer.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/common/BitMatrix.h>
+
+namespace zxing {
+
+	class HybridBinarizer : public GlobalHistogramBinarizer {
+	 private:
+    Ref<BitMatrix> matrix_;
+	  Ref<BitArray> cached_row_;
+	  int cached_row_num_;
+
+	public:
+		HybridBinarizer(Ref<LuminanceSource> source);
+		virtual ~HybridBinarizer();
+
+		virtual Ref<BitMatrix> getBlackMatrix();
+		Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source);
+  private:
+    // We'll be using one-D arrays because C++ can't dynamically allocate 2D
+    // arrays
+    int* calculateBlackPoints(unsigned char* luminances,
+                              int subWidth,
+                              int subHeight,
+                              int width,
+                              int height);
+    void calculateThresholdForBlock(unsigned char* luminances,
+                                    int subWidth,
+                                    int subHeight,
+                                    int width,
+                                    int height,
+                                    int blackPoints[],
+                                    Ref<BitMatrix> const& matrix);
+    void threshold8x8Block(unsigned char* luminances,
+                           int xoffset,
+                           int yoffset,
+                           int threshold,
+                           int stride,
+                           Ref<BitMatrix> const& matrix);
+	};
+
+}
+
+#endif
+
+// file: zxing/common/reedsolomon/GF256.h
+
+#ifndef __GF256_H__
+// #define __GF256_H__
+
+/*
+ *  GF256.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <memory>
+// #include <vector>
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+class GF256Poly;
+
+class GF256 {
+  /**
+   * <p>This class contains utility methods for performing mathematical
+   * operations over the Galois Field GF(256). Operations use a given
+   * primitive polynomial in calculations.</p>
+   *
+   * <p>Throughout this package, elements of GF(256) are represented as an
+   * <code>int</code> for convenience and speed (but at the cost of memory).
+   * Only the bottom 8 bits are really used.</p>
+   *
+   * @author srowen@google.com (Sean Owen)
+   * @author christian.brunschen@gmail.com (Christian Brunschen)
+   */
+private:
+  std::vector<int> exp_;
+  std::vector<int> log_;
+  Ref<GF256Poly> zero_;
+  Ref<GF256Poly> one_;
+
+  GF256(int primitive);
+
+public:
+  Ref<GF256Poly> getZero();
+  Ref<GF256Poly> getOne();
+  Ref<GF256Poly> buildMonomial(int degree, int coefficient);
+  static int addOrSubtract(int a, int b);
+  int exp(int a);
+  int log(int a);
+  int inverse(int a);
+  int multiply(int a, int b);
+
+  static GF256 QR_CODE_FIELD;
+  static GF256 DATA_MATRIX_FIELD;
+
+  friend std::ostream& operator<<(std::ostream& out, const GF256& field);
+};
+}
+
+#endif // __GF256_H__
+
+// file: zxing/common/reedsolomon/GF256Poly.h
+
+#ifndef __GF256_POLY_H__
+// #define __GF256_POLY_H__
+
+/*
+ *  GF256Poly.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <memory>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+
+namespace zxing {
+class GF256;
+
+class GF256Poly : public Counted {
+private:
+  GF256 &field;
+  ArrayRef<int> coefficients;
+  void fixCoefficients();
+public:
+  GF256Poly(GF256 &field, ArrayRef<int> c);
+  ~GF256Poly();
+
+  int getDegree();
+  bool isZero();
+  int getCoefficient(int degree);
+  int evaluateAt(int a);
+  Ref<GF256Poly> addOrSubtract(Ref<GF256Poly> other);
+  Ref<GF256Poly> multiply(Ref<GF256Poly> other);
+  Ref<GF256Poly> multiply(int scalar);
+  Ref<GF256Poly> multiplyByMonomial(int degree, int coefficient);
+  const char *description() const;
+  friend std::ostream& operator<<(std::ostream& out, const GF256Poly& poly);
+
+};
+}
+
+#endif // __GF256_POLY_H__
+
+// file: zxing/common/reedsolomon/ReedSolomonDecoder.h
+
+#ifndef __REED_SOLOMON_DECODER_H__
+// #define __REED_SOLOMON_DECODER_H__
+
+/*
+ *  ReedSolomonDecoder.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <memory>
+// #include <vector>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+
+namespace zxing {
+class GF256;
+class GF256Poly;
+
+class ReedSolomonDecoder {
+private:
+  GF256 &field;
+public:
+  ReedSolomonDecoder(GF256 &fld);
+  ~ReedSolomonDecoder();
+  void decode(ArrayRef<int> received, int twoS);
+private:
+  std::vector<Ref<GF256Poly> > runEuclideanAlgorithm(Ref<GF256Poly> a, Ref<GF256Poly> b, int R);
+  ArrayRef<int> findErrorLocations(Ref<GF256Poly> errorLocator);
+  ArrayRef<int> findErrorMagnitudes(Ref<GF256Poly> errorEvaluator, ArrayRef<int> errorLocations, bool dataMatrix);
+};
+}
+
+#endif // __REED_SOLOMON_DECODER_H__
+
+// file: zxing/common/reedsolomon/ReedSolomonException.h
+
+#ifndef __REED_SOLOMON_EXCEPTION_H__
+// #define __REED_SOLOMON_EXCEPTION_H__
+
+/*
+ *  ReedSolomonException.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Exception.h>
+
+namespace zxing {
+class ReedSolomonException : public Exception {
+public:
+  ReedSolomonException(const char *msg) throw();
+  ~ReedSolomonException() throw();
+};
+}
+
+#endif // __REED_SOLOMON_EXCEPTION_H__
+
+// file: zxing/BarcodeFormat.h
+
+#ifndef __BARCODE_FORMAT_H__
+// #define __BARCODE_FORMAT_H__
+
+/*
+ *  BarcodeFormat.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace zxing {
+
+	typedef enum BarcodeFormat {
+		BarcodeFormat_None = 0,
+		BarcodeFormat_QR_CODE,
+		BarcodeFormat_DATA_MATRIX,
+		BarcodeFormat_UPC_E,
+		BarcodeFormat_UPC_A,
+		BarcodeFormat_EAN_8,
+		BarcodeFormat_EAN_13,
+		BarcodeFormat_CODE_128,
+		BarcodeFormat_CODE_39,
+		BarcodeFormat_ITF
+	} BarcodeFormat;
+
+	/* if you update the enum, please update the name in BarcodeFormat.cpp */
+	extern const char *barcodeFormatNames[];
+}
+
+#endif // __BARCODE_FORMAT_H__
+
+// file: zxing/BinaryBitmap.h
+
+#ifndef __BINARYBITMAP_H__
+// #define __BINARYBITMAP_H__
+
+/*
+ *  BinaryBitmap.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Binarizer.h>
+
+namespace zxing {
+
+	class BinaryBitmap : public Counted {
+	private:
+		Ref<Binarizer> binarizer_;
+		int cached_y_;
+
+	public:
+		BinaryBitmap(Ref<Binarizer> binarizer);
+		virtual ~BinaryBitmap();
+
+		Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
+		Ref<BitMatrix> getBlackMatrix();
+
+		Ref<LuminanceSource> getLuminanceSource() const;
+
+		int getWidth() const;
+		int getHeight() const;
+
+		bool isRotateSupported() const;
+		Ref<BinaryBitmap> rotateCounterClockwise();
+
+		bool isCropSupported() const;
+		Ref<BinaryBitmap> crop(int left, int top, int width, int height);
+
+	};
+
+}
+
+#endif /* BINARYBITMAP_H_ */
+
+// file: zxing/ResultPointCallback.h
+
+#ifndef __RESULT_POINT_CALLBACK_H__
+// #define __RESULT_POINT_CALLBACK_H__
+
+/*
+ *  ResultPointCallback.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+
+namespace zxing {
+
+class ResultPoint;
+
+class ResultPointCallback : public Counted {
+protected:
+  ResultPointCallback() {}
+public:
+  virtual void foundPossibleResultPoint(ResultPoint const& point) = 0;
+  virtual ~ResultPointCallback();
+};
+
+}
+
+#endif // __RESULT_POINT_CALLBACK_H__
+
+// file: zxing/DecodeHints.h
+
+#ifndef __DECODEHINTS_H_
+#define __DECODEHINTS_H_
+/*
+ *  DecodeHintType.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/BarcodeFormat.h>
+// #include <zxing/ResultPointCallback.h>
+
+namespace zxing {
+
+typedef unsigned int DecodeHintType;
+
+class DecodeHints {
+
+ private:
+
+  DecodeHintType hints;
+
+  Ref<ResultPointCallback> callback;
+
+ public:
+
+  static const DecodeHintType BARCODEFORMAT_QR_CODE_HINT = 1 << BarcodeFormat_QR_CODE;
+  static const DecodeHintType BARCODEFORMAT_DATA_MATRIX_HINT = 1 << BarcodeFormat_DATA_MATRIX;
+  static const DecodeHintType BARCODEFORMAT_UPC_E_HINT = 1 << BarcodeFormat_UPC_E;
+  static const DecodeHintType BARCODEFORMAT_UPC_A_HINT = 1 << BarcodeFormat_UPC_A;
+  static const DecodeHintType BARCODEFORMAT_EAN_8_HINT = 1 << BarcodeFormat_EAN_8;
+  static const DecodeHintType BARCODEFORMAT_EAN_13_HINT = 1 << BarcodeFormat_EAN_13;
+  static const DecodeHintType BARCODEFORMAT_CODE_128_HINT = 1 << BarcodeFormat_CODE_128;
+  static const DecodeHintType BARCODEFORMAT_CODE_39_HINT = 1 << BarcodeFormat_CODE_39;
+  static const DecodeHintType BARCODEFORMAT_ITF_HINT = 1 << BarcodeFormat_ITF;
+  static const DecodeHintType CHARACTER_SET = 1 << 30;
+  static const DecodeHintType TRYHARDER_HINT = 1 << 31;
+
+  static const DecodeHints PRODUCT_HINT;
+  static const DecodeHints ONED_HINT;
+  static const DecodeHints DEFAULT_HINT;
+
+  DecodeHints();
+  DecodeHints(DecodeHintType init);
+
+  void addFormat(BarcodeFormat toadd);
+  bool containsFormat(BarcodeFormat tocheck) const;
+  void setTryHarder(bool toset);
+  bool getTryHarder() const;
+
+  void setResultPointCallback(Ref<ResultPointCallback> const&);
+  Ref<ResultPointCallback> getResultPointCallback() const;
+
+};
+
+}
+
+#endif
+
+// file: zxing/Result.h
+
+#ifndef __RESULT_H__
+// #define __RESULT_H__
+
+/*
+ *  Result.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <vector>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Str.h>
+// #include <zxing/ResultPoint.h>
+// #include <zxing/BarcodeFormat.h>
+
+namespace zxing {
+
+class Result : public Counted {
+private:
+  Ref<String> text_;
+  ArrayRef<unsigned char> rawBytes_;
+  std::vector<Ref<ResultPoint> > resultPoints_;
+  BarcodeFormat format_;
+
+public:
+  Result(Ref<String> text, ArrayRef<unsigned char> rawBytes, std::vector<Ref<ResultPoint> > resultPoints,
+         BarcodeFormat format);
+  ~Result();
+  Ref<String> getText();
+  ArrayRef<unsigned char> getRawBytes();
+  const std::vector<Ref<ResultPoint> >& getResultPoints() const;
+  std::vector<Ref<ResultPoint> >& getResultPoints();
+  BarcodeFormat getBarcodeFormat() const;
+
+  friend std::ostream& operator<<(std::ostream &out, Result& result);
+};
+
+}
+#endif // __RESULT_H__
+
+// file: zxing/Reader.h
+
+#ifndef __READER_H__
+// #define __READER_H__
+
+/*
+ *  Reader.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/BinaryBitmap.h>
+// #include <zxing/Result.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+
+ class Reader : public Counted {
+  protected:
+   Reader() {}
+  public:
+   virtual Ref<Result> decode(Ref<BinaryBitmap> image);
+   virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints) = 0;
+   virtual ~Reader();
+};
+
+}
+
+#endif // __READER_H__
+
+// file: zxing/MultiFormatReader.h
+
+#ifndef __MULTI_FORMAT_READER_H__
+// #define __MULTI_FORMAT_READER_H__
+
+/*
+ *  MultiFormatBarcodeReader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// #include <zxing/Reader.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Result.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+  class MultiFormatReader : public Reader {
+
+  private:
+    Ref<Result> decodeInternal(Ref<BinaryBitmap> image);
+
+    std::vector<Ref<Reader> > readers_;
+    DecodeHints hints_;
+
+  public:
+    MultiFormatReader();
+
+    Ref<Result> decode(Ref<BinaryBitmap> image);
+    Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+    Ref<Result> decodeWithState(Ref<BinaryBitmap> image);
+    void setHints(DecodeHints hints);
+    ~MultiFormatReader();
+  };
+}
+
+#endif
+
+// file: zxing/ReaderException.h
+
+#ifndef __READER_EXCEPTION_H__
+// #define __READER_EXCEPTION_H__
+
+/*
+ *  ReaderException.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Exception.h>
+
+namespace zxing {
+
+class ReaderException : public Exception {
+public:
+  ReaderException();
+  ReaderException(const char *msg);
+  ~ReaderException() throw();
+};
+
+}
+#endif // __READER_EXCEPTION_H__
+
+// file: zxing/datamatrix/decoder/Decoder.h
+
+#ifndef __DECODER_DM_H__
+// #define __DECODER_DM_H__
+
+/*
+ *  Decoder.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/reedsolomon/ReedSolomonDecoder.h>
+// #include <zxing/common/reedsolomon/GF256.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/DecoderResult.h>
+// #include <zxing/common/BitMatrix.h>
+
+
+namespace zxing {
+namespace datamatrix {
+
+class Decoder {
+private:
+  ReedSolomonDecoder rsDecoder_;
+
+  void correctErrors(ArrayRef<unsigned char> bytes, int numDataCodewords);
+
+public:
+  Decoder();
+
+  Ref<DecoderResult> decode(Ref<BitMatrix> bits);
+};
+
+}
+}
+
+#endif // __DECODER_DM_H__
+
+// file: zxing/datamatrix/DataMatrixReader.h
+
+#ifndef __DATA_MATRIX_READER_H__
+// #define __DATA_MATRIX_READER_H__
+
+/*
+ *  DataMatrixReader.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Reader.h>
+// #include <zxing/DecodeHints.h>
+// #include <zxing/datamatrix/decoder/Decoder.h>
+
+namespace zxing {
+namespace datamatrix {
+
+class DataMatrixReader : public Reader {
+private:
+  Decoder decoder_;
+
+public:
+  DataMatrixReader();
+  virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+  virtual ~DataMatrixReader();
+
+};
+
+}
+}
+
+#endif // __DATA_MATRIX_READER_H__
+
+// file: zxing/datamatrix/Version.h
+
+#ifndef __VERSION_H__
+// #define __VERSION_H__
+
+/*
+ *  Version.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <vector>
+
+namespace zxing {
+namespace datamatrix {
+
+class ECB {
+private:
+  int count_;
+  int dataCodewords_;
+public:
+  ECB(int count, int dataCodewords);
+  int getCount();
+  int getDataCodewords();
+};
+
+class ECBlocks {
+private:
+  int ecCodewords_;
+  std::vector<ECB*> ecBlocks_;
+public:
+  ECBlocks(int ecCodewords, ECB *ecBlocks);
+  ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2);
+  int getECCodewords();
+  std::vector<ECB*>& getECBlocks();
+  ~ECBlocks();
+};
+
+class Version : public Counted {
+private:
+  int versionNumber_;
+  int symbolSizeRows_;
+  int symbolSizeColumns_;
+  int dataRegionSizeRows_;
+  int dataRegionSizeColumns_;
+  ECBlocks* ecBlocks_;
+  int totalCodewords_;
+  Version(int versionNumber, int symbolSizeRows, int symbolSizeColumns, int dataRegionSizeRows,
+		  int dataRegionSizeColumns, ECBlocks *ecBlocks);
+
+public:
+  static std::vector<Ref<Version> > VERSIONS;
+
+  ~Version();
+  int getVersionNumber();
+  int getSymbolSizeRows();
+  int getSymbolSizeColumns();
+  int getDataRegionSizeRows();
+  int getDataRegionSizeColumns();
+  int getTotalCodewords();
+  ECBlocks* getECBlocks();
+  static int  buildVersions();
+  Ref<Version> getVersionForDimensions(int numRows, int numColumns);
+
+private:
+  Version(const Version&);
+  Version & operator=(const Version&);
+};
+}
+}
+
+#endif // __VERSION_H__
+
+// file: zxing/datamatrix/decoder/BitMatrixParser.h
+
+#ifndef __BIT_MATRIX_PARSER_DM_H__
+// #define __BIT_MATRIX_PARSER_DM_H__
+
+/*
+ *  BitMatrixParser.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/datamatrix/Version.h>
+
+namespace zxing {
+namespace datamatrix {
+
+class BitMatrixParser : public Counted {
+private:
+  Ref<BitMatrix> bitMatrix_;
+  Ref<Version> parsedVersion_;
+  Ref<BitMatrix> readBitMatrix_;
+
+  int copyBit(size_t x, size_t y, int versionBits);
+
+public:
+  BitMatrixParser(Ref<BitMatrix> bitMatrix);
+  Ref<Version> readVersion(Ref<BitMatrix> bitMatrix);
+  ArrayRef<unsigned char> readCodewords();
+  bool readModule(int row, int column, int numRows, int numColumns);
+
+private:
+  int readUtah(int row, int column, int numRows, int numColumns);
+  int readCorner1(int numRows, int numColumns);
+  int readCorner2(int numRows, int numColumns);
+  int readCorner3(int numRows, int numColumns);
+  int readCorner4(int numRows, int numColumns);
+  Ref<BitMatrix> extractDataRegion(Ref<BitMatrix> bitMatrix);
+};
+
+}
+}
+
+#endif // __BIT_MATRIX_PARSER_DM_H__
+
+// file: zxing/datamatrix/decoder/DataBlock.h
+
+#ifndef __DATA_BLOCK_DM_H__
+// #define __DATA_BLOCK_DM_H__
+
+/*
+ *  DataBlock.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/datamatrix/Version.h>
+
+namespace zxing {
+namespace datamatrix {
+
+class DataBlock : public Counted {
+private:
+  int numDataCodewords_;
+  ArrayRef<unsigned char> codewords_;
+
+  DataBlock(int numDataCodewords, ArrayRef<unsigned char> codewords);
+
+public:
+  static std::vector<Ref<DataBlock> > getDataBlocks(ArrayRef<unsigned char> rawCodewords, Version *version);
+
+  int getNumDataCodewords();
+  ArrayRef<unsigned char> getCodewords();
+};
+
+}
+}
+
+#endif // __DATA_BLOCK_DM_H__
+
+// file: zxing/datamatrix/decoder/DecodedBitStreamParser.h
+
+#ifndef __DECODED_BIT_STREAM_PARSER_DM_H__
+// #define __DECODED_BIT_STREAM_PARSER_DM_H__
+
+/*
+ *  DecodedBitStreamParser.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <sstream>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/BitSource.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/DecoderResult.h>
+
+
+namespace zxing {
+namespace datamatrix {
+
+class DecodedBitStreamParser {
+private:
+  static const int PAD_ENCODE = 0;  // Not really an encoding
+  static const int ASCII_ENCODE = 1;
+  static const int C40_ENCODE = 2;
+  static const int TEXT_ENCODE = 3;
+  static const int ANSIX12_ENCODE = 4;
+  static const int EDIFACT_ENCODE = 5;
+  static const int BASE256_ENCODE = 6;
+
+  /**
+   * See ISO 16022:2006, Annex C Table C.1
+   * The C40 Basic Character Set (*'s used for placeholders for the shift values)
+   */
+  static const char C40_BASIC_SET_CHARS[];
+
+  static const char C40_SHIFT2_SET_CHARS[];
+  /**
+   * See ISO 16022:2006, Annex C Table C.2
+   * The Text Basic Character Set (*'s used for placeholders for the shift values)
+   */
+  static const char TEXT_BASIC_SET_CHARS[];
+
+  static const char TEXT_SHIFT3_SET_CHARS[];
+  /**
+   * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
+   */
+  int decodeAsciiSegment(Ref<BitSource> bits, std::ostringstream &result, std::ostringstream &resultTrailer);
+  /**
+   * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
+   */
+  void decodeC40Segment(Ref<BitSource> bits, std::ostringstream &result);
+  /**
+   * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
+   */
+  void decodeTextSegment(Ref<BitSource> bits, std::ostringstream &result);
+  /**
+   * See ISO 16022:2006, 5.2.7
+   */
+  void decodeAnsiX12Segment(Ref<BitSource> bits, std::ostringstream &result);
+  /**
+   * See ISO 16022:2006, 5.2.8 and Annex C Table C.3
+   */
+  void decodeEdifactSegment(Ref<BitSource> bits, std::ostringstream &result);
+  /**
+   * See ISO 16022:2006, 5.2.9 and Annex B, B.2
+   */
+  void decodeBase256Segment(Ref<BitSource> bits, std::ostringstream &result, std::vector<unsigned char> byteSegments);
+
+  void parseTwoBytes(int firstByte, int secondByte, int*& result);
+  /**
+   * See ISO 16022:2006, Annex B, B.2
+   */
+  unsigned char unrandomize255State(int randomizedBase256Codeword,
+                                          int base256CodewordPosition) {
+    int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;
+    int tempVariable = randomizedBase256Codeword - pseudoRandomNumber;
+    return (unsigned char) (tempVariable >= 0 ? tempVariable : (tempVariable + 256));
+  };
+  void append(std::ostream &ost, const unsigned char *bufIn, size_t nIn, const char *src);
+
+public:
+  DecodedBitStreamParser() { };
+  Ref<DecoderResult> decode(ArrayRef<unsigned char> bytes);
+};
+
+}
+}
+
+#endif // __DECODED_BIT_STREAM_PARSER_DM_H__
+
+// file: zxing/datamatrix/detector/CornerPoint.h
+
+#ifndef __CORNER_FINDER_H__
+// #define __CORNER_FINDER_H__
+
+/*
+ *  CornerPoint.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPoint.h>
+// #include <cmath>
+
+namespace zxing {
+	namespace datamatrix {
+
+		class CornerPoint : public ResultPoint {
+		private:
+			int counter_;
+
+		public:
+			CornerPoint(float posX, float posY);
+			int getCount() const;
+			void incrementCount();
+			bool equals(Ref<CornerPoint> other) const;
+		};
+	}
+}
+
+#endif // __CORNER_FINDER_H__
+
+// file: zxing/datamatrix/detector/MonochromeRectangleDetector.h
+
+#ifndef __MONOCHROMERECTANGLEDETECTOR_H__
+// #define __MONOCHROMERECTANGLEDETECTOR_H__
+
+/*
+ *  MonochromeRectangleDetector.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/ReaderException.h>
+// #include <zxing/ResultPoint.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/datamatrix/detector/CornerPoint.h>
+
+namespace zxing {
+namespace datamatrix {
+
+struct TwoInts: public Counted {
+	int start;
+	int end;
+};
+
+class MonochromeRectangleDetector : public Counted {
+private:
+  static const int MAX_MODULES = 32;
+  Ref<BitMatrix> image_;
+
+public:
+  MonochromeRectangleDetector(Ref<BitMatrix> image) : image_(image) {  };
+
+  std::vector<Ref<CornerPoint> > detect();
+
+private:
+  Ref<CornerPoint> findCornerFromCenter(int centerX, int deltaX, int left, int right,
+      int centerY, int deltaY, int top, int bottom, int maxWhiteRun);
+
+  Ref<TwoInts> blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
+      bool horizontal);
+
+  int max(int a, float b) { return (float) a > b ? a : (int) b;};
+};
+}
+}
+
+#endif // __MONOCHROMERECTANGLEDETECTOR_H__
+
+// file: zxing/datamatrix/detector/Detector.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __DETECTOR_H__
+// #define __DETECTOR_H__
+
+/*
+ *  Detector.h
+ *  zxing
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/DetectorResult.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/PerspectiveTransform.h>
+// #include <zxing/common/detector/WhiteRectangleDetector.h>
+
+namespace zxing {
+namespace datamatrix {
+
+class ResultPointsAndTransitions: public Counted {
+  private:
+    Ref<ResultPoint> to_;
+    Ref<ResultPoint> from_;
+    int transitions_;
+
+  public:
+    ResultPointsAndTransitions();
+    ResultPointsAndTransitions(Ref<ResultPoint> from, Ref<ResultPoint> to, int transitions);
+    Ref<ResultPoint> getFrom();
+    Ref<ResultPoint> getTo();
+    int getTransitions();
+};
+
+class Detector: public Counted {
+  private:
+    Ref<BitMatrix> image_;
+
+  protected:
+    Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimensionX, int dimensionY,
+        Ref<PerspectiveTransform> transform);
+
+    void insertionSort(std::vector<Ref<ResultPointsAndTransitions> >& vector);
+
+    Ref<ResultPoint> correctTopRightRectangular(Ref<ResultPoint> bottomLeft,
+        Ref<ResultPoint> bottomRight, Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight,
+        int dimensionTop, int dimensionRight);
+    Ref<ResultPoint> correctTopRight(Ref<ResultPoint> bottomLeft, Ref<ResultPoint> bottomRight,
+        Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, int dimension);
+    bool isValid(Ref<ResultPoint> p);
+    int distance(Ref<ResultPoint> a, Ref<ResultPoint> b);
+    Ref<ResultPointsAndTransitions> transitionsBetween(Ref<ResultPoint> from, Ref<ResultPoint> to);
+    int min(int a, int b) {
+      return a > b ? b : a;
+    }
+    /**
+     * Ends up being a bit faster than round(). This merely rounds its
+     * argument to the nearest int, where x.5 rounds up.
+     */
+    int round(float d) {
+      return (int) (d + 0.5f);
+    }
+
+  public:
+    Ref<BitMatrix> getImage();
+    Detector(Ref<BitMatrix> image);
+
+    virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft,
+        Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft, Ref<ResultPoint> bottomRight,
+        int dimensionX, int dimensionY);
+
+    Ref<DetectorResult> detect();
+
+  private:
+    int compare(Ref<ResultPointsAndTransitions> a, Ref<ResultPointsAndTransitions> b);
+};
+
+}
+}
+
+#endif // __DETECTOR_H__
+
+// file: zxing/oned/OneDReader.h
+
+#ifndef __ONED_READER_H__
+// #define __ONED_READER_H__
+
+/*
+ *  OneDReader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Reader.h>
+
+namespace zxing {
+	namespace oned {
+		class OneDReader : public Reader {
+		private:
+			static const int INTEGER_MATH_SHIFT = 8;
+
+			Ref<Result> doDecode(Ref<BinaryBitmap> image, DecodeHints hints);
+		public:
+			static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
+
+			OneDReader();
+			virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+
+			// Implementations must not throw any exceptions. If a barcode is not found on this row,
+			// a empty ref should be returned e.g. return Ref<Result>();
+			virtual Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row) = 0;
+
+			static unsigned int patternMatchVariance(int counters[], int countersSize,
+			    const int pattern[], int maxIndividualVariance);
+			static bool recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount);
+			virtual ~OneDReader();
+		};
+	}
+}
+
+#endif
+
+// file: zxing/oned/Code128Reader.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __CODE_128_READER_H__
+// #define __CODE_128_READER_H__
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+	namespace oned {
+		class Code128Reader : public OneDReader {
+
+		private:
+      enum {MAX_AVG_VARIANCE = (unsigned int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 250/1000)};
+      enum {MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 700/1000)};
+			static const int CODE_SHIFT = 98;
+
+			static const int CODE_CODE_C = 99;
+			static const int CODE_CODE_B = 100;
+			static const int CODE_CODE_A = 101;
+
+			static const int CODE_FNC_1 = 102;
+			static const int CODE_FNC_2 = 97;
+			static const int CODE_FNC_3 = 96;
+			static const int CODE_FNC_4_A = 101;
+			static const int CODE_FNC_4_B = 100;
+
+			static const int CODE_START_A = 103;
+			static const int CODE_START_B = 104;
+			static const int CODE_START_C = 105;
+			static const int CODE_STOP = 106;
+
+			static int* findStartPattern(Ref<BitArray> row);
+			static int decodeCode(Ref<BitArray> row, int counters[], int countersCount, int rowOffset);
+
+			void append(char* s, char c);
+		public:
+			Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+			Code128Reader();
+			~Code128Reader();
+		};
+	}
+}
+
+#endif
+
+// file: zxing/oned/Code39Reader.h
+
+#ifndef __CODE_39_READER_H__
+// #define __CODE_39_READER_H__
+/*
+ *  Code39Reader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+	namespace oned {
+
+		/**
+		 * <p>Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.</p>
+		 * Ported form Java (author Sean Owen)
+		 * @author Lukasz Warchol
+		 */
+		class Code39Reader : public OneDReader {
+
+		private:
+			std::string alphabet_string;
+
+			bool usingCheckDigit;
+			bool extendedMode;
+
+			static int* findAsteriskPattern(Ref<BitArray> row);														//throws ReaderException
+			static int toNarrowWidePattern(int counters[], int countersLen);
+			static char patternToChar(int pattern);																	//throws ReaderException
+			static Ref<String> decodeExtended(std::string encoded);													//throws ReaderException
+
+			void append(char* s, char c);
+		public:
+			Code39Reader();
+			Code39Reader(bool usingCheckDigit_);
+			Code39Reader(bool usingCheckDigit_, bool extendedMode_);
+
+			Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+    };
+	}
+}
+
+#endif
+
+// file: zxing/oned/UPCEANReader.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __UPC_EAN_READER_H__
+// #define __UPC_EAN_READER_H__
+
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Result.h>
+
+typedef enum UPC_EAN_PATTERNS {
+	UPC_EAN_PATTERNS_L_PATTERNS = 0,
+	UPC_EAN_PATTERNS_L_AND_G_PATTERNS
+} UPC_EAN_PATTERNS;
+
+namespace zxing {
+	namespace oned {
+		class UPCEANReader : public OneDReader {
+
+		private:
+      enum {MAX_AVG_VARIANCE = (unsigned int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 420/1000)};
+      enum {MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 700/1000)};
+
+			static bool findStartGuardPattern(Ref<BitArray> row, int* rangeStart, int* rangeEnd);
+
+			virtual bool decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin, int* endGuardEnd);
+
+			static bool checkStandardUPCEANChecksum(std::string s);
+		protected:
+			static bool findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
+			    const int pattern[], int patternLen, int* start, int* end);
+
+			virtual int getMIDDLE_PATTERN_LEN();
+			virtual const int* getMIDDLE_PATTERN();
+
+		public:
+			UPCEANReader();
+
+      // Returns < 0 on failure, >= 0 on success.
+			virtual int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+			    std::string& resultString) = 0;
+
+			Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+
+			// TODO(dswitkin): Should this be virtual so that UPCAReader can override it?
+			Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+          int startGuardEnd);
+
+      // Returns < 0 on failure, >= 0 on success.
+			static int decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
+			    UPC_EAN_PATTERNS patternType);
+
+			virtual bool checkChecksum(std::string s);
+
+			virtual BarcodeFormat getBarcodeFormat() = 0;
+			virtual ~UPCEANReader();
+		};
+	}
+}
+
+#endif
+
+// file: zxing/oned/EAN13Reader.h
+
+#ifndef __EAN_13_READER_H__
+// #define __EAN_13_READER_H__
+
+/*
+ *  EAN13Reader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/UPCEANReader.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+  namespace oned {
+    class EAN13Reader : public UPCEANReader {
+
+    private:
+      static bool determineFirstDigit(std::string& resultString, int lgPatternFound);
+
+    public:
+      EAN13Reader();
+
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+          std::string& resultString);
+
+      BarcodeFormat getBarcodeFormat();
+    };
+  }
+}
+
+#endif
+
+// file: zxing/oned/EAN8Reader.h
+
+#ifndef __EAN_8_READER_H__
+// #define __EAN_8_READER_H__
+
+/*
+ *  EAN8Reader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/UPCEANReader.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+  namespace oned {
+    class EAN8Reader : public UPCEANReader {
+
+    public:
+      EAN8Reader();
+
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+          std::string& resultString);
+
+      BarcodeFormat getBarcodeFormat();
+    };
+  }
+}
+
+#endif
+
+// file: zxing/oned/ITFReader.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __ITF_READER_H__
+// #define __ITF_READER_H__
+
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+// #include <zxing/common/BitArray.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+	namespace oned {
+		class ITFReader : public OneDReader {
+
+		private:
+      enum {MAX_AVG_VARIANCE = (unsigned int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 420/1000)};
+			enum {MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 800/1000)};
+			// Stores the actual narrow line width of the image being decoded.
+			int narrowLineWidth;
+
+			int* decodeStart(Ref<BitArray> row);																		//throws ReaderException
+			int* decodeEnd(Ref<BitArray> row);																				//throws ReaderException
+			static void decodeMiddle(Ref<BitArray> row, int payloadStart, int payloadEnd, std::string& resultString);	//throws ReaderException
+			void validateQuietZone(Ref<BitArray> row, int startPattern);												//throws ReaderException
+			static int skipWhiteSpace(Ref<BitArray> row);																//throws ReaderException
+
+			static int* findGuardPattern(Ref<BitArray> row, int rowOffset, const int pattern[], int patternLen);		//throws ReaderException
+			static int decodeDigit(int counters[], int countersLen);													//throws ReaderException
+
+			void append(char* s, char c);
+		public:
+			Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);									///throws ReaderException
+			ITFReader();
+			~ITFReader();
+		};
+	}
+}
+
+#endif
+
+// file: zxing/oned/MultiFormatOneDReader.h
+
+#ifndef __MULTI_FORMAT_ONED_READER_H__
+// #define __MULTI_FORMAT_ONED_READER_H__
+/*
+ *  MultiFormatOneDReader.h
+ *  ZXing
+ *
+  *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+
+namespace zxing {
+  namespace oned {
+    class MultiFormatOneDReader : public OneDReader {
+
+    private:
+      std::vector<Ref<OneDReader> > readers;
+    public:
+      MultiFormatOneDReader(DecodeHints hints);
+
+      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+    };
+  }
+}
+
+#endif
+
+// file: zxing/oned/MultiFormatUPCEANReader.h
+
+#ifndef __MULTI_FORMAT_UPC_EAN_READER_H__
+// #define __MULTI_FORMAT_UPC_EAN_READER_H__
+/*
+ *  MultiFormatUPCEANReader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/OneDReader.h>
+
+namespace zxing {
+  namespace oned {
+    class MultiFormatUPCEANReader : public OneDReader {
+
+    private:
+      std::vector<Ref<OneDReader> > readers;
+    public:
+      MultiFormatUPCEANReader(DecodeHints hints);
+
+      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+    };
+  }
+}
+
+#endif
+
+// file: zxing/oned/OneDResultPoint.h
+
+#ifndef __ONED_RESULT_POINT_H__
+// #define __ONED_RESULT_POINT_H__
+/*
+ *  OneDResultPoint.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// #include <zxing/ResultPoint.h>
+// #include <cmath>
+
+namespace zxing {
+	namespace oned {
+
+		class OneDResultPoint : public ResultPoint {
+
+		public:
+			OneDResultPoint(float posX, float posY);
+		};
+	}
+}
+
+#endif
+
+// file: zxing/oned/UPCAReader.h
+
+#ifndef __UPCA_READER_H__
+// #define __UPCA_READER_H__
+/*
+ *  UPCAReader.h
+ *  ZXing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/EAN13Reader.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+  namespace oned {
+    class UPCAReader : public UPCEANReader {
+
+    private:
+      EAN13Reader ean13Reader;
+      static Ref<Result> maybeReturnResult(Ref<Result> result);
+
+    public:
+      UPCAReader();
+
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+          std::string& resultString);
+
+      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+          int startGuardEnd);
+      Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+
+      BarcodeFormat getBarcodeFormat();
+    };
+  }
+}
+
+#endif
+
+// file: zxing/oned/UPCEReader.h
+
+#ifndef __UPC_E_READER_H__
+// #define __UPC_E_READER_H__
+
+/*
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/oned/UPCEANReader.h>
+// #include <zxing/Result.h>
+
+namespace zxing {
+  namespace oned {
+    class UPCEReader : public UPCEANReader {
+
+    private:
+      static bool determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound);
+    protected:
+      bool decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin, int* endGuardEnd);
+      bool checkChecksum(std::string s);
+    public:
+      UPCEReader();
+
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
+          std::string& resultString);
+      static std::string convertUPCEtoUPCA(std::string upce);
+
+      BarcodeFormat getBarcodeFormat();
+    };
+  }
+}
+
+#endif
+
+// file: zxing/qrcode/ErrorCorrectionLevel.h
+
+#ifndef __ERROR_CORRECTION_LEVEL_H__
+// #define __ERROR_CORRECTION_LEVEL_H__
+
+/*
+ *  ErrorCorrectionLevel.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+namespace qrcode {
+
+class ErrorCorrectionLevel {
+private:
+  int ordinal_;
+  int bits_;
+  std::string name_;
+  ErrorCorrectionLevel(int inOrdinal, int bits, char const* name);
+  static ErrorCorrectionLevel *FOR_BITS[];
+  static int N_LEVELS;
+public:
+  static ErrorCorrectionLevel L;
+  static ErrorCorrectionLevel M;
+  static ErrorCorrectionLevel Q;
+  static ErrorCorrectionLevel H;
+
+  int ordinal() const;
+  int bits() const;
+  std::string const& name() const;
+  operator std::string const& () const;
+
+  static ErrorCorrectionLevel& forBits(int bits);
+};
+}
+}
+
+#endif // __ERROR_CORRECTION_LEVEL_H__
+
+// file: zxing/qrcode/FormatInformation.h
+
+#ifndef __FORMAT_INFORMATION_H__
+// #define __FORMAT_INFORMATION_H__
+
+/*
+ *  FormatInformation.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/ErrorCorrectionLevel.h>
+// #include <zxing/common/Counted.h>
+// #include <iostream>
+
+namespace zxing {
+namespace qrcode {
+
+class FormatInformation : public Counted {
+private:
+  static int FORMAT_INFO_MASK_QR;
+  static int FORMAT_INFO_DECODE_LOOKUP[][2];
+  static int N_FORMAT_INFO_DECODE_LOOKUPS;
+  static int BITS_SET_IN_HALF_BYTE[];
+
+  ErrorCorrectionLevel &errorCorrectionLevel_;
+  unsigned char dataMask_;
+
+  FormatInformation(int formatInfo);
+
+public:
+  static int numBitsDiffering(unsigned int a, unsigned int b);
+  static Ref<FormatInformation> decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2);
+  static Ref<FormatInformation> doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2);
+  ErrorCorrectionLevel &getErrorCorrectionLevel();
+  unsigned char getDataMask();
+  friend bool operator==(const FormatInformation &a, const FormatInformation &b);
+  friend std::ostream& operator<<(std::ostream& out, const FormatInformation& fi);
+};
+}
+}
+
+#endif // __FORMAT_INFORMATION_H__
+
+// file: zxing/qrcode/decoder/Decoder.h
+
+#ifndef __DECODER_H__
+// #define __DECODER_H__
+
+/*
+ *  Decoder.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/reedsolomon/ReedSolomonDecoder.h>
+// #include <zxing/common/reedsolomon/GF256.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/DecoderResult.h>
+// #include <zxing/common/BitMatrix.h>
+
+namespace zxing {
+namespace qrcode {
+
+class Decoder {
+private:
+  ReedSolomonDecoder rsDecoder_;
+
+  void correctErrors(ArrayRef<unsigned char> bytes, int numDataCodewords);
+
+public:
+  Decoder();
+  Ref<DecoderResult> decode(Ref<BitMatrix> bits);
+};
+
+}
+}
+
+#endif // __DECODER_H__
+
+// file: zxing/qrcode/QRCodeReader.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __QR_CODE_READER_H__
+// #define __QR_CODE_READER_H__
+
+/*
+ *  QRCodeReader.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Reader.h>
+// #include <zxing/qrcode/decoder/Decoder.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+	namespace qrcode {
+
+		class QRCodeReader : public Reader {
+		private:
+			Decoder decoder_;
+
+    protected:
+      Decoder& getDecoder();
+
+		public:
+			QRCodeReader();
+			virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+			virtual ~QRCodeReader();
+
+		};
+	}
+}
+
+#endif // __QR_CODE_READER_H__
+
+// file: zxing/qrcode/Version.h
+
+#ifndef __VERSION_H__
+// #define __VERSION_H__
+
+/*
+ *  Version.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/qrcode/ErrorCorrectionLevel.h>
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <vector>
+
+namespace zxing {
+namespace qrcode {
+
+class ECB {
+private:
+  int count_;
+  int dataCodewords_;
+public:
+  ECB(int count, int dataCodewords);
+  int getCount();
+  int getDataCodewords();
+};
+
+class ECBlocks {
+private:
+  int ecCodewords_;
+  std::vector<ECB*> ecBlocks_;
+public:
+  ECBlocks(int ecCodewords, ECB *ecBlocks);
+  ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2);
+  int getECCodewords();
+  std::vector<ECB*>& getECBlocks();
+  ~ECBlocks();
+};
+
+class Version : public Counted {
+
+private:
+  int versionNumber_;
+  std::vector<int> &alignmentPatternCenters_;
+  std::vector<ECBlocks*> ecBlocks_;
+  int totalCodewords_;
+  Version(int versionNumber, std::vector<int> *alignmentPatternCenters, ECBlocks *ecBlocks1, ECBlocks *ecBlocks2,
+          ECBlocks *ecBlocks3, ECBlocks *ecBlocks4);
+
+public:
+  static unsigned int VERSION_DECODE_INFO[];
+  static int N_VERSION_DECODE_INFOS;
+  static std::vector<Ref<Version> > VERSIONS;
+
+  ~Version();
+  int getVersionNumber();
+  std::vector<int> &getAlignmentPatternCenters();
+  int getTotalCodewords();
+  int getDimensionForVersion();
+  ECBlocks &getECBlocksForLevel(ErrorCorrectionLevel &ecLevel);
+  static Version *getProvisionalVersionForDimension(int dimension);
+  static Version *getVersionForNumber(int versionNumber);
+  static Version *decodeVersionInformation(unsigned int versionBits);
+  Ref<BitMatrix> buildFunctionPattern();
+  static int buildVersions();
+};
+}
+}
+
+#endif // __VERSION_H__
+
+// file: zxing/qrcode/decoder/BitMatrixParser.h
+
+#ifndef __BIT_MATRIX_PARSER_H__
+// #define __BIT_MATRIX_PARSER_H__
+
+/*
+ *  BitMatrixParser.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/qrcode/Version.h>
+// #include <zxing/qrcode/FormatInformation.h>
+
+namespace zxing {
+namespace qrcode {
+
+class BitMatrixParser : public Counted {
+private:
+  Ref<BitMatrix> bitMatrix_;
+  Version *parsedVersion_;
+  Ref<FormatInformation> parsedFormatInfo_;
+
+  int copyBit(size_t x, size_t y, int versionBits);
+
+public:
+  BitMatrixParser(Ref<BitMatrix> bitMatrix);
+  Ref<FormatInformation> readFormatInformation();
+  Version *readVersion();
+  ArrayRef<unsigned char> readCodewords();
+
+private:
+  BitMatrixParser(const BitMatrixParser&);
+  BitMatrixParser& operator =(const BitMatrixParser&);
+
+};
+
+}
+}
+
+#endif // __BIT_MATRIX_PARSER_H__
+
+// file: zxing/qrcode/decoder/DataBlock.h
+
+#ifndef __DATA_BLOCK_H__
+// #define __DATA_BLOCK_H__
+
+/*
+ *  DataBlock.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/qrcode/Version.h>
+// #include <zxing/qrcode/ErrorCorrectionLevel.h>
+
+namespace zxing {
+namespace qrcode {
+
+class DataBlock : public Counted {
+private:
+  int numDataCodewords_;
+  ArrayRef<unsigned char> codewords_;
+
+  DataBlock(int numDataCodewords, ArrayRef<unsigned char> codewords);
+
+public:
+  static std::vector<Ref<DataBlock> >
+  getDataBlocks(ArrayRef<unsigned char> rawCodewords, Version *version, ErrorCorrectionLevel &ecLevel);
+
+  int getNumDataCodewords();
+  ArrayRef<unsigned char> getCodewords();
+};
+
+}
+}
+
+#endif // __DATA_BLOCK_H__
+
+// file: zxing/qrcode/decoder/DataMask.h
+
+#ifndef __DATA_MASK_H__
+// #define __DATA_MASK_H__
+
+/*
+ *  DataMask.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Array.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitMatrix.h>
+
+// #include <vector>
+
+namespace zxing {
+namespace qrcode {
+
+class DataMask : public Counted {
+private:
+  static std::vector<Ref<DataMask> > DATA_MASKS;
+
+protected:
+
+public:
+  static int buildDataMasks();
+  DataMask();
+  virtual ~DataMask();
+  void unmaskBitMatrix(BitMatrix& matrix, size_t dimension);
+  virtual bool isMasked(size_t x, size_t y) = 0;
+  static DataMask& forReference(int reference);
+};
+
+}
+}
+
+#endif // __DATA_MASK_H__
+
+// file: zxing/qrcode/decoder/Mode.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __MODE_H__
+// #define __MODE_H__
+
+/*
+ *  Mode.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/qrcode/Version.h>
+
+namespace zxing {
+namespace qrcode {
+
+class Mode {
+private:
+  int characterCountBitsForVersions0To9_;
+  int characterCountBitsForVersions10To26_;
+  int characterCountBitsForVersions27AndHigher_;
+  int bits_;
+  std::string name_;
+
+  Mode(int cbv0_9, int cbv10_26, int cbv27, int bits, char const* name);
+
+public:
+  static Mode TERMINATOR;
+  static Mode NUMERIC;
+  static Mode ALPHANUMERIC;
+  static Mode STRUCTURED_APPEND;
+  static Mode BYTE;
+  static Mode ECI;
+  static Mode KANJI;
+  static Mode FNC1_FIRST_POSITION;
+  static Mode FNC1_SECOND_POSITION;
+  static Mode HANZI;
+
+  static Mode& forBits(int bits);
+  int getCharacterCountBits(Version *version);
+};
+}
+}
+
+#endif // __MODE_H__
+
+// file: zxing/common/ECI.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __ECI__
+#define __ECI__
+
+/*
+ * Copyright 2008-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace zxing {
+  namespace common {
+    class ECI;
+  }
+}
+class zxing::common::ECI {
+private:
+  const int value;
+
+protected:
+  ECI(int value);
+
+public:
+  int getValue() const;
+
+  static ECI* getECIByValue(int value);
+};
+
+#endif
+
+// file: zxing/common/CharacterSetECI.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __CHARACTERSET_ECI__
+#define __CHARACTERSET_ECI__
+
+/*
+ * Copyright 2008-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <map>
+// #include <zxing/common/ECI.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+  namespace common {
+    class CharacterSetECI;
+  }
+}
+
+class zxing::common::CharacterSetECI : public ECI {
+private:
+  static std::map<int, CharacterSetECI*> VALUE_TO_ECI;
+  static std::map<std::string, CharacterSetECI*> NAME_TO_ECI;
+  static const bool inited;
+  static bool init_tables();
+
+  char const* const encodingName;
+
+  CharacterSetECI(int value, char const* encodingName);
+
+  static void addCharacterSet(int value, char const* encodingName);
+  static void addCharacterSet(int value, char const* const* encodingNames);
+
+public:
+  char const* getEncodingName();
+
+  static CharacterSetECI* getCharacterSetECIByValue(int value);
+  static CharacterSetECI* getCharacterSetECIByName(std::string const& name);
+};
+
+#endif
+
+// file: zxing/qrcode/decoder/DecodedBitStreamParser.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __DECODED_BIT_STREAM_PARSER_H__
+// #define __DECODED_BIT_STREAM_PARSER_H__
+
+/*
+ *  DecodedBitStreamParser.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <sstream>
+// #include <map>
+// #include <zxing/qrcode/decoder/Mode.h>
+// #include <zxing/common/BitSource.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <zxing/common/DecoderResult.h>
+// #include <zxing/common/CharacterSetECI.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+namespace qrcode {
+
+class DecodedBitStreamParser {
+public:
+  typedef std::map<DecodeHintType, std::string> Hashtable;
+
+private:
+  static char const ALPHANUMERIC_CHARS[];
+  static char toAlphaNumericChar(size_t value);
+
+  static void decodeHanziSegment(Ref<BitSource> bits, std::string &result, int count);
+  static void decodeKanjiSegment(Ref<BitSource> bits, std::string &result, int count);
+  static void decodeByteSegment(Ref<BitSource> bits, std::string &result, int count);
+  static void decodeByteSegment(Ref<BitSource> bits_,
+                                std::string& result,
+                                int count,
+                                zxing::common::CharacterSetECI* currentCharacterSetECI,
+                                ArrayRef< ArrayRef<unsigned char> >& byteSegments,
+                                Hashtable const& hints);
+  static void decodeAlphanumericSegment(Ref<BitSource> bits, std::string &result, int count, bool fc1InEffect);
+  static void decodeNumericSegment(Ref<BitSource> bits, std::string &result, int count);
+
+  static void append(std::string &ost, const unsigned char *bufIn, size_t nIn, const char *src);
+  static void append(std::string &ost, std::string const& in, const char *src);
+
+public:
+  static Ref<DecoderResult> decode(ArrayRef<unsigned char> bytes,
+                                   Version *version,
+                                   ErrorCorrectionLevel const& ecLevel,
+                                   Hashtable const& hints);
+};
+
+}
+}
+
+#endif // __DECODED_BIT_STREAM_PARSER_H__
+
+// file: zxing/qrcode/detector/AlignmentPattern.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __ALIGNMENT_PATTERN_H__
+// #define __ALIGNMENT_PATTERN_H__
+
+/*
+ *  AlignmentPattern.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPoint.h>
+// #include <cmath>
+
+namespace zxing {
+	namespace qrcode {
+
+		class AlignmentPattern : public ResultPoint {
+		private:
+			float estimatedModuleSize_;
+
+		public:
+			AlignmentPattern(float posX, float posY, float estimatedModuleSize);
+			bool aboutEquals(float moduleSize, float i, float j) const;
+      Ref<AlignmentPattern> combineEstimate(float i, float j,
+                                            float newModuleSize) const;
+		};
+
+	}
+}
+
+#endif // __ALIGNMENT_PATTERN_H__
+
+// file: zxing/qrcode/detector/AlignmentPatternFinder.h
+
+#ifndef __ALIGNMENT_PATTERN_FINDER_H__
+// #define __ALIGNMENT_PATTERN_FINDER_H__
+
+/*
+ *  AlignmentPatternFinder.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "AlignmentPattern.h"
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/ResultPointCallback.h>
+// #include <vector>
+
+namespace zxing {
+namespace qrcode {
+
+class AlignmentPatternFinder : public Counted {
+private:
+  static int CENTER_QUORUM;
+  static int MIN_SKIP;
+  static int MAX_MODULES;
+
+  Ref<BitMatrix> image_;
+  std::vector<AlignmentPattern *> *possibleCenters_;
+  size_t startX_;
+  size_t startY_;
+  size_t width_;
+  size_t height_;
+  float moduleSize_;
+
+  static float centerFromEnd(std::vector<int> &stateCount, int end);
+  bool foundPatternCross(std::vector<int> &stateCount);
+
+  float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal);
+
+  Ref<AlignmentPattern> handlePossibleCenter(std::vector<int> &stateCount, size_t i, size_t j);
+
+public:
+  AlignmentPatternFinder(Ref<BitMatrix> image, size_t startX, size_t startY, size_t width, size_t height,
+                         float moduleSize, Ref<ResultPointCallback>const& callback);
+  ~AlignmentPatternFinder();
+  Ref<AlignmentPattern> find();
+
+private:
+  AlignmentPatternFinder(const AlignmentPatternFinder&);
+  AlignmentPatternFinder& operator =(const AlignmentPatternFinder&);
+
+  Ref<ResultPointCallback> callback_;
+};
+}
+}
+
+#endif // __ALIGNMENT_PATTERN_FINDER_H__
+
+// file: zxing/qrcode/detector/FinderPattern.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+#ifndef __FINDER_PATTERN_H__
+// #define __FINDER_PATTERN_H__
+
+/*
+ *  FinderPattern.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ResultPoint.h>
+// #include <cmath>
+
+namespace zxing {
+	namespace qrcode {
+
+		class FinderPattern : public ResultPoint {
+		private:
+			float estimatedModuleSize_;
+			int count_;
+
+		public:
+			FinderPattern(float posX, float posY, float estimatedModuleSize);
+			FinderPattern(float posX, float posY, float estimatedModuleSize, int count);
+			int getCount() const;
+			float getEstimatedModuleSize() const;
+			void incrementCount();
+			bool aboutEquals(float moduleSize, float i, float j) const;
+			Ref<FinderPattern> combineEstimate(float i, float j, float newModuleSize) const;
+		};
+	}
+}
+
+#endif // __FINDER_PATTERN_H__
+
+// file: zxing/qrcode/detector/FinderPatternInfo.h
+
+#ifndef __FINDER_PATTERN_INFO_H__
+// #define __FINDER_PATTERN_INFO_H__
+
+/*
+ *  FinderPatternInfo.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPattern.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/Array.h>
+// #include <vector>
+
+namespace zxing {
+namespace qrcode {
+
+class FinderPatternInfo : public Counted {
+private:
+  Ref<FinderPattern> bottomLeft_;
+  Ref<FinderPattern> topLeft_;
+  Ref<FinderPattern> topRight_;
+
+public:
+  FinderPatternInfo(std::vector<Ref<FinderPattern> > patternCenters);
+
+  Ref<FinderPattern> getBottomLeft();
+  Ref<FinderPattern> getTopLeft();
+  Ref<FinderPattern> getTopRight();
+};
+}
+}
+
+#endif // __FINDER_PATTERN_INFO_H__
+
+// file: zxing/qrcode/detector/Detector.h
+
+#ifndef __DETECTOR_H__
+// #define __DETECTOR_H__
+
+/*
+ *  Detector.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/DetectorResult.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/qrcode/detector/AlignmentPattern.h>
+// #include <zxing/common/PerspectiveTransform.h>
+// #include <zxing/ResultPointCallback.h>
+// #include <zxing/qrcode/detector/FinderPatternInfo.h>
+
+namespace zxing {
+
+class DecodeHints;
+
+namespace qrcode {
+
+class Detector : public Counted {
+private:
+  Ref<BitMatrix> image_;
+  Ref<ResultPointCallback> callback_;
+
+protected:
+  Ref<BitMatrix> getImage();
+
+  static Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform>);
+  static int computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
+                              float moduleSize);
+  float calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft);
+  float calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern);
+  float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY);
+  float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY);
+  Ref<AlignmentPattern> findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
+      float allowanceFactor);
+  Ref<DetectorResult> processFinderPatternInfo(Ref<FinderPatternInfo> info);
+public:
+
+  virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+      ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
+
+  Detector(Ref<BitMatrix> image);
+  Ref<DetectorResult> detect(DecodeHints const& hints);
+};
+}
+}
+
+#endif // __DETECTOR_H__
+
+// file: zxing/qrcode/detector/FinderPatternFinder.h
+
+#ifndef __FINDER_PATTERN_FINDER_H__
+// #define __FINDER_PATTERN_FINDER_H__
+
+/*
+ *  FinderPatternFinder.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPattern.h>
+// #include <zxing/qrcode/detector/FinderPatternInfo.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/ResultPointCallback.h>
+// #include <vector>
+
+namespace zxing {
+
+class DecodeHints;
+
+namespace qrcode {
+
+class FinderPatternFinder {
+private:
+  static int CENTER_QUORUM;
+
+protected:
+  static int MIN_SKIP;
+  static int MAX_MODULES;
+
+  Ref<BitMatrix> image_;
+  std::vector<Ref<FinderPattern> > possibleCenters_;
+  bool hasSkipped_;
+
+  Ref<ResultPointCallback> callback_;
+
+  /** stateCount must be int[5] */
+  static float centerFromEnd(int* stateCount, int end);
+  static bool foundPatternCross(int* stateCount);
+
+  float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal);
+  float crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount, int originalStateCountTotal);
+
+  /** stateCount must be int[5] */
+  bool handlePossibleCenter(int* stateCount, size_t i, size_t j);
+  int findRowSkip();
+  bool haveMultiplyConfirmedCenters();
+  std::vector<Ref<FinderPattern> > selectBestPatterns();
+  static std::vector<Ref<FinderPattern> > orderBestPatterns(std::vector<Ref<FinderPattern> > patterns);
+public:
+  static float distance(Ref<ResultPoint> p1, Ref<ResultPoint> p2);
+  FinderPatternFinder(Ref<BitMatrix> image, Ref<ResultPointCallback>const&);
+  Ref<FinderPatternInfo> find(DecodeHints const& hints);
+};
+}
+}
+
+#endif // __FINDER_PATTERN_FINDER_H__
+
+// file: zxing/qrcode/detector/QREdgeDetector.h
+
+#ifndef __QREDGEDETECTOR_H__
+// #define __QREDGEDETECTOR_H__
+/*
+ *  QREdgeDetector.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+// #include <zxing/qrcode/detector/Detector.h>
+// #include <zxing/common/Point.h>
+
+namespace zxing {
+namespace qrcode {
+
+class QREdgeDetector : public Detector {
+public:
+  QREdgeDetector(Ref<BitMatrix> image);
+
+  virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+      ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
+
+private:
+  Point findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension);
+  Line findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert);
+
+  Point endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to);
+
+  Ref<PerspectiveTransform> get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension);
+};
+
+}
+}
+#endif // QREDGEDETECTOR_H_
+
+// file: zxing/FormatException.h
+
+#ifndef __FORMAT_EXCEPTION_H__
+// #define __FORMAT_EXCEPTION_H__
+
+/*
+ *  FormatException.h
+ *  zxing
+ *
+ *  Copyright 2010 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+
+class FormatException : public ReaderException {
+public:
+  FormatException();
+  FormatException(const char *msg);
+  ~FormatException() throw();
+};
+
+}
+#endif // __FORMAT_EXCEPTION_H__
+
+// file: zxing/NotFoundException.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __NOT_FOUND_EXCEPTION_H__
+// #define __NOT_FOUND_EXCEPTION_H__
+
+/*
+ * Copyright 20011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/ReaderException.h>
+
+namespace zxing {
+
+  class NotFoundException : public ReaderException {
+  public:
+    NotFoundException(const char *msg);
+    ~NotFoundException() throw();
+  };
+
+}
+#endif // __NOT_FOUND_EXCEPTION_H__
+
+// file: zxing/common/StringUtils.h
+
+// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
+
+#ifndef __STRING_UTILS__
+#define __STRING_UTILS__
+
+/*
+ * Copyright (C) 2010-2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <string>
+// #include <map>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+  namespace common {
+    class StringUtils;
+  }
+}
+
+class zxing::common::StringUtils {
+private:
+  static char const* const PLATFORM_DEFAULT_ENCODING;
+
+  StringUtils() {}
+
+public:
+  static char const* const ASCII;
+  static char const* const SHIFT_JIS;
+  static char const* const GB2312;
+  static char const* const EUC_JP;
+  static char const* const UTF8;
+  static char const* const ISO88591;
+  static const bool ASSUME_SHIFT_JIS;
+
+  typedef std::map<DecodeHintType, std::string> Hashtable;
+
+  static std::string guessEncoding(unsigned char* bytes, int length, Hashtable const& hints);
+};
+
+#endif
+
+// file: zxing/common/detector/MonochromeRectangleDetector.h
+
+#ifndef __MONOCHROMERECTANGLEDETECTOR_H__
+// #define __MONOCHROMERECTANGLEDETECTOR_H__
+
+/*
+ *  MonochromeRectangleDetector.h
+ *  y_wmk
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010 y_wmk authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/NotFoundException.h>
+// #include <zxing/ResultPoint.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/ResultPoint.h>
+
+
+namespace zxing {
+
+struct TwoInts: public Counted {
+	int start;
+	int end;
+};
+
+class MonochromeRectangleDetector : public Counted {
+private:
+  static const int MAX_MODULES = 32;
+  Ref<BitMatrix> image_;
+
+public:
+  MonochromeRectangleDetector(Ref<BitMatrix> image) : image_(image) {  };
+
+  std::vector<Ref<ResultPoint> > detect();
+
+private:
+  Ref<ResultPoint> findCornerFromCenter(int centerX, int deltaX, int left, int right,
+      int centerY, int deltaY, int top, int bottom, int maxWhiteRun);
+
+  Ref<TwoInts> blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
+      bool horizontal);
+
+  int max(int a, float b) { return (float) a > b ? a : (int) b;};
+};
+}
+
+#endif // __MONOCHROMERECTANGLEDETECTOR_H__
+
+// file: zxing/common/detector/WhiteRectangleDetector.h
+
+#ifndef __WHITERECTANGLEDETECTOR_H__
+// #define __WHITERECTANGLEDETECTOR_H__
+
+/*
+ *  WhiteRectangleDetector.h
+ *
+ *
+ *  Created by Luiz Silva on 09/02/2010.
+ *  Copyright 2010  authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <vector>
+// #include <zxing/ReaderException.h>
+// #include <zxing/ResultPoint.h>
+// #include <zxing/common/BitMatrix.h>
+// #include <zxing/common/Counted.h>
+// #include <zxing/ResultPoint.h>
+
+
+namespace zxing {
+
+class WhiteRectangleDetector : public Counted {
+  private:
+    static int INIT_SIZE;
+    static int CORR;
+    Ref<BitMatrix> image_;
+    int width_;
+    int height_;
+
+  public:
+    WhiteRectangleDetector(Ref<BitMatrix> image);
+    std::vector<Ref<ResultPoint> > detect();
+
+  private:
+    int round(float a);
+    Ref<ResultPoint> getBlackPointOnSegment(float aX, float aY, float bX, float bY);
+    int distanceL2(float aX, float aY, float bX, float bY);
+    std::vector<Ref<ResultPoint> > centerEdges(Ref<ResultPoint> y, Ref<ResultPoint> z,
+                                    Ref<ResultPoint> x, Ref<ResultPoint> t);
+    bool containsBlackPoint(int a, int b, int fixed, bool horizontal);
+};
+}
+
+#endif
+
+// file: zxing/datamatrix/detector/DetectorException.h
+
+/*
+ * DetectorException.h
+ *
+ *  Created on: Aug 26, 2011
+ *      Author: luiz
+ */
+
+#ifndef DETECTOREXCEPTION_H_
+#define DETECTOREXCEPTION_H_
+
+// #include <zxing/Exception.h>
+
+namespace zxing {
+namespace datamatrix {
+
+class DetectorException : public Exception {
+  public:
+    DetectorException(const char *msg);
+    virtual ~DetectorException() throw();
+};
+} /* namespace nexxera */
+} /* namespace zxing */
+#endif /* DETECTOREXCEPTION_H_ */
+
+// file: zxing/multi/ByQuadrantReader.h
+
+#ifndef __BY_QUADRANT_READER_H__
+// #define __BY_QUADRANT_READER_H__
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/Reader.h>
+// #include <zxing/BinaryBitmap.h>
+// #include <zxing/Result.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+namespace multi {
+class ByQuadrantReader : public Reader {
+  private:
+    Reader& delegate_;
+
+  public:
+    ByQuadrantReader(Reader& delegate);
+    virtual ~ByQuadrantReader();
+    virtual Ref<Result> decode(Ref<BinaryBitmap> image);
+    virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
+};
+} // End zxing::multi namespace
+} // End zxing namespace
+
+#endif // __BY_QUADRANT_READER_H__
+
+// file: zxing/multi/MultipleBarcodeReader.h
+
+#ifndef __MULTIPLE_BARCODE_READER_H__
+// #define __MULTIPLE_BARCODE_READER_H__
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/common/Counted.h>
+// #include <zxing/Result.h>
+// #include <zxing/BinaryBitmap.h>
+// #include <zxing/DecodeHints.h>
+// #include <vector>
+
+namespace zxing {
+namespace multi {
+class MultipleBarcodeReader : public Counted {
+  protected:
+    MultipleBarcodeReader() {}
+  public:
+    virtual std::vector<Ref<Result> > decodeMultiple(Ref<BinaryBitmap> image);
+    virtual std::vector<Ref<Result> > decodeMultiple(Ref<BinaryBitmap> image, DecodeHints hints) = 0;
+    virtual ~MultipleBarcodeReader();
+};
+} // End zxing::multi namespace
+} // End zxing namespace
+
+#endif // __MULTIPLE_BARCODE_READER_H__
+
+// file: zxing/multi/GenericMultipleBarcodeReader.h
+
+#ifndef __GENERIC_MULTIPLE_BARCODE_READER_H__
+// #define __GENERIC_MULTIPLE_BARCODE_READER_H__
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/MultipleBarcodeReader.h>
+// #include <zxing/Reader.h>
+
+namespace zxing {
+namespace multi {
+class GenericMultipleBarcodeReader : public MultipleBarcodeReader {
+  private:
+    static Ref<Result> translateResultPoints(Ref<Result> result,
+                                             int xOffset,
+                                             int yOffset);
+    void doDecodeMultiple(Ref<BinaryBitmap> image,
+                          DecodeHints hints,
+                          std::vector<Ref<Result> >& results,
+                          int xOffset,
+                          int yOffset);
+    Reader& delegate_;
+    static const int MIN_DIMENSION_TO_RECUR = 100;
+
+  public:
+    GenericMultipleBarcodeReader(Reader& delegate);
+    virtual ~GenericMultipleBarcodeReader();
+    virtual std::vector<Ref<Result> > decodeMultiple(Ref<BinaryBitmap> image,
+                                                     DecodeHints hints);
+};
+} // End zxing::multi namespace
+} // End zxing namespace
+
+#endif // __GENERIC_MULTIPLE_BARCODE_READER_H__
+
+// file: zxing/multi/qrcode/QRCodeMultiReader.h
+
+#ifndef __QRCODE_MULTI_READER_H__
+// #define __QRCODE_MULTI_READER_H__
+
+/*
+ *  Copyright 2011 ZXing authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/multi/MultipleBarcodeReader.h>
+// #include <zxing/qrcode/QRCodeReader.h>
+
+namespace zxing {
+namespace multi {
+class QRCodeMultiReader: public zxing::qrcode::QRCodeReader, public MultipleBarcodeReader {
+  public:
+    QRCodeMultiReader();
+    virtual ~QRCodeMultiReader();
+    virtual std::vector<Ref<Result> > decodeMultiple(Ref<BinaryBitmap> image, DecodeHints hints);
+};
+} // End zxing::multi namespace
+} // End zxing namespace
+
+#endif // __QRCODE_MULTI_READER_H__
+
+// file: zxing/multi/qrcode/detector/MultiDetector.h
+
+#ifndef __MULTI_DETECTOR_H__
+// #define __MULTI_DETECTOR_H__
+
+/*
+ *  Copyright 2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/Detector.h>
+// #include <zxing/common/DetectorResult.h>
+// #include <zxing/DecodeHints.h>
+
+namespace zxing {
+namespace multi {
+class MultiDetector : public zxing::qrcode::Detector {
+  public:
+    MultiDetector(Ref<BitMatrix> image);
+    virtual ~MultiDetector();
+    virtual std::vector<Ref<DetectorResult> > detectMulti(DecodeHints hints);
+};
+} // End zxing::multi namespace
+} // End zxing namespace
+
+#endif // __MULTI_DETECTOR_H__
+
+// file: zxing/multi/qrcode/detector/MultiFinderPatternFinder.h
+
+#ifndef __MULTI_FINDER_PATTERN_FINDER_H__
+// #define __MULTI_FINDER_PATTERN_FINDER_H__
+
+/*
+ *  Copyright 2011 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include <zxing/qrcode/detector/FinderPattern.h>
+// #include <zxing/qrcode/detector/FinderPatternFinder.h>
+// #include <zxing/qrcode/detector/FinderPatternInfo.h>
+
+namespace zxing {
+namespace multi {
+class MultiFinderPatternFinder : zxing::qrcode::FinderPatternFinder {
+  private:
+    std::vector<std::vector<Ref<zxing::qrcode::FinderPattern> > > selectBestPatterns();
+
+    static const float MAX_MODULE_COUNT_PER_EDGE;
+    static const float MIN_MODULE_COUNT_PER_EDGE;
+    static const float DIFF_MODSIZE_CUTOFF_PERCENT;
+    static const float DIFF_MODSIZE_CUTOFF;
+
+  public:
+    MultiFinderPatternFinder(Ref<BitMatrix> image, Ref<ResultPointCallback> resultPointCallback);
+    virtual ~MultiFinderPatternFinder();
+    virtual std::vector<Ref<zxing::qrcode::FinderPatternInfo> > findMulti(DecodeHints const& hints);
+
+
+};
+}
+}
+
+#endif // __MULTI_FINDER_PATTERN_FINDER_H__
+

+ 723 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/BarcodeScannerProxy.js

xqd
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+var urlutil = require('cordova/urlutil');
+
+var CAMERA_STREAM_STATE_CHECK_RETRY_TIMEOUT = 200; // milliseconds
+var OPERATION_IS_IN_PROGRESS = -2147024567;
+var REGDB_E_CLASSNOTREG = -2147221164;
+var INITIAL_FOCUS_DELAY = 200; // milliseconds
+var CHECK_PLAYING_TIMEOUT = 100; // milliseconds
+
+/**
+ * List of supported barcode formats from ZXing library. Used to return format
+ *   name instead of number code as per plugin spec.
+ *
+ * @enum {String}
+ */
+var BARCODE_FORMAT = {
+    1: 'AZTEC',
+    2: 'CODABAR',
+    4: 'CODE_39',
+    8: 'CODE_93',
+    16: 'CODE_128',
+    32: 'DATA_MATRIX',
+    64: 'EAN_8',
+    128: 'EAN_13',
+    256: 'ITF',
+    512: 'MAXICODE',
+    1024: 'PDF_417',
+    2048: 'QR_CODE',
+    4096: 'RSS_14',
+    8192: 'RSS_EXPANDED',
+    16384: 'UPC_A',
+    32768: 'UPC_E',
+    61918: 'All_1D',
+    65536: 'UPC_EAN_EXTENSION',
+    131072: 'MSI',
+    262144: 'PLESSEY'
+};
+
+/**
+ * Detects the first appropriate camera located at the back panel of device. If
+ *   there is no back cameras, returns the first available.
+ *
+ * @returns {Promise<String>} Camera id
+ */
+function findCamera() {
+    var Devices = Windows.Devices.Enumeration;
+
+    // Enumerate cameras and add them to the list
+    return Devices.DeviceInformation.findAllAsync(Devices.DeviceClass.videoCapture)
+    .then(function (cameras) {
+
+        if (!cameras || cameras.length === 0) {
+            throw new Error("No cameras found");
+        }
+
+        var backCameras = cameras.filter(function (camera) {
+            return camera.enclosureLocation && camera.enclosureLocation.panel === Devices.Panel.back;
+        });
+
+        // If there is back cameras, return the id of the first,
+        // otherwise take the first available device's id
+        return (backCameras[0] || cameras[0]).id;
+    });
+}
+
+/**
+ * @param {Windows.Graphics.Display.DisplayOrientations} displayOrientation
+ * @return {Number}
+ */
+function videoPreviewRotationLookup(displayOrientation, isMirrored) {
+    var degreesToRotate;
+
+    switch (displayOrientation) {
+        case Windows.Graphics.Display.DisplayOrientations.landscape:
+            degreesToRotate = 0;
+            break;
+        case Windows.Graphics.Display.DisplayOrientations.portrait:
+            if (isMirrored) {
+                degreesToRotate = 270;
+            } else {
+                degreesToRotate = 90;
+            }
+            break;
+        case Windows.Graphics.Display.DisplayOrientations.landscapeFlipped:
+            degreesToRotate = 180;
+            break;
+        case Windows.Graphics.Display.DisplayOrientations.portraitFlipped:
+            if (isMirrored) {
+                degreesToRotate = 90;
+            } else {
+                degreesToRotate = 270;
+            }
+            break;
+        default:
+            degreesToRotate = 0;
+            break;
+    }
+
+    return degreesToRotate;
+}
+
+/**
+ * The pure JS implementation of barcode reader from WinRTBarcodeReader.winmd.
+ *   Works only on Windows 10 devices and more efficient than original one.
+ *
+ * @class {BarcodeReader}
+ */
+function BarcodeReader () {
+    this._promise = null;
+    this._cancelled = false;
+}
+
+/**
+ * Returns an instance of Barcode reader, depending on capabilities of Media
+ *   Capture API
+ *
+ * @static
+ * @constructs {BarcodeReader}
+ *
+ * @param   {MediaCapture}   mediaCaptureInstance  Instance of
+ *   Windows.Media.Capture.MediaCapture class
+ *
+ * @return  {BarcodeReader}  BarcodeReader instance that could be used for
+ *   scanning
+ */
+BarcodeReader.get = function (mediaCaptureInstance) {
+    if (mediaCaptureInstance.getPreviewFrameAsync && ZXing.BarcodeReader) {
+        return new BarcodeReader();
+    }
+
+    // If there is no corresponding API (Win8/8.1/Phone8.1) use old approach with WinMD library
+    return new WinRTBarcodeReader.Reader();
+
+};
+
+/**
+ * Initializes instance of reader.
+ *
+ * @param   {MediaCapture}  capture  Instance of
+ *   Windows.Media.Capture.MediaCapture class, used for acquiring images/ video
+ *   stream for barcode scanner.
+ * @param   {Number}  width    Video/image frame width
+ * @param   {Number}  height   Video/image frame height
+ */
+BarcodeReader.prototype.init = function (capture, width, height) {
+    this._capture = capture;
+    this._width = width;
+    this._height = height;
+    this._zxingReader = new ZXing.BarcodeReader();
+    this._zxingReader.tryHarder = true;
+};
+
+/**
+ * Starts barcode search routines asyncronously.
+ *
+ * @return  {Promise<ScanResult>}  barcode scan result or null if search
+ *   cancelled.
+ */
+BarcodeReader.prototype.readCode = function () {
+
+    /**
+     * Grabs a frame from preview stream uning Win10-only API and tries to
+     *   get a barcode using zxing reader provided. If there is no barcode
+     *   found, returns null.
+     */
+    function scanBarcodeAsync(mediaCapture, zxingReader, frameWidth, frameHeight) {
+        // Shortcuts for namespaces
+        var Imaging = Windows.Graphics.Imaging;
+        var Streams = Windows.Storage.Streams;
+
+        var frame = new Windows.Media.VideoFrame(Imaging.BitmapPixelFormat.bgra8, frameWidth, frameHeight);
+        return mediaCapture.getPreviewFrameAsync(frame)
+        .then(function (capturedFrame) {
+
+            // Copy captured frame to buffer for further deserialization
+            var bitmap = capturedFrame.softwareBitmap;
+            var rawBuffer = new Streams.Buffer(bitmap.pixelWidth * bitmap.pixelHeight * 4);
+            capturedFrame.softwareBitmap.copyToBuffer(rawBuffer);
+            capturedFrame.close();
+
+            // Get raw pixel data from buffer
+            var data = new Uint8Array(rawBuffer.length);
+            var dataReader = Streams.DataReader.fromBuffer(rawBuffer);
+            dataReader.readBytes(data);
+            dataReader.close();
+
+            return zxingReader.decode(data, frameWidth, frameHeight, ZXing.BitmapFormat.bgra32);
+        });
+    }
+
+    var self = this;
+    return scanBarcodeAsync(this._capture, this._zxingReader, this._width, this._height)
+    .then(function (result) {
+        if (self._cancelled)
+            return null;
+
+        return result || (self._promise = self.readCode());
+    });
+};
+
+/**
+ * Stops barcode search
+ */
+BarcodeReader.prototype.stop = function () {
+    this._cancelled = true;
+};
+
+function degreesToRotation(degrees) {
+    switch (degrees) {
+        // portrait
+        case 90:
+            return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+        // landscape
+        case 0:
+            return Windows.Media.Capture.VideoRotation.none;
+        // portrait-flipped
+        case 270:
+            return Windows.Media.Capture.VideoRotation.clockwise270Degrees;
+        // landscape-flipped
+        case 180:
+            return Windows.Media.Capture.VideoRotation.clockwise180Degrees;
+        default:
+            // Falling back to portrait default
+            return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+    }
+}
+
+module.exports = {
+
+    /**
+     * Scans image via device camera and retieves barcode from it.
+     * @param  {function} success Success callback
+     * @param  {function} fail    Error callback
+     * @param  {array} args       Arguments array
+     */
+    scan: function (success, fail, args) {
+        var capturePreview,
+            capturePreviewAlignmentMark,
+            captureCancelButton,
+            navigationButtonsDiv,
+            previewMirroring,
+            closeButton,
+            capture,
+            reader;
+
+        // Save call state for suspend/resume
+        BarcodeReader.scanCallArgs = {
+            success: success,
+            fail: fail,
+            args: args
+        };
+
+        function updatePreviewForRotation(evt) {
+            if (!capture) {
+                return;
+            }
+
+            var displayInformation = (evt && evt.target) || Windows.Graphics.Display.DisplayInformation.getForCurrentView();
+            var currentOrientation = displayInformation.currentOrientation;
+
+            previewMirroring = capture.getPreviewMirroring();
+
+            // Lookup up the rotation degrees.
+            var rotDegree = videoPreviewRotationLookup(currentOrientation, previewMirroring);
+
+            capture.setPreviewRotation(degreesToRotation(rotDegree));
+            return WinJS.Promise.as();
+        }
+
+        /**
+         * Creates a preview frame and necessary objects
+         */
+        function createPreview() {
+
+            // Create fullscreen preview
+            var capturePreviewFrameStyle = document.createElement('link');
+            capturePreviewFrameStyle.rel = "stylesheet";
+            capturePreviewFrameStyle.type = "text/css";
+            capturePreviewFrameStyle.href = urlutil.makeAbsolute("/www/css/plugin-barcodeScanner.css");
+
+            document.head.appendChild(capturePreviewFrameStyle);
+
+            capturePreviewFrame = document.createElement('div');
+            capturePreviewFrame.className = "barcode-scanner-wrap";
+
+            capturePreview = document.createElement("video");
+            capturePreview.className = "barcode-scanner-preview";
+            capturePreview.addEventListener('click', function () {
+                focus();
+            });
+
+            capturePreviewAlignmentMark = document.createElement('div');
+            capturePreviewAlignmentMark.className = "barcode-scanner-mark";
+
+            navigationButtonsDiv = document.createElement("div");
+            navigationButtonsDiv.className = "barcode-scanner-app-bar";
+            navigationButtonsDiv.onclick = function (e) {
+                e.cancelBubble = true;
+            };
+
+            closeButton = document.createElement("div");
+            closeButton.innerText = "close";
+            closeButton.className = "app-bar-action action-close";
+            navigationButtonsDiv.appendChild(closeButton);
+
+            BarcodeReader.scanCancelled = false;
+            closeButton.addEventListener("click", cancelPreview, false);
+            document.addEventListener('backbutton', cancelPreview, false);
+
+            [capturePreview, capturePreviewAlignmentMark, navigationButtonsDiv].forEach(function (element) {
+                capturePreviewFrame.appendChild(element);
+            });
+        }
+
+        function focus(controller) {
+
+            var result = WinJS.Promise.wrap();
+
+            if (!capturePreview || capturePreview.paused) {
+                // If the preview is not yet playing, there is no sense in running focus
+                return result;
+            }
+
+            if (!controller) {
+                try {
+                    controller = capture && capture.videoDeviceController;
+                } catch (err) {
+                    console.log('Failed to access focus control for current camera: ' + err);
+                    return result;
+                }
+            }
+
+            if (!controller.focusControl || !controller.focusControl.supported) {
+                console.log('Focus control for current camera is not supported');
+                return result;
+            }
+
+            // Multiple calls to focusAsync leads to internal focusing hang on some Windows Phone 8.1 devices
+            // Also need to wrap in try/catch to avoid crash on Surface 3 - looks like focusState property
+            // somehow is not accessible there. See https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/288
+            try {
+                if (controller.focusControl.focusState === Windows.Media.Devices.MediaCaptureFocusState.searching) {
+                    return result;
+                }
+            } catch (e) {
+                // Nothing to do - just continue w/ focusing
+            }
+
+            // The delay prevents focus hang on slow devices
+            return WinJS.Promise.timeout(INITIAL_FOCUS_DELAY)
+            .then(function () {
+                try {
+                    return controller.focusControl.focusAsync().then(function () {
+                        return result;
+                    }, function (e) {
+                        // This happens on mutliple taps
+                        if (e.number !== OPERATION_IS_IN_PROGRESS) {
+                            console.error('focusAsync failed: ' + e);
+                            return WinJS.Promise.wrapError(e);
+                        }
+                        return result;
+                    });
+                } catch (e) {
+                    // This happens on mutliple taps
+                    if (e.number !== OPERATION_IS_IN_PROGRESS) {
+                        console.error('focusAsync failed: ' + e);
+                        return WinJS.Promise.wrapError(e);
+                    }
+                    return result;
+                }
+            });
+        }
+
+        function setupFocus(focusControl) {
+
+            function supportsFocusMode(mode) {
+                return focusControl.supportedFocusModes.indexOf(mode).returnValue;
+            }
+
+            if (!focusControl || !focusControl.supported || !focusControl.configure) {
+                return WinJS.Promise.wrap();
+            }
+
+            var FocusMode = Windows.Media.Devices.FocusMode;
+            var focusConfig = new Windows.Media.Devices.FocusSettings();
+            focusConfig.autoFocusRange = Windows.Media.Devices.AutoFocusRange.normal;
+
+            // Determine a focus position if the focus search fails:
+            focusConfig.disableDriverFallback = false;
+
+            if (supportsFocusMode(FocusMode.continuous)) {
+                console.log("Device supports continuous focus mode");
+                focusConfig.mode = FocusMode.continuous;
+            } else if (supportsFocusMode(FocusMode.auto)) {
+                console.log("Device doesn\'t support continuous focus mode, switching to autofocus mode");
+                focusConfig.mode = FocusMode.auto;
+            }
+
+            focusControl.configure(focusConfig);
+
+            // Continuous focus should start only after preview has started. See 'Remarks' at
+            // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.devices.focuscontrol.configure.aspx
+            function waitForIsPlaying() {
+                var isPlaying = !capturePreview.paused && !capturePreview.ended && capturePreview.readyState > 2;
+
+                if (!isPlaying) {
+                    return WinJS.Promise.timeout(CHECK_PLAYING_TIMEOUT)
+                    .then(function () {
+                        return waitForIsPlaying();
+                    });
+                }
+
+                return focus();
+            }
+
+            return waitForIsPlaying();
+        }
+
+        function disableZoomAndScroll() {
+            document.body.classList.add('no-zoom');
+            document.body.classList.add('no-scroll');
+        }
+
+        function enableZoomAndScroll() {
+            document.body.classList.remove('no-zoom');
+            document.body.classList.remove('no-scroll');
+        }
+
+        /**
+         * Starts stream transmission to preview frame and then run barcode search
+         */
+        function startPreview() {
+            return findCamera()
+            .then(function (id) {
+                var captureSettings;
+
+                try {
+                    captureSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
+                } catch (e) {
+                    if (e.number === REGDB_E_CLASSNOTREG) {
+                        throw new Error('Ensure that you have Windows Media Player and Media Feature pack installed.');
+                    }
+
+                    throw e;
+                }
+
+                captureSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.video;
+                captureSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.videoPreview;
+                captureSettings.videoDeviceId = id;
+
+                capture = new Windows.Media.Capture.MediaCapture();
+                return capture.initializeAsync(captureSettings);
+            })
+            .then(function () {
+
+                var controller = capture.videoDeviceController;
+                var deviceProps = controller.getAvailableMediaStreamProperties(Windows.Media.Capture.MediaStreamType.videoPreview);
+
+                deviceProps = Array.prototype.slice.call(deviceProps);
+                deviceProps = deviceProps.filter(function (prop) {
+                    // filter out streams with "unknown" subtype - causes errors on some devices
+                    return prop.subtype !== "Unknown";
+                }).sort(function (propA, propB) {
+                    // sort properties by resolution
+                    return propB.width - propA.width;
+                });
+
+                var preferredProps = deviceProps.filter(function(prop){
+                    // Filter out props where frame size is between 640*480 and 1280*720
+                    return prop.width >= 640 && prop.height >= 480 && prop.width <= 1280 && prop.height <= 720;
+                });
+
+                // prefer video frame size between between 640*480 and 1280*720
+                // use maximum resolution otherwise
+                var maxResProps = preferredProps[0] || deviceProps[0];
+                return controller.setMediaStreamPropertiesAsync(Windows.Media.Capture.MediaStreamType.videoPreview, maxResProps)
+                .then(function () {
+                    return {
+                        capture: capture,
+                        width: maxResProps.width,
+                        height: maxResProps.height
+                    };
+                });
+            })
+            .then(function (captureSettings) {
+
+                capturePreview.msZoom = true;
+                capturePreview.src = URL.createObjectURL(capture);
+                capturePreview.play();
+
+                // Insert preview frame and controls into page
+                document.body.appendChild(capturePreviewFrame);
+
+                disableZoomAndScroll();
+
+                return setupFocus(captureSettings.capture.videoDeviceController.focusControl)
+                .then(function () {
+                    Windows.Graphics.Display.DisplayInformation.getForCurrentView().addEventListener("orientationchanged", updatePreviewForRotation, false);
+                    return updatePreviewForRotation();
+                })
+                .then(function () {
+
+                    if (!Windows.Media.Devices.CameraStreamState) {
+                        // CameraStreamState is available starting with Windows 10 so skip this check for 8.1
+                        // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.devices.camerastreamstate
+                        return WinJS.Promise.as();
+                    }
+
+                    function checkCameraStreamState() {
+                        if (capture.cameraStreamState !== Windows.Media.Devices.CameraStreamState.streaming) {
+
+                            // Using loop as MediaCapture.CameraStreamStateChanged does not fire with CameraStreamState.streaming state.
+                            return WinJS.Promise.timeout(CAMERA_STREAM_STATE_CHECK_RETRY_TIMEOUT)
+                            .then(function () {
+                                return checkCameraStreamState();
+                            });
+                        }
+
+                        return WinJS.Promise.as();
+                    }
+
+                    // Ensure CameraStreamState is Streaming
+                    return checkCameraStreamState();
+                })
+                .then(function () {
+                    return captureSettings;
+                });
+            });
+        }
+
+        /**
+         * Removes preview frame and corresponding objects from window
+         */
+        function destroyPreview() {
+            var promise = WinJS.Promise.as();
+
+            Windows.Graphics.Display.DisplayInformation.getForCurrentView().removeEventListener("orientationchanged", updatePreviewForRotation, false);
+            document.removeEventListener('backbutton', cancelPreview);
+
+            if (capturePreview) {
+                var isPlaying = !capturePreview.paused && !capturePreview.ended && capturePreview.readyState > 2;
+                if (isPlaying) {
+                    capturePreview.pause();
+                }
+
+                // http://stackoverflow.com/a/28060352/4177762
+                capturePreview.src = "";
+                if (capturePreview.load) {
+                    capturePreview.load();
+                }
+            }
+
+            if (capturePreviewFrame) {
+                try {
+                    document.body.removeChild(capturePreviewFrame);
+                } catch (e) {
+                    // Catching NotFoundError
+                    console.error(e);
+                }
+            }
+            capturePreviewFrame = null;
+
+            reader && reader.stop();
+            reader = null;
+
+            if (capture) {
+                try {
+                    promise = capture.stopRecordAsync();
+                } catch (e) {
+                    // Catching NotFoundError
+                    console.error(e);
+                }
+            }
+            capture = null;
+
+            enableZoomAndScroll();
+
+            return promise;
+        }
+
+        /**
+         * Stops preview and then call success callback with cancelled=true
+         * See https://github.com/phonegap-build/BarcodeScanner#using-the-plugin
+         */
+        function cancelPreview() {
+            BarcodeReader.scanCancelled = true;
+            reader && reader.stop();
+        }
+
+        function checkCancelled() {
+            if (BarcodeReader.scanCancelled || BarcodeReader.suspended) {
+                throw new Error('Canceled');
+            }
+        }
+
+        // Timeout is needed so that the .done finalizer below can be attached to the promise.
+        BarcodeReader.scanPromise = WinJS.Promise.timeout()
+        .then(function() {
+            createPreview();
+            checkCancelled();
+            return startPreview();
+        })
+        .then(function (captureSettings) {
+            checkCancelled();
+            reader = BarcodeReader.get(captureSettings.capture);
+            reader.init(captureSettings.capture, captureSettings.width, captureSettings.height);
+
+            // Add a small timeout before capturing first frame otherwise
+            // we would get an 'Invalid state' error from 'getPreviewFrameAsync'
+            return WinJS.Promise.timeout(200)
+            .then(function () {
+                checkCancelled();
+                return reader.readCode();
+            });
+        })
+        .then(function (result) {
+            // Suppress null result (cancel) on suspending
+            if (BarcodeReader.suspended) {
+                return;
+            }
+
+            destroyPreview();
+            success({
+                text: result && result.text,
+                format: result && BARCODE_FORMAT[result.barcodeFormat],
+                cancelled: !result
+            });
+        });
+
+        // Catching any errors here
+        BarcodeReader.scanPromise.done(function () { }, function (error) {
+            // Suppress null result (cancel) on suspending
+            if (BarcodeReader.suspended) {
+                return;
+            }
+
+            destroyPreview();
+            if (error.message == 'Canceled') {
+                success({
+                    cancelled: true
+                });
+            } else {
+                fail(error);
+            }
+        });
+
+        BarcodeReader.videoPreviewIsVisible = function () {
+            return capturePreviewFrame !== null;
+        }
+
+        BarcodeReader.destroyPreview = destroyPreview;
+    },
+
+    /**
+     * Encodes specified data into barcode
+     * @param  {function} success Success callback
+     * @param  {function} fail    Error callback
+     * @param  {array} args       Arguments array
+     */
+    encode: function (success, fail, args) {
+        fail("Not implemented yet");
+    }
+};
+
+var app = WinJS.Application;
+
+function waitForScanEnd() {
+    return BarcodeReader.scanPromise || WinJS.Promise.as();
+}
+
+function suspend(args) {
+    BarcodeReader.suspended = true;
+    if (args) {
+        args.setPromise(BarcodeReader.destroyPreview()
+        .then(waitForScanEnd, waitForScanEnd));
+    } else {
+        BarcodeReader.destroyPreview();
+    }
+}
+
+function resume() {
+    BarcodeReader.suspended = false;
+    module.exports.scan(BarcodeReader.scanCallArgs.success, BarcodeReader.scanCallArgs.fail, BarcodeReader.scanCallArgs.args);
+}
+
+function onVisibilityChanged() {
+    if (document.visibilityState === 'hidden'
+        && BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) {
+        suspend();
+    } else if (BarcodeReader.suspended) {
+        resume();
+    }
+}
+
+// Windows 8.1 projects
+document.addEventListener('msvisibilitychange', onVisibilityChanged);
+// Windows 10 projects
+document.addEventListener('visibilitychange', onVisibilityChanged);
+
+// About to be suspended
+app.addEventListener('checkpoint', function (args) {
+    if (BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) {
+        suspend(args);
+    }
+});
+
+// Resuming from a user suspension
+Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", function () {
+    if (BarcodeReader.suspended) {
+        resume();
+    }
+}, false);
+
+require("cordova/exec/proxy").add("BarcodeScanner", module.exports);

+ 89 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/assets/plugin-barcodeScanner.css

xqd
@@ -0,0 +1,89 @@
+.barcode-scanner-wrap {
+    margin: 0;
+    padding: 0;
+    outline: 0;
+    font-size: 100%;
+    vertical-align: baseline;
+    background: 0 0 black;
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 9999999;
+    -ms-user-select: none;
+}
+
+.barcode-scanner-preview {
+    width: auto;
+    height: calc(100% - 70px);
+    position: absolute;
+    top: calc(50% - 35px);
+    left: 50%;
+    transform: translateX(-50%) translateY(-50%);
+}
+
+.barcode-scanner-mark {
+    position: absolute;
+    left: 0;
+    top: 50%;
+    width: 100%;
+    height: 3px;
+    background: red;
+    z-index: 9999999;
+}
+
+.barcode-scanner-app-bar {
+    height: 70px;
+    width: 100%;
+    padding-top: 10px;
+    z-index: 9999999;
+    text-align: center;
+    user-select: none;
+    position: absolute;
+    bottom: 0px;
+}
+
+.app-bar-action {
+    width: 40px;
+    height: 40px;
+    margin: 0 auto;
+    font-family: "Segoe UI Symbol";
+    color: white;
+    font-size: 12px;
+    text-transform: lowercase;
+    text-align: center;
+    cursor: default;
+}
+
+@media all and (orientation: landscape) {
+    .app-bar-action {
+        float: right;
+        margin-right: 20px;
+    }
+}
+
+.app-bar-action::before {
+    font-size: 28px;
+    display: block;
+    height: 36px;
+}
+
+.action-close::before {
+    content: "\E0C7";
+    /* close icon is larger so we re-size it to fit other icons */
+    font-size: 20px;
+    line-height: 40px;
+}
+
+.action-close:hover::before {
+    content: "\E0CA";
+}
+
+.no-zoom {
+    -ms-content-zooming: none;
+}
+
+.no-scroll {
+    overflow: hidden;
+}

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/ANY/ZXing.winmd


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/ARM/ZXing.winmd


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/x64/ZXing.winmd


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib.UW/x86/ZXing.winmd


+ 39 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/Properties/AssemblyInfo.cs

xqd
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WinRTBarcodeReader")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WinRTBarcodeReader")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]

+ 173 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/Reader.cs

xqd
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+namespace WinRTBarcodeReader
+{
+    using System;
+    using System.Threading;
+    using System.Threading.Tasks;
+
+    using Windows.Foundation;
+    using Windows.Graphics.Imaging;
+    using Windows.Media.Capture;
+    using Windows.Media.MediaProperties;
+    using Windows.Storage.Streams;
+
+    using ZXing;
+
+    /// <summary>
+    /// Defines the Reader type, that perform barcode search asynchronously.
+    /// </summary>
+    public sealed class Reader
+    {
+        #region Private fields
+
+        /// <summary>
+        ///     Data reader, used to create bitmap array.
+        /// </summary>
+        private BarcodeReader barcodeReader;
+
+        /// <summary>
+        ///     The cancel search flag.
+        /// </summary>
+        private CancellationTokenSource cancelSearch;
+
+        /// <summary>
+        ///     MediaCapture instance, used for barcode search.
+        /// </summary>
+        private MediaCapture capture;
+
+        /// <summary>
+        ///     Encoding properties for mediaCapture object.
+        /// </summary>
+        private ImageEncodingProperties encodingProps;
+
+        /// <summary>
+        ///     Flag that indicates successful barcode search.
+        /// </summary>
+        private bool barcodeFoundOrCancelled;
+
+        /// <summary>
+        ///     Image stream for MediaCapture content.
+        /// </summary>
+        private InMemoryRandomAccessStream imageStream;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Reader" /> class.
+        /// </summary>
+        /// <param name="capture">MediaCapture instance.</param>
+        /// <param name="width">Capture frame width.</param>
+        /// <param name="height">Capture frame height.</param>
+        public void Init(MediaCapture capture, uint width, uint height)
+        {
+            this.capture = capture;
+            encodingProps = ImageEncodingProperties.CreateJpeg();
+            encodingProps.Width = width;
+            encodingProps.Height = height;
+
+            barcodeReader = new BarcodeReader {Options = {TryHarder = true}};
+            cancelSearch = new CancellationTokenSource();
+        }
+
+        #endregion
+
+        #region Public methods
+
+        /// <summary>
+        /// Perform async MediaCapture analysis and searches for barcode.
+        /// </summary>
+        /// <returns>IAsyncOperation object</returns>
+        public IAsyncOperation<Result> ReadCode()
+        {
+            return this.Read().AsAsyncOperation();
+        }
+
+        /// <summary>
+        /// Send signal to stop barcode search.
+        /// </summary>
+        public void Stop()
+        {
+            this.cancelSearch.Cancel();
+        }
+
+        #endregion
+
+        #region Private methods
+
+        /// <summary>
+        /// Perform async MediaCapture analysis and searches for barcode.
+        /// </summary>
+        /// <returns>Task object</returns>
+        private async Task<Result> Read()
+        {
+            Result result = null;
+            try
+            {
+                while (result == null)
+                {
+                    result = await GetCameraImage(cancelSearch.Token);
+                }
+            }
+            catch (OperationCanceledException) { }
+
+            return result;
+        }
+
+        /// <summary>
+        /// Perform image capture from mediaCapture object
+        /// </summary>
+        /// <param name="cancelToken">
+        /// The cancel Token.
+        /// </param>
+        /// <returns>
+        /// Decoded barcode string.
+        /// </returns>
+        private async Task<Result> GetCameraImage(CancellationToken cancelToken)
+        {
+            if (cancelToken.IsCancellationRequested)
+            {
+                throw new OperationCanceledException(cancelToken);
+            }
+
+            imageStream = new InMemoryRandomAccessStream();
+
+            await capture.CapturePhotoToStreamAsync(encodingProps, imageStream);
+            await imageStream.FlushAsync();
+
+            var decoder = await BitmapDecoder.CreateAsync(imageStream);
+
+            byte[] pixels =
+                (await
+                    decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8,
+                        BitmapAlphaMode.Ignore,
+                        new BitmapTransform(),
+                        ExifOrientationMode.IgnoreExifOrientation,
+                        ColorManagementMode.DoNotColorManage)).DetachPixelData();
+
+            const BitmapFormat format = BitmapFormat.RGB32;
+
+            imageStream.Dispose();
+
+            var result =
+                await
+                    Task.Run(
+                        () => barcodeReader.Decode(pixels, (int) decoder.PixelWidth, (int) decoder.PixelHeight, format),
+                        cancelToken);
+
+            return result;
+        }
+
+        #endregion
+    }
+}

+ 137 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/WinRTBarcodeReader.csproj

xqd
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+  Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+-->
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectName>WinRTBarcodeReader</ProjectName>
+    <ProjectGuid>{01412F36-3781-4AF0-903C-ACEA7552C99C}</ProjectGuid>
+    <OutputType>winmdobj</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>WinRTBarcodeReader</RootNamespace>
+    <AssemblyName>WinRTBarcodeReader</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetPlatformVersion>8.1</TargetPlatformVersion>
+    <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+    <TargetFrameworkVersion />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugSymbols>false</DebugSymbols>
+    <DebugType>None</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\ARM\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+    <OutputPath>bin\ARM\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugSymbols>false</DebugSymbols>
+    <DebugType>None</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugSymbols>false</DebugSymbols>
+    <DebugType>None</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugSymbols>false</DebugSymbols>
+    <DebugType>None</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="Reader.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="ZXing">
+      <HintPath>ZXing.winmd</HintPath>
+    </Reference>
+  </ItemGroup>
+  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+    <VisualStudioVersion>12.0</VisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/windows/lib/ZXing.winmd


+ 117 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScanner.cs

xqd
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+ namespace WPCordovaClassLib.Cordova.Commands
+{
+    using System.Runtime.Serialization;
+    using Microsoft.Phone.Tasks;
+    using WPCordovaClassLib.Cordova.JSON;
+    using ZXing;
+
+    /// <summary>
+    /// Class that extends cordova with Barcode scanner functionality.
+    /// </summary>
+    public class BarcodeScanner : BaseCommand
+    {
+        /// <summary>
+        /// Scans the barcode.
+        /// </summary>
+        /// <param name="options">Parameter is ignored.</param>
+        public void scan(string options)
+        {
+            var task = new BarcodeScannerTask();
+            task.Completed += this.TaskCompleted;
+            task.Show();
+        }
+
+        /// <summary>
+        /// Handler for barcode scanner task.
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="e">The scan result.</param>
+        private void TaskCompleted(object sender, BarcodeScannerTask.ScanResult e)
+        {
+            PluginResult result;
+
+            switch (e.TaskResult)
+            {
+                case TaskResult.OK:
+                    result = new PluginResult(PluginResult.Status.OK);
+                    result.Message = JsonHelper.Serialize(new BarcodeResult(e.Barcode));
+                    break;
+                case TaskResult.Cancel:
+                    // If scan is cancelled we return PluginResult.Status.OK with Message contains cancelled: true
+                    // See plugin docs https://github.com/MSOpenTech/BarcodeScanner#using-the-plugin
+                    result = new PluginResult(PluginResult.Status.OK);
+                    result.Message = JsonHelper.Serialize(new BarcodeResult());
+                    break;
+                default:
+                    result = new PluginResult(PluginResult.Status.ERROR);
+                    break;
+            }
+
+            this.DispatchCommandResult(result);
+        }
+    }
+
+    /// <summary>
+    /// Represents the barcode scan result, that should be serialized and passed to JS layer.
+    /// </summary>
+    [DataContract]
+    public sealed class BarcodeResult
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BarcodeResult"/> class.
+        /// </summary>
+        /// <param name="canceled">if set to <c>true</c> [canceled].</param>
+        public BarcodeResult(bool canceled = true)
+        {
+            this.Cancelled = canceled;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BarcodeResult"/> class.
+        /// </summary>
+        /// <param name="barcode">The barcode result.</param>
+        public BarcodeResult(Result barcode)
+        {
+            this.Cancelled = false;
+            this.Format = barcode.BarcodeFormat.ToString();
+            this.Text = barcode.Text;
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether barcode scan is cancelled.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if cancelled; otherwise, <c>false</c>.
+        /// </value>
+        [DataMember(Name = "cancelled")]
+        public bool Cancelled { get; private set; }
+
+        /// <summary>
+        /// Gets the format of barcode.
+        /// </summary>
+        /// <value>
+        /// The barcode format.
+        /// </value>
+        [DataMember(Name = "format")]
+        public string Format { get; private set; }
+
+        /// <summary>
+        /// Gets the barcode text.
+        /// </summary>
+        /// <value>
+        /// The barcode text.
+        /// </value>
+        [DataMember(Name = "text")]
+        public string Text { get; private set; }
+    }
+}

+ 103 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerTask.cs

xqd
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+    using System;
+    using System.Windows;
+    using System.Windows.Navigation;
+
+    using Microsoft.Phone.Controls;
+    using Microsoft.Phone.Tasks;
+    using ZXing;
+
+    /// <summary>
+    /// Class that represents barcode scanner task that mimics standart WP8 tasks.
+    /// </summary>
+    public class BarcodeScannerTask
+    {
+        /// <summary>
+        /// Occurs when task is [completed].
+        /// </summary>
+        public event EventHandler<ScanResult> Completed;
+
+        /// <summary>
+        /// Shows barcode scanner interface.
+        /// </summary>
+        public void Show()
+        {
+            Deployment.Current.Dispatcher.BeginInvoke(() =>
+            {
+                var root = Application.Current.RootVisual as PhoneApplicationFrame;
+
+                if (root == null)
+                {
+                    return;
+                }
+
+                root.Navigated += this.OnNavigated;
+                root.Navigate(new Uri("/Plugins/phonegap-plugin-barcodescanner/BarcodeScannerUI.xaml", UriKind.Relative));
+            });
+        }
+
+        /// <summary>
+        /// Called when [navigated].
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="e">The <see cref="NavigationEventArgs"/> instance containing the event data.</param>
+        private void OnNavigated(object sender, NavigationEventArgs e)
+        {
+            if (!(e.Content is BarcodeScannerUI))
+            {
+                return;
+            }
+
+            var phoneApplicationFrame = Application.Current.RootVisual as PhoneApplicationFrame;
+            if (phoneApplicationFrame != null)
+            {
+                phoneApplicationFrame.Navigated -= this.OnNavigated;
+            }
+
+            var barcodeScanner = (BarcodeScannerUI)e.Content;
+
+            if (barcodeScanner != null)
+            {
+                barcodeScanner.Completed += this.Completed;
+            }
+            else if (this.Completed != null)
+            {
+                this.Completed(this, new ScanResult(TaskResult.Cancel));
+            }
+        }
+
+        /// <summary>
+        /// Represents barcode scan result.
+        /// </summary>
+        public class ScanResult : TaskEventArgs
+        {
+            /// <summary>
+            /// Initializes a new instance of the <see cref="ScanResult"/> class.
+            /// </summary>
+            /// <param name="taskResult">One of the enumeration values that specifies the status of the task.</param>
+            public ScanResult(TaskResult taskResult)
+                : base(taskResult)
+            {
+            }
+
+            /// <summary>
+            /// Gets the barcode scan result.
+            /// </summary>
+            /// <value>
+            /// The barcode scan result.
+            /// </value>
+            public Result Barcode { get; internal set; }
+        }
+    }
+}

+ 46 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerUI.xaml

xqd
@@ -0,0 +1,46 @@
+<!-- 
+  Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+  
+    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+-->
+<phone:PhoneApplicationPage
+    x:Class="WPCordovaClassLib.Cordova.Commands.BarcodeScannerUI"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    FontFamily="{StaticResource PhoneFontFamilyNormal}"
+    FontSize="{StaticResource PhoneFontSizeNormal}"
+    Foreground="{StaticResource PhoneForegroundBrush}"
+    SupportedOrientations="Portrait" Orientation="Portrait"
+    mc:Ignorable="d"
+    shell:SystemTray.IsVisible="True" CacheMode="BitmapCache" >
+    <phone:PhoneApplicationPage.ApplicationBar>
+        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False" Mode="Minimized">
+            <shell:ApplicationBarIconButton IconUri="/www/Images/appbar.cancel.png" IsEnabled="True" Text="Cancel" Click="CancelScan"/>
+        </shell:ApplicationBar>
+    </phone:PhoneApplicationPage.ApplicationBar>
+
+    <Grid Background="Transparent">
+        <Canvas x:Name="CameraCanvas">
+            <Canvas.Background>
+                <VideoBrush x:Name="CameraBrush">
+                    <VideoBrush.RelativeTransform>
+                        <CompositeTransform
+                            CenterX="0.5"
+                            CenterY="0.5"
+                            Rotation="90"/>
+                    </VideoBrush.RelativeTransform>
+                </VideoBrush>
+            </Canvas.Background>
+        </Canvas>
+        <Rectangle Margin="0" Stroke="Red" Height="2"/>
+    </Grid>
+
+</phone:PhoneApplicationPage>

+ 182 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/BarcodeScannerUI.xaml.cs

xqd
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ */
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+    using System;
+    using System.Windows;
+    using System.Windows.Controls;
+    using System.Windows.Input;
+    using System.Windows.Media.Imaging;
+    using System.Windows.Navigation;
+    using System.Windows.Threading;
+
+    using Microsoft.Devices;
+    using Microsoft.Phone.Tasks;
+
+    using ZXing;
+
+    /// <summary>
+    /// Class that represents UI for barcode scanner.
+    /// </summary>
+    public partial class BarcodeScannerUI
+    {
+        /// <summary>
+        /// The result of scan operation.
+        /// </summary>
+        private BarcodeScannerTask.ScanResult result;
+
+        /// <summary>
+        /// The barcode reader object
+        /// </summary>
+        private BarcodeReader reader;
+
+        /// <summary>
+        /// Device camera object
+        /// </summary>
+        private PhotoCamera camera;
+
+        private DispatcherTimer timer;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BarcodeScannerUI"/> class.
+        /// This implementation not use camera autofocus.
+        /// </summary>
+        public BarcodeScannerUI()
+        {
+            this.InitializeComponent();
+
+            // Instantiate objects and start camera preview
+            this.camera = new PhotoCamera();
+            this.reader = new BarcodeReader {Options = {TryHarder = true}};
+            this.CameraBrush.SetSource(this.camera);
+
+            // Bind events
+            this.camera.Initialized += this.CameraInitialized;
+            this.reader.ResultFound += this.ReaderResultFound;
+
+            this.timer = new DispatcherTimer {Interval = TimeSpan.FromMilliseconds(100)};
+            this.timer.Tick += (sender, args) => ScanForBarcode();
+
+            this.BackKeyPress += CancelScan;
+
+            CameraButtons.ShutterKeyHalfPressed += StartCameraFocus;
+            camera.AutoFocusCompleted += StartCameraFocus;
+
+        }
+
+        private void StartCameraFocus(object sender, EventArgs eventArgs)
+        {
+            camera.Focus();
+        }
+
+        /// <summary>
+        /// Occurs when barcode scan is [completed].
+        /// </summary>
+        public event EventHandler<BarcodeScannerTask.ScanResult> Completed;
+
+        /// <summary>
+        /// Called when a page is no longer the active page in a frame.
+        /// </summary>
+        /// <param name="e">An object that contains the event data.</param>
+        protected override void OnNavigatedFrom(NavigationEventArgs e)
+        {
+            // If result is null, user is cancelled scan operation
+            this.result = this.result ?? new BarcodeScannerTask.ScanResult(TaskResult.Cancel);
+            this.Completed(this, this.result);
+            this.CleanUp();
+            base.OnNavigatedFrom(e);
+        }
+
+        /// <summary>
+        /// Called when device camera initialized.
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="e">The <see cref="CameraOperationCompletedEventArgs"/> instance containing the event data.</param>
+        private void CameraInitialized(object sender, CameraOperationCompletedEventArgs e)
+        {
+            if (e.Succeeded)
+            {
+                if (camera.IsFocusSupported)
+                {
+                    camera.Focus();
+                }
+
+                // Start scan process in separate thread
+                this.Dispatcher.BeginInvoke(() => timer.Start());
+            }
+            else
+            {
+                this.result = new BarcodeScannerTask.ScanResult(TaskResult.None);
+                NavigationService.GoBack();
+            }
+        }
+
+        private void ScanForBarcode()
+        {
+            var cameraBuffer = new WriteableBitmap(
+                                (int)camera.PreviewResolution.Width,
+                                (int)camera.PreviewResolution.Height);
+
+            camera.GetPreviewBufferArgb32(cameraBuffer.Pixels);
+            cameraBuffer.Invalidate();
+
+            reader.Decode(cameraBuffer);
+        }
+
+        /// <summary>
+        /// Called when reader find barcode.
+        /// </summary>
+        /// <param name="obj">Scan result object.</param>
+        private void ReaderResultFound(Result obj)
+        {
+            VibrateController.Default.Start(TimeSpan.FromMilliseconds(100));
+            this.result = new BarcodeScannerTask.ScanResult(TaskResult.OK) { Barcode = obj };
+            NavigationService.GoBack();
+        }
+
+        /// <summary>
+        /// Cleans up resources and removes unnecessary callbacks.
+        /// </summary>
+        private void CleanUp()
+        {
+            CameraButtons.ShutterKeyHalfPressed -= StartCameraFocus;
+            if (this.camera != null)
+            {
+                this.camera.AutoFocusCompleted -= StartCameraFocus;
+                this.camera.Initialized -= this.CameraInitialized;
+                this.camera.Dispose();
+                this.camera = null;
+            }
+
+            if (this.reader != null)
+            {
+                this.reader.ResultFound -= this.ReaderResultFound;
+                this.reader = null;
+            }
+
+            if (this.timer != null)
+            {
+                this.timer.Stop();
+                this.timer = null;
+            }
+        }
+
+        private void ApplicationBarIconButton_Click(object sender, EventArgs e)
+        {
+            NavigationService.GoBack();
+        }
+
+        private void CancelScan(object sender, EventArgs eventArgs)
+        {
+            NavigationService.GoBack();
+        }
+    }
+}

BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/assets/cancel.png


BIN
miaomiao/plugins/phonegap-plugin-barcodescanner/src/wp8/lib/zxing.wp8.0.dll


+ 156 - 0
miaomiao/plugins/phonegap-plugin-barcodescanner/www/barcodescanner.js

xqd
@@ -0,0 +1,156 @@
+/**
+ * cordova is available under the MIT License (2008).
+ * See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) Matt Kane 2010
+ * Copyright (c) 2011, IBM Corporation
+ * Copyright (c) 2012-2017, Adobe Systems
+ */
+
+
+        var exec = cordova.require("cordova/exec");
+
+        var scanInProgress = false;
+
+        /**
+         * Constructor.
+         *
+         * @returns {BarcodeScanner}
+         */
+        function BarcodeScanner() {
+
+            /**
+             * Encoding constants.
+             *
+             * @type Object
+             */
+            this.Encode = {
+                TEXT_TYPE: "TEXT_TYPE",
+                EMAIL_TYPE: "EMAIL_TYPE",
+                PHONE_TYPE: "PHONE_TYPE",
+                SMS_TYPE: "SMS_TYPE"
+                //  CONTACT_TYPE: "CONTACT_TYPE",  // TODO:  not implemented, requires passing a Bundle class from Javascript to Java
+                //  LOCATION_TYPE: "LOCATION_TYPE" // TODO:  not implemented, requires passing a Bundle class from Javascript to Java
+            };
+
+    /**
+     * Barcode format constants, defined in ZXing library.
+     *
+     * @type Object
+     */
+    this.format = {
+        "all_1D": 61918,
+        "aztec": 1,
+        "codabar": 2,
+        "code_128": 16,
+        "code_39": 4,
+        "code_93": 8,
+        "data_MATRIX": 32,
+        "ean_13": 128,
+        "ean_8": 64,
+        "itf": 256,
+        "maxicode": 512,
+        "msi": 131072,
+        "pdf_417": 1024,
+        "plessey": 262144,
+        "qr_CODE": 2048,
+        "rss_14": 4096,
+        "rss_EXPANDED": 8192,
+        "upc_A": 16384,
+        "upc_E": 32768,
+        "upc_EAN_EXTENSION": 65536
+        };
+  }
+
+/**
+ * Read code from scanner.
+ *
+ * @param {Function} successCallback This function will recieve a result object: {
+         *        text : '12345-mock',    // The code that was scanned.
+         *        format : 'FORMAT_NAME', // Code format.
+         *        cancelled : true/false, // Was canceled.
+         *    }
+ * @param {Function} errorCallback
+ * @param config
+ */
+BarcodeScanner.prototype.scan = function (successCallback, errorCallback, config) {
+
+            if (config instanceof Array) {
+                // do nothing
+            } else {
+                if (typeof(config) === 'object') {
+                    // string spaces between formats, ZXing does not like that
+                    if (config.formats) {
+                        config.formats = config.formats.replace(/\s+/g, '');
+                    }
+                    config = [ config ];
+                } else {
+                    config = [];
+                }
+            }
+
+            if (errorCallback == null) {
+                errorCallback = function () {
+                };
+            }
+
+            if (typeof errorCallback != "function") {
+                console.log("BarcodeScanner.scan failure: failure parameter not a function");
+                return;
+            }
+
+            if (typeof successCallback != "function") {
+                console.log("BarcodeScanner.scan failure: success callback parameter must be a function");
+                return;
+            }
+
+            if (scanInProgress) {
+                errorCallback('Scan is already in progress');
+                return;
+            }
+
+            scanInProgress = true;
+
+            exec(
+                function(result) {
+                    scanInProgress = false;
+                    // work around bug in ZXing library
+                    if (result.format === 'UPC_A' && result.text.length === 13) {
+                        result.text = result.text.substring(1);
+                    }
+                    successCallback(result);
+                },
+                function(error) {
+                    scanInProgress = false;
+                    errorCallback(error);
+                },
+                'BarcodeScanner',
+                'scan',
+                config
+            );
+        };
+
+        //-------------------------------------------------------------------
+        BarcodeScanner.prototype.encode = function (type, data, successCallback, errorCallback, options) {
+            if (errorCallback == null) {
+                errorCallback = function () {
+                };
+            }
+
+            if (typeof errorCallback != "function") {
+                console.log("BarcodeScanner.encode failure: failure parameter not a function");
+                return;
+            }
+
+            if (typeof successCallback != "function") {
+                console.log("BarcodeScanner.encode failure: success callback parameter must be a function");
+                return;
+            }
+
+            exec(successCallback, errorCallback, 'BarcodeScanner', 'encode', [
+                {"type": type, "data": data, "options": options}
+            ]);
+        };
+
+        var barcodeScanner = new BarcodeScanner();
+        module.exports = barcodeScanner;

BIN
miaomiao/resources/android/icon/drawable-hdpi-icon.png


BIN
miaomiao/resources/android/icon/drawable-ldpi-icon.png


BIN
miaomiao/resources/android/icon/drawable-mdpi-icon.png


BIN
miaomiao/resources/android/icon/drawable-xhdpi-icon.png


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác