@woosh/meep-engine 3.9.0 → 3.10.0

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 (696) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/package.json +3 -2
  4. package/src/avif/encode_image_source.d.ts +70 -0
  5. package/src/avif/encode_image_source.d.ts.map +1 -0
  6. package/src/avif/encode_image_source.js +117 -0
  7. package/src/avif/encoder_worker.js +15 -126
  8. package/src/avif/index.d.ts +4 -2
  9. package/src/avif/index.js +21 -2
  10. package/src/avif/native/DECISIONS.md +537 -0
  11. package/src/avif/native/NOTICE.md +61 -0
  12. package/src/avif/native/api/AvifDecoder.d.ts +67 -0
  13. package/src/avif/native/api/AvifDecoder.d.ts.map +1 -0
  14. package/src/avif/native/api/AvifDecoder.js +121 -0
  15. package/src/avif/native/api/apply_transformations.d.ts +30 -0
  16. package/src/avif/native/api/apply_transformations.d.ts.map +1 -0
  17. package/src/avif/native/api/apply_transformations.js +120 -0
  18. package/src/avif/native/api/avif_to_sampler2d.d.ts +25 -0
  19. package/src/avif/native/api/avif_to_sampler2d.d.ts.map +1 -0
  20. package/src/avif/native/api/avif_to_sampler2d.js +42 -0
  21. package/src/avif/native/api/convert_to_rgba.d.ts +54 -0
  22. package/src/avif/native/api/convert_to_rgba.d.ts.map +1 -0
  23. package/src/avif/native/api/convert_to_rgba.js +204 -0
  24. package/src/avif/native/api/decode_avif.d.ts +24 -0
  25. package/src/avif/native/api/decode_avif.d.ts.map +1 -0
  26. package/src/avif/native/api/decode_avif.js +111 -0
  27. package/src/avif/native/api/decode_image_item.d.ts +18 -0
  28. package/src/avif/native/api/decode_image_item.d.ts.map +1 -0
  29. package/src/avif/native/api/decode_image_item.js +234 -0
  30. package/src/avif/native/api/encode_avif.d.ts +73 -0
  31. package/src/avif/native/api/encode_avif.d.ts.map +1 -0
  32. package/src/avif/native/api/encode_avif.js +488 -0
  33. package/src/avif/native/api/sampler2d_to_avif.d.ts +22 -0
  34. package/src/avif/native/api/sampler2d_to_avif.d.ts.map +1 -0
  35. package/src/avif/native/api/sampler2d_to_avif.js +108 -0
  36. package/src/avif/native/av1/decode/Av1FrameContext.d.ts +286 -0
  37. package/src/avif/native/av1/decode/Av1FrameContext.d.ts.map +1 -0
  38. package/src/avif/native/av1/decode/Av1FrameContext.js +622 -0
  39. package/src/avif/native/av1/decode/block_decoded.d.ts +27 -0
  40. package/src/avif/native/av1/decode/block_decoded.d.ts.map +1 -0
  41. package/src/avif/native/av1/decode/block_decoded.js +59 -0
  42. package/src/avif/native/av1/decode/decode_av1_still.d.ts +22 -0
  43. package/src/avif/native/av1/decode/decode_av1_still.d.ts.map +1 -0
  44. package/src/avif/native/av1/decode/decode_av1_still.js +309 -0
  45. package/src/avif/native/av1/decode/decode_coefficients.d.ts +20 -0
  46. package/src/avif/native/av1/decode/decode_coefficients.d.ts.map +1 -0
  47. package/src/avif/native/av1/decode/decode_coefficients.js +259 -0
  48. package/src/avif/native/av1/decode/decode_palette.d.ts +28 -0
  49. package/src/avif/native/av1/decode/decode_palette.d.ts.map +1 -0
  50. package/src/avif/native/av1/decode/decode_palette.js +442 -0
  51. package/src/avif/native/av1/decode/decode_tile.d.ts +14 -0
  52. package/src/avif/native/av1/decode/decode_tile.d.ts.map +1 -0
  53. package/src/avif/native/av1/decode/decode_tile.js +1213 -0
  54. package/src/avif/native/av1/decode/get_scan.d.ts +16 -0
  55. package/src/avif/native/av1/decode/get_scan.d.ts.map +1 -0
  56. package/src/avif/native/av1/decode/get_scan.js +138 -0
  57. package/src/avif/native/av1/decode/read_lr.d.ts +35 -0
  58. package/src/avif/native/av1/decode/read_lr.d.ts.map +1 -0
  59. package/src/avif/native/av1/decode/read_lr.js +277 -0
  60. package/src/avif/native/av1/decode/read_transform_type.d.ts +19 -0
  61. package/src/avif/native/av1/decode/read_transform_type.d.ts.map +1 -0
  62. package/src/avif/native/av1/decode/read_transform_type.js +92 -0
  63. package/src/avif/native/av1/decode/reconstruct.d.ts +36 -0
  64. package/src/avif/native/av1/decode/reconstruct.d.ts.map +1 -0
  65. package/src/avif/native/av1/decode/reconstruct.js +241 -0
  66. package/src/avif/native/av1/decode/transform_type.d.ts +49 -0
  67. package/src/avif/native/av1/decode/transform_type.d.ts.map +1 -0
  68. package/src/avif/native/av1/decode/transform_type.js +137 -0
  69. package/src/avif/native/av1/encode/Av1BlockSnapshot.d.ts +81 -0
  70. package/src/avif/native/av1/encode/Av1BlockSnapshot.d.ts.map +1 -0
  71. package/src/avif/native/av1/encode/Av1BlockSnapshot.js +299 -0
  72. package/src/avif/native/av1/encode/Av1EncodeContext.d.ts +384 -0
  73. package/src/avif/native/av1/encode/Av1EncodeContext.d.ts.map +1 -0
  74. package/src/avif/native/av1/encode/Av1EncodeContext.js +590 -0
  75. package/src/avif/native/av1/encode/build_headers.d.ts +50 -0
  76. package/src/avif/native/av1/encode/build_headers.d.ts.map +1 -0
  77. package/src/avif/native/av1/encode/build_headers.js +359 -0
  78. package/src/avif/native/av1/encode/choose_chroma_alpha.d.ts +26 -0
  79. package/src/avif/native/av1/encode/choose_chroma_alpha.d.ts.map +1 -0
  80. package/src/avif/native/av1/encode/choose_chroma_alpha.js +90 -0
  81. package/src/avif/native/av1/encode/choose_filters.d.ts +21 -0
  82. package/src/avif/native/av1/encode/choose_filters.d.ts.map +1 -0
  83. package/src/avif/native/av1/encode/choose_filters.js +318 -0
  84. package/src/avif/native/av1/encode/choose_restoration.d.ts +35 -0
  85. package/src/avif/native/av1/encode/choose_restoration.d.ts.map +1 -0
  86. package/src/avif/native/av1/encode/choose_restoration.js +616 -0
  87. package/src/avif/native/av1/encode/decode_effort.d.ts +57 -0
  88. package/src/avif/native/av1/encode/decode_effort.d.ts.map +1 -0
  89. package/src/avif/native/av1/encode/decode_effort.js +59 -0
  90. package/src/avif/native/av1/encode/encode_av1_still.d.ts +17 -0
  91. package/src/avif/native/av1/encode/encode_av1_still.d.ts.map +1 -0
  92. package/src/avif/native/av1/encode/encode_av1_still.js +194 -0
  93. package/src/avif/native/av1/encode/encode_effort.d.ts +56 -0
  94. package/src/avif/native/av1/encode/encode_effort.d.ts.map +1 -0
  95. package/src/avif/native/av1/encode/encode_effort.js +97 -0
  96. package/src/avif/native/av1/encode/encode_tile.d.ts +26 -0
  97. package/src/avif/native/av1/encode/encode_tile.d.ts.map +1 -0
  98. package/src/avif/native/av1/encode/encode_tile.js +2331 -0
  99. package/src/avif/native/av1/encode/quantise.d.ts +51 -0
  100. package/src/avif/native/av1/encode/quantise.d.ts.map +1 -0
  101. package/src/avif/native/av1/encode/quantise.js +212 -0
  102. package/src/avif/native/av1/encode/write_coefficients.d.ts +42 -0
  103. package/src/avif/native/av1/encode/write_coefficients.d.ts.map +1 -0
  104. package/src/avif/native/av1/encode/write_coefficients.js +367 -0
  105. package/src/avif/native/av1/encode/write_lr.d.ts +33 -0
  106. package/src/avif/native/av1/encode/write_lr.d.ts.map +1 -0
  107. package/src/avif/native/av1/encode/write_lr.js +174 -0
  108. package/src/avif/native/av1/encode/write_transform_type.d.ts +21 -0
  109. package/src/avif/native/av1/encode/write_transform_type.d.ts.map +1 -0
  110. package/src/avif/native/av1/encode/write_transform_type.js +70 -0
  111. package/src/avif/native/av1/entropy/CdfContext.d.ts +167 -0
  112. package/src/avif/native/av1/entropy/CdfContext.d.ts.map +1 -0
  113. package/src/avif/native/av1/entropy/CdfContext.js +433 -0
  114. package/src/avif/native/av1/entropy/SymbolReader.d.ts +103 -0
  115. package/src/avif/native/av1/entropy/SymbolReader.d.ts.map +1 -0
  116. package/src/avif/native/av1/entropy/SymbolReader.js +317 -0
  117. package/src/avif/native/av1/entropy/SymbolWriter.d.ts +107 -0
  118. package/src/avif/native/av1/entropy/SymbolWriter.d.ts.map +1 -0
  119. package/src/avif/native/av1/entropy/SymbolWriter.js +352 -0
  120. package/src/avif/native/av1/entropy/coefficient_context.d.ts +71 -0
  121. package/src/avif/native/av1/entropy/coefficient_context.d.ts.map +1 -0
  122. package/src/avif/native/av1/entropy/coefficient_context.js +325 -0
  123. package/src/avif/native/av1/entropy/partition_cdf.d.ts +54 -0
  124. package/src/avif/native/av1/entropy/partition_cdf.d.ts.map +1 -0
  125. package/src/avif/native/av1/entropy/partition_cdf.js +98 -0
  126. package/src/avif/native/av1/entropy/symbol_cost.d.ts +37 -0
  127. package/src/avif/native/av1/entropy/symbol_cost.d.ts.map +1 -0
  128. package/src/avif/native/av1/entropy/symbol_cost.js +76 -0
  129. package/src/avif/native/av1/filter/cdef.d.ts +15 -0
  130. package/src/avif/native/av1/filter/cdef.d.ts.map +1 -0
  131. package/src/avif/native/av1/filter/cdef.js +313 -0
  132. package/src/avif/native/av1/filter/loop_filter.d.ts +14 -0
  133. package/src/avif/native/av1/filter/loop_filter.d.ts.map +1 -0
  134. package/src/avif/native/av1/filter/loop_filter.js +377 -0
  135. package/src/avif/native/av1/filter/loop_restoration.d.ts +42 -0
  136. package/src/avif/native/av1/filter/loop_restoration.d.ts.map +1 -0
  137. package/src/avif/native/av1/filter/loop_restoration.js +451 -0
  138. package/src/avif/native/av1/filter/superres.d.ts +18 -0
  139. package/src/avif/native/av1/filter/superres.d.ts.map +1 -0
  140. package/src/avif/native/av1/filter/superres.js +86 -0
  141. package/src/avif/native/av1/grain/FilmGrainState.d.ts +62 -0
  142. package/src/avif/native/av1/grain/FilmGrainState.d.ts.map +1 -0
  143. package/src/avif/native/av1/grain/FilmGrainState.js +87 -0
  144. package/src/avif/native/av1/grain/film_grain.d.ts +16 -0
  145. package/src/avif/native/av1/grain/film_grain.d.ts.map +1 -0
  146. package/src/avif/native/av1/grain/film_grain.js +623 -0
  147. package/src/avif/native/av1/obu/FrameHeader.d.ts +248 -0
  148. package/src/avif/native/av1/obu/FrameHeader.d.ts.map +1 -0
  149. package/src/avif/native/av1/obu/FrameHeader.js +381 -0
  150. package/src/avif/native/av1/obu/ObuHeader.d.ts +53 -0
  151. package/src/avif/native/av1/obu/ObuHeader.d.ts.map +1 -0
  152. package/src/avif/native/av1/obu/ObuHeader.js +62 -0
  153. package/src/avif/native/av1/obu/SequenceHeader.d.ts +157 -0
  154. package/src/avif/native/av1/obu/SequenceHeader.d.ts.map +1 -0
  155. package/src/avif/native/av1/obu/SequenceHeader.js +225 -0
  156. package/src/avif/native/av1/obu/for_each_obu.d.ts +24 -0
  157. package/src/avif/native/av1/obu/for_each_obu.d.ts.map +1 -0
  158. package/src/avif/native/av1/obu/for_each_obu.js +50 -0
  159. package/src/avif/native/av1/obu/parse_frame_header.d.ts +18 -0
  160. package/src/avif/native/av1/obu/parse_frame_header.d.ts.map +1 -0
  161. package/src/avif/native/av1/obu/parse_frame_header.js +841 -0
  162. package/src/avif/native/av1/obu/parse_obu_header.d.ts +23 -0
  163. package/src/avif/native/av1/obu/parse_obu_header.d.ts.map +1 -0
  164. package/src/avif/native/av1/obu/parse_obu_header.js +69 -0
  165. package/src/avif/native/av1/obu/parse_sequence_header.d.ts +17 -0
  166. package/src/avif/native/av1/obu/parse_sequence_header.d.ts.map +1 -0
  167. package/src/avif/native/av1/obu/parse_sequence_header.js +263 -0
  168. package/src/avif/native/av1/obu/write_frame_header.d.ts +16 -0
  169. package/src/avif/native/av1/obu/write_frame_header.d.ts.map +1 -0
  170. package/src/avif/native/av1/obu/write_frame_header.js +579 -0
  171. package/src/avif/native/av1/obu/write_sequence_header.d.ts +17 -0
  172. package/src/avif/native/av1/obu/write_sequence_header.d.ts.map +1 -0
  173. package/src/avif/native/av1/obu/write_sequence_header.js +189 -0
  174. package/src/avif/native/av1/predict/IntraPredictionState.d.ts +49 -0
  175. package/src/avif/native/av1/predict/IntraPredictionState.d.ts.map +1 -0
  176. package/src/avif/native/av1/predict/IntraPredictionState.js +58 -0
  177. package/src/avif/native/av1/predict/intra_filter_type.d.ts +17 -0
  178. package/src/avif/native/av1/predict/intra_filter_type.d.ts.map +1 -0
  179. package/src/avif/native/av1/predict/intra_filter_type.js +79 -0
  180. package/src/avif/native/av1/predict/predict_chroma_from_luma.d.ts +50 -0
  181. package/src/avif/native/av1/predict/predict_chroma_from_luma.d.ts.map +1 -0
  182. package/src/avif/native/av1/predict/predict_chroma_from_luma.js +153 -0
  183. package/src/avif/native/av1/predict/predict_intra.d.ts +42 -0
  184. package/src/avif/native/av1/predict/predict_intra.d.ts.map +1 -0
  185. package/src/avif/native/av1/predict/predict_intra.js +803 -0
  186. package/src/avif/native/av1/predict/predict_palette.d.ts +23 -0
  187. package/src/avif/native/av1/predict/predict_palette.d.ts.map +1 -0
  188. package/src/avif/native/av1/predict/predict_palette.js +36 -0
  189. package/src/avif/native/av1/tables/av1_symbols.d.ts +411 -0
  190. package/src/avif/native/av1/tables/av1_symbols.d.ts.map +1 -0
  191. package/src/avif/native/av1/tables/av1_symbols.js +419 -0
  192. package/src/avif/native/av1/tables/block_tables.d.ts +181 -0
  193. package/src/avif/native/av1/tables/block_tables.d.ts.map +1 -0
  194. package/src/avif/native/av1/tables/block_tables.js +270 -0
  195. package/src/avif/native/av1/tables/cdf_tables.d.ts +961 -0
  196. package/src/avif/native/av1/tables/cdf_tables.d.ts.map +1 -0
  197. package/src/avif/native/av1/tables/cdf_tables.js +1893 -0
  198. package/src/avif/native/av1/tables/coefficient_tables.d.ts +41 -0
  199. package/src/avif/native/av1/tables/coefficient_tables.d.ts.map +1 -0
  200. package/src/avif/native/av1/tables/coefficient_tables.js +82 -0
  201. package/src/avif/native/av1/tables/derived_block_tables.d.ts +15 -0
  202. package/src/avif/native/av1/tables/derived_block_tables.d.ts.map +1 -0
  203. package/src/avif/native/av1/tables/derived_block_tables.js +23 -0
  204. package/src/avif/native/av1/tables/filter_tables.d.ts +171 -0
  205. package/src/avif/native/av1/tables/filter_tables.d.ts.map +1 -0
  206. package/src/avif/native/av1/tables/filter_tables.js +313 -0
  207. package/src/avif/native/av1/tables/grain_tables.d.ts +11 -0
  208. package/src/avif/native/av1/tables/grain_tables.d.ts.map +1 -0
  209. package/src/avif/native/av1/tables/grain_tables.js +190 -0
  210. package/src/avif/native/av1/tables/prediction_tables.d.ts +141 -0
  211. package/src/avif/native/av1/tables/prediction_tables.d.ts.map +1 -0
  212. package/src/avif/native/av1/tables/prediction_tables.js +223 -0
  213. package/src/avif/native/av1/tables/quantizer_matrix_tables.d.ts +21 -0
  214. package/src/avif/native/av1/tables/quantizer_matrix_tables.d.ts.map +1 -0
  215. package/src/avif/native/av1/tables/quantizer_matrix_tables.js +38 -0
  216. package/src/avif/native/av1/tables/quantizer_tables.d.ts +21 -0
  217. package/src/avif/native/av1/tables/quantizer_tables.d.ts.map +1 -0
  218. package/src/avif/native/av1/tables/quantizer_tables.js +160 -0
  219. package/src/avif/native/av1/tables/scan_tables.d.ts +321 -0
  220. package/src/avif/native/av1/tables/scan_tables.d.ts.map +1 -0
  221. package/src/avif/native/av1/tables/scan_tables.js +727 -0
  222. package/src/avif/native/av1/tables/segmentation_tables.d.ts +31 -0
  223. package/src/avif/native/av1/tables/segmentation_tables.d.ts.map +1 -0
  224. package/src/avif/native/av1/tables/segmentation_tables.js +48 -0
  225. package/src/avif/native/av1/tables/transform_tables.d.ts +91 -0
  226. package/src/avif/native/av1/tables/transform_tables.d.ts.map +1 -0
  227. package/src/avif/native/av1/tables/transform_tables.js +140 -0
  228. package/src/avif/native/av1/tables/unpack_table.d.ts +33 -0
  229. package/src/avif/native/av1/tables/unpack_table.d.ts.map +1 -0
  230. package/src/avif/native/av1/tables/unpack_table.js +73 -0
  231. package/src/avif/native/av1/transform/forward_transform_2d.d.ts +61 -0
  232. package/src/avif/native/av1/transform/forward_transform_2d.d.ts.map +1 -0
  233. package/src/avif/native/av1/transform/forward_transform_2d.js +574 -0
  234. package/src/avif/native/av1/transform/inverse_transform_1d.d.ts +76 -0
  235. package/src/avif/native/av1/transform/inverse_transform_1d.d.ts.map +1 -0
  236. package/src/avif/native/av1/transform/inverse_transform_1d.js +590 -0
  237. package/src/avif/native/av1/transform/inverse_transform_2d.d.ts +46 -0
  238. package/src/avif/native/av1/transform/inverse_transform_2d.d.ts.map +1 -0
  239. package/src/avif/native/av1/transform/inverse_transform_2d.js +180 -0
  240. package/src/avif/native/av1/util/ceil_log2.d.ts +13 -0
  241. package/src/avif/native/av1/util/ceil_log2.d.ts.map +1 -0
  242. package/src/avif/native/av1/util/ceil_log2.js +18 -0
  243. package/src/avif/native/av1/util/floor_log2.d.ts +20 -0
  244. package/src/avif/native/av1/util/floor_log2.d.ts.map +1 -0
  245. package/src/avif/native/av1/util/floor_log2.js +20 -0
  246. package/src/avif/native/av1/util/round2.d.ts +22 -0
  247. package/src/avif/native/av1/util/round2.d.ts.map +1 -0
  248. package/src/avif/native/av1/util/round2.js +27 -0
  249. package/src/avif/native/av1/util/round2_signed.d.ts +14 -0
  250. package/src/avif/native/av1/util/round2_signed.d.ts.map +1 -0
  251. package/src/avif/native/av1/util/round2_signed.js +17 -0
  252. package/src/avif/native/av1/util/tile_log2.d.ts +16 -0
  253. package/src/avif/native/av1/util/tile_log2.d.ts.map +1 -0
  254. package/src/avif/native/av1/util/tile_log2.js +23 -0
  255. package/src/avif/native/bitstream/BitReader.d.ts +174 -0
  256. package/src/avif/native/bitstream/BitReader.d.ts.map +1 -0
  257. package/src/avif/native/bitstream/BitReader.js +391 -0
  258. package/src/avif/native/bitstream/BitWriter.d.ts +122 -0
  259. package/src/avif/native/bitstream/BitWriter.d.ts.map +1 -0
  260. package/src/avif/native/bitstream/BitWriter.js +351 -0
  261. package/src/avif/native/color/ColourTransform.d.ts +62 -0
  262. package/src/avif/native/color/ColourTransform.d.ts.map +1 -0
  263. package/src/avif/native/color/ColourTransform.js +189 -0
  264. package/src/avif/native/color/YuvImage.d.ts +51 -0
  265. package/src/avif/native/color/YuvImage.d.ts.map +1 -0
  266. package/src/avif/native/color/YuvImage.js +66 -0
  267. package/src/avif/native/color/clamp_sample.d.ts +18 -0
  268. package/src/avif/native/color/clamp_sample.d.ts.map +1 -0
  269. package/src/avif/native/color/clamp_sample.js +25 -0
  270. package/src/avif/native/color/linear_to_transfer.d.ts +24 -0
  271. package/src/avif/native/color/linear_to_transfer.d.ts.map +1 -0
  272. package/src/avif/native/color/linear_to_transfer.js +126 -0
  273. package/src/avif/native/color/primaries.d.ts +20 -0
  274. package/src/avif/native/color/primaries.d.ts.map +1 -0
  275. package/src/avif/native/color/primaries.js +94 -0
  276. package/src/avif/native/color/rgb_row_to_ycbcr.d.ts +20 -0
  277. package/src/avif/native/color/rgb_row_to_ycbcr.d.ts.map +1 -0
  278. package/src/avif/native/color/rgb_row_to_ycbcr.js +78 -0
  279. package/src/avif/native/color/transfer_to_linear.d.ts +49 -0
  280. package/src/avif/native/color/transfer_to_linear.d.ts.map +1 -0
  281. package/src/avif/native/color/transfer_to_linear.js +171 -0
  282. package/src/avif/native/color/upsample_chroma_row.d.ts +35 -0
  283. package/src/avif/native/color/upsample_chroma_row.d.ts.map +1 -0
  284. package/src/avif/native/color/upsample_chroma_row.js +89 -0
  285. package/src/avif/native/color/ycbcr_row_to_rgb.d.ts +23 -0
  286. package/src/avif/native/color/ycbcr_row_to_rgb.d.ts.map +1 -0
  287. package/src/avif/native/color/ycbcr_row_to_rgb.js +78 -0
  288. package/src/avif/native/heif/AvifFile.d.ts +112 -0
  289. package/src/avif/native/heif/AvifFile.d.ts.map +1 -0
  290. package/src/avif/native/heif/AvifFile.js +142 -0
  291. package/src/avif/native/heif/ItemProperty.d.ts +244 -0
  292. package/src/avif/native/heif/ItemProperty.d.ts.map +1 -0
  293. package/src/avif/native/heif/ItemProperty.js +321 -0
  294. package/src/avif/native/heif/find_item_property.d.ts +17 -0
  295. package/src/avif/native/heif/find_item_property.d.ts.map +1 -0
  296. package/src/avif/native/heif/find_item_property.js +28 -0
  297. package/src/avif/native/heif/find_item_references.d.ts +16 -0
  298. package/src/avif/native/heif/find_item_references.d.ts.map +1 -0
  299. package/src/avif/native/heif/find_item_references.js +29 -0
  300. package/src/avif/native/heif/find_items_referencing.d.ts +17 -0
  301. package/src/avif/native/heif/find_items_referencing.d.ts.map +1 -0
  302. package/src/avif/native/heif/find_items_referencing.js +36 -0
  303. package/src/avif/native/heif/parse_avif_file.d.ts +15 -0
  304. package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -0
  305. package/src/avif/native/heif/parse_avif_file.js +383 -0
  306. package/src/avif/native/heif/parse_image_grid.d.ts +18 -0
  307. package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -0
  308. package/src/avif/native/heif/parse_image_grid.js +48 -0
  309. package/src/avif/native/heif/parse_item_property.d.ts +18 -0
  310. package/src/avif/native/heif/parse_item_property.d.ts.map +1 -0
  311. package/src/avif/native/heif/parse_item_property.js +243 -0
  312. package/src/avif/native/heif/read_item_data.d.ts +22 -0
  313. package/src/avif/native/heif/read_item_data.d.ts.map +1 -0
  314. package/src/avif/native/heif/read_item_data.js +97 -0
  315. package/src/avif/native/heif/write_avif_file.d.ts +50 -0
  316. package/src/avif/native/heif/write_avif_file.d.ts.map +1 -0
  317. package/src/avif/native/heif/write_avif_file.js +348 -0
  318. package/src/avif/native/heif/write_item_property.d.ts +16 -0
  319. package/src/avif/native/heif/write_item_property.d.ts.map +1 -0
  320. package/src/avif/native/heif/write_item_property.js +182 -0
  321. package/src/avif/native/index.d.ts +14 -0
  322. package/src/avif/native/index.d.ts.map +1 -0
  323. package/src/avif/native/index.js +56 -0
  324. package/src/avif/native/isobmff/BoxHeader.d.ts +50 -0
  325. package/src/avif/native/isobmff/BoxHeader.d.ts.map +1 -0
  326. package/src/avif/native/isobmff/BoxHeader.js +57 -0
  327. package/src/avif/native/isobmff/BoxWriter.d.ts +118 -0
  328. package/src/avif/native/isobmff/BoxWriter.d.ts.map +1 -0
  329. package/src/avif/native/isobmff/BoxWriter.js +264 -0
  330. package/src/avif/native/isobmff/ByteCursor.d.ts +125 -0
  331. package/src/avif/native/isobmff/ByteCursor.d.ts.map +1 -0
  332. package/src/avif/native/isobmff/ByteCursor.js +298 -0
  333. package/src/avif/native/isobmff/for_each_box.d.ts +23 -0
  334. package/src/avif/native/isobmff/for_each_box.d.ts.map +1 -0
  335. package/src/avif/native/isobmff/for_each_box.js +39 -0
  336. package/src/avif/native/isobmff/read_box_header.d.ts +22 -0
  337. package/src/avif/native/isobmff/read_box_header.d.ts.map +1 -0
  338. package/src/avif/native/isobmff/read_box_header.js +59 -0
  339. package/src/avif/native/isobmff/read_full_box_header.d.ts +26 -0
  340. package/src/avif/native/isobmff/read_full_box_header.d.ts.map +1 -0
  341. package/src/avif/native/isobmff/read_full_box_header.js +33 -0
  342. package/src/avif/threaded_image_encoder.d.ts +7 -2
  343. package/src/avif/threaded_image_encoder.d.ts.map +1 -1
  344. package/src/avif/threaded_image_encoder.js +107 -21
  345. package/src/core/binary/BinaryBuffer.d.ts +40 -0
  346. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  347. package/src/core/binary/BinaryBuffer.js +100 -0
  348. package/src/core/binary/hash/crc32.d.ts +16 -0
  349. package/src/core/binary/hash/crc32.d.ts.map +1 -0
  350. package/src/core/binary/hash/crc32.js +96 -0
  351. package/src/core/binary/utf8/utf8_decode.d.ts +21 -0
  352. package/src/core/binary/utf8/utf8_decode.d.ts.map +1 -0
  353. package/src/core/binary/utf8/utf8_decode.js +43 -0
  354. package/src/core/binary/utf8/utf8_encode_into.d.ts +20 -0
  355. package/src/core/binary/utf8/utf8_encode_into.d.ts.map +1 -0
  356. package/src/core/binary/utf8/utf8_encode_into.js +48 -0
  357. package/src/core/binary/utf8/utf8_encoded_length.d.ts +14 -0
  358. package/src/core/binary/utf8/utf8_encoded_length.d.ts.map +1 -0
  359. package/src/core/binary/utf8/utf8_encoded_length.js +36 -0
  360. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +417 -0
  361. package/src/core/color/COLOR_REVIEW_2026_08_28.md +779 -0
  362. package/src/core/color/Color.d.ts +128 -20
  363. package/src/core/color/Color.d.ts.map +1 -1
  364. package/src/core/color/Color.js +959 -866
  365. package/src/core/color/PQ/PQ_constants.d.ts +10 -0
  366. package/src/core/color/PQ/PQ_constants.d.ts.map +1 -1
  367. package/src/core/color/PQ/PQ_constants.js +10 -0
  368. package/src/core/color/PQ/linear_to_PQ.d.ts.map +1 -1
  369. package/src/core/color/PQ/linear_to_PQ.js +6 -0
  370. package/src/core/color/REC709_PRIMARIES.d.ts +50 -0
  371. package/src/core/color/REC709_PRIMARIES.d.ts.map +1 -0
  372. package/src/core/color/REC709_PRIMARIES.js +53 -0
  373. package/src/core/color/construct/color_from_hex.d.ts +21 -0
  374. package/src/core/color/construct/color_from_hex.d.ts.map +1 -0
  375. package/src/core/color/construct/color_from_hex.js +33 -0
  376. package/src/core/color/construct/color_from_temperature.d.ts +22 -0
  377. package/src/core/color/construct/color_from_temperature.d.ts.map +1 -0
  378. package/src/core/color/construct/color_from_temperature.js +33 -0
  379. package/src/core/color/construct/color_from_uint24.d.ts +19 -0
  380. package/src/core/color/construct/color_from_uint24.d.ts.map +1 -0
  381. package/src/core/color/construct/color_from_uint24.js +26 -0
  382. package/src/core/color/construct/color_from_uint32.d.ts +20 -0
  383. package/src/core/color/construct/color_from_uint32.d.ts.map +1 -0
  384. package/src/core/color/construct/color_from_uint32.js +39 -0
  385. package/src/core/color/construct/color_gray.d.ts +17 -0
  386. package/src/core/color/construct/color_gray.d.ts.map +1 -0
  387. package/src/core/color/construct/color_gray.js +22 -0
  388. package/src/core/color/hex/hex2rgb.d.ts +1 -11
  389. package/src/core/color/hex/hex2rgb.d.ts.map +1 -1
  390. package/src/core/color/hex/hex2rgb.js +7 -24
  391. package/src/core/color/hex/hex_to_rgb.d.ts +18 -0
  392. package/src/core/color/hex/hex_to_rgb.d.ts.map +1 -0
  393. package/src/core/color/hex/hex_to_rgb.js +62 -0
  394. package/src/core/color/hex/rgb2hex.d.ts +1 -8
  395. package/src/core/color/hex/rgb2hex.d.ts.map +1 -1
  396. package/src/core/color/hex/rgb2hex.js +7 -13
  397. package/src/core/color/hex/rgb_to_hex.d.ts +9 -0
  398. package/src/core/color/hex/rgb_to_hex.d.ts.map +1 -0
  399. package/src/core/color/hex/rgb_to_hex.js +13 -0
  400. package/src/core/color/hex/rgba_to_hex.d.ts +19 -0
  401. package/src/core/color/hex/rgba_to_hex.d.ts.map +1 -0
  402. package/src/core/color/hex/rgba_to_hex.js +23 -0
  403. package/src/core/color/hsv/hsv2rgb.d.ts +1 -12
  404. package/src/core/color/hsv/hsv2rgb.d.ts.map +1 -1
  405. package/src/core/color/hsv/hsv2rgb.js +8 -21
  406. package/src/core/color/hsv/hsv2rgb_float.d.ts +1 -12
  407. package/src/core/color/hsv/hsv2rgb_float.d.ts.map +1 -1
  408. package/src/core/color/hsv/hsv2rgb_float.js +8 -56
  409. package/src/core/color/hsv/hsv_to_rgb.d.ts +13 -0
  410. package/src/core/color/hsv/hsv_to_rgb.d.ts.map +1 -0
  411. package/src/core/color/hsv/hsv_to_rgb.js +39 -0
  412. package/src/core/color/hsv/hsv_to_rgb_uint8.d.ts +13 -0
  413. package/src/core/color/hsv/hsv_to_rgb_uint8.d.ts.map +1 -0
  414. package/src/core/color/hsv/hsv_to_rgb_uint8.js +21 -0
  415. package/src/core/color/hsv/hue_to_rgb_sextant.d.ts +24 -0
  416. package/src/core/color/hsv/hue_to_rgb_sextant.d.ts.map +1 -0
  417. package/src/core/color/hsv/hue_to_rgb_sextant.js +67 -0
  418. package/src/core/color/hsv/rgb2hsv.d.ts +1 -12
  419. package/src/core/color/hsv/rgb2hsv.d.ts.map +1 -1
  420. package/src/core/color/hsv/rgb2hsv.js +7 -42
  421. package/src/core/color/hsv/rgb_to_hsv.d.ts +13 -0
  422. package/src/core/color/hsv/rgb_to_hsv.d.ts.map +1 -0
  423. package/src/core/color/hsv/rgb_to_hsv.js +42 -0
  424. package/src/core/color/hunt/hpe_to_xyz.d.ts +2 -0
  425. package/src/core/color/hunt/hpe_to_xyz.d.ts.map +1 -0
  426. package/src/core/color/hunt/hpe_to_xyz.js +4 -0
  427. package/src/core/color/hunt/xyz_to_hpe.d.ts +1 -6
  428. package/src/core/color/hunt/xyz_to_hpe.d.ts.map +1 -1
  429. package/src/core/color/hunt/xyz_to_hpe.js +12 -15
  430. package/src/core/color/illuminant/D65_spd_tabulated.d.ts.map +1 -1
  431. package/src/core/color/illuminant/D65_spd_tabulated.js +107 -104
  432. package/src/core/color/int2rgb.d.ts +1 -10
  433. package/src/core/color/int2rgb.d.ts.map +1 -1
  434. package/src/core/color/int2rgb.js +7 -12
  435. package/src/core/color/int_to_rgb.d.ts +21 -0
  436. package/src/core/color/int_to_rgb.d.ts.map +1 -0
  437. package/src/core/color/int_to_rgb.js +33 -0
  438. package/src/core/color/kelvin/kelvin_to_rgb.d.ts.map +1 -1
  439. package/src/core/color/kelvin/kelvin_to_rgb.js +22 -2
  440. package/src/core/color/kelvin/rgb_to_kelvin.d.ts +22 -2
  441. package/src/core/color/kelvin/rgb_to_kelvin.d.ts.map +1 -1
  442. package/src/core/color/kelvin/rgb_to_kelvin.js +22 -2
  443. package/src/core/color/lab/lab_to_xyz.d.ts +20 -0
  444. package/src/core/color/lab/lab_to_xyz.d.ts.map +1 -0
  445. package/src/core/color/lab/lab_to_xyz.js +69 -0
  446. package/src/core/color/oklab/gamut_clip_adaptive_l0.d.ts +34 -0
  447. package/src/core/color/oklab/gamut_clip_adaptive_l0.d.ts.map +1 -0
  448. package/src/core/color/oklab/gamut_clip_adaptive_l0.js +46 -0
  449. package/src/core/color/oklab/gamut_clip_at_l0.d.ts +33 -0
  450. package/src/core/color/oklab/gamut_clip_at_l0.d.ts.map +1 -0
  451. package/src/core/color/oklab/gamut_clip_at_l0.js +84 -0
  452. package/src/core/color/oklab/gamut_clip_preserve_chroma.d.ts +24 -0
  453. package/src/core/color/oklab/gamut_clip_preserve_chroma.d.ts.map +1 -0
  454. package/src/core/color/oklab/gamut_clip_preserve_chroma.js +37 -0
  455. package/src/core/color/oklab/gamut_clip_project_to_lcusp.d.ts +23 -0
  456. package/src/core/color/oklab/gamut_clip_project_to_lcusp.d.ts.map +1 -0
  457. package/src/core/color/oklab/gamut_clip_project_to_lcusp.js +46 -0
  458. package/src/core/color/oklab/linear_srgb_to_okhsl.d.ts +19 -0
  459. package/src/core/color/oklab/linear_srgb_to_okhsl.d.ts.map +1 -0
  460. package/src/core/color/oklab/linear_srgb_to_okhsl.js +93 -0
  461. package/src/core/color/oklab/linear_srgb_to_okhsv.d.ts +12 -4
  462. package/src/core/color/oklab/linear_srgb_to_okhsv.d.ts.map +1 -1
  463. package/src/core/color/oklab/linear_srgb_to_okhsv.js +108 -84
  464. package/src/core/color/oklab/linear_srgb_to_oklab.d.ts +13 -4
  465. package/src/core/color/oklab/linear_srgb_to_oklab.d.ts.map +1 -1
  466. package/src/core/color/oklab/linear_srgb_to_oklab.js +28 -19
  467. package/src/core/color/oklab/okhsl_chroma_bounds.d.ts +51 -0
  468. package/src/core/color/oklab/okhsl_chroma_bounds.d.ts.map +1 -0
  469. package/src/core/color/oklab/okhsl_chroma_bounds.js +128 -0
  470. package/src/core/color/oklab/okhsl_to_linear_srgb.d.ts +19 -0
  471. package/src/core/color/oklab/okhsl_to_linear_srgb.d.ts.map +1 -0
  472. package/src/core/color/oklab/okhsl_to_linear_srgb.js +85 -0
  473. package/src/core/color/oklab/oklab_to_oklch.d.ts +24 -0
  474. package/src/core/color/oklab/oklab_to_oklch.d.ts.map +1 -0
  475. package/src/core/color/oklab/oklab_to_oklch.js +35 -0
  476. package/src/core/color/oklab/oklch_to_oklab.d.ts +18 -0
  477. package/src/core/color/oklab/oklch_to_oklab.d.ts.map +1 -0
  478. package/src/core/color/oklab/oklch_to_oklab.js +26 -0
  479. package/src/core/color/oklab/toe.d.ts +12 -0
  480. package/src/core/color/oklab/toe.d.ts.map +1 -1
  481. package/src/core/color/oklab/toe.js +34 -22
  482. package/src/core/color/operations/color_add.d.ts +21 -0
  483. package/src/core/color/operations/color_add.d.ts.map +1 -0
  484. package/src/core/color/operations/color_add.js +23 -0
  485. package/src/core/color/operations/color_add_scaled.d.ts +20 -0
  486. package/src/core/color/operations/color_add_scaled.d.ts.map +1 -0
  487. package/src/core/color/operations/color_add_scaled.js +30 -0
  488. package/src/core/color/operations/color_clamp.d.ts +22 -0
  489. package/src/core/color/operations/color_clamp.d.ts.map +1 -0
  490. package/src/core/color/operations/color_clamp.js +25 -0
  491. package/src/core/color/operations/color_darken.d.ts +2 -1
  492. package/src/core/color/operations/color_darken.d.ts.map +1 -1
  493. package/src/core/color/operations/color_darken.js +25 -24
  494. package/src/core/color/operations/color_desaturate.d.ts +2 -1
  495. package/src/core/color/operations/color_desaturate.d.ts.map +1 -1
  496. package/src/core/color/operations/color_desaturate.js +25 -24
  497. package/src/core/color/operations/color_get_hsl.d.ts +18 -0
  498. package/src/core/color/operations/color_get_hsl.d.ts.map +1 -0
  499. package/src/core/color/operations/color_get_hsl.js +60 -0
  500. package/src/core/color/operations/color_is_in_gamut.d.ts +20 -0
  501. package/src/core/color/operations/color_is_in_gamut.d.ts.map +1 -0
  502. package/src/core/color/operations/color_is_in_gamut.js +30 -0
  503. package/src/core/color/operations/color_lerp.d.ts +12 -3
  504. package/src/core/color/operations/color_lerp.d.ts.map +1 -1
  505. package/src/core/color/operations/color_lerp.js +55 -46
  506. package/src/core/color/operations/color_lighten.d.ts +9 -5
  507. package/src/core/color/operations/color_lighten.d.ts.map +1 -1
  508. package/src/core/color/operations/color_lighten.js +29 -24
  509. package/src/core/color/operations/color_mix_okhsv_channel.d.ts +24 -0
  510. package/src/core/color/operations/color_mix_okhsv_channel.d.ts.map +1 -0
  511. package/src/core/color/operations/color_mix_okhsv_channel.js +48 -0
  512. package/src/core/color/operations/color_multiply_rgb.d.ts +21 -0
  513. package/src/core/color/operations/color_multiply_rgb.d.ts.map +1 -0
  514. package/src/core/color/operations/color_multiply_rgb.js +26 -0
  515. package/src/core/color/operations/color_saturate.d.ts +9 -5
  516. package/src/core/color/operations/color_saturate.d.ts.map +1 -1
  517. package/src/core/color/operations/color_saturate.js +29 -24
  518. package/src/core/color/operations/color_scale_okhsv_channel.d.ts +1 -1
  519. package/src/core/color/operations/color_scale_okhsv_channel.d.ts.map +1 -1
  520. package/src/core/color/operations/color_scale_okhsv_channel.js +58 -45
  521. package/src/core/color/operations/color_srgb_apply.d.ts +28 -0
  522. package/src/core/color/operations/color_srgb_apply.d.ts.map +1 -0
  523. package/src/core/color/operations/color_srgb_apply.js +40 -0
  524. package/src/core/color/operations/color_sub.d.ts +16 -0
  525. package/src/core/color/operations/color_sub.d.ts.map +1 -0
  526. package/src/core/color/operations/color_sub.js +18 -0
  527. package/src/core/color/parse_color.d.ts +10 -1
  528. package/src/core/color/parse_color.d.ts.map +1 -1
  529. package/src/core/color/parse_color.js +100 -84
  530. package/src/core/color/parse_color_normalized.d.ts +24 -0
  531. package/src/core/color/parse_color_normalized.d.ts.map +1 -0
  532. package/src/core/color/parse_color_normalized.js +38 -0
  533. package/src/core/color/rgb2uint24.d.ts +1 -8
  534. package/src/core/color/rgb2uint24.d.ts.map +1 -1
  535. package/src/core/color/rgb2uint24.js +7 -20
  536. package/src/core/color/rgb2uint32.d.ts +1 -9
  537. package/src/core/color/rgb2uint32.d.ts.map +1 -1
  538. package/src/core/color/rgb2uint32.js +7 -18
  539. package/src/core/color/rgb_to_luminance.d.ts +14 -5
  540. package/src/core/color/rgb_to_luminance.d.ts.map +1 -1
  541. package/src/core/color/rgb_to_luminance.js +24 -13
  542. package/src/core/color/rgb_to_uint24.d.ts +9 -0
  543. package/src/core/color/rgb_to_uint24.d.ts.map +1 -0
  544. package/src/core/color/rgb_to_uint24.js +20 -0
  545. package/src/core/color/rgb_to_uint32.d.ts +10 -0
  546. package/src/core/color/rgb_to_uint32.d.ts.map +1 -0
  547. package/src/core/color/rgb_to_uint32.js +21 -0
  548. package/src/core/color/sRGB/linear_to_sRGB.d.ts +7 -0
  549. package/src/core/color/sRGB/linear_to_sRGB.d.ts.map +1 -1
  550. package/src/core/color/sRGB/linear_to_sRGB.js +39 -32
  551. package/src/core/color/xyz/hpe_to_xyz.d.ts +24 -0
  552. package/src/core/color/xyz/hpe_to_xyz.d.ts.map +1 -0
  553. package/src/core/color/xyz/hpe_to_xyz.js +39 -0
  554. package/src/core/color/xyz/rgb_to_xyz.d.ts +17 -2
  555. package/src/core/color/xyz/rgb_to_xyz.d.ts.map +1 -1
  556. package/src/core/color/xyz/rgb_to_xyz.js +44 -18
  557. package/src/core/color/xyz/xyz_cmf_tabulated.d.ts.map +1 -1
  558. package/src/core/color/xyz/xyz_cmf_tabulated.js +217 -211
  559. package/src/core/color/xyz/xyz_cmf_wyman.d.ts +4 -0
  560. package/src/core/color/xyz/xyz_cmf_wyman.d.ts.map +1 -1
  561. package/src/core/color/xyz/xyz_cmf_wyman.js +74 -65
  562. package/src/core/color/xyz/xyz_to_hpe.d.ts +18 -0
  563. package/src/core/color/xyz/xyz_to_hpe.d.ts.map +1 -0
  564. package/src/core/color/xyz/xyz_to_hpe.js +33 -0
  565. package/src/core/color/xyz/xyz_to_rgb.d.ts +17 -2
  566. package/src/core/color/xyz/xyz_to_rgb.d.ts.map +1 -1
  567. package/src/core/color/xyz/xyz_to_rgb.js +39 -16
  568. package/src/core/color/ycxcz/xyz_to_ycxcz.d.ts +7 -2
  569. package/src/core/color/ycxcz/xyz_to_ycxcz.d.ts.map +1 -1
  570. package/src/core/color/ycxcz/xyz_to_ycxcz.js +33 -28
  571. package/src/core/events/signal/Signal.js +820 -820
  572. package/src/core/math/clamp_index.d.ts +18 -0
  573. package/src/core/math/clamp_index.d.ts.map +1 -0
  574. package/src/core/math/clamp_index.js +23 -0
  575. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +803 -0
  576. package/src/engine/asset/loaders/image/jpeg/JpegFrame.d.ts +5 -3
  577. package/src/engine/asset/loaders/image/jpeg/JpegFrame.d.ts.map +1 -1
  578. package/src/engine/asset/loaders/image/jpeg/JpegFrame.js +5 -3
  579. package/src/engine/asset/loaders/image/jpeg/JpegFrameComponent.d.ts +2 -1
  580. package/src/engine/asset/loaders/image/jpeg/JpegFrameComponent.d.ts.map +1 -1
  581. package/src/engine/asset/loaders/image/jpeg/JpegFrameComponent.js +2 -1
  582. package/src/engine/asset/loaders/image/jpeg/JpegImage.d.ts +17 -0
  583. package/src/engine/asset/loaders/image/jpeg/JpegImage.d.ts.map +1 -1
  584. package/src/engine/asset/loaders/image/jpeg/JpegImage.js +197 -157
  585. package/src/engine/asset/loaders/image/jpeg/idct8x8_float.d.ts +0 -1
  586. package/src/engine/asset/loaders/image/jpeg/idct8x8_float.d.ts.map +1 -1
  587. package/src/engine/asset/loaders/image/jpeg/idct8x8_float.js +0 -1
  588. package/src/engine/asset/loaders/image/jpeg/jpeg_component_row.d.ts +28 -0
  589. package/src/engine/asset/loaders/image/jpeg/jpeg_component_row.d.ts.map +1 -0
  590. package/src/engine/asset/loaders/image/jpeg/jpeg_component_row.js +31 -0
  591. package/src/engine/asset/loaders/image/png/PNG.d.ts +3 -18
  592. package/src/engine/asset/loaders/image/png/PNG.d.ts.map +1 -1
  593. package/src/engine/asset/loaders/image/png/PNG.js +3 -139
  594. package/src/engine/asset/loaders/image/png/PNGReader.d.ts +16 -16
  595. package/src/engine/asset/loaders/image/png/PNGReader.d.ts.map +1 -1
  596. package/src/engine/asset/loaders/image/png/PNGReader.js +143 -160
  597. package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_iTXt.js +3 -3
  598. package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_zTXt.js +3 -3
  599. package/src/engine/asset/loaders/image/png/crc32.d.ts +1 -15
  600. package/src/engine/asset/loaders/image/png/crc32.d.ts.map +1 -1
  601. package/src/engine/asset/loaders/image/png/crc32.js +5 -89
  602. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.d.ts +12 -10
  603. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.d.ts.map +1 -1
  604. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +20 -45
  605. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.d.ts +2 -1
  606. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.d.ts.map +1 -1
  607. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +2 -0
  608. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.d.ts +2 -1
  609. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.d.ts.map +1 -1
  610. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +2 -0
  611. package/src/engine/asset/loaders/image/png/filter/png_unfilter.d.ts +22 -0
  612. package/src/engine/asset/loaders/image/png/filter/png_unfilter.d.ts.map +1 -0
  613. package/src/engine/asset/loaders/image/png/filter/png_unfilter.js +68 -0
  614. package/src/engine/asset/loaders/image/png/png_inflate.d.ts +20 -0
  615. package/src/engine/asset/loaders/image/png/png_inflate.d.ts.map +1 -0
  616. package/src/engine/asset/loaders/image/png/png_inflate.js +85 -0
  617. package/src/engine/asset/loaders/image/png/png_unpack_samples.d.ts +22 -0
  618. package/src/engine/asset/loaders/image/png/png_unpack_samples.d.ts.map +1 -0
  619. package/src/engine/asset/loaders/image/png/png_unpack_samples.js +38 -0
  620. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  621. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +135 -132
  622. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +16 -3
  623. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  624. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1157 -1149
  625. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  626. package/src/engine/physics/ecs/PhysicsSystem.d.ts +72 -81
  627. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  628. package/src/engine/physics/ecs/PhysicsSystem.js +86 -77
  629. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  630. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +451 -0
  631. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +625 -0
  632. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  633. package/src/shade/renderer/scene/serialization/decode_image_source_hdr.d.ts +14 -3
  634. package/src/shade/renderer/scene/serialization/decode_image_source_hdr.d.ts.map +1 -1
  635. package/src/shade/renderer/scene/serialization/decode_image_source_hdr.js +50 -51
  636. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts.map +1 -1
  637. package/src/shade/renderer/scene/serialization/deserialize_scene.js +531 -521
  638. package/src/shade/renderer/scene/serialization/write_image_source.d.ts.map +1 -1
  639. package/src/shade/renderer/scene/serialization/write_image_source.js +6 -4
  640. package/src/shade/renderer/shader/chunk/color/chunk_rgb_to_luminance.d.ts.map +1 -1
  641. package/src/shade/renderer/shader/chunk/color/chunk_rgb_to_luminance.js +34 -32
  642. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts +31 -0
  643. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts.map +1 -1
  644. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js +62 -31
  645. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_inverse_eotf_st2084.d.ts +10 -0
  646. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_inverse_eotf_st2084.d.ts.map +1 -1
  647. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_inverse_eotf_st2084.js +32 -22
  648. package/src/shade/renderer/shader/chunk/color/sRGB/chunk_sRGBTransferOETF.d.ts.map +1 -1
  649. package/src/shade/renderer/shader/chunk/color/sRGB/chunk_sRGBTransferOETF.js +22 -21
  650. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts +6 -0
  651. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts.map +1 -1
  652. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.js +110 -104
  653. package/src/shade/renderer/shader/chunk/color/xyz/chunk_rgb_to_xyz.d.ts.map +1 -1
  654. package/src/shade/renderer/shader/chunk/color/xyz/chunk_rgb_to_xyz.js +23 -21
  655. package/src/view/elements/ColorPickerView.js +296 -296
  656. package/src/avif/codec/dec/Readme.md +0 -14
  657. package/src/avif/codec/dec/avif_dec.cpp +0 -234
  658. package/src/avif/codec/dec/avif_dec.d.ts +0 -3
  659. package/src/avif/codec/dec/avif_dec.d.ts.map +0 -1
  660. package/src/avif/codec/dec/avif_dec.js +0 -16
  661. package/src/avif/codec/dec/avif_dec.wasm +0 -0
  662. package/src/avif/codec/enc/README.md +0 -37
  663. package/src/avif/codec/enc/avif_enc.cpp +0 -216
  664. package/src/avif/codec/enc/avif_enc.d.ts +0 -3
  665. package/src/avif/codec/enc/avif_enc.d.ts.map +0 -1
  666. package/src/avif/codec/enc/avif_enc.js +0 -6144
  667. package/src/avif/codec/enc/avif_enc.wasm +0 -0
  668. package/src/avif/codec/enc/avif_enc_mt.d.ts +0 -3
  669. package/src/avif/codec/enc/avif_enc_mt.d.ts.map +0 -1
  670. package/src/avif/codec/enc/avif_enc_mt.js +0 -6811
  671. package/src/avif/codec/enc/avif_enc_mt.wasm +0 -0
  672. package/src/avif/codec/enc/avif_enc_mt.worker.d.mts +0 -2
  673. package/src/avif/codec/enc/avif_enc_mt.worker.d.mts.map +0 -1
  674. package/src/avif/codec/enc/avif_enc_mt.worker.d.ts +0 -11
  675. package/src/avif/codec/enc/avif_enc_mt.worker.d.ts.map +0 -1
  676. package/src/avif/codec/enc/avif_enc_mt.worker.js +0 -171
  677. package/src/avif/codec/enc/avif_enc_mt.worker.mjs +0 -1
  678. package/src/avif/decode.d.ts +0 -3
  679. package/src/avif/decode.d.ts.map +0 -1
  680. package/src/avif/decode.js +0 -42
  681. package/src/avif/encode.d.ts +0 -3
  682. package/src/avif/encode.d.ts.map +0 -1
  683. package/src/avif/encode.js +0 -75
  684. package/src/avif/meta.d.ts +0 -24
  685. package/src/avif/meta.d.ts.map +0 -1
  686. package/src/avif/meta.js +0 -23
  687. package/src/avif/tsconfig.tsbuildinfo +0 -1
  688. package/src/avif/utils.d.ts +0 -17
  689. package/src/avif/utils.d.ts.map +0 -1
  690. package/src/avif/utils.js +0 -31
  691. package/src/engine/asset/loaders/image/jpeg/idct8x8_fixed.d.ts +0 -23
  692. package/src/engine/asset/loaders/image/jpeg/idct8x8_fixed.d.ts.map +0 -1
  693. package/src/engine/asset/loaders/image/jpeg/idct8x8_fixed.js +0 -214
  694. package/src/engine/asset/loaders/image/png/inflate.d.ts +0 -7
  695. package/src/engine/asset/loaders/image/png/inflate.d.ts.map +0 -1
  696. package/src/engine/asset/loaders/image/png/inflate.js +0 -20
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Number of bytes {@link utf8_encode_into} will write for `text`, excluding any terminator the
3
+ * caller adds.
4
+ *
5
+ * Exists so a caller can size or grow a buffer before encoding into it, which is what lets the
6
+ * encode itself be a single pass with no allocation.
7
+ *
8
+ * @param {string} text
9
+ * @returns {number}
10
+ *
11
+ * @copyright Company Named Limited (c) 2026
12
+ */
13
+ export function utf8_encoded_length(text) {
14
+ const length = text.length;
15
+
16
+ let count = 0;
17
+
18
+ for (let i = 0; i < length; i++) {
19
+ const code = text.codePointAt(i);
20
+
21
+ if (code < 0x80) {
22
+ count += 1;
23
+ } else if (code < 0x800) {
24
+ count += 2;
25
+ } else if (code < 0x10000) {
26
+ count += 3;
27
+ } else {
28
+ count += 4;
29
+
30
+ // codePointAt consumed both halves of the surrogate pair
31
+ i++;
32
+ }
33
+ }
34
+
35
+ return count;
36
+ }
@@ -0,0 +1,417 @@
1
+ # COLOR_FIX_PLAN — `src/core/color`
2
+
3
+ Date: 2026-08-28 · Companion to [COLOR_REVIEW_2026_08_28.md](COLOR_REVIEW_2026_08_28.md) ·
4
+ Findings are referenced by their review IDs (`C1`…`C16`, `§n`).
5
+
6
+ Each step is independently shippable and ordered so that nothing later depends on a decision not yet
7
+ made. Every step names the files it touches and the test that proves it.
8
+
9
+ ---
10
+
11
+ ## Scope corrections applied
12
+
13
+ Four corrections to the review were supplied and are binding on this plan:
14
+
15
+ | # | Correction | Effect on the plan |
16
+ |---|---|---|
17
+ | **R1** | Don't overload the `Color` class | No new methods on `Color`. All new behaviour ships as free functions (`color_*`). §4.2's "missing members" become **Phase 6 files**, not class methods. Existing methods stay where they are — this is an additive rule, not a migration mandate. |
18
+ | **R2** | Colour-space tag refused; `Color` is a low-level class | The review's §3.4 recommendation (a) and (b) are both **dropped**. `Color` stays four floats plus alpha with no space metadata. The space contract moves to *function* names and docs instead — **Phase 3**. |
19
+ | **R3** | Unused/unimported code is not suspect; meep is a library with downstream consumers | **No deletions anywhere.** Review §1.4, §5.5, §5.6 and §5.8 are struck as *deletion* items. Their real consequence inverts: unimported code is public API that no in-repo caller exercises, so defects in it are unguarded and its **missing specs move up in priority** (Phase 7). |
20
+ | **R4** | `prototype*.js` are playgrounds, stripped at ship | `kelvin/prototype_kelvin_to_rgb.js` is **out of scope**. Its `document.body` side effect and `engine/`/`view/` imports are expected for that file class. |
21
+
22
+ ### Explicitly not doing
23
+
24
+ - Deleting `int2rgb.js`, `sRGB_cmf.js`, `xyz_cmf_wyman.js`, `D65_spd_analytical.js`,
25
+ `planckian_radiance.js`, `find_gamut_intersection.js`, `xyz_to_hpe.js`, `MAGMA_LUT.js`, or any of
26
+ `operations/`. (R3)
27
+ - Touching `prototype_kelvin_to_rgb.js`. (R4)
28
+ - Adding a colour-space field, enum, or brand to `Color`. (R2)
29
+ - Adding `add`/`sub`/`lerp`/`clamp`/`fromHex` &c. as `Color` methods. (R1)
30
+
31
+ ---
32
+
33
+ ## Conventions this plan introduces
34
+
35
+ Two placement rules, so Phase 6 doesn't turn into a debate per file:
36
+
37
+ - **`operations/`** — free functions whose *input* is a `Color`. Existing precedent:
38
+ `color_lerp`, `color_darken`, `color_scale_okhsv_channel`.
39
+ - **`construct/`** — new directory; free functions that *produce* a `Color` from non-`Color` input
40
+ (`color_from_hex`, `color_from_uint24`, …). Keeps `operations/` meaning "transform", and keeps
41
+ factories out of the class per R1.
42
+
43
+ Naming follows the newer Layer-A style throughout: `snake_case`, `color_*` prefix, verb after the
44
+ noun (`color_from_hex`, not `hex_to_color`, so the whole family sorts together).
45
+
46
+ ---
47
+
48
+ ## Phase 1 — Major correctness
49
+
50
+ > Every step here: **write the failing spec first**, then fix. All four are currently invisible to
51
+ > the suite (33 files / 158 tests, all green).
52
+
53
+ ### Step 1 — Stop dropping alpha in the two `Color` sRGB statics · `C5` · major
54
+
55
+ **Files:** [Color.js](Color.js) (`from_linear_to_sRGB` ~L788, `from_sRGB_to_linear` ~L801)
56
+
57
+ **Do:**
58
+ 1. Convert into a local scratch triple, then write the result through `output.set(r, g, b, input.a)`.
59
+ This fixes both halves of C5 at once: alpha is carried, and the write goes through `set()` so
60
+ `onChanged` fires and the no-change short-circuit applies.
61
+ 2. Do **not** keep the positional `output[0] = …` path — that is the mechanism of the silent
62
+ mutation.
63
+
64
+ **Test:** `Color.spec.js` — (a) alpha survives a round trip through both statics; (b) passing an
65
+ existing `Color` as `output` fires `onChanged` exactly once with the correct old/new payload.
66
+
67
+ **Why first:** `Color.onChanged` has live consumers — `engine/graphics/render/forward_plus/model/PointLight.js`,
68
+ `SpotLight.js`, and `view/elements/ColorPickerView.js` all subscribe. Today a colour converted in
69
+ place updates without notifying any of them.
70
+
71
+ ---
72
+
73
+ ### Step 2 — Stop dropping alpha in the four OkHSV operations · `C6` · major
74
+
75
+ **Files:** [operations/color_scale_okhsv_channel.js](operations/color_scale_okhsv_channel.js)
76
+
77
+ **Do:** add `result.a = input.a;` before the return. One line fixes `color_lighten`,
78
+ `color_darken`, `color_saturate` and `color_desaturate` together, and brings them in line with
79
+ `color_lerp`, which already interpolates alpha.
80
+
81
+ **Test:** new `operations/color_scale_okhsv_channel.spec.js` asserting alpha passthrough; extend
82
+ `color_darken.spec.js` with an alpha case.
83
+
84
+ ---
85
+
86
+ ### Step 3 — Make `hex2rgb` reject or expand short-form hex · `C3` · major
87
+
88
+ **Files:** [hex/hex2rgb.js](hex/hex2rgb.js)
89
+
90
+ **Do:**
91
+ 1. Branch on `hex.length`: accept `#RGB` (4) and `#RGBA` (5) by nibble expansion (`f` → `ff`),
92
+ plus the existing `#RRGGBB` (7) and `#RRGGBBAA` (9).
93
+ 2. Anything else → `throw new Error()` naming the offending string. Do not rely on the caller's
94
+ `assert.notNaN` — that guard is downstream, mislabels the cause, and disappears if asserts are
95
+ stripped from a build.
96
+
97
+ **Test:** extend `hex/hex2rgb.spec.js` — `#f00` → `{255,0,0,255}`, `#f00a` → alpha `0xAA`,
98
+ `#ff00` (4 digits *without* `#`-relative alpha intent), `#gg0000`, and `''` all throw.
99
+
100
+ ---
101
+
102
+ ### Step 4 — Mask and validate `parse_color`'s numeric branch · `C4` · major
103
+
104
+ **Files:** [parse_color.js](parse_color.js) (~L66-70)
105
+
106
+ **Do:**
107
+ 1. Mask all three channels (`(c >> 16) & 0xFF`), not two of three.
108
+ 2. Reject `c < 0 || c > 0xFFFFFF` with a thrown error. Decide and document explicitly whether
109
+ `0xAARRGGBB` is supported — today it is neither supported nor rejected, which is how
110
+ `0xFF8000FF` becomes `r: -0.502`.
111
+ 3. `Color`'s HDR tolerance means no assert downstream will ever catch this, so the check has to be
112
+ here.
113
+
114
+ **Test:** `parse_color.spec.js` — `0xFF8000` decodes; `0xFF8000FF`, `-1`, `0x1000000` throw.
115
+
116
+ ---
117
+
118
+ ### Step 5 — Close the 2000 K seam in `kelvin_to_rgb` · `C1` · major
119
+
120
+ **Files:** [kelvin/kelvin_to_rgb.js](kelvin/kelvin_to_rgb.js) (`approximate_regime_red`, ~L23)
121
+
122
+ **Do:** the blue gate `t <= 20 ? 0 : clamp01(fit)` steps 0 → 0.0779 in one 0.01 K increment because
123
+ the fit does not reach zero at its own gate. Pick one:
124
+ - **(a) preferred** — shift/rescale the blue term so it is continuous at `t = 20`; or
125
+ - **(b)** blend across a short window (`t ∈ [20, 21]`) using `inverseLerp` + `lerp`, mirroring the
126
+ existing `BLEND_MIN`/`BLEND_MAX` treatment of the 6600 K seam.
127
+
128
+ (b) matches the file's established house style and is the lower-risk change; (a) is correct rather
129
+ than papered over. The 1000 K seam already does the right thing (hue locked to the red regime's
130
+ `t = 10` value, matching to 6 dp) and needs no change.
131
+
132
+ **Test:** new `kelvin_seam.spec.js` — sweep 500 K…40000 K in fine steps, assert a bounded
133
+ first difference per channel. This test shape catches all three seams and is the reason C1 survived
134
+ 9 existing tests.
135
+
136
+ ---
137
+
138
+ ### Step 6 — Restore injectivity to `rgb_to_kelvin` below 2000 K · `C2` · major
139
+
140
+ **Files:** [kelvin/rgb_to_kelvin.js](kelvin/rgb_to_kelvin.js)
141
+
142
+ **Do:** depends on Step 5 — the collapse is downstream of the flat `b/r === 0` region. After Step 5,
143
+ re-measure. Then either:
144
+ - **(a) minimal** — keep the bisection, verify it now resolves below 2000 K, and correct the JSDoc
145
+ (it promises "approx 1000 to 40000" but returns `0` for black); or
146
+ - **(b) better** — replace with McCamy's approximation over CIE 1960 `uv`, or Robertson. No solver,
147
+ uses all three channels (the current version never reads green, so any colour with a matching
148
+ `b/r` maps to the same temperature regardless of distance from the Planckian locus), and has a
149
+ defined Duv validity domain.
150
+
151
+ **Test:** extend `rgb_to_kelvin.spec.js` — round-trip `kelvin_to_rgb → rgb_to_kelvin` at 800, 1200,
152
+ 1500, 1800, 1999, 2100, 2700, 5000, 6500, 20000 K within tolerance.
153
+
154
+ ---
155
+
156
+ ## Phase 2 — Minor correctness
157
+
158
+ Small, independent, one commit each.
159
+
160
+ | Step | Finding | File | Do | Test |
161
+ |---|---|---|---|---|
162
+ | **7** | `C7` | [rgb2uint32.js](rgb2uint32.js) | Append `>>> 0` to the return. Behaviour-preserving: both existing consumers (`Color.spec.js`, `deserialize_scene.js`) already normalise. Removes a method whose name promises `uint32` and returns `-1` for white. | Drop the `>>> 0` from `Color.spec.js`'s assertions; they must still pass. |
163
+ | **8** | `C12` | [oklab/linear_srgb_to_okhsv.js](oklab/linear_srgb_to_okhsv.js) | Early-return `h = 0, s = 0, v = toe(L)` when `C < epsilon`, not only when `L === 0`. Today every neutral gets the arbitrary hue `0.2496` with `s ≈ 1e-7`. | Neutrals at several lightnesses return `s === 0`; `v` still round-trips. |
164
+ | **9** | `C12` | [operations/color_scale_okhsv_channel.js](operations/color_scale_okhsv_channel.js) | `clamp01` the three output channels. OkHSV round-trips overshoot by ~1e-7 (`v = 1.0000000270` for white), so the operations can return out-of-`[0,1]` colours. | White in → all channels exactly ≤ 1. |
165
+ | **10** | `C13` | [operations/color_lighten.js](operations/color_lighten.js) | Multiplicative `v * (1 + amount)` has a fixed point at 0, so black cannot be lightened. Switch to `v + amount * (1 - v)` (no fixed point at either end) or document the limitation. Mirror the decision in `color_saturate`. | `color_lighten(black, 1)` ≠ black. |
166
+ | **11** | `C8` | [Color.js](Color.js) `setHCL` ~L332, `setHSI` ~L393 | Decide per method: clamped-to-gamut, or unbounded-caller-clamps. Document the choice. Add a `default:` to both switches (unreachable today, one refactor from `undefined`). If `setHSI` cannot be validated against a reference, its own `NOTE: I'm not sure if the implementation is correct` should be resolved or the method marked `@deprecated` — **not deleted** (R3). | New `Color` spec cases for both, at the primaries and at neutral. |
167
+ | **12** | `C9` | [Color.js](Color.js) ~L702 | `multiplyScalar` and `multiply` scale alpha. Keep the behaviour, document it explicitly, and add `color_multiply_rgb` in Phase 6 for the exposure/tint case. | Doc-only; spec pins current behaviour so it can't drift. |
168
+ | **13** | `C10` | [Color.js](Color.js) ~L501 | `fromUint`: mask red with `& 0xFF`. Superseded in substance by Step 20 (single unpacker) but harmless and immediate. | `fromUint(toUint())` round-trip across the full byte range. |
169
+ | **14** | `C11` | [parse_color.js](parse_color.js) L6-8 | Anchor the three regexes (`^…$` after `trim()`), **or** document the substring-scan behaviour. Today `'background: rgb(1,2,3) !important'` parses, which contradicts the docstring. | Malformed-wrapper strings throw (or are documented as accepted). |
170
+ | **15** | `C15` | [Color.js](Color.js) ~L563 | `hash()` → `toUint32()` (after Step 7) so alpha participates. Currently colours differing only in alpha collide. | Two colours differing only in alpha hash differently. |
171
+ | **16** | `C16` | [illuminant/D65_spd_tabulated.js](illuminant/D65_spd_tabulated.js), [xyz/xyz_cmf_tabulated.js](xyz/xyz_cmf_tabulated.js) | Same problem, two shapes: `<=`/`>=` with an inner equality re-test vs `<`/`>` with a clamped `i1`; one asserts its input, the other doesn't. Converge on one. | Both return the tabulated endpoint exactly at both bounds and `0` outside. |
172
+ | **17** | `C14` | [rgb_to_luminance.js](rgb_to_luminance.js) | Doc-only. Replace *"linear or gamma-corrected"* with the GPU twin's wording: input must be linear for the result to be luminance; on encoded input this is luma (`Y′`). Cross-reference `chunk_rgb_to_luminance`. | — |
173
+
174
+ ---
175
+
176
+ ## Phase 3 — Space contract without a space tag
177
+
178
+ > Replaces review §3.4. R2 forbids putting the contract *in* `Color`; it goes into function names and
179
+ > docs instead, which is the right layer given `Color` is deliberately low-level.
180
+
181
+ ### Step 18 — State the contract on `Color` and on every consumer
182
+
183
+ **Files:** [Color.js](Color.js) class JSDoc; `operations/*`; `rgb_to_luminance.js` (done in Step 17)
184
+
185
+ **Do:**
186
+ 1. `Color` class docstring: state plainly that `Color` is a **space-agnostic** 4-float container —
187
+ it holds whatever the caller put in it, values may fall outside `[0,1]` for HDR, and *the
188
+ functions operating on it* declare which space they expect. Also correct the false
189
+ `@extends {Array.<number>}` (`Array.isArray(color) === false`) and document that the numeric
190
+ index setters (`set 0(v)`) bypass `set()` and therefore do not notify `onChanged`.
191
+ 2. Every function in `operations/` gets an explicit `@param {Color} input **linear** sRGB` line.
192
+ They all call `linear_srgb_to_okhsv` today, so linear is the existing de facto contract —
193
+ write it down.
194
+ 3. `Color.parse` / `toHex` / `toCssRGBAString` get the converse note: these produce/consume
195
+ **encoded** sRGB, so a `Color` built by `parse` must be converted before reaching `operations/`.
196
+
197
+ **Test:** doc-only, but add one spec to `color_darken.spec.js` that builds its input via
198
+ `Color.from_sRGB_to_linear(Color.parse('#808080'))` — the correct pipeline — so the intended usage is
199
+ executable and visible.
200
+
201
+ ### Step 19 — Add encoded-input variants so callers aren't required to remember
202
+
203
+ **Files:** new `operations/color_srgb_scale_okhsv_channel.js` (or a `{ encoded: true }` option — pick one)
204
+
205
+ **Do:** the UI path (`ColorPickerView`, `ColorEditor`, anything built from `Color.parse`) holds
206
+ encoded values, and the operations assume linear. Provide the decode→operate→encode wrapper once,
207
+ here, rather than in every caller. This is the practical substitute for the refused space tag.
208
+
209
+ **Test:** encoded variant on `#808080` produces a visibly different (and correct) result from
210
+ feeding the same encoded values to the linear variant.
211
+
212
+ ---
213
+
214
+ ## Phase 4 — Deduplication (no deletions — R3)
215
+
216
+ Consolidate by **delegation**, keeping every existing export in place so downstream imports keep
217
+ working.
218
+
219
+ ### Step 20 — One uint24 unpacker, three call sites · `§5.1`
220
+
221
+ **Files:** [int2rgb.js](int2rgb.js) (keep, becomes the implementation), [Color.js](Color.js)
222
+ `fromUint`, [parse_color.js](parse_color.js) numeric branch
223
+
224
+ **Do:** three copies exist with three masking behaviours. Make `int2rgb` the masked, validating
225
+ implementation and have `Color.fromUint` and `parse_color` call it. Subsumes Steps 4 and 13.
226
+ `int2rgb` keeps its export and signature.
227
+
228
+ **Test:** all three paths agree across the byte range and reject out-of-range identically.
229
+
230
+ ### Step 21 — Reuse the existing hue-wrap helper · `§5.2`
231
+
232
+ **Files:** [Color.js](Color.js) `setHSL`/`setHCL`/`setHSI`, [hsv/hsv2rgb_float.js](hsv/hsv2rgb_float.js)
233
+
234
+ **Do:** the same wrap is inlined four times in two different orders (`% 1` then fix-up, vs fix-up
235
+ then `% 1`). `core/math/euclidean_modulo.js` **already exists** and is exactly this:
236
+ `euclidean_modulo(h, 1)`. Replace all four. No new helper needed.
237
+
238
+ **Test:** existing specs must stay green; add negative and >1 hue cases (`-3.5`, `2.25`) to each of
239
+ the four.
240
+
241
+ ### Step 22 — One sextant dispatch · `§5.3`
242
+
243
+ **Files:** [Color.js](Color.js) `setHCL`/`setHSI`, [hsv/hsv2rgb_float.js](hsv/hsv2rgb_float.js),
244
+ new `hsv/hue_to_rgb_sextant.js`
245
+
246
+ **Do:** `setHCL` and `setHSI` contain byte-identical 30-line switches; `hsv2rgb_float` has a third
247
+ variant. Extract `hue_to_rgb_sextant(out, h_face, c, x)`. This is also what makes Step 11's clamp a
248
+ one-place change instead of three.
249
+
250
+ **Test:** existing HSV/HSL specs green; new direct spec for the helper at all six sextant boundaries.
251
+
252
+ ### Step 23 — Cross-reference the two lerps · `§5.4`
253
+
254
+ **Files:** [Color.js](Color.js) `lerpColors`, [operations/color_lerp.js](operations/color_lerp.js)
255
+
256
+ **Do:** doc-only. `lerpColors` is per-channel linear; `color_lerp` is OkHSV shortest-arc. Neither
257
+ mentions the other, and the results differ substantially at mid-`t`. Add `@see` both ways and one
258
+ sentence on when to pick which.
259
+
260
+ ### Step 24 — Disambiguate spec filenames and suite names · `§5.9`
261
+
262
+ **Files:** [xyz/XYZ.spec.js](xyz/XYZ.spec.js) → `rgb_xyz_roundtrip.spec.js`;
263
+ [oklab/XYZ.spec.js](oklab/XYZ.spec.js) → `oklab_xyz_roundtrip.spec.js`;
264
+ [sRGB/sRGB.spec.js](sRGB/sRGB.spec.js) → `srgb_transfer_roundtrip.spec.js`
265
+
266
+ **Do:** two files share the name `XYZ.spec.js` and three share the test name
267
+ `"to/from consistency"`, so a failure report is ambiguous. Rename files and give each test a
268
+ distinct name.
269
+
270
+ ---
271
+
272
+ ## Phase 5 — Cross-boundary consistency
273
+
274
+ ### Step 25 — Reconcile the PQ/ST 2084 reference white · `§3.5` · **highest cross-cutting risk**
275
+
276
+ **Files:** [PQ/PQ_constants.js](PQ/PQ_constants.js) (203 nits, BT.2408) vs
277
+ `src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js` and
278
+ `chunk_inverse_eotf_st2084.js` (100 nits)
279
+
280
+ **Do:** the same engine holds two SDR-white conventions — content encoded on the CPU path and decoded
281
+ on the GPU path is off by 2.03×. Decide which is normative (BT.2408's 203 is the modern answer and is
282
+ what `avif/encoder_worker.js` already ships), then make the other match. `PQ_constants.js` explicitly
283
+ documents why folding a white point into the transfer function is dangerous; the GPU chunk folds a
284
+ *different* one in.
285
+
286
+ **Test:** a spec that runs the JS `linear_to_PQ`/`PQ_to_linear` pair against the WGSL chunks' expected
287
+ values at several nit levels — per the project's WGSL-validate / JS-emulator tiering.
288
+
289
+ ### Step 26 — Single source of truth for shared constants · `§5.7`
290
+
291
+ **Files:** [rgb_to_luminance.js](rgb_to_luminance.js), [xyz/rgb_to_xyz.js](xyz/rgb_to_xyz.js),
292
+ the corresponding WGSL chunks
293
+
294
+ **Do:** the Rec.709 luma weights appear at 4, 15 and 20 significant digits in three places; the sRGB
295
+ OETF exponent and the XYZ matrix each have two spellings. Generate the shared matrices and
296
+ transfer-function coefficients into both JS and WGSL from one definition — the AVIF work already does
297
+ exactly this (`feat(avif): generate the normative AV1 constant tables`), so the mechanism exists.
298
+ This is what makes Step 25 stay fixed.
299
+
300
+ **Test:** generated output is committed; a spec asserts JS and WGSL constants agree bit-for-bit.
301
+
302
+ ---
303
+
304
+ ## Phase 6 — Missing members, as free functions (R1)
305
+
306
+ New files only. **No `Color` methods are added.** Order within the phase is by value; each is
307
+ independent.
308
+
309
+ ### Step 27 — Gamut clipping · `§4.3` · highest-value missing feature
310
+
311
+ **Files:** new `oklab/gamut_clip_preserve_chroma.js`, `oklab/gamut_clip_project_to_lcusp.js`,
312
+ `oklab/gamut_clip_adaptive_l0.js`
313
+
314
+ **Do:** [find_gamut_intersection.js](oklab/find_gamut_intersection.js) is present and correct and is
315
+ the primitive these are built from — the hard part is already written, only the thin wrappers are
316
+ missing. Ships the package's only route to "make this out-of-gamut colour displayable".
317
+
318
+ **Test:** new `gamut_clip.spec.js` — clipped colours are in-gamut; in-gamut colours are unchanged;
319
+ hue is preserved by the preserve-chroma variant.
320
+
321
+ ### Step 28 — Missing inverses · `§4.1`
322
+
323
+ | New file | Note |
324
+ |---|---|
325
+ | `lab/lab_to_xyz.js` | Lab is currently write-only, which defeats the main reason to enter it. |
326
+ | `hunt/hpe_to_xyz.js` | Pairs with the existing `xyz_to_hpe`. |
327
+ | `hex/rgba2hex.js` | `hex2rgb` already **reads** `#RRGGBBAA`; nothing can write it. |
328
+ | `oklab/oklab_to_oklch.js`, `oklch_to_oklab.js` | The space CSS Color 4 exposes and the natural one for hue rotation. |
329
+ | `oklab/okhsl_*.js` | Ottosson defines OkHSL beside OkHSV; `toe`/`toe_inv` are already here. Better basis for lighten/darken than OkHSV (Step 10). |
330
+
331
+ **Test:** absolute reference values, not only mutual round-trips — see Step 32.
332
+
333
+ ### Step 29 — `Color` free functions replacing the "missing methods" · `§4.2` under R1
334
+
335
+ **Files:** new, in `operations/` (Color in) and `construct/` (Color out)
336
+
337
+ | File | Replaces the rejected method |
338
+ |---|---|
339
+ | `operations/color_add.js`, `color_sub.js`, `color_add_scaled.js` | `Color.prototype.add` &c. |
340
+ | `operations/color_multiply_rgb.js` | the alpha-preserving multiply (Step 12) |
341
+ | `operations/color_clamp.js`, `color_is_in_gamut.js` | pairs with Steps 9 & 11 |
342
+ | `construct/color_from_hex.js` | `Color.fromHex` |
343
+ | `construct/color_from_uint24.js`, `color_from_uint32.js` | `Color.fromUint` as a static |
344
+ | `construct/color_from_temperature.js` | wraps the existing `kelvin_to_rgb` |
345
+ | `construct/color_gray.js` | — |
346
+ | `operations/color_get_hsl.js` | `getHSV` exists, `getHSL` does not |
347
+
348
+ **Do:** each is a thin function over machinery that already exists. Existing `Color` methods are left
349
+ untouched — this is additive.
350
+
351
+ ### Step 30 — Lazy `onChanged` · `§4.2` · **defer; highest blast radius**
352
+
353
+ **Files:** [Color.js](Color.js) constructor + `set()`
354
+
355
+ **Do:** every `Color` eagerly allocates a `Signal`; measured **71.7 ms vs 17.9 ms per 500k
356
+ constructions** — a 4× cost on a low-level type used in per-particle and per-vertex paths, which sits
357
+ badly with R2's "Color is a low-level class". Make the signal lazy (allocate on first `add`, guard
358
+ the `send8`). `Color.onChanged` has three known consumer sites (`PointLight`, `SpotLight`,
359
+ `ColorPickerView`) but is accessed as a plain property, so a getter must preserve that shape.
360
+
361
+ **Test:** existing `onChanged` specs green; a new allocation benchmark spec pinning the improvement;
362
+ manual check of the three consumers.
363
+
364
+ **Sequencing:** do this **after** Step 1, which is the step that makes `onChanged` correct in the
365
+ first place.
366
+
367
+ ---
368
+
369
+ ## Phase 7 — Test coverage (raised in priority by R3)
370
+
371
+ > Because nothing downstream is visible from this repo, the specs *are* the contract for the 33
372
+ > unspecced source files. Absolute reference values, not just mutual inverses.
373
+
374
+ | Step | Target | What to add |
375
+ |---|---|---|
376
+ | **31** | `oklab/` primitives | `linear_srgb_to_oklab`, `oklab_to_linear_srgb`, `find_cusp`, `toe`/`toe_inv`, `find_gamut_intersection` — currently 6 assertions across two whole-pipeline round-trips, and `find_gamut_intersection` has none. Add per-function specs with published reference values. |
377
+ | **32** | Matrix pairs | `rgb_to_xyz`/`xyz_to_rgb`, `ycxcz`, `YCoCg`, `PQ` are covered only by mutual round-trips — a forward matrix wrong in both directions passes. Add absolute expected values (D65 white, the three primaries, mid-grey). |
378
+ | **33** | Untested leaves | `rgb_to_luminance` (3 non-spec importers), `rgb2uint24`/`rgb2uint32`, `hsv2rgb_float`, `xyz_to_hpe`, `rgb_to_xyz`, `PQ_constants`. |
379
+ | **34** | Seams | The sweep spec from Step 5, generalised: assert bounded first differences across every piecewise function in the package (`kelvin_to_rgb`, `convert_channel_*`, `xyz_to_lab`'s `compress`). |
380
+ | **35** | Alpha | An alpha case on every function in `operations/` and on both `Color` sRGB statics. Steps 1 and 2 survived because none existed. |
381
+ | **36** | Allocation | A guard spec on `Color` construction cost, so Step 30 can't regress. |
382
+
383
+ ---
384
+
385
+ ## Phase 8 — Convention convergence (last, one sweep)
386
+
387
+ > Large, mechanical, mostly rename. Deliberately last so churn lands once, after behaviour is
388
+ > correct. Nothing here is a deletion (R3) — old names stay as re-exports for one release if needed.
389
+
390
+ | Step | Finding | Do |
391
+ |---|---|---|
392
+ | **37** | `§3.1` | Give `rgb_to_xyz` / `xyz_to_rgb` the `(out, out_off, in, in_off)` signature. Highest-value single change in the phase — 4 non-spec importers each, and they're the two most-imported conversions in the package. Keep the current 2-arg form as a delegating overload. |
393
+ | **38** | `§3.1` | Same treatment for the remaining `(out, in)` member, `xyz_to_hpe`. Leave `(out, …scalars)` alone where inputs genuinely aren't a contiguous triple (`kelvin_to_rgb`, the CMFs). |
394
+ | **39** | `§3.2` | Rename `hsv2rgb` → an explicitly byte-scaled name so the unsuffixed name isn't the non-default unit. Fix `parse_color`'s mixed `[0-255, 0-255, 0-255, 0-1]` return, moving the `/255` knowledge out of `Color.parse`. |
395
+ | **40** | `§3.3` | `name2name` → `name_to_name` across Layer B (`hsv2rgb`, `rgb2hsv`, `rgb2hex`, `hex2rgb`, `int2rgb`, `rgb2uint24`, `rgb2uint32`). Splits cleanly by age, so it's mechanical. |
396
+ | **41** | `§3.3` | One casing for the `sRGB` token (`sRGB_to_linear` vs `linear_srgb_to_oklab`), and one for directory names (`PQ`/`YCbCr`/`YCoCg`/`sRGB` vs the twelve lowercase ones). |
397
+ | **42** | `§1.3` | `hunt/` holds `xyz_to_hpe`, the Hunt–Pointer–Estévez *matrix*, while the Hunt-*effect* function lives in `lab/` and carries a disclaimer saying so. Move `xyz_to_hpe` to `xyz/` and retire the `hunt/` directory (move, not delete). |
398
+ | **43** | `§3.6` | One assert policy. Today `planckian_radiance` and `D65_spd_tabulated` validate scalars while `xyz_cmf_tabulated`, `xyz_cmf_wyman`, `linear_to_PQ` and `D65_spd_analytical` don't; `kelvin_to_rgb` asserts, `rgb_to_ycocg` doesn't. Also add the missing `@author`/`@copyright` to `linear_srgb_to_okhsv`, `linear_srgb_to_oklab`, `toe`. |
399
+
400
+ ---
401
+
402
+ ## Suggested batching
403
+
404
+ | Batch | Steps | Character |
405
+ |---|---|---|
406
+ | **A** | 1–4 | Alpha + ingest. Small edits, immediate risk reduction, no design decisions. |
407
+ | **B** | 5–6 | Kelvin. One decision (a vs b), one new test shape that pays off in Step 34. |
408
+ | **C** | 7–17 | Minor correctness sweep. Mostly one-liners plus docs. |
409
+ | **D** | 18–19 | Space contract. Doc + one new wrapper; unblocks correct downstream usage. |
410
+ | **E** | 20–24 | Deduplication by delegation. No exports removed. |
411
+ | **F** | 25–26 | CPU/GPU reconciliation. Do before more HDR work lands. |
412
+ | **G** | 27–29 | New surface area. Purely additive, no risk to existing callers. |
413
+ | **H** | 31–36, 30 | Coverage, then the lazy signal last (Step 30 needs 36 as its guard). |
414
+ | **I** | 37–43 | Convention sweep. |
415
+
416
+ **Regression baseline for every batch:** `npx vitest run src/core/color` — currently 33 files, 158
417
+ tests, all passing. No step in this plan may reduce that count.