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,706 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ImageBuffer.rgr - Raw RGBA pixel buffer for image manipulation
4
+ ; Provides a simple interface for pixel operations
5
+ ;
6
+ ; Note: JPEG decoding/encoding requires complex algorithms (DCT, Huffman, quantization).
7
+ ; This module works with raw pixel data and uses PPM format for I/O (simple, uncompressed).
8
+
9
+ Import "Buffer.rgr"
10
+
11
+ class Color {
12
+ def r:int 0
13
+ def g:int 0
14
+ def b:int 0
15
+ def a:int 255
16
+
17
+ Constructor () {
18
+ }
19
+
20
+ fn setRGB:void (red:int green:int blue:int) {
21
+ r = red
22
+ g = green
23
+ b = blue
24
+ a = 255
25
+ }
26
+
27
+ fn setRGBA:void (red:int green:int blue:int alpha:int) {
28
+ r = red
29
+ g = green
30
+ b = blue
31
+ a = alpha
32
+ }
33
+
34
+ fn clamp:int (val:int) {
35
+ if (val < 0) { return 0 }
36
+ if (val > 255) { return 255 }
37
+ return val
38
+ }
39
+
40
+ fn set:void (red:int green:int blue:int) {
41
+ r = (this.clamp(red))
42
+ g = (this.clamp(green))
43
+ b = (this.clamp(blue))
44
+ }
45
+
46
+ fn grayscale:int () {
47
+ ; Luminance formula: 0.299*R + 0.587*G + 0.114*B
48
+ ; Using integer approximation: (77*R + 150*G + 29*B) >> 8
49
+ return (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
50
+ }
51
+
52
+ fn toGrayscale:void () {
53
+ def gray:int (this.grayscale())
54
+ r = gray
55
+ g = gray
56
+ b = gray
57
+ }
58
+
59
+ fn invert:void () {
60
+ r = 255 - r
61
+ g = 255 - g
62
+ b = 255 - b
63
+ }
64
+
65
+ fn adjustBrightness:void (amount:int) {
66
+ r = (this.clamp(r + amount))
67
+ g = (this.clamp(g + amount))
68
+ b = (this.clamp(b + amount))
69
+ }
70
+ }
71
+
72
+ class ImageBuffer {
73
+ def width:int 0
74
+ def height:int 0
75
+ def pixels:buffer (buffer_alloc 0)
76
+
77
+ Constructor () {
78
+ }
79
+
80
+ fn init:void (w:int h:int) {
81
+ width = w
82
+ height = h
83
+ def size:int (w * h * 4)
84
+ pixels = (buffer_alloc size)
85
+ this.fill(255 255 255 255)
86
+ }
87
+
88
+ ; Allocate RGBA storage without initializing pixels (caller fills).
89
+ fn initClear:void (w:int h:int) {
90
+ width = w
91
+ height = h
92
+ pixels = (buffer_alloc (w * h * 4))
93
+ }
94
+
95
+ fn fillTransparent:void () {
96
+ def size:int (width * height * 4)
97
+ buffer_fill pixels 0 0 size
98
+ }
99
+
100
+ fn getPixelOffset:int (x:int y:int) {
101
+ return ((y * width) + x) * 4
102
+ }
103
+
104
+ fn isValidCoord:boolean (x:int y:int) {
105
+ if (x < 0) { return false }
106
+ if (y < 0) { return false }
107
+ if (x >= width) { return false }
108
+ if (y >= height) { return false }
109
+ return true
110
+ }
111
+
112
+ fn getPixel:Color (x:int y:int) {
113
+ def c (new Color())
114
+ if (this.isValidCoord(x y)) {
115
+ def off:int (this.getPixelOffset(x y))
116
+ c.r = (buffer_get pixels off)
117
+ c.g = (buffer_get pixels (off + 1))
118
+ c.b = (buffer_get pixels (off + 2))
119
+ c.a = (buffer_get pixels (off + 3))
120
+ }
121
+ return c
122
+ }
123
+
124
+ fn setPixel:void (x:int y:int c:Color) {
125
+ if (this.isValidCoord(x y)) {
126
+ def off:int (this.getPixelOffset(x y))
127
+ buffer_set pixels off c.r
128
+ buffer_set pixels (off + 1) c.g
129
+ buffer_set pixels (off + 2) c.b
130
+ buffer_set pixels (off + 3) c.a
131
+ }
132
+ }
133
+
134
+ fn setPixelRGB:void (x:int y:int r:int g:int b:int) {
135
+ if (this.isValidCoord(x y)) {
136
+ def off:int (this.getPixelOffset(x y))
137
+ buffer_set pixels off r
138
+ buffer_set pixels (off + 1) g
139
+ buffer_set pixels (off + 2) b
140
+ buffer_set pixels (off + 3) 255
141
+ }
142
+ }
143
+
144
+ fn setPixelRGBA:void (x:int y:int r:int g:int b:int a:int) {
145
+ if (this.isValidCoord(x y)) {
146
+ def off:int (this.getPixelOffset(x y))
147
+ buffer_set pixels off r
148
+ buffer_set pixels (off + 1) g
149
+ buffer_set pixels (off + 2) b
150
+ buffer_set pixels (off + 3) a
151
+ }
152
+ }
153
+
154
+ fn getRawBuffer:buffer () {
155
+ return pixels
156
+ }
157
+
158
+ fn fill:void (r:int g:int b:int a:int) {
159
+ def size:int (width * height * 4)
160
+ def i 0
161
+ while (i < size) {
162
+ buffer_set pixels i r
163
+ buffer_set pixels (i + 1) g
164
+ buffer_set pixels (i + 2) b
165
+ buffer_set pixels (i + 3) a
166
+ i = i + 4
167
+ }
168
+ }
169
+
170
+ fn fillRect:void (x:int y:int w:int h:int c:Color) {
171
+ def endX:int (x + w)
172
+ def endY:int (y + h)
173
+ def py:int y
174
+ while (py < endY) {
175
+ def px:int x
176
+ while (px < endX) {
177
+ this.setPixel(px py c)
178
+ px = px + 1
179
+ }
180
+ py = py + 1
181
+ }
182
+ }
183
+
184
+ ; Image operations
185
+
186
+ fn invert:void () {
187
+ def size:int (width * height)
188
+ def i 0
189
+ while (i < size) {
190
+ def off:int (i * 4)
191
+ def r:int (buffer_get pixels off)
192
+ def g:int (buffer_get pixels (off + 1))
193
+ def b:int (buffer_get pixels (off + 2))
194
+ buffer_set pixels off (255 - r)
195
+ buffer_set pixels (off + 1) (255 - g)
196
+ buffer_set pixels (off + 2) (255 - b)
197
+ i = i + 1
198
+ }
199
+ }
200
+
201
+ fn grayscale:void () {
202
+ def size:int (width * height)
203
+ def i 0
204
+ while (i < size) {
205
+ def off:int (i * 4)
206
+ def r:int (buffer_get pixels off)
207
+ def g:int (buffer_get pixels (off + 1))
208
+ def b:int (buffer_get pixels (off + 2))
209
+ ; Luminance: (77*R + 150*G + 29*B) >> 8
210
+ def gray:int (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
211
+ buffer_set pixels off gray
212
+ buffer_set pixels (off + 1) gray
213
+ buffer_set pixels (off + 2) gray
214
+ i = i + 1
215
+ }
216
+ }
217
+
218
+ fn adjustBrightness:void (amount:int) {
219
+ def size:int (width * height)
220
+ def i 0
221
+ while (i < size) {
222
+ def off:int (i * 4)
223
+ def r:int (buffer_get pixels off)
224
+ def g:int (buffer_get pixels (off + 1))
225
+ def b:int (buffer_get pixels (off + 2))
226
+ r = r + amount
227
+ g = g + amount
228
+ b = b + amount
229
+ if (r < 0) { r = 0 }
230
+ if (r > 255) { r = 255 }
231
+ if (g < 0) { g = 0 }
232
+ if (g > 255) { g = 255 }
233
+ if (b < 0) { b = 0 }
234
+ if (b > 255) { b = 255 }
235
+ buffer_set pixels off r
236
+ buffer_set pixels (off + 1) g
237
+ buffer_set pixels (off + 2) b
238
+ i = i + 1
239
+ }
240
+ }
241
+
242
+ fn threshold:void (level:int) {
243
+ ; Convert to black and white based on threshold
244
+ def size:int (width * height)
245
+ def i 0
246
+ while (i < size) {
247
+ def off:int (i * 4)
248
+ def r:int (buffer_get pixels off)
249
+ def g:int (buffer_get pixels (off + 1))
250
+ def b:int (buffer_get pixels (off + 2))
251
+ def gray:int (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
252
+ def val:int 0
253
+ if (gray >= level) {
254
+ val = 255
255
+ }
256
+ buffer_set pixels off val
257
+ buffer_set pixels (off + 1) val
258
+ buffer_set pixels (off + 2) val
259
+ i = i + 1
260
+ }
261
+ }
262
+
263
+ fn sepia:void () {
264
+ ; Sepia tone effect
265
+ def size:int (width * height)
266
+ def i 0
267
+ while (i < size) {
268
+ def off:int (i * 4)
269
+ def r:int (buffer_get pixels off)
270
+ def g:int (buffer_get pixels (off + 1))
271
+ def b:int (buffer_get pixels (off + 2))
272
+ ; Sepia formula (integer approximation)
273
+ def newR:int (bit_shr ((r * 101) + (g * 197) + (b * 48)) 8)
274
+ def newG:int (bit_shr ((r * 89) + (g * 175) + (b * 43)) 8)
275
+ def newB:int (bit_shr ((r * 70) + (g * 137) + (b * 33)) 8)
276
+ if (newR > 255) { newR = 255 }
277
+ if (newG > 255) { newG = 255 }
278
+ if (newB > 255) { newB = 255 }
279
+ buffer_set pixels off newR
280
+ buffer_set pixels (off + 1) newG
281
+ buffer_set pixels (off + 2) newB
282
+ i = i + 1
283
+ }
284
+ }
285
+
286
+ fn flipHorizontal:void () {
287
+ def y 0
288
+ while (y < height) {
289
+ def x 0
290
+ def halfW:int (bit_shr width 1)
291
+ while (x < halfW) {
292
+ def x2:int ((width - 1) - x)
293
+ def off1:int (this.getPixelOffset(x y))
294
+ def off2:int (this.getPixelOffset(x2 y))
295
+ ; Swap pixels
296
+ def r1:int (buffer_get pixels off1)
297
+ def g1:int (buffer_get pixels (off1 + 1))
298
+ def b1:int (buffer_get pixels (off1 + 2))
299
+ def a1:int (buffer_get pixels (off1 + 3))
300
+ def r2:int (buffer_get pixels off2)
301
+ def g2:int (buffer_get pixels (off2 + 1))
302
+ def b2:int (buffer_get pixels (off2 + 2))
303
+ def a2:int (buffer_get pixels (off2 + 3))
304
+ buffer_set pixels off1 r2
305
+ buffer_set pixels (off1 + 1) g2
306
+ buffer_set pixels (off1 + 2) b2
307
+ buffer_set pixels (off1 + 3) a2
308
+ buffer_set pixels off2 r1
309
+ buffer_set pixels (off2 + 1) g1
310
+ buffer_set pixels (off2 + 2) b1
311
+ buffer_set pixels (off2 + 3) a1
312
+ x = x + 1
313
+ }
314
+ y = y + 1
315
+ }
316
+ }
317
+
318
+ fn flipVertical:void () {
319
+ def y 0
320
+ def halfH:int (bit_shr height 1)
321
+ while (y < halfH) {
322
+ def y2:int ((height - 1) - y)
323
+ def x 0
324
+ while (x < width) {
325
+ def off1:int (this.getPixelOffset(x y))
326
+ def off2:int (this.getPixelOffset(x y2))
327
+ ; Swap pixels
328
+ def r1:int (buffer_get pixels off1)
329
+ def g1:int (buffer_get pixels (off1 + 1))
330
+ def b1:int (buffer_get pixels (off1 + 2))
331
+ def a1:int (buffer_get pixels (off1 + 3))
332
+ def r2:int (buffer_get pixels off2)
333
+ def g2:int (buffer_get pixels (off2 + 1))
334
+ def b2:int (buffer_get pixels (off2 + 2))
335
+ def a2:int (buffer_get pixels (off2 + 3))
336
+ buffer_set pixels off1 r2
337
+ buffer_set pixels (off1 + 1) g2
338
+ buffer_set pixels (off1 + 2) b2
339
+ buffer_set pixels (off1 + 3) a2
340
+ buffer_set pixels off2 r1
341
+ buffer_set pixels (off2 + 1) g1
342
+ buffer_set pixels (off2 + 2) b1
343
+ buffer_set pixels (off2 + 3) a1
344
+ x = x + 1
345
+ }
346
+ y = y + 1
347
+ }
348
+ }
349
+
350
+ ; Drawing primitives
351
+
352
+ fn drawLine:void (x1:int y1:int x2:int y2:int c:Color) {
353
+ ; Bresenham's line algorithm
354
+ def dx:int (x2 - x1)
355
+ def dy:int (y2 - y1)
356
+ if (dx < 0) { dx = 0 - dx }
357
+ if (dy < 0) { dy = 0 - dy }
358
+
359
+ def sx:int 1
360
+ if (x1 > x2) { sx = -1 }
361
+ def sy:int 1
362
+ if (y1 > y2) { sy = -1 }
363
+
364
+ def err:int (dx - dy)
365
+ def x:int x1
366
+ def y:int y1
367
+
368
+ def done:boolean false
369
+ while (done == false) {
370
+ this.setPixel(x y c)
371
+ if ((x == x2) && (y == y2)) {
372
+ done = true
373
+ } {
374
+ def e2:int (err * 2)
375
+ if (e2 > (0 - dy)) {
376
+ err = err - dy
377
+ x = x + sx
378
+ }
379
+ if (e2 < dx) {
380
+ err = err + dx
381
+ y = y + sy
382
+ }
383
+ }
384
+ }
385
+ }
386
+
387
+ fn drawRect:void (x:int y:int w:int h:int c:Color) {
388
+ this.drawLine(x y (x + w - 1) y c)
389
+ this.drawLine((x + w - 1) y (x + w - 1) (y + h - 1) c)
390
+ this.drawLine((x + w - 1) (y + h - 1) x (y + h - 1) c)
391
+ this.drawLine(x (y + h - 1) x y c)
392
+ }
393
+
394
+ fn scale:ImageBuffer (factor:int) {
395
+ ; Scale image by integer factor (nearest neighbor)
396
+ def newW:int (width * factor)
397
+ def newH:int (height * factor)
398
+ return (this.scaleToSize(newW newH))
399
+ }
400
+
401
+ fn scaleToSize:ImageBuffer (newW:int newH:int) {
402
+ ; Scale image to specific size using bilinear interpolation
403
+ def result (new ImageBuffer())
404
+ result.init(newW newH)
405
+
406
+ def scaleX:double ((to_double width) / (to_double newW))
407
+ def scaleY:double ((to_double height) / (to_double newH))
408
+
409
+ def destY 0
410
+ while (destY < newH) {
411
+ def srcYf:double ((to_double destY) * scaleY)
412
+ def srcY0:int (to_int srcYf)
413
+ def srcY1:int (srcY0 + 1)
414
+ if (srcY1 >= height) { srcY1 = (height - 1) }
415
+ def fy:double (srcYf - (to_double srcY0))
416
+
417
+ def destX 0
418
+ while (destX < newW) {
419
+ def srcXf:double ((to_double destX) * scaleX)
420
+ def srcX0:int (to_int srcXf)
421
+ def srcX1:int (srcX0 + 1)
422
+ if (srcX1 >= width) { srcX1 = (width - 1) }
423
+ def fx:double (srcXf - (to_double srcX0))
424
+
425
+ ; Bilinear interpolation
426
+ def off00:int (((srcY0 * width) + srcX0) * 4)
427
+ def off01:int (((srcY0 * width) + srcX1) * 4)
428
+ def off10:int (((srcY1 * width) + srcX0) * 4)
429
+ def off11:int (((srcY1 * width) + srcX1) * 4)
430
+
431
+ ; Interpolate each channel
432
+ def r:int (this.bilinear(
433
+ (buffer_get pixels off00)
434
+ (buffer_get pixels off01)
435
+ (buffer_get pixels off10)
436
+ (buffer_get pixels off11)
437
+ fx fy))
438
+ def g:int (this.bilinear(
439
+ (buffer_get pixels (off00 + 1))
440
+ (buffer_get pixels (off01 + 1))
441
+ (buffer_get pixels (off10 + 1))
442
+ (buffer_get pixels (off11 + 1))
443
+ fx fy))
444
+ def b:int (this.bilinear(
445
+ (buffer_get pixels (off00 + 2))
446
+ (buffer_get pixels (off01 + 2))
447
+ (buffer_get pixels (off10 + 2))
448
+ (buffer_get pixels (off11 + 2))
449
+ fx fy))
450
+ def a:int (this.bilinear(
451
+ (buffer_get pixels (off00 + 3))
452
+ (buffer_get pixels (off01 + 3))
453
+ (buffer_get pixels (off10 + 3))
454
+ (buffer_get pixels (off11 + 3))
455
+ fx fy))
456
+
457
+ ; Write to destination
458
+ def destOff:int (((destY * newW) + destX) * 4)
459
+ buffer_set result.pixels destOff r
460
+ buffer_set result.pixels (destOff + 1) g
461
+ buffer_set result.pixels (destOff + 2) b
462
+ buffer_set result.pixels (destOff + 3) a
463
+ destX = destX + 1
464
+ }
465
+ destY = destY + 1
466
+ }
467
+
468
+ return result
469
+ }
470
+
471
+ fn bilinear:int (v00:int v01:int v10:int v11:int fx:double fy:double) {
472
+ ; Bilinear interpolation helper
473
+ def top:double ((to_double v00) * (1.0 - fx) + (to_double v01) * fx)
474
+ def bottom:double ((to_double v10) * (1.0 - fx) + (to_double v11) * fx)
475
+ def result:double (top * (1.0 - fy) + bottom * fy)
476
+ return (to_int result)
477
+ }
478
+
479
+ fn rotate90CW:ImageBuffer () {
480
+ ; Rotate 90 degrees clockwise
481
+ ; New dimensions: width becomes height, height becomes width
482
+ def result (new ImageBuffer())
483
+ result.init(height width)
484
+
485
+ def y 0
486
+ while (y < height) {
487
+ def x 0
488
+ while (x < width) {
489
+ ; Source pixel at (x, y) goes to (height-1-y, x) in destination
490
+ ; After 90 CW: newX = height - 1 - y, newY = x
491
+ def newX:int (height - 1 - y)
492
+ def newY:int x
493
+
494
+ def srcOff:int (((y * width) + x) * 4)
495
+ def destOff:int (((newY * height) + newX) * 4)
496
+
497
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
498
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
499
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
500
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
501
+
502
+ x = x + 1
503
+ }
504
+ y = y + 1
505
+ }
506
+
507
+ return result
508
+ }
509
+
510
+ fn rotate180:ImageBuffer () {
511
+ ; Rotate 180 degrees
512
+ def result (new ImageBuffer())
513
+ result.init(width height)
514
+
515
+ def y 0
516
+ while (y < height) {
517
+ def x 0
518
+ while (x < width) {
519
+ def newX:int (width - 1 - x)
520
+ def newY:int (height - 1 - y)
521
+
522
+ def srcOff:int (((y * width) + x) * 4)
523
+ def destOff:int (((newY * width) + newX) * 4)
524
+
525
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
526
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
527
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
528
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
529
+
530
+ x = x + 1
531
+ }
532
+ y = y + 1
533
+ }
534
+
535
+ return result
536
+ }
537
+
538
+ fn rotate270CW:ImageBuffer () {
539
+ ; Rotate 270 degrees clockwise (= 90 counter-clockwise)
540
+ def result (new ImageBuffer())
541
+ result.init(height width)
542
+
543
+ def y 0
544
+ while (y < height) {
545
+ def x 0
546
+ while (x < width) {
547
+ ; After 270 CW (90 CCW): newX = y, newY = width - 1 - x
548
+ def newX:int y
549
+ def newY:int (width - 1 - x)
550
+
551
+ def srcOff:int (((y * width) + x) * 4)
552
+ def destOff:int (((newY * height) + newX) * 4)
553
+
554
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
555
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
556
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
557
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
558
+
559
+ x = x + 1
560
+ }
561
+ y = y + 1
562
+ }
563
+
564
+ return result
565
+ }
566
+
567
+ fn transpose:ImageBuffer () {
568
+ ; Transpose: swap x and y (mirror along diagonal)
569
+ def result (new ImageBuffer())
570
+ result.init(height width)
571
+
572
+ def y 0
573
+ while (y < height) {
574
+ def x 0
575
+ while (x < width) {
576
+ def srcOff:int (((y * width) + x) * 4)
577
+ def destOff:int (((x * height) + y) * 4)
578
+
579
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
580
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
581
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
582
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
583
+
584
+ x = x + 1
585
+ }
586
+ y = y + 1
587
+ }
588
+
589
+ return result
590
+ }
591
+
592
+ fn transverse:ImageBuffer () {
593
+ ; Transverse: rotate 90 CW then flip horizontal (or flip vertical then rotate 90 CW)
594
+ def result (new ImageBuffer())
595
+ result.init(height width)
596
+
597
+ def y 0
598
+ while (y < height) {
599
+ def x 0
600
+ while (x < width) {
601
+ ; Transverse: newX = height - 1 - y, newY = width - 1 - x... wait
602
+ ; Actually: transpose + rotate 180 = newX = y, newY = width - 1 - x
603
+ ; No: transverse is anti-diagonal reflection
604
+ ; pixel(x,y) -> pixel(height-1-y, width-1-x) in transposed space
605
+ def newX:int (height - 1 - y)
606
+ def newY:int (width - 1 - x)
607
+
608
+ def srcOff:int (((y * width) + x) * 4)
609
+ def destOff:int (((newY * height) + newX) * 4)
610
+
611
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
612
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
613
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
614
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
615
+
616
+ x = x + 1
617
+ }
618
+ y = y + 1
619
+ }
620
+
621
+ return result
622
+ }
623
+
624
+ fn applyExifOrientation:ImageBuffer (orientation:int) {
625
+ ; Apply EXIF orientation correction
626
+ ; Orientation values:
627
+ ; 1 = Normal (no transform needed)
628
+ ; 2 = Flip horizontal
629
+ ; 3 = Rotate 180
630
+ ; 4 = Flip vertical
631
+ ; 5 = Transpose (flip horizontal + rotate 270)
632
+ ; 6 = Rotate 90 CW
633
+ ; 7 = Transverse (flip horizontal + rotate 90)
634
+ ; 8 = Rotate 270 CW (= rotate 90 CCW)
635
+
636
+ if (orientation == 1) {
637
+ ; Normal - return copy
638
+ return (this.scale(1))
639
+ }
640
+
641
+ if (orientation == 2) {
642
+ ; Flip horizontal
643
+ def result (new ImageBuffer())
644
+ result.init(width height)
645
+ def y 0
646
+ while (y < height) {
647
+ def x 0
648
+ while (x < width) {
649
+ def srcOff:int (((y * width) + x) * 4)
650
+ def destOff:int (((y * width) + (width - 1 - x)) * 4)
651
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
652
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
653
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
654
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
655
+ x = x + 1
656
+ }
657
+ y = y + 1
658
+ }
659
+ return result
660
+ }
661
+
662
+ if (orientation == 3) {
663
+ return (this.rotate180())
664
+ }
665
+
666
+ if (orientation == 4) {
667
+ ; Flip vertical
668
+ def result (new ImageBuffer())
669
+ result.init(width height)
670
+ def y 0
671
+ while (y < height) {
672
+ def x 0
673
+ while (x < width) {
674
+ def srcOff:int (((y * width) + x) * 4)
675
+ def destOff:int ((((height - 1 - y) * width) + x) * 4)
676
+ buffer_set result.pixels destOff (buffer_get pixels srcOff)
677
+ buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
678
+ buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
679
+ buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
680
+ x = x + 1
681
+ }
682
+ y = y + 1
683
+ }
684
+ return result
685
+ }
686
+
687
+ if (orientation == 5) {
688
+ return (this.transpose())
689
+ }
690
+
691
+ if (orientation == 6) {
692
+ return (this.rotate90CW())
693
+ }
694
+
695
+ if (orientation == 7) {
696
+ return (this.transverse())
697
+ }
698
+
699
+ if (orientation == 8) {
700
+ return (this.rotate270CW())
701
+ }
702
+
703
+ ; Unknown orientation - return copy
704
+ return (this.scale(1))
705
+ }
706
+ }