ranger-compiler 3.5.0 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. package/CHANGELOG.md +1160 -19
  2. package/LICENSE +3 -1
  3. package/README.md +124 -29
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79924 -56922
  7. package/dist/lib/JSON.rgr +102 -91
  8. package/dist/lib/Shell.rgr +4 -4
  9. package/dist/lib/apple/AppleToolchain.rgr +4 -4
  10. package/dist/lib/apple/README.md +5 -4
  11. package/dist/lib/apple/apple_test.rgr +1 -1
  12. package/dist/lib/core/README.md +1 -1
  13. package/dist/lib/evg/EVG.rgr +12 -0
  14. package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
  15. package/dist/lib/evg/EVGA11yTree.rgr +894 -0
  16. package/dist/lib/evg/EVGBox.rgr +267 -0
  17. package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
  18. package/dist/lib/evg/EVGCodepoint.rgr +316 -0
  19. package/dist/lib/evg/EVGColor.rgr +700 -0
  20. package/dist/lib/evg/EVGCommands.rgr +177 -0
  21. package/dist/lib/evg/EVGComponent.rgr +331 -0
  22. package/dist/lib/evg/EVGComponentTest.rgr +387 -0
  23. package/dist/lib/evg/EVGConnector.rgr +541 -0
  24. package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
  25. package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
  26. package/dist/lib/evg/EVGEasing.rgr +370 -0
  27. package/dist/lib/evg/EVGEffectTest.rgr +253 -0
  28. package/dist/lib/evg/EVGElement.rgr +4914 -0
  29. package/dist/lib/evg/EVGFixedTest.rgr +289 -0
  30. package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
  31. package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
  32. package/dist/lib/evg/EVGFling.rgr +244 -0
  33. package/dist/lib/evg/EVGFocus.rgr +400 -0
  34. package/dist/lib/evg/EVGFocusTest.rgr +399 -0
  35. package/dist/lib/evg/EVGGradient.rgr +322 -0
  36. package/dist/lib/evg/EVGGrapheme.rgr +190 -0
  37. package/dist/lib/evg/EVGGrid.rgr +975 -0
  38. package/dist/lib/evg/EVGHitTest.rgr +208 -0
  39. package/dist/lib/evg/EVGHoles.rgr +294 -0
  40. package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
  41. package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
  42. package/dist/lib/evg/EVGHostTree.rgr +834 -0
  43. package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
  44. package/dist/lib/evg/EVGImageDecode.rgr +117 -0
  45. package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
  46. package/dist/lib/evg/EVGInspect.rgr +883 -0
  47. package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
  48. package/dist/lib/evg/EVGJsonTest.rgr +535 -0
  49. package/dist/lib/evg/EVGLayout.rgr +4220 -0
  50. package/dist/lib/evg/EVGMeasure.rgr +1267 -0
  51. package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
  52. package/dist/lib/evg/EVGPatch.rgr +1721 -0
  53. package/dist/lib/evg/EVGPatchTest.rgr +692 -0
  54. package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
  55. package/dist/lib/evg/EVGReconcile.rgr +226 -0
  56. package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
  57. package/dist/lib/evg/EVGReject.rgr +126 -0
  58. package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
  59. package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
  60. package/dist/lib/evg/EVGRuler.rgr +232 -0
  61. package/dist/lib/evg/EVGRulerTest.rgr +172 -0
  62. package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
  63. package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
  64. package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
  65. package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
  66. package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
  67. package/dist/lib/evg/EVGText.rgr +105 -0
  68. package/dist/lib/evg/EVGTextEngine.rgr +536 -0
  69. package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
  70. package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
  71. package/dist/lib/evg/EVGToolbar.rgr +1369 -0
  72. package/dist/lib/evg/EVGTransition.rgr +728 -0
  73. package/dist/lib/evg/EVGTreeJson.rgr +721 -0
  74. package/dist/lib/evg/EVGUnit.rgr +554 -0
  75. package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
  76. package/dist/lib/evg/EvgApp.rgr +189 -0
  77. package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
  78. package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
  79. package/dist/lib/evg/EvgHost.rgr +451 -0
  80. package/dist/lib/evg/EvgTest.rgr +91 -0
  81. package/dist/lib/evg/EvgTraceColor.rgr +236 -0
  82. package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
  83. package/dist/lib/evg/EvgTraceFit.rgr +767 -0
  84. package/dist/lib/evg/EvgTracePath.rgr +435 -0
  85. package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
  86. package/dist/lib/evg/EvgViewport.rgr +313 -0
  87. package/dist/lib/evg/FxDemoDoc.rgr +185 -0
  88. package/dist/lib/evg/HOSTS.md +227 -0
  89. package/dist/lib/evg/ISSUES.md +835 -0
  90. package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
  91. package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
  92. package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
  93. package/dist/lib/evg/PLAN_EVG.md +518 -0
  94. package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
  95. package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
  96. package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
  97. package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
  98. package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
  99. package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
  100. package/dist/lib/evg/PathBuilder.rgr +333 -0
  101. package/dist/lib/evg/README.md +1236 -0
  102. package/dist/lib/evg/SPEC.md +1252 -0
  103. package/dist/lib/evg/SVGPathParser.rgr +1199 -0
  104. package/dist/lib/evg/SvgParser.rgr +1736 -0
  105. package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
  106. package/dist/lib/evg/VectorShapes.rgr +331 -0
  107. package/dist/lib/evg/VectorStroke.rgr +107 -0
  108. package/dist/lib/evg/VectorViewBox.rgr +380 -0
  109. package/dist/lib/evg/agent/README.md +290 -0
  110. package/dist/lib/evg/agent/evg_agent.rgr +899 -0
  111. package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
  112. package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
  113. package/dist/lib/evg/agent/fixtures/connector.css +63 -0
  114. package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
  115. package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
  116. package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
  117. package/dist/lib/evg/agent/fixtures/popover.css +99 -0
  118. package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
  119. package/dist/lib/evg/agent/roundtrip.sh +74 -0
  120. package/dist/lib/evg/agent/smoke.sh +230 -0
  121. package/dist/lib/evg/android/README.md +97 -0
  122. package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
  123. package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
  124. package/dist/lib/evg/android/androidstubs/App.kt +30 -0
  125. package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
  126. package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
  127. package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
  128. package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
  129. package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
  130. package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
  131. package/dist/lib/evg/android/androidstubs/View.kt +113 -0
  132. package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
  133. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
  134. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
  135. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
  136. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
  137. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
  138. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
  139. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
  140. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
  141. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
  142. package/dist/lib/evg/apple/README.md +128 -0
  143. package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
  144. package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
  145. package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
  146. package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
  147. package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
  148. package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
  149. package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
  150. package/dist/lib/evg/bench/README.md +64 -0
  151. package/dist/lib/evg/bench/layout-bench.mjs +316 -0
  152. package/dist/lib/evg/bench/layout-cases.mjs +510 -0
  153. package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
  154. package/dist/lib/evg/bin/.gitignore +17 -0
  155. package/dist/lib/evg/evg_test.rgr +313 -0
  156. package/dist/lib/evg/gl/README.md +198 -0
  157. package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
  158. package/dist/lib/evg/gl/blur-check.mjs +399 -0
  159. package/dist/lib/evg/gl/boxmodel.json +1 -0
  160. package/dist/lib/evg/gl/demo.html +46 -0
  161. package/dist/lib/evg/gl/effect-presets.css +285 -0
  162. package/dist/lib/evg/gl/effect-presets.js +63 -0
  163. package/dist/lib/evg/gl/effect-shots.mjs +135 -0
  164. package/dist/lib/evg/gl/evg-a11y.js +566 -0
  165. package/dist/lib/evg/gl/evg-binary.js +160 -0
  166. package/dist/lib/evg/gl/evg-engine.js +296 -0
  167. package/dist/lib/evg/gl/evg-fx.js +237 -0
  168. package/dist/lib/evg/gl/evg-gestures.js +209 -0
  169. package/dist/lib/evg/gl/evg-list.js +167 -0
  170. package/dist/lib/evg/gl/evg-measure.js +186 -0
  171. package/dist/lib/evg/gl/evg-textinput.js +303 -0
  172. package/dist/lib/evg/gl/evg-view.js +144 -0
  173. package/dist/lib/evg/gl/evg-webgl.js +3942 -0
  174. package/dist/lib/evg/gl/fx-check.mjs +998 -0
  175. package/dist/lib/evg/gl/fx-demo.html +166 -0
  176. package/dist/lib/evg/gl/fx-demo.js +2 -0
  177. package/dist/lib/evg/gl/fx-serve.mjs +47 -0
  178. package/dist/lib/evg/gl/gestures-check.mjs +189 -0
  179. package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
  180. package/dist/lib/evg/gl/measure-check.mjs +135 -0
  181. package/dist/lib/evg/gl/rotation-check.mjs +207 -0
  182. package/dist/lib/evg/gl/shift-check.mjs +113 -0
  183. package/dist/lib/evg/gl/stroke-check.mjs +168 -0
  184. package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
  185. package/dist/lib/evg/gl/view-check.mjs +343 -0
  186. package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
  187. package/dist/lib/evg/html/evg-dom.js +318 -0
  188. package/dist/lib/evg/html/evg-html.js +600 -0
  189. package/dist/lib/evg/inspect/README.md +415 -0
  190. package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
  191. package/dist/lib/evg/inspect/evg-inspect.js +947 -0
  192. package/dist/lib/evg/inspect/shots/css.png +0 -0
  193. package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
  194. package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
  195. package/dist/lib/evg/inspect/shots/state.png +0 -0
  196. package/dist/lib/evg/inspect/shots.mjs +226 -0
  197. package/dist/lib/evg/oracle/css-blur.json +576 -0
  198. package/dist/lib/evg/oracle/css-box.json +157 -0
  199. package/dist/lib/evg/oracle/css-timing.json +709 -0
  200. package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
  201. package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
  202. package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
  203. package/dist/lib/evg/original/EVGColor.clj +310 -0
  204. package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
  205. package/dist/lib/evg/original/SVGPath.rgr +627 -0
  206. package/dist/lib/evg/original/Vec2.crgr +103 -0
  207. package/dist/lib/evg/ranger.json +9 -0
  208. package/dist/lib/evg/showcase/README.md +246 -0
  209. package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
  210. package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
  211. package/dist/lib/evg/showcase/build.mjs +651 -0
  212. package/dist/lib/evg/showcase/pages/album.tsx +30 -0
  213. package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
  214. package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
  215. package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
  216. package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
  217. package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
  218. package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
  219. package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
  220. package/dist/lib/evg/showcase/pages/more.tsx +332 -0
  221. package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
  222. package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
  223. package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
  224. package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
  225. package/dist/lib/evg/showcase/pages/units.tsx +35 -0
  226. package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
  227. package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
  228. package/dist/lib/evg/showcase/pages/views.tsx +223 -0
  229. package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
  230. package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
  231. package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
  232. package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
  233. package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
  234. package/dist/lib/evg/showcase/themes/more-default.css +128 -0
  235. package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
  236. package/dist/lib/evg/showcase/themes/showcase.css +508 -0
  237. package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
  238. package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
  239. package/dist/lib/evg/showcase/themes/views-default.css +15 -0
  240. package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
  241. package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
  242. package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
  243. package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
  244. package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
  245. package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
  246. package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
  247. package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
  248. package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
  249. package/dist/lib/evg/web/responsive/README.md +97 -0
  250. package/dist/lib/evg/web/responsive/build.mjs +90 -0
  251. package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
  252. package/dist/lib/evg/web/responsive/index.html +177 -0
  253. package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
  254. package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
  255. package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
  256. package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
  257. package/dist/lib/evg/web/tools/minify.mjs +60 -0
  258. package/dist/lib/evg/web/tracer/build.mjs +87 -0
  259. package/dist/lib/evg/web/tracer/index.html +2805 -0
  260. package/dist/lib/evg/web/tracer/sample.png +0 -0
  261. package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
  262. package/dist/lib/evgr/Cargo.lock +21 -0
  263. package/dist/lib/evgr/Cargo.toml +19 -0
  264. package/dist/lib/evgr/README.md +140 -0
  265. package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
  266. package/dist/lib/evgr/bench/compare.mjs +252 -0
  267. package/dist/lib/evgr/bench/speed.mjs +277 -0
  268. package/dist/lib/evgr/bin/.gitignore +3 -0
  269. package/dist/lib/evgr/src/bin/bench.rs +106 -0
  270. package/dist/lib/evgr/src/bin/smoke.rs +13 -0
  271. package/dist/lib/evgr/src/grid.rs +730 -0
  272. package/dist/lib/evgr/src/lib.rs +1003 -0
  273. package/dist/lib/evgr/src/style.rs +468 -0
  274. package/dist/lib/evgr/src/text.rs +83 -0
  275. package/dist/lib/image/BitReader.rgr +171 -0
  276. package/dist/lib/image/Buffer.rgr +173 -0
  277. package/dist/lib/image/DCT.rgr +283 -0
  278. package/dist/lib/image/Deflate.rgr +339 -0
  279. package/dist/lib/image/HuffmanDecoder.rgr +181 -0
  280. package/dist/lib/image/ImageBuffer.rgr +706 -0
  281. package/dist/lib/image/JPEGDecoder.rgr +808 -0
  282. package/dist/lib/image/PNGDecoder.rgr +544 -0
  283. package/dist/lib/image/PNGEncoder.rgr +388 -0
  284. package/dist/lib/image/PPMImage.rgr +224 -0
  285. package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
  286. package/dist/lib/image/README.md +33 -0
  287. package/dist/lib/image/RasterBuffer.rgr +294 -0
  288. package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
  289. package/dist/lib/image/WebPDecoder.rgr +433 -0
  290. package/dist/lib/image/WebPLossless.rgr +1035 -0
  291. package/dist/lib/image/WebPLossy.rgr +1929 -0
  292. package/dist/lib/image/ranger.json +9 -0
  293. package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
  294. package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
  295. package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
  296. package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
  297. package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
  298. package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
  299. package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
  300. package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
  301. package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
  302. package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
  303. package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
  304. package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
  305. package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
  306. package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
  307. package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
  308. package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
  309. package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
  310. package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
  311. package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
  312. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
  313. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
  314. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
  315. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
  316. package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
  317. package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
  318. package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
  319. package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
  320. package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
  321. package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
  322. package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
  323. package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
  324. package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
  325. package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
  326. package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
  327. package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
  328. package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
  329. package/dist/lib/image/tests/run_webp_tests.sh +39 -0
  330. package/dist/lib/rust/RsJson.rgr +468 -0
  331. package/dist/lib/rust/RsPrelude.rgr +1663 -0
  332. package/dist/lib/shell_test.rgr +7 -7
  333. package/dist/lib/stdlib.rgr +21 -5
  334. package/dist/lib/zip/ranger.json +6 -0
  335. package/dist/rgrc.js +87318 -67610
  336. package/package.json +1010 -1040
  337. package/dist/README.md +0 -117
  338. package/dist/package.json +0 -47
