ranger-compiler 3.5.1 → 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 +1064 -20
  2. package/LICENSE +3 -1
  3. package/README.md +123 -28
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79923 -56921
  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,468 @@
1
+ //! The CSS properties EVGr reads, from a declaration block
2
+ //! (`display:flex;width:100px`) into the fields of a node.
3
+
4
+ use ranger::prelude::*;
5
+
6
+ use crate::EvgrNode;
7
+
8
+ /// A length: `auto`, pixels, a percentage of the containing block, or a
9
+ /// `calc()` of the two (`v` percent plus `px` pixels).
10
+ #[derive(Clone, Copy)]
11
+ pub struct Len {
12
+ /// 0 auto, 1 px, 2 percent, 3 calc
13
+ pub kind: int,
14
+ pub v: double,
15
+ pub px: double,
16
+ }
17
+
18
+ impl Len {
19
+ pub fn auto() -> Len {
20
+ Len { kind: 0, v: 0.0, px: 0.0 }
21
+ }
22
+
23
+ pub fn px(v: double) -> Len {
24
+ Len { kind: 1, v, px: 0.0 }
25
+ }
26
+
27
+ /// Pixels against `base`; -1.0 when auto, or a percentage of an
28
+ /// indefinite base.
29
+ pub fn resolve(&self, base: double) -> double {
30
+ if self.kind == 1 {
31
+ return self.v;
32
+ }
33
+ if self.kind == 2 && base >= 0.0 {
34
+ return base * self.v / 100.0;
35
+ }
36
+ if self.kind == 3 {
37
+ if self.v == 0.0 {
38
+ return self.px;
39
+ }
40
+ if base >= 0.0 {
41
+ return base * self.v / 100.0 + self.px;
42
+ }
43
+ }
44
+ -1.0
45
+ }
46
+
47
+ pub fn is_auto(&self) -> bool {
48
+ self.kind == 0
49
+ }
50
+ }
51
+
52
+ // the alignment keywords, as numbers
53
+ pub const START: int = 0;
54
+ pub const END: int = 1;
55
+ pub const CENTER: int = 2;
56
+ pub const STRETCH: int = 3;
57
+ pub const BETWEEN: int = 4;
58
+ pub const AROUND: int = 5;
59
+ pub const EVENLY: int = 6;
60
+ pub const BASELINE: int = 7;
61
+ /// `align-self: auto` / an `align-items` left at EVG's default
62
+ pub const UNSET: int = -1;
63
+
64
+ pub fn parse_len(v: &str) -> Len {
65
+ let t = v.trim();
66
+ if t == "auto" || t.is_empty() {
67
+ return Len::auto();
68
+ }
69
+ if t.starts_with("calc(") && t.ends_with(")") {
70
+ return parse_calc(&t[5..t.as_bytes().len() - 1]);
71
+ }
72
+ if let Some(n) = t.strip_suffix("px") {
73
+ return Len::px(number(n));
74
+ }
75
+ if let Some(p) = t.strip_suffix("%") {
76
+ return Len { kind: 2, v: number(p), px: 0.0 };
77
+ }
78
+ Len::px(number(t))
79
+ }
80
+
81
+ /// `calc(100% - 40px)`: a sum of percentages and pixels, the operators
82
+ /// between terms standing apart as CSS requires.
83
+ fn parse_calc(body: &str) -> Len {
84
+ let mut pct = 0.0;
85
+ let mut px = 0.0;
86
+ let mut sign = 1.0;
87
+ for tok in body.split_whitespace() {
88
+ if tok == "+" {
89
+ sign = 1.0;
90
+ continue;
91
+ }
92
+ if tok == "-" {
93
+ sign = -1.0;
94
+ continue;
95
+ }
96
+ let l = parse_len(tok);
97
+ if l.kind == 2 {
98
+ pct += sign * l.v;
99
+ } else {
100
+ px += sign * l.resolve(0.0);
101
+ }
102
+ sign = 1.0;
103
+ }
104
+ Len { kind: 3, v: pct, px }
105
+ }
106
+
107
+ pub fn number(v: &str) -> double {
108
+ v.trim().parse::<double>().unwrap_or(0.0)
109
+ }
110
+
111
+ pub fn align_of(v: &str) -> int {
112
+ let t = v.trim();
113
+ if t == "flex-start" || t == "start" || t == "normal" || t == "left" || t == "self-start" {
114
+ return START;
115
+ }
116
+ if t == "flex-end" || t == "end" || t == "right" || t == "self-end" {
117
+ return END;
118
+ }
119
+ if t == "center" {
120
+ return CENTER;
121
+ }
122
+ if t == "stretch" {
123
+ return STRETCH;
124
+ }
125
+ if t == "space-between" {
126
+ return BETWEEN;
127
+ }
128
+ if t == "space-around" {
129
+ return AROUND;
130
+ }
131
+ if t == "space-evenly" {
132
+ return EVENLY;
133
+ }
134
+ if t == "baseline" {
135
+ return BASELINE;
136
+ }
137
+ START
138
+ }
139
+
140
+ /// The values of a shorthand (`padding: 4px 8px`), as CSS spreads them over
141
+ /// top, right, bottom, left.
142
+ fn four_len(v: &str) -> Vec<Len> {
143
+ let parts: Vec<&str> = v.split_whitespace().collect();
144
+ let mut n: Vec<Len> = Vec::new();
145
+ for p in &parts {
146
+ n.push(parse_len(p));
147
+ }
148
+ let mut out: Vec<Len> = Vec::new();
149
+ if n.len() == 1 {
150
+ out.push(n[0]);
151
+ out.push(n[0]);
152
+ out.push(n[0]);
153
+ out.push(n[0]);
154
+ } else if n.len() == 2 {
155
+ out.push(n[0]);
156
+ out.push(n[1]);
157
+ out.push(n[0]);
158
+ out.push(n[1]);
159
+ } else if n.len() == 3 {
160
+ out.push(n[0]);
161
+ out.push(n[1]);
162
+ out.push(n[2]);
163
+ out.push(n[1]);
164
+ } else if n.len() >= 4 {
165
+ out.push(n[0]);
166
+ out.push(n[1]);
167
+ out.push(n[2]);
168
+ out.push(n[3]);
169
+ } else {
170
+ out.push(Len::px(0.0));
171
+ out.push(Len::px(0.0));
172
+ out.push(Len::px(0.0));
173
+ out.push(Len::px(0.0));
174
+ }
175
+ out
176
+ }
177
+
178
+ fn four(v: &str) -> Vec<double> {
179
+ let parts: Vec<&str> = v.split_whitespace().collect();
180
+ let mut n: Vec<double> = Vec::new();
181
+ for p in &parts {
182
+ n.push(parse_len(p).resolve(0.0).max(0.0));
183
+ }
184
+ let mut out: Vec<double> = Vec::new();
185
+ if n.len() == 1 {
186
+ out.push(n[0]);
187
+ out.push(n[0]);
188
+ out.push(n[0]);
189
+ out.push(n[0]);
190
+ } else if n.len() == 2 {
191
+ out.push(n[0]);
192
+ out.push(n[1]);
193
+ out.push(n[0]);
194
+ out.push(n[1]);
195
+ } else if n.len() == 3 {
196
+ out.push(n[0]);
197
+ out.push(n[1]);
198
+ out.push(n[2]);
199
+ out.push(n[1]);
200
+ } else if n.len() >= 4 {
201
+ out.push(n[0]);
202
+ out.push(n[1]);
203
+ out.push(n[2]);
204
+ out.push(n[3]);
205
+ } else {
206
+ out.push(0.0);
207
+ out.push(0.0);
208
+ out.push(0.0);
209
+ out.push(0.0);
210
+ }
211
+ out
212
+ }
213
+
214
+ /// Applies one declaration; answers false for a property EVGr does not lay
215
+ /// out (the caller counts those).
216
+ pub fn apply(n: &mut EvgrNode, name: &str, value: &str) -> bool {
217
+ let v = value.trim();
218
+ if name == "display" {
219
+ if v == "flex" || v == "inline-flex" {
220
+ n.display = 1;
221
+ } else if v == "none" {
222
+ n.display = 2;
223
+ } else if v == "grid" || v == "inline-grid" {
224
+ n.display = 3;
225
+ } else {
226
+ n.display = 0;
227
+ }
228
+ return true;
229
+ }
230
+ if name == "flex-direction" {
231
+ n.row = v == "row" || v == "row-reverse";
232
+ n.reverse = v == "row-reverse" || v == "column-reverse";
233
+ return true;
234
+ }
235
+ if name == "flex-wrap" {
236
+ n.wrap = v == "wrap" || v == "wrap-reverse";
237
+ return true;
238
+ }
239
+ if name == "width" {
240
+ n.width = parse_len(v);
241
+ return true;
242
+ }
243
+ if name == "height" {
244
+ n.height = parse_len(v);
245
+ return true;
246
+ }
247
+ if name == "min-width" {
248
+ n.min_w = parse_len(v);
249
+ return true;
250
+ }
251
+ if name == "max-width" {
252
+ n.max_w = parse_len(v);
253
+ return true;
254
+ }
255
+ if name == "min-height" {
256
+ n.min_h = parse_len(v);
257
+ return true;
258
+ }
259
+ if name == "max-height" {
260
+ n.max_h = parse_len(v);
261
+ return true;
262
+ }
263
+ // padding: a percentage is of the containing block's width, so the
264
+ // lengths are kept and resolved when the box is laid out
265
+ if name == "padding" {
266
+ let p = four_len(v);
267
+ n.pad_t_len = p[0];
268
+ n.pad_r_len = p[1];
269
+ n.pad_b_len = p[2];
270
+ n.pad_l_len = p[3];
271
+ n.resolve_pads(0.0);
272
+ return true;
273
+ }
274
+ if name == "padding-top" {
275
+ n.pad_t_len = parse_len(v);
276
+ n.resolve_pads(0.0);
277
+ return true;
278
+ }
279
+ if name == "padding-right" {
280
+ n.pad_r_len = parse_len(v);
281
+ n.resolve_pads(0.0);
282
+ return true;
283
+ }
284
+ if name == "padding-bottom" {
285
+ n.pad_b_len = parse_len(v);
286
+ n.resolve_pads(0.0);
287
+ return true;
288
+ }
289
+ if name == "padding-left" {
290
+ n.pad_l_len = parse_len(v);
291
+ n.resolve_pads(0.0);
292
+ return true;
293
+ }
294
+ if name == "aspect-ratio" {
295
+ let parts: Vec<&str> = v.split('/').collect();
296
+ let a = number(parts[0]);
297
+ let mut b = 1.0;
298
+ if parts.len() >= 2 {
299
+ b = number(parts[1]);
300
+ }
301
+ if a > 0.0 && b > 0.0 {
302
+ n.ratio = a / b;
303
+ }
304
+ return true;
305
+ }
306
+ if name == "margin" {
307
+ let m = four(v);
308
+ n.mar_t = m[0];
309
+ n.mar_r = m[1];
310
+ n.mar_b = m[2];
311
+ n.mar_l = m[3];
312
+ return true;
313
+ }
314
+ if name == "margin-top" {
315
+ n.mar_t = parse_len(v).resolve(0.0).max(0.0);
316
+ return true;
317
+ }
318
+ if name == "margin-right" {
319
+ n.mar_r = parse_len(v).resolve(0.0).max(0.0);
320
+ return true;
321
+ }
322
+ if name == "margin-bottom" {
323
+ n.mar_b = parse_len(v).resolve(0.0).max(0.0);
324
+ return true;
325
+ }
326
+ if name == "margin-left" {
327
+ n.mar_l = parse_len(v).resolve(0.0).max(0.0);
328
+ return true;
329
+ }
330
+ if name == "gap" {
331
+ let parts: Vec<&str> = v.split_whitespace().collect();
332
+ if parts.len() >= 2 {
333
+ n.row_gap = parse_len(parts[0]).resolve(0.0).max(0.0);
334
+ n.col_gap = parse_len(parts[1]).resolve(0.0).max(0.0);
335
+ } else {
336
+ n.row_gap = parse_len(v).resolve(0.0).max(0.0);
337
+ n.col_gap = n.row_gap;
338
+ }
339
+ return true;
340
+ }
341
+ if name == "row-gap" {
342
+ n.row_gap = parse_len(v).resolve(0.0).max(0.0);
343
+ return true;
344
+ }
345
+ if name == "column-gap" {
346
+ n.col_gap = parse_len(v).resolve(0.0).max(0.0);
347
+ return true;
348
+ }
349
+ if name == "flex-grow" {
350
+ n.grow = number(v);
351
+ return true;
352
+ }
353
+ if name == "flex-shrink" {
354
+ n.shrink = number(v);
355
+ return true;
356
+ }
357
+ if name == "flex-basis" {
358
+ n.basis = parse_len(v);
359
+ return true;
360
+ }
361
+ if name == "flex" {
362
+ // `flex: 1` is `1 1 0`, `auto` is `1 1 auto`, `none` is `0 0 auto`
363
+ if v == "none" {
364
+ n.grow = 0.0;
365
+ n.shrink = 0.0;
366
+ n.basis = Len::auto();
367
+ return true;
368
+ }
369
+ if v == "auto" {
370
+ n.grow = 1.0;
371
+ n.shrink = 1.0;
372
+ n.basis = Len::auto();
373
+ return true;
374
+ }
375
+ let parts: Vec<&str> = v.split_whitespace().collect();
376
+ n.grow = number(parts[0]);
377
+ n.shrink = 1.0;
378
+ n.basis = Len::px(0.0);
379
+ if parts.len() >= 2 {
380
+ n.shrink = number(parts[1]);
381
+ }
382
+ if parts.len() >= 3 {
383
+ n.basis = parse_len(parts[2]);
384
+ }
385
+ return true;
386
+ }
387
+ if name == "justify-content" {
388
+ n.justify = align_of(v);
389
+ return true;
390
+ }
391
+ if name == "align-items" {
392
+ n.align_items = align_of(v);
393
+ return true;
394
+ }
395
+ if name == "align-self" {
396
+ if v == "auto" {
397
+ n.align_self = UNSET;
398
+ } else {
399
+ n.align_self = align_of(v);
400
+ }
401
+ return true;
402
+ }
403
+ if name == "align-content" {
404
+ n.align_content = align_of(v);
405
+ return true;
406
+ }
407
+ if name == "position" {
408
+ n.absolute = v == "absolute" || v == "fixed";
409
+ return true;
410
+ }
411
+ if name == "top" {
412
+ n.top = parse_len(v);
413
+ return true;
414
+ }
415
+ if name == "right" {
416
+ n.right = parse_len(v);
417
+ return true;
418
+ }
419
+ if name == "bottom" {
420
+ n.bottom = parse_len(v);
421
+ return true;
422
+ }
423
+ if name == "left" {
424
+ n.left = parse_len(v);
425
+ return true;
426
+ }
427
+ if name == "font-size" {
428
+ n.font_size = parse_len(v).resolve(0.0);
429
+ return true;
430
+ }
431
+ if name == "grid-template-columns" {
432
+ n.grid_cols = v.to_string();
433
+ return true;
434
+ }
435
+ if name == "grid-template-rows" {
436
+ n.grid_rows = v.to_string();
437
+ return true;
438
+ }
439
+ if name == "grid-template-areas" {
440
+ n.grid_areas = v.to_string();
441
+ return true;
442
+ }
443
+ if name == "grid-auto-rows" {
444
+ n.grid_auto_rows = v.to_string();
445
+ return true;
446
+ }
447
+ if name == "grid-auto-flow" {
448
+ n.grid_dense = v.contains("dense");
449
+ return true;
450
+ }
451
+ if name == "grid-column" {
452
+ n.grid_column = v.to_string();
453
+ return true;
454
+ }
455
+ if name == "grid-row" {
456
+ n.grid_row = v.to_string();
457
+ return true;
458
+ }
459
+ if name == "grid-area" {
460
+ n.grid_area = v.to_string();
461
+ return true;
462
+ }
463
+ // no effect on boxes
464
+ if name == "background-color" || name == "background" || name == "color" || name == "overflow" || name == "box-sizing" || name == "font-family" {
465
+ return true;
466
+ }
467
+ false
468
+ }
@@ -0,0 +1,83 @@
1
+ //! Text: EVG's default measurer (the advance table of `EVGTextMeasurer`,
2
+ //! line height 1.15 em) and greedy wrapping at spaces.
3
+
4
+ use ranger::prelude::*;
5
+
6
+ /// Advances of the characters 32..126 in em, as `EVGTextMeasurer.advanceEm`.
7
+ pub fn advance_table() -> Vec<double> {
8
+ vec![
9
+ 0.27783, 0.27783, 0.35498, 0.55615, 0.55615, 0.88916, 0.66699, 0.19092,
10
+ 0.33301, 0.33301, 0.38916, 0.58398, 0.27783, 0.33301, 0.27783, 0.27783,
11
+ 0.55615, 0.55615, 0.55615, 0.55615, 0.55615, 0.55615, 0.55615, 0.55615,
12
+ 0.55615, 0.55615, 0.27783, 0.27783, 0.58398, 0.58398, 0.58398, 0.55615,
13
+ 1.01514, 0.66699, 0.66699, 0.72217, 0.72217, 0.66699, 0.61084, 0.77783,
14
+ 0.72217, 0.27783, 0.50000, 0.66699, 0.55615, 0.83301, 0.72217, 0.77783,
15
+ 0.66699, 0.77783, 0.72217, 0.66699, 0.61084, 0.72217, 0.66699, 0.94385,
16
+ 0.66699, 0.66699, 0.61084, 0.27783, 0.27783, 0.27783, 0.46924, 0.55615,
17
+ 0.33301, 0.55615, 0.55615, 0.50000, 0.55615, 0.55615, 0.27783, 0.55615,
18
+ 0.55615, 0.22217, 0.22217, 0.50000, 0.22217, 0.83301, 0.55615, 0.55615,
19
+ 0.55615, 0.55615, 0.33301, 0.50000, 0.27783, 0.55615, 0.50000, 0.72217,
20
+ 0.50000, 0.50000, 0.50000, 0.33398, 0.25977, 0.33398, 0.58398,
21
+ ]
22
+ }
23
+
24
+ pub fn line_height(font_size: double) -> double {
25
+ font_size * 1.15
26
+ }
27
+
28
+ pub fn measure(table: &Vec<double>, text: &str, font_size: double) -> double {
29
+ let mut w = 0.0;
30
+ for c in text.chars() {
31
+ let code = c as int;
32
+ if code >= 32 && code <= 126 {
33
+ w += table[(code - 32) as usize] * font_size;
34
+ } else {
35
+ w += 0.55 * font_size;
36
+ }
37
+ }
38
+ w
39
+ }
40
+
41
+ /// The widest word: the narrowest the text can be.
42
+ pub fn min_width(table: &Vec<double>, text: &str, font_size: double) -> double {
43
+ let mut best = 0.0;
44
+ for word in text.split_whitespace() {
45
+ let w = measure(table, word, font_size);
46
+ if w > best {
47
+ best = w;
48
+ }
49
+ }
50
+ best
51
+ }
52
+
53
+ /// Lines of `text` broken at spaces to fit `max_w` (a word wider than that
54
+ /// stands on its own line): how many, and the widest.
55
+ pub fn wrap(table: &Vec<double>, text: &str, font_size: double, max_w: double) -> (int, double) {
56
+ let space = measure(table, " ", font_size);
57
+ let mut lines = 0;
58
+ let mut widest = 0.0;
59
+ let mut cur = -1.0;
60
+ for word in text.split_whitespace() {
61
+ let w = measure(table, word, font_size);
62
+ if cur < 0.0 {
63
+ cur = w;
64
+ lines += 1;
65
+ } else if cur + space + w <= max_w + 0.001 {
66
+ cur = cur + space + w;
67
+ } else {
68
+ if cur > widest {
69
+ widest = cur;
70
+ }
71
+ cur = w;
72
+ lines += 1;
73
+ }
74
+ }
75
+ if cur > widest {
76
+ widest = cur;
77
+ }
78
+ if lines == 0 {
79
+ lines = 1;
80
+ widest = 0.0;
81
+ }
82
+ (lines, widest)
83
+ }
@@ -0,0 +1,171 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; BitReader.rgr - Bit-level stream reader for JPEG decoding
4
+ ; Handles reading individual bits and byte stuffing (FF00 → FF)
5
+
6
+ class BitReader {
7
+ def data:buffer (buffer_alloc 0)
8
+ def dataStart:int 0 ; Start position in buffer
9
+ def dataEnd:int 0 ; End position in buffer
10
+ def bytePos:int 0 ; Current byte position
11
+ def bitPos:int 0 ; Bits remaining in current byte (8 = full byte)
12
+ def currentByte:int 0 ; Current byte being read
13
+ def eof:boolean false
14
+
15
+ Constructor () {
16
+ }
17
+
18
+ fn init:void (buf:buffer startPos:int length:int) {
19
+ data = buf
20
+ dataStart = startPos
21
+ dataEnd = startPos + length
22
+ bytePos = startPos
23
+ bitPos = 0
24
+ currentByte = 0
25
+ eof = false
26
+ }
27
+
28
+ fn loadNextByte:void () {
29
+ ; Load next byte, handling FF00 byte stuffing and RST markers
30
+ if (bytePos >= dataEnd) {
31
+ eof = true
32
+ currentByte = 0
33
+ bitPos = 8
34
+ return
35
+ }
36
+
37
+ currentByte = (buffer_get data bytePos)
38
+ bytePos = bytePos + 1
39
+
40
+ ; Check for byte stuffing and markers
41
+ if (currentByte == 255) {
42
+ if (bytePos < dataEnd) {
43
+ def nextByte:int (buffer_get data bytePos)
44
+ if (nextByte == 0) {
45
+ ; FF00 = literal FF, skip the 00
46
+ bytePos = bytePos + 1
47
+ } {
48
+ ; RST markers (D0-D7 = 208-215) - skip them
49
+ ; These should only appear if DRI is set, but we skip them anyway
50
+ ; as they should not affect entropy data
51
+ if ((nextByte >= 208) && (nextByte <= 215)) {
52
+ ; Skip the RST marker
53
+ bytePos = bytePos + 1
54
+ ; Load the next actual byte
55
+ this.loadNextByte()
56
+ return
57
+ }
58
+ ; FF followed by FF is padding, skip
59
+ if (nextByte == 255) {
60
+ ; FF FF padding, skip
61
+ bytePos = bytePos + 1
62
+ this.loadNextByte()
63
+ return
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ bitPos = 8
70
+ }
71
+
72
+ fn readBit:int () {
73
+ ; Read single bit, MSB first
74
+ if (bitPos == 0) {
75
+ this.loadNextByte()
76
+ }
77
+
78
+ if eof {
79
+ return 0
80
+ }
81
+
82
+ bitPos = bitPos - 1
83
+ def bit:int (bit_and (bit_shr currentByte bitPos) 1)
84
+ return bit
85
+ }
86
+
87
+ fn readBits:int (count:int) {
88
+ ; Read multiple bits, MSB first
89
+ def result:int 0
90
+ def i:int 0
91
+ while (i < count) {
92
+ result = (bit_or (bit_shl result 1) (this.readBit()))
93
+ i = i + 1
94
+ }
95
+ return result
96
+ }
97
+
98
+ fn peekBits:int (count:int) {
99
+ ; Peek at bits without consuming them
100
+ ; Save state
101
+ def savedBytePos:int bytePos
102
+ def savedBitPos:int bitPos
103
+ def savedCurrentByte:int currentByte
104
+ def savedEof:boolean eof
105
+
106
+ def result:int (this.readBits(count))
107
+
108
+ ; Restore state
109
+ bytePos = savedBytePos
110
+ bitPos = savedBitPos
111
+ currentByte = savedCurrentByte
112
+ eof = savedEof
113
+
114
+ return result
115
+ }
116
+
117
+ fn alignToByte:void () {
118
+ ; Skip remaining bits in current byte
119
+ bitPos = 0
120
+ }
121
+
122
+ fn skipRestartMarker:boolean () {
123
+ ; Skip RST marker (FF D0-D7) after alignToByte()
124
+ ; Returns true if marker was found and skipped, false otherwise
125
+ ; Must be called after alignToByte() at restart interval boundaries
126
+
127
+ if (bytePos + 1 >= dataEnd) {
128
+ return false
129
+ }
130
+
131
+ def byte1:int (buffer_get data bytePos)
132
+ def byte2:int (buffer_get data (bytePos + 1))
133
+
134
+ if ((byte1 == 255) && (byte2 >= 208) && (byte2 <= 215)) {
135
+ ; Valid RST marker found, skip it
136
+ bytePos = bytePos + 2
137
+ return true
138
+ }
139
+
140
+ ; No RST marker found - this might indicate corruption or no DRI
141
+ return false
142
+ }
143
+
144
+ fn getBytePosition:int () {
145
+ return bytePos
146
+ }
147
+
148
+ fn isEOF:boolean () {
149
+ return eof
150
+ }
151
+
152
+ fn receiveExtend:int (length:int) {
153
+ ; JPEG-specific: read 'length' bits and extend sign
154
+ ; Used for DC and AC coefficient decoding
155
+ if (length == 0) {
156
+ return 0
157
+ }
158
+
159
+ def value:int (this.readBits(length))
160
+
161
+ ; If MSB is 0, value is negative
162
+ ; threshold = 2^(length-1)
163
+ def threshold:int (bit_shl 1 (length - 1))
164
+ if (value < threshold) {
165
+ ; Negative value: subtract 2^length - 1
166
+ value = value - ((bit_shl threshold 1) - 1)
167
+ }
168
+
169
+ return value
170
+ }
171
+ }