rhodes 3.0.2 → 3.1.0.beta.1

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