@@ -0,0 +1,1154 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ProgressiveJPEGDecoder.rgr - Progressive JPEG decoder
4
+ ; Progressive JPEG uses multiple scans to refine image quality
5
+
6
+ Import "Buffer.rgr"
7
+ Import "BitReader.rgr"
8
+ Import "HuffmanDecoder.rgr"
9
+ Import "DCT.rgr"
10
+ Import "ImageBuffer.rgr"
11
+ Import "JPEGDecoder.rgr"
12
+
13
+ ; Wrapper class for coefficient array (to allow array of arrays)
14
+ class CoeffBuffer {
15
+ def coeffs:[int]
16
+ def numBlocks:int 0
17
+
18
+ Constructor () {
19
+ }
20
+
21
+ fn init:void (blocks:int) {
22
+ numBlocks = blocks
23
+ clear coeffs
24
+ def numCoeffs:int (blocks * 64)
25
+ def i 0
26
+ while (i < numCoeffs) {
27
+ push coeffs 0
28
+ i = i + 1
29
+ }
30
+ }
31
+
32
+ fn get:int (blockIdx:int k:int) {
33
+ def offset:int ((blockIdx * 64) + k)
34
+ return (at coeffs offset)
35
+ }
36
+
37
+ fn setVal:void (blockIdx:int k:int value:int) {
38
+ def offset:int ((blockIdx * 64) + k)
39
+ set coeffs offset value
40
+ }
41
+ }
42
+
43
+ class ProgressiveJPEGDecoder {
44
+ ; A picture is decoded because something is being DRAWN, not because
45
+ ; anybody asked about the JPEG — the same reason `JPEGDecoder` has this.
46
+ ; Twenty-four lines of narration per photograph is noise, and on a native
47
+ ; host it is noise on somebody's terminal.
48
+ def quiet:boolean false
49
+ def data:buffer (buffer_alloc 0)
50
+ def dataLen:int 0
51
+
52
+ ; Image properties
53
+ def width:int 0
54
+ def height:int 0
55
+ def numComponents:int 0
56
+ def precision:int 8
57
+ def isProgressive:boolean false
58
+
59
+ ; Components
60
+ def components:[JPEGComponent]
61
+
62
+ ; Quantization tables (up to 4)
63
+ def quantTables:[QuantizationTable]
64
+
65
+ ; Huffman decoder
66
+ def huffman:HuffmanDecoder (new HuffmanDecoder())
67
+
68
+ ; DCT transformer
69
+ def idct:IDCT (new IDCT())
70
+
71
+ ; MCU dimensions
72
+ def mcuWidth:int 8
73
+ def mcuHeight:int 8
74
+ def mcusPerRow:int 0
75
+ def mcusPerCol:int 0
76
+ def maxHSamp:int 1
77
+ def maxVSamp:int 1
78
+
79
+ ; Progressive coefficient storage
80
+ def coeffBuffers:[CoeffBuffer]
81
+
82
+ ; Scan parameters
83
+ def scanSs:int 0
84
+ def scanSe:int 63
85
+ def scanAh:int 0
86
+ def scanAl:int 0
87
+
88
+ ; EOBRUN for AC successive approximation
89
+ def eobrun:int 0
90
+
91
+ Constructor () {
92
+ huffman = (new HuffmanDecoder())
93
+ idct = (new IDCT())
94
+
95
+ def i 0
96
+ while (i < 4) {
97
+ push quantTables (new QuantizationTable())
98
+ i = i + 1
99
+ }
100
+ }
101
+
102
+ fn readUint16BE:int (pos:int) {
103
+ def high:int (buffer_get data pos)
104
+ def low:int (buffer_get data (pos + 1))
105
+ return ((high * 256) + low)
106
+ }
107
+
108
+ fn parseSOF:void (pos:int length:int sofType:int) {
109
+ precision = (buffer_get data pos)
110
+ height = (this.readUint16BE(pos + 1))
111
+ width = (this.readUint16BE(pos + 3))
112
+ numComponents = (buffer_get data (pos + 5))
113
+
114
+ if (sofType == 2) {
115
+ isProgressive = true
116
+ if (quiet == false) {
117
+ print (" Progressive JPEG: " + (to_string width) + "x" + (to_string height) + ", " + (to_string numComponents) + " components")
118
+ }
119
+ } {
120
+ isProgressive = false
121
+ if (quiet == false) {
122
+ print (" Baseline JPEG: " + (to_string width) + "x" + (to_string height) + ", " + (to_string numComponents) + " components")
123
+ }
124
+ }
125
+
126
+ clear components
127
+ maxHSamp = 1
128
+ maxVSamp = 1
129
+
130
+ def i 0
131
+ def offset:int (pos + 6)
132
+ while (i < numComponents) {
133
+ def comp (new JPEGComponent())
134
+ comp.id = (buffer_get data offset)
135
+ def sampling:int (buffer_get data (offset + 1))
136
+ comp.hSamp = (bit_shr sampling 4)
137
+ comp.vSamp = (bit_and sampling 15)
138
+ comp.quantTableId = (buffer_get data (offset + 2))
139
+
140
+ if (comp.hSamp > maxHSamp) { maxHSamp = comp.hSamp }
141
+ if (comp.vSamp > maxVSamp) { maxVSamp = comp.vSamp }
142
+
143
+ push components comp
144
+ if (quiet == false) {
145
+ print (" Component " + (to_string comp.id) + ": " + (to_string comp.hSamp) + "x" + (to_string comp.vSamp) + " sampling")
146
+ }
147
+
148
+ offset = offset + 3
149
+ i = i + 1
150
+ }
151
+
152
+ mcuWidth = maxHSamp * 8
153
+ mcuHeight = maxVSamp * 8
154
+ mcusPerRow = (to_int ((width + mcuWidth - 1) / mcuWidth))
155
+ mcusPerCol = (to_int ((height + mcuHeight - 1) / mcuHeight))
156
+
157
+ if (quiet == false) {
158
+ print (" MCU grid: " + (to_string mcusPerRow) + "x" + (to_string mcusPerCol))
159
+ }
160
+
161
+ this.allocateCoeffBuffers()
162
+ }
163
+
164
+ fn allocateCoeffBuffers:void () {
165
+ clear coeffBuffers
166
+ def totalMCUs:int (mcusPerRow * mcusPerCol)
167
+
168
+ def c 0
169
+ while (c < numComponents) {
170
+ def comp:JPEGComponent (at components c)
171
+ def blocksInComp:int (totalMCUs * comp.hSamp * comp.vSamp)
172
+
173
+ def buf (new CoeffBuffer())
174
+ buf.init(blocksInComp)
175
+ push coeffBuffers buf
176
+
177
+ c = c + 1
178
+ }
179
+ }
180
+
181
+ fn parseDQT:void (pos:int length:int) {
182
+ def endPos:int (pos + length)
183
+
184
+ while (pos < endPos) {
185
+ def info:int (buffer_get data pos)
186
+ pos = pos + 1
187
+
188
+ def prec:int (bit_shr info 4)
189
+ def tableId:int (bit_and info 15)
190
+
191
+ def table:QuantizationTable (at quantTables tableId)
192
+ table.id = tableId
193
+ clear table.values
194
+
195
+ def i 0
196
+ while (i < 64) {
197
+ if (prec == 0) {
198
+ push table.values (buffer_get data pos)
199
+ pos = pos + 1
200
+ } {
201
+ push table.values (this.readUint16BE(pos))
202
+ pos = pos + 2
203
+ }
204
+ i = i + 1
205
+ }
206
+
207
+ if (quiet == false) {
208
+ print (" Quantization table " + (to_string tableId))
209
+ }
210
+ }
211
+ }
212
+
213
+ fn parseSOS:int (pos:int length:int) {
214
+ def numScanComponents:int (buffer_get data pos)
215
+ pos = pos + 1
216
+
217
+ def scanComponents:[int]
218
+
219
+ def i 0
220
+ while (i < numScanComponents) {
221
+ def compId:int (buffer_get data pos)
222
+ def tableSelect:int (buffer_get data (pos + 1))
223
+ pos = pos + 2
224
+
225
+ def j 0
226
+ while (j < numComponents) {
227
+ def comp:JPEGComponent (at components j)
228
+ if (comp.id == compId) {
229
+ comp.dcTableId = (bit_shr tableSelect 4)
230
+ comp.acTableId = (bit_and tableSelect 15)
231
+ push scanComponents j
232
+ }
233
+ j = j + 1
234
+ }
235
+
236
+ i = i + 1
237
+ }
238
+
239
+ scanSs = (buffer_get data pos)
240
+ scanSe = (buffer_get data (pos + 1))
241
+ def approx:int (buffer_get data (pos + 2))
242
+ scanAh = (bit_shr approx 4)
243
+ scanAl = (bit_and approx 15)
244
+ pos = pos + 3
245
+
246
+ def scanType:string "data"
247
+ if ((scanSs == 0) && (scanSe == 0)) {
248
+ if (scanAh == 0) {
249
+ scanType = "DC first"
250
+ } {
251
+ scanType = "DC refine"
252
+ }
253
+ } {
254
+ if (scanAh == 0) {
255
+ scanType = "AC first"
256
+ } {
257
+ scanType = "AC refine"
258
+ }
259
+ }
260
+
261
+ ; Print scan details with component info
262
+ def compList:string ""
263
+ def si 0
264
+ while (si < (array_length scanComponents)) {
265
+ if (si > 0) { compList = compList + "," }
266
+ compList = compList + (to_string (at scanComponents si))
267
+ si = si + 1
268
+ }
269
+ if (quiet == false) {
270
+ print (" Scan: comps=[" + compList + "] Ss=" + (to_string scanSs) + " Se=" + (to_string scanSe) + " Ah=" + (to_string scanAh) + " Al=" + (to_string scanAl) + " (" + scanType + ")")
271
+ }
272
+
273
+ ; Find scan data end
274
+ def scanStart:int pos
275
+ def searchPos:int pos
276
+ while (searchPos < (dataLen - 1)) {
277
+ def b:int (buffer_get data searchPos)
278
+ if (b == 255) {
279
+ def nextB:int (buffer_get data (searchPos + 1))
280
+ if ((nextB != 0) && (nextB != 255)) {
281
+ if ((nextB >= 208) && (nextB <= 215)) {
282
+ searchPos = searchPos + 2
283
+ continue
284
+ }
285
+ break
286
+ }
287
+ }
288
+ searchPos = searchPos + 1
289
+ }
290
+ def scanLen:int (searchPos - scanStart)
291
+
292
+ def reader (new BitReader())
293
+ reader.init(data scanStart scanLen)
294
+
295
+ eobrun = 0
296
+
297
+ ; Reset DC predictors for DC-first scans
298
+ if ((scanSs == 0) && (scanAh == 0)) {
299
+ def c 0
300
+ while (c < numComponents) {
301
+ def comp:JPEGComponent (at components c)
302
+ comp.prevDC = 0
303
+ c = c + 1
304
+ }
305
+ }
306
+
307
+ if (isProgressive) {
308
+ this.decodeProgressiveScan(reader scanComponents)
309
+ } {
310
+ this.decodeBaselineScan(reader scanComponents)
311
+ }
312
+
313
+ return searchPos
314
+ }
315
+
316
+ fn decodeProgressiveScan:void (reader:BitReader scanComps:[int]) {
317
+ def numScanComps:int (array_length scanComps)
318
+
319
+ def isDCFirst:boolean ((scanSs == 0) && (scanSe == 0) && (scanAh == 0))
320
+ def isDCRefine:boolean ((scanSs == 0) && (scanSe == 0) && (scanAh > 0))
321
+ def isACFirst:boolean ((scanSs > 0) && (scanAh == 0))
322
+ def isACRefine:boolean ((scanSs > 0) && (scanAh > 0))
323
+
324
+ if (numScanComps > 1) {
325
+ this.decodeInterleavedDC(reader scanComps isDCFirst isDCRefine)
326
+ } {
327
+ def compIdx:int (at scanComps 0)
328
+ if (isDCFirst) {
329
+ this.decodeDCFirst(reader compIdx)
330
+ }
331
+ if (isDCRefine) {
332
+ this.decodeDCRefine(reader compIdx)
333
+ }
334
+ if (isACFirst) {
335
+ this.decodeACFirst(reader compIdx)
336
+ }
337
+ if (isACRefine) {
338
+ this.decodeACRefine(reader compIdx)
339
+ }
340
+ }
341
+ }
342
+
343
+ fn decodeInterleavedDC:void (reader:BitReader scanComps:[int] isDCFirst:boolean isDCRefine:boolean) {
344
+ def mcuY 0
345
+ while (mcuY < mcusPerCol) {
346
+ def mcuX 0
347
+ while (mcuX < mcusPerRow) {
348
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
349
+
350
+ def sc 0
351
+ def numScanComps:int (array_length scanComps)
352
+ while (sc < numScanComps) {
353
+ def compIdx:int (at scanComps sc)
354
+ def comp:JPEGComponent (at components compIdx)
355
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
356
+
357
+ def bv 0
358
+ while (bv < comp.vSamp) {
359
+ def bh 0
360
+ while (bh < comp.hSamp) {
361
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
362
+
363
+ if (isDCFirst) {
364
+ def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
365
+ def dcCategory:int (dcTable.decode(reader))
366
+ def dcDiff:int (reader.receiveExtend(dcCategory))
367
+ def dcValue:int (comp.prevDC + dcDiff)
368
+ comp.prevDC = dcValue
369
+ buf.setVal(blockIdx 0 (bit_shl dcValue scanAl))
370
+ }
371
+ if (isDCRefine) {
372
+ def bit:int (reader.readBit())
373
+ def oldVal:int (buf.get(blockIdx 0))
374
+ buf.setVal(blockIdx 0 (bit_or oldVal (bit_shl bit scanAl)))
375
+ }
376
+
377
+ bh = bh + 1
378
+ }
379
+ bv = bv + 1
380
+ }
381
+
382
+ sc = sc + 1
383
+ }
384
+
385
+ mcuX = mcuX + 1
386
+ }
387
+ mcuY = mcuY + 1
388
+ }
389
+ }
390
+
391
+ fn decodeDCFirst:void (reader:BitReader compIdx:int) {
392
+ def comp:JPEGComponent (at components compIdx)
393
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
394
+
395
+ def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
396
+
397
+ ; Non-interleaved: iterate by MCU position to get correct block order
398
+ def mcuY 0
399
+ while (mcuY < mcusPerCol) {
400
+ def mcuX 0
401
+ while (mcuX < mcusPerRow) {
402
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
403
+
404
+ def bv 0
405
+ while (bv < comp.vSamp) {
406
+ def bh 0
407
+ while (bh < comp.hSamp) {
408
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
409
+
410
+ def dcCategory:int (dcTable.decode(reader))
411
+ def dcDiff:int (reader.receiveExtend(dcCategory))
412
+ def dcValue:int (comp.prevDC + dcDiff)
413
+ comp.prevDC = dcValue
414
+
415
+ buf.setVal(blockIdx 0 (bit_shl dcValue scanAl))
416
+
417
+ bh = bh + 1
418
+ }
419
+ bv = bv + 1
420
+ }
421
+
422
+ mcuX = mcuX + 1
423
+ }
424
+ mcuY = mcuY + 1
425
+ }
426
+ }
427
+
428
+ fn decodeDCRefine:void (reader:BitReader compIdx:int) {
429
+ def comp:JPEGComponent (at components compIdx)
430
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
431
+
432
+ ; Non-interleaved: iterate by MCU position
433
+ def mcuY 0
434
+ while (mcuY < mcusPerCol) {
435
+ def mcuX 0
436
+ while (mcuX < mcusPerRow) {
437
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
438
+
439
+ def bv 0
440
+ while (bv < comp.vSamp) {
441
+ def bh 0
442
+ while (bh < comp.hSamp) {
443
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
444
+
445
+ def bit:int (reader.readBit())
446
+ def oldVal:int (buf.get(blockIdx 0))
447
+ buf.setVal(blockIdx 0 (bit_or oldVal (bit_shl bit scanAl)))
448
+
449
+ bh = bh + 1
450
+ }
451
+ bv = bv + 1
452
+ }
453
+
454
+ mcuX = mcuX + 1
455
+ }
456
+ mcuY = mcuY + 1
457
+ }
458
+ }
459
+
460
+ fn decodeACFirst:void (reader:BitReader compIdx:int) {
461
+ def comp:JPEGComponent (at components compIdx)
462
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
463
+ def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
464
+
465
+ ; Non-interleaved: iterate by MCU position
466
+ def mcuY 0
467
+ while (mcuY < mcusPerCol) {
468
+ def mcuX 0
469
+ while (mcuX < mcusPerRow) {
470
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
471
+
472
+ def bv 0
473
+ while (bv < comp.vSamp) {
474
+ def bh 0
475
+ while (bh < comp.hSamp) {
476
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
477
+
478
+ if (eobrun > 0) {
479
+ eobrun = eobrun - 1
480
+ } {
481
+ def k:int scanSs
482
+
483
+ while (k <= scanSe) {
484
+ def symbol:int (acTable.decode(reader))
485
+ def run:int (bit_shr symbol 4)
486
+ def size:int (bit_and symbol 15)
487
+
488
+ if (size == 0) {
489
+ if (run == 15) {
490
+ k = k + 16
491
+ } {
492
+ if (run > 0) {
493
+ eobrun = (bit_shl 1 run)
494
+ eobrun = eobrun + (reader.readBits(run))
495
+ } {
496
+ eobrun = 1
497
+ }
498
+ eobrun = eobrun - 1
499
+ k = 64
500
+ }
501
+ } {
502
+ k = k + run
503
+
504
+ if (k <= scanSe) {
505
+ def acValue:int (reader.receiveExtend(size))
506
+ buf.setVal(blockIdx k (bit_shl acValue scanAl))
507
+ k = k + 1
508
+ }
509
+ }
510
+ }
511
+ }
512
+
513
+ bh = bh + 1
514
+ }
515
+ bv = bv + 1
516
+ }
517
+
518
+ mcuX = mcuX + 1
519
+ }
520
+ mcuY = mcuY + 1
521
+ }
522
+ }
523
+
524
+ fn decodeACRefine:void (reader:BitReader compIdx:int) {
525
+ def comp:JPEGComponent (at components compIdx)
526
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
527
+ def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
528
+
529
+ ; Non-interleaved: iterate by MCU position
530
+ def mcuY 0
531
+ while (mcuY < mcusPerCol) {
532
+ def mcuX 0
533
+ while (mcuX < mcusPerRow) {
534
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
535
+
536
+ def bv 0
537
+ while (bv < comp.vSamp) {
538
+ def bh 0
539
+ while (bh < comp.hSamp) {
540
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
541
+
542
+ this.decodeACRefineBlock(reader buf blockIdx acTable)
543
+
544
+ bh = bh + 1
545
+ }
546
+ bv = bv + 1
547
+ }
548
+
549
+ mcuX = mcuX + 1
550
+ }
551
+ mcuY = mcuY + 1
552
+ }
553
+ }
554
+
555
+ fn decodeACRefineBlock:void (reader:BitReader buf:CoeffBuffer blockIdx:int acTable:HuffmanTable) {
556
+ def k:int scanSs
557
+
558
+ if (eobrun > 0) {
559
+ while (k <= scanSe) {
560
+ def oldVal:int (buf.get(blockIdx k))
561
+ if (oldVal != 0) {
562
+ def bit:int (reader.readBit())
563
+ if (bit != 0) {
564
+ if (oldVal > 0) {
565
+ buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
566
+ } {
567
+ buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
568
+ }
569
+ }
570
+ }
571
+ k = k + 1
572
+ }
573
+ eobrun = eobrun - 1
574
+ return
575
+ }
576
+
577
+ while (k <= scanSe) {
578
+ def symbol:int (acTable.decode(reader))
579
+ def run:int (bit_shr symbol 4)
580
+ def size:int (bit_and symbol 15)
581
+
582
+ if (size == 0) {
583
+ if (run == 15) {
584
+ def zerosToSkip:int 16
585
+ while ((zerosToSkip > 0) && (k <= scanSe)) {
586
+ def oldVal:int (buf.get(blockIdx k))
587
+ if (oldVal != 0) {
588
+ def bit:int (reader.readBit())
589
+ if (bit != 0) {
590
+ if (oldVal > 0) {
591
+ buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
592
+ } {
593
+ buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
594
+ }
595
+ }
596
+ } {
597
+ zerosToSkip = zerosToSkip - 1
598
+ }
599
+ k = k + 1
600
+ }
601
+ } {
602
+ if (run > 0) {
603
+ eobrun = (bit_shl 1 run)
604
+ eobrun = eobrun + (reader.readBits(run))
605
+ } {
606
+ eobrun = 1
607
+ }
608
+ while (k <= scanSe) {
609
+ def oldVal:int (buf.get(blockIdx k))
610
+ if (oldVal != 0) {
611
+ def bit:int (reader.readBit())
612
+ if (bit != 0) {
613
+ if (oldVal > 0) {
614
+ buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
615
+ } {
616
+ buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
617
+ }
618
+ }
619
+ }
620
+ k = k + 1
621
+ }
622
+ eobrun = eobrun - 1
623
+ }
624
+ } {
625
+ ; size == 1: new non-zero coefficient after 'run' zeros
626
+ ; First read the sign bit for the new coefficient
627
+ def signBit:int (reader.readBit())
628
+ def newCoeff:int (bit_shl 1 scanAl)
629
+ if (signBit == 0) {
630
+ newCoeff = (0 - newCoeff)
631
+ }
632
+
633
+ def zerosToSkip:int run
634
+ while (k <= scanSe) {
635
+ def oldVal:int (buf.get(blockIdx k))
636
+ if (oldVal != 0) {
637
+ ; Refine existing non-zero coefficient
638
+ def bit:int (reader.readBit())
639
+ if (bit != 0) {
640
+ if (oldVal > 0) {
641
+ buf.setVal(blockIdx k (bit_or oldVal (bit_shl 1 scanAl)))
642
+ } {
643
+ buf.setVal(blockIdx k (oldVal - (bit_shl 1 scanAl)))
644
+ }
645
+ }
646
+ } {
647
+ ; Zero position
648
+ if (zerosToSkip > 0) {
649
+ zerosToSkip = zerosToSkip - 1
650
+ } {
651
+ ; Found the position for new coefficient
652
+ buf.setVal(blockIdx k newCoeff)
653
+ k = k + 1
654
+ break
655
+ }
656
+ }
657
+ k = k + 1
658
+ }
659
+ }
660
+ }
661
+ }
662
+
663
+ fn decodeBaselineScan:void (reader:BitReader scanComps:[int]) {
664
+ def mcuY 0
665
+ while (mcuY < mcusPerCol) {
666
+ def mcuX 0
667
+ while (mcuX < mcusPerRow) {
668
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
669
+
670
+ def sc 0
671
+ def numScanComps:int (array_length scanComps)
672
+ while (sc < numScanComps) {
673
+ def compIdx:int (at scanComps sc)
674
+ def comp:JPEGComponent (at components compIdx)
675
+ def quantTable:QuantizationTable (at quantTables comp.quantTableId)
676
+ def buf:CoeffBuffer (at coeffBuffers compIdx)
677
+
678
+ def bv 0
679
+ while (bv < comp.vSamp) {
680
+ def bh 0
681
+ while (bh < comp.hSamp) {
682
+ def blockIdx:int (mcuIdx * comp.hSamp * comp.vSamp + bv * comp.hSamp + bh)
683
+
684
+ ; Decode DC
685
+ def dcTable:HuffmanTable (huffman.getDCTable(comp.dcTableId))
686
+ def dcCategory:int (dcTable.decode(reader))
687
+ def dcDiff:int (reader.receiveExtend(dcCategory))
688
+ def dcValue:int (comp.prevDC + dcDiff)
689
+ comp.prevDC = dcValue
690
+
691
+ def dcQuant:int (at quantTable.values 0)
692
+ buf.setVal(blockIdx 0 (dcValue * dcQuant))
693
+
694
+ ; Decode AC
695
+ def acTable:HuffmanTable (huffman.getACTable(comp.acTableId))
696
+ def k 1
697
+ while (k < 64) {
698
+ def acSymbol:int (acTable.decode(reader))
699
+
700
+ if (acSymbol == 0) {
701
+ k = 64
702
+ } {
703
+ def run:int (bit_shr acSymbol 4)
704
+ def size:int (bit_and acSymbol 15)
705
+
706
+ if (acSymbol == 240) {
707
+ k = k + 16
708
+ } {
709
+ k = k + run
710
+ if (k < 64) {
711
+ def acValue:int (reader.receiveExtend(size))
712
+ def acQuant:int (at quantTable.values k)
713
+ buf.setVal(blockIdx k (acValue * acQuant))
714
+ k = k + 1
715
+ }
716
+ }
717
+ }
718
+ }
719
+
720
+ bh = bh + 1
721
+ }
722
+ bv = bv + 1
723
+ }
724
+
725
+ sc = sc + 1
726
+ }
727
+
728
+ mcuX = mcuX + 1
729
+ }
730
+ mcuY = mcuY + 1
731
+ }
732
+ }
733
+
734
+ fn parseMarkers:boolean () {
735
+ def pos 0
736
+
737
+ if (dataLen < 2) {
738
+ if (quiet == false) {
739
+ print "Error: File too small"
740
+ }
741
+ return false
742
+ }
743
+
744
+ def m1:int (buffer_get data 0)
745
+ def m2:int (buffer_get data 1)
746
+ if ((m1 != 255) || (m2 != 216)) {
747
+ if (quiet == false) {
748
+ print "Error: Not a JPEG file"
749
+ }
750
+ return false
751
+ }
752
+
753
+ pos = 2
754
+ if (quiet == false) {
755
+ print "Parsing JPEG markers..."
756
+ }
757
+
758
+ while (pos < (dataLen - 1)) {
759
+ def marker1:int (buffer_get data pos)
760
+ if (marker1 != 255) {
761
+ pos = pos + 1
762
+ continue
763
+ }
764
+
765
+ def marker2:int (buffer_get data (pos + 1))
766
+
767
+ if (marker2 == 255) {
768
+ pos = pos + 1
769
+ continue
770
+ }
771
+
772
+ if (marker2 == 0) {
773
+ pos = pos + 2
774
+ continue
775
+ }
776
+
777
+ if (marker2 == 216) {
778
+ pos = pos + 2
779
+ continue
780
+ }
781
+ if (marker2 == 217) {
782
+ if (quiet == false) {
783
+ print " End of Image"
784
+ }
785
+ return true
786
+ }
787
+ if ((marker2 >= 208) && (marker2 <= 215)) {
788
+ pos = pos + 2
789
+ continue
790
+ }
791
+
792
+ if ((pos + 4) > dataLen) {
793
+ return true
794
+ }
795
+ def markerLen:int (this.readUint16BE(pos + 2))
796
+ def dataStart:int (pos + 4)
797
+ def markerDataLen:int (markerLen - 2)
798
+
799
+ if (marker2 == 192) {
800
+ if (quiet == false) {
801
+ print " SOF0 (Baseline DCT)"
802
+ }
803
+ this.parseSOF(dataStart markerDataLen 0)
804
+ }
805
+ if (marker2 == 193) {
806
+ if (quiet == false) {
807
+ print " SOF1 (Extended Sequential)"
808
+ }
809
+ this.parseSOF(dataStart markerDataLen 1)
810
+ }
811
+ if (marker2 == 194) {
812
+ if (quiet == false) {
813
+ print " SOF2 (Progressive DCT)"
814
+ }
815
+ this.parseSOF(dataStart markerDataLen 2)
816
+ }
817
+ if (marker2 == 196) {
818
+ if (quiet == false) {
819
+ print " DHT (Huffman Tables)"
820
+ }
821
+ huffman.parseDHT(data dataStart markerDataLen)
822
+ }
823
+ if (marker2 == 219) {
824
+ if (quiet == false) {
825
+ print " DQT (Quantization Tables)"
826
+ }
827
+ this.parseDQT(dataStart markerDataLen)
828
+ }
829
+ if (marker2 == 218) {
830
+ if (quiet == false) {
831
+ print " SOS (Start of Scan)"
832
+ }
833
+ def nextPos:int (this.parseSOS(dataStart markerDataLen))
834
+ pos = nextPos
835
+ continue
836
+ }
837
+ if (marker2 == 224) {
838
+ if (quiet == false) {
839
+ print " APP0 (JFIF)"
840
+ }
841
+ }
842
+ if (marker2 == 225) {
843
+ if (quiet == false) {
844
+ print " APP1 (EXIF)"
845
+ }
846
+ }
847
+
848
+ pos = pos + 2 + markerLen
849
+ }
850
+
851
+ return true
852
+ }
853
+
854
+ fn dequantizeCoefficients:void () {
855
+ def c 0
856
+ while (c < numComponents) {
857
+ def comp:JPEGComponent (at components c)
858
+ def quantTable:QuantizationTable (at quantTables comp.quantTableId)
859
+ def buf:CoeffBuffer (at coeffBuffers c)
860
+
861
+ def blockIdx 0
862
+ while (blockIdx < buf.numBlocks) {
863
+ def k 0
864
+ while (k < 64) {
865
+ def oldVal:int (buf.get(blockIdx k))
866
+ def quantVal:int (at quantTable.values k)
867
+ buf.setVal(blockIdx k (oldVal * quantVal))
868
+ k = k + 1
869
+ }
870
+
871
+ blockIdx = blockIdx + 1
872
+ }
873
+
874
+ c = c + 1
875
+ }
876
+ }
877
+
878
+ fn buildImage:ImageBuffer () {
879
+ if (isProgressive) {
880
+ if (quiet == false) {
881
+ print "Dequantizing coefficients..."
882
+ }
883
+ this.dequantizeCoefficients()
884
+ }
885
+
886
+ def img (new ImageBuffer())
887
+ img.init(width height)
888
+
889
+ if (quiet == false) {
890
+ print "Building image..."
891
+ }
892
+
893
+ def mcuY 0
894
+ while (mcuY < mcusPerCol) {
895
+ def mcuX 0
896
+ while (mcuX < mcusPerRow) {
897
+ def mcuIdx:int ((mcuY * mcusPerRow) + mcuX)
898
+ def baseX:int (mcuX * mcuWidth)
899
+ def baseY:int (mcuY * mcuHeight)
900
+
901
+ def comp0:JPEGComponent (at components 0)
902
+ def yBuf:CoeffBuffer (at coeffBuffers 0)
903
+
904
+ ; IDCT for Y blocks
905
+ def yBlocksData:[int]
906
+ def bv 0
907
+ while (bv < comp0.vSamp) {
908
+ def bh 0
909
+ while (bh < comp0.hSamp) {
910
+ def blockIdx:int (mcuIdx * comp0.hSamp * comp0.vSamp + bv * comp0.hSamp + bh)
911
+
912
+ def blockCoeffs:int_buffer (int_buffer_alloc 64)
913
+ def k 0
914
+ while (k < 64) {
915
+ int_buffer_set blockCoeffs k (yBuf.get(blockIdx k))
916
+ k = k + 1
917
+ }
918
+
919
+ def tempBlock:int_buffer (idct.dezigzag(blockCoeffs))
920
+
921
+ def blockPixels:int_buffer (int_buffer_alloc 64)
922
+ int_buffer_fill blockPixels 0 0 64
923
+ idct.transform(tempBlock blockPixels)
924
+
925
+ k = 0
926
+ while (k < 64) {
927
+ push yBlocksData (int_buffer_get blockPixels k)
928
+ k = k + 1
929
+ }
930
+
931
+ bh = bh + 1
932
+ }
933
+ bv = bv + 1
934
+ }
935
+
936
+ ; Cb/Cr blocks
937
+ def cbBlock:[int]
938
+ def crBlock:[int]
939
+
940
+ if (numComponents >= 3) {
941
+ ; Cb
942
+ def cbBuf:CoeffBuffer (at coeffBuffers 1)
943
+ def cbBlockIdx:int (mcuIdx)
944
+
945
+ def blockCoeffs:int_buffer (int_buffer_alloc 64)
946
+ def k 0
947
+ while (k < 64) {
948
+ int_buffer_set blockCoeffs k (cbBuf.get(cbBlockIdx k))
949
+ k = k + 1
950
+ }
951
+
952
+ def tempBlock:int_buffer (idct.dezigzag(blockCoeffs))
953
+ def cbPixels:int_buffer (int_buffer_alloc 64)
954
+ int_buffer_fill cbPixels 0 0 64
955
+ idct.transform(tempBlock cbPixels)
956
+ k = 0
957
+ while (k < 64) {
958
+ push cbBlock (int_buffer_get cbPixels k)
959
+ k = k + 1
960
+ }
961
+
962
+ ; Cr
963
+ def crBuf:CoeffBuffer (at coeffBuffers 2)
964
+ def crBlockIdx:int (mcuIdx)
965
+
966
+ def crCoeffs:int_buffer (int_buffer_alloc 64)
967
+ k = 0
968
+ while (k < 64) {
969
+ int_buffer_set crCoeffs k (crBuf.get(crBlockIdx k))
970
+ k = k + 1
971
+ }
972
+
973
+ def crTempBlock:int_buffer (idct.dezigzag(crCoeffs))
974
+ def crPixels:int_buffer (int_buffer_alloc 64)
975
+ int_buffer_fill crPixels 0 0 64
976
+ idct.transform(crTempBlock crPixels)
977
+ k = 0
978
+ while (k < 64) {
979
+ push crBlock (int_buffer_get crPixels k)
980
+ k = k + 1
981
+ }
982
+ }
983
+
984
+ this.writeMCU(img baseX baseY yBlocksData cbBlock crBlock)
985
+
986
+ mcuX = mcuX + 1
987
+ }
988
+ mcuY = mcuY + 1
989
+ }
990
+
991
+ return img
992
+ }
993
+
994
+ fn writeMCU:void (img:ImageBuffer baseX:int baseY:int yBlocksData:[int] cbBlock:[int] crBlock:[int]) {
995
+ def comp0:JPEGComponent (at components 0)
996
+
997
+ if ((maxHSamp == 1) && (maxVSamp == 1)) {
998
+ def py 0
999
+ while (py < 8) {
1000
+ def px 0
1001
+ while (px < 8) {
1002
+ def imgX:int (baseX + px)
1003
+ def imgY:int (baseY + py)
1004
+
1005
+ if ((imgX < width) && (imgY < height)) {
1006
+ def idx:int ((py * 8) + px)
1007
+ def y:int (at yBlocksData idx)
1008
+
1009
+ def cb:int 128
1010
+ def cr:int 128
1011
+ if (numComponents >= 3) {
1012
+ cb = (at cbBlock idx)
1013
+ cr = (at crBlock idx)
1014
+ }
1015
+
1016
+ def r:int (y + (bit_shr (359 * (cr - 128)) 8))
1017
+ def g:int (y - (bit_shr (88 * (cb - 128)) 8) - (bit_shr (183 * (cr - 128)) 8))
1018
+ def b:int (y + (bit_shr (454 * (cb - 128)) 8))
1019
+
1020
+ if (r < 0) { r = 0 }
1021
+ if (r > 255) { r = 255 }
1022
+ if (g < 0) { g = 0 }
1023
+ if (g > 255) { g = 255 }
1024
+ if (b < 0) { b = 0 }
1025
+ if (b > 255) { b = 255 }
1026
+
1027
+ img.setPixelRGB(imgX imgY r g b)
1028
+ }
1029
+ px = px + 1
1030
+ }
1031
+ py = py + 1
1032
+ }
1033
+ return
1034
+ }
1035
+
1036
+ if ((maxHSamp == 2) && (maxVSamp == 2)) {
1037
+ def blockIdx 0
1038
+ def blockY 0
1039
+ while (blockY < 2) {
1040
+ def blockX 0
1041
+ while (blockX < 2) {
1042
+ def yBlockOffset:int (blockIdx * 64)
1043
+
1044
+ def py 0
1045
+ while (py < 8) {
1046
+ def px 0
1047
+ while (px < 8) {
1048
+ def imgX:int (baseX + (blockX * 8) + px)
1049
+ def imgY:int (baseY + (blockY * 8) + py)
1050
+
1051
+ if ((imgX < width) && (imgY < height)) {
1052
+ def yIdx:int (yBlockOffset + (py * 8) + px)
1053
+ def y:int (at yBlocksData yIdx)
1054
+
1055
+ def chromaX:int ((blockX * 4) + (bit_shr px 1))
1056
+ def chromaY:int ((blockY * 4) + (bit_shr py 1))
1057
+ def chromaIdx:int ((chromaY * 8) + chromaX)
1058
+
1059
+ def cb:int 128
1060
+ def cr:int 128
1061
+ if (numComponents >= 3) {
1062
+ cb = (at cbBlock chromaIdx)
1063
+ cr = (at crBlock chromaIdx)
1064
+ }
1065
+
1066
+ def r:int (y + (bit_shr (359 * (cr - 128)) 8))
1067
+ def g:int (y - (bit_shr (88 * (cb - 128)) 8) - (bit_shr (183 * (cr - 128)) 8))
1068
+ def b:int (y + (bit_shr (454 * (cb - 128)) 8))
1069
+
1070
+ if (r < 0) { r = 0 }
1071
+ if (r > 255) { r = 255 }
1072
+ if (g < 0) { g = 0 }
1073
+ if (g > 255) { g = 255 }
1074
+ if (b < 0) { b = 0 }
1075
+ if (b > 255) { b = 255 }
1076
+
1077
+ img.setPixelRGB(imgX imgY r g b)
1078
+ }
1079
+ px = px + 1
1080
+ }
1081
+ py = py + 1
1082
+ }
1083
+
1084
+ blockIdx = blockIdx + 1
1085
+ blockX = blockX + 1
1086
+ }
1087
+ blockY = blockY + 1
1088
+ }
1089
+ return
1090
+ }
1091
+
1092
+ ; Fallback grayscale
1093
+ def yLen:int (array_length yBlocksData)
1094
+ if (yLen > 0) {
1095
+ def py 0
1096
+ while (py < 8) {
1097
+ def px 0
1098
+ while (px < 8) {
1099
+ def imgX:int (baseX + px)
1100
+ def imgY:int (baseY + py)
1101
+ if ((imgX < width) && (imgY < height)) {
1102
+ def y:int (at yBlocksData ((py * 8) + px))
1103
+ img.setPixelRGB(imgX imgY y y y)
1104
+ }
1105
+ px = px + 1
1106
+ }
1107
+ py = py + 1
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ fn decode:ImageBuffer (dirPath:string fileName:string) {
1113
+ def bytes:buffer (buffer_read_file dirPath fileName)
1114
+ if (quiet == false) {
1115
+ print ("Decoding JPEG: " + fileName + " (" + (to_string (buffer_length bytes)) + " bytes)")
1116
+ }
1117
+ return (this.decodeBytes(bytes))
1118
+ }
1119
+
1120
+ ; The same decode, from bytes already in hand. `EVGImageDecode` sniffs the
1121
+ ; markers and dispatches, and it has bytes, not a path — without this it
1122
+ ; could reach the baseline decoder and not this one, so a progressive JPEG
1123
+ ; in a document was "some of the photos are simply missing".
1124
+ fn decodeBytes:ImageBuffer (bytes:buffer) {
1125
+ data = bytes
1126
+ dataLen = (buffer_length data)
1127
+
1128
+ def ok:boolean (this.parseMarkers())
1129
+ if (ok == false) {
1130
+ if (quiet == false) {
1131
+ print "Error parsing JPEG markers"
1132
+ }
1133
+ def errImg (new ImageBuffer())
1134
+ errImg.init(1 1)
1135
+ return errImg
1136
+ }
1137
+
1138
+ if ((width == 0) || (height == 0)) {
1139
+ if (quiet == false) {
1140
+ print "Error: Invalid image dimensions"
1141
+ }
1142
+ def errImg (new ImageBuffer())
1143
+ errImg.init(1 1)
1144
+ return errImg
1145
+ }
1146
+
1147
+ def img:ImageBuffer (this.buildImage())
1148
+
1149
+ if (quiet == false) {
1150
+ print "Decode complete!"
1151
+ }
1152
+ return img
1153
+ }
1154
+ }