@woosh/meep-engine 3.14.1 → 3.14.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 (220) hide show
  1. package/README.md +31 -24
  2. package/package.json +1 -1
  3. package/src/avif/native/DECISIONS.md +544 -536
  4. package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -1
  5. package/src/avif/native/heif/parse_avif_file.js +384 -383
  6. package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -1
  7. package/src/avif/native/heif/parse_image_grid.js +49 -48
  8. package/src/basis/BasisBitReader.d.ts +77 -0
  9. package/src/basis/BasisBitReader.d.ts.map +1 -0
  10. package/src/basis/BasisBitReader.js +231 -0
  11. package/src/basis/BasisHuffmanTable.d.ts +53 -0
  12. package/src/basis/BasisHuffmanTable.d.ts.map +1 -0
  13. package/src/basis/BasisHuffmanTable.js +263 -0
  14. package/src/basis/basis_read_huffman_table.d.ts +20 -0
  15. package/src/basis/basis_read_huffman_table.d.ts.map +1 -0
  16. package/src/basis/basis_read_huffman_table.js +187 -0
  17. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts +50 -0
  18. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
  19. package/src/basis/etc1s/Etc1sSelectorHistory.js +89 -0
  20. package/src/basis/etc1s/etc1s_block_colors.d.ts +14 -0
  21. package/src/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
  22. package/src/basis/etc1s/etc1s_block_colors.js +75 -0
  23. package/src/basis/etc1s/etc1s_decode_slice.d.ts +57 -0
  24. package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
  25. package/src/basis/etc1s/etc1s_decode_slice.js +258 -0
  26. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts +48 -0
  27. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
  28. package/src/basis/etc1s/etc1s_read_endpoint_codebook.js +111 -0
  29. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts +42 -0
  30. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
  31. package/src/basis/etc1s/etc1s_read_selector_codebook.js +127 -0
  32. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts +54 -0
  33. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
  34. package/src/basis/etc1s/etc1s_read_slice_tables.js +47 -0
  35. package/src/basis/transcode/build_range_plan.js +54 -0
  36. package/src/basis/transcode/etc1s_to_bc1.d.ts +24 -0
  37. package/src/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
  38. package/src/basis/transcode/etc1s_to_bc1.js +205 -0
  39. package/src/basis/transcode/etc1s_to_bc7.d.ts +30 -0
  40. package/src/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
  41. package/src/basis/transcode/etc1s_to_bc7.js +496 -0
  42. package/src/basis/transcode/fit_endpoints.d.ts +59 -0
  43. package/src/basis/transcode/fit_endpoints.d.ts.map +1 -0
  44. package/src/basis/transcode/fit_endpoints.js +226 -0
  45. package/src/{avif/native/isobmff → core/binary}/ByteCursor.d.ts +19 -6
  46. package/src/core/binary/ByteCursor.d.ts.map +1 -0
  47. package/src/{avif/native/isobmff → core/binary}/ByteCursor.js +41 -14
  48. package/src/engine/EngineHarness.js +1 -1
  49. package/src/engine/asset/codec/Codec.d.ts.map +1 -0
  50. package/src/engine/asset/codec/CodecWithFallback.d.ts.map +1 -0
  51. package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.js +2 -2
  52. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +4 -4
  53. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
  54. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  55. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
  56. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +1 -1
  57. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
  58. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +1 -1
  59. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +1 -1
  60. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
  61. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
  62. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  63. package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -0
  64. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  65. package/src/engine/physics/broadphase/generate_pairs.js +7 -1
  66. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  67. package/src/ktx2/KTX2_IDENTIFIER.d.ts +14 -0
  68. package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
  69. package/src/ktx2/KTX2_IDENTIFIER.js +15 -0
  70. package/src/ktx2/KhrDfModel.d.ts +35 -0
  71. package/src/ktx2/KhrDfModel.d.ts.map +1 -0
  72. package/src/ktx2/KhrDfModel.js +49 -0
  73. package/src/ktx2/SupercompressionScheme.d.ts +16 -0
  74. package/src/ktx2/SupercompressionScheme.d.ts.map +1 -0
  75. package/src/ktx2/SupercompressionScheme.js +23 -0
  76. package/src/ktx2/ktx2_read.d.ts +71 -0
  77. package/src/ktx2/ktx2_read.d.ts.map +1 -0
  78. package/src/ktx2/ktx2_read.js +581 -0
  79. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
  80. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
  81. package/src/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
  82. package/src/ktx2/vk_format_to_texture_format.d.ts +55 -0
  83. package/src/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
  84. package/src/ktx2/vk_format_to_texture_format.js +290 -0
  85. package/src/shade/descriptor/GPUTextureUsage.d.ts +23 -0
  86. package/src/shade/descriptor/GPUTextureUsage.d.ts.map +1 -0
  87. package/src/shade/descriptor/GPUTextureUsage.js +24 -0
  88. package/src/shade/descriptor/WebGPUExtensionType.d.ts +3 -0
  89. package/src/shade/descriptor/WebGPUExtensionType.js +26 -0
  90. package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -6
  91. package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
  92. package/src/shade/descriptor/texture/TextureDescriptor.js +24 -40
  93. package/src/shade/descriptor/texture/format/TextureFormat.d.ts +125 -0
  94. package/src/shade/descriptor/texture/format/TextureFormat.d.ts.map +1 -0
  95. package/src/shade/descriptor/texture/format/TextureFormat.js +146 -0
  96. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +60 -0
  97. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
  98. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +102 -0
  99. package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
  100. package/src/shade/device/graph/TextureResourceDescriptor.js +160 -155
  101. package/src/shade/device/mock/SoftwareGPUQueue.d.ts +11 -4
  102. package/src/shade/device/mock/SoftwareGPUQueue.d.ts.map +1 -1
  103. package/src/shade/device/mock/SoftwareGPUQueue.js +31 -37
  104. package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
  105. package/src/shade/device/mock/SoftwareGPUTexture.js +8 -4
  106. package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -1
  107. package/src/shade/device/timing/profile/frame_graph_extract_topology.js +164 -174
  108. package/src/shade/playground/ground_seam/README.md +235 -0
  109. package/src/shade/playground/ground_seam/capture_scene_color.d.ts +45 -0
  110. package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -0
  111. package/src/shade/playground/ground_seam/capture_scene_color.js +242 -0
  112. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts +11 -0
  113. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts.map +1 -0
  114. package/src/shade/playground/ground_seam/depth_step_across_seam.js +185 -0
  115. package/src/shade/playground/ground_seam/index.html +195 -0
  116. package/src/shade/playground/ground_seam/main.d.ts +2 -0
  117. package/src/shade/playground/ground_seam/main.d.ts.map +1 -0
  118. package/src/shade/playground/ground_seam/main.js +879 -0
  119. package/src/shade/playground/ground_seam/make_grid_texture.d.ts +29 -0
  120. package/src/shade/playground/ground_seam/make_grid_texture.d.ts.map +1 -0
  121. package/src/shade/playground/ground_seam/make_grid_texture.js +105 -0
  122. package/src/shade/playground/ground_seam/make_ground.d.ts +70 -0
  123. package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -0
  124. package/src/shade/playground/ground_seam/make_ground.js +161 -0
  125. package/src/shade/playground/ground_seam/measure_flicker.d.ts +71 -0
  126. package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -0
  127. package/src/shade/playground/ground_seam/measure_flicker.js +531 -0
  128. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  129. package/src/shade/renderer/Renderer.js +2519 -2511
  130. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +275 -274
  132. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  133. package/src/shade/renderer/light/GPULightCollection.js +323 -314
  134. package/src/shade/renderer/lightmap/GPULightMap.js +336 -336
  135. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  136. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +12 -2
  137. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  138. package/src/shade/renderer/material/standard/fragment_gbuffer.js +3 -1
  139. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  140. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  141. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +3 -1
  142. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  143. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  144. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js +3 -1
  145. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  146. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js +3 -1
  147. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts +28 -0
  148. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts.map +1 -0
  149. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js +39 -0
  150. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts +45 -0
  151. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts.map +1 -1
  152. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js +94 -61
  153. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts +24 -0
  154. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts.map +1 -0
  155. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.js +43 -0
  156. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +1462 -0
  157. package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
  158. package/src/shade/renderer/texture/TextureManager.js +20 -8
  159. package/src/shade/renderer/texture/TextureRole.d.ts +19 -0
  160. package/src/shade/renderer/texture/TextureRole.d.ts.map +1 -0
  161. package/src/shade/renderer/texture/TextureRole.js +26 -0
  162. package/src/shade/renderer/texture/TextureVariantSet.d.ts +71 -0
  163. package/src/shade/renderer/texture/TextureVariantSet.d.ts.map +1 -0
  164. package/src/shade/renderer/texture/TextureVariantSet.js +105 -0
  165. package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
  166. package/src/shade/renderer/texture/download_texture_data.js +22 -0
  167. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +15 -0
  168. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -0
  169. package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +50 -0
  170. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts +27 -0
  171. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts.map +1 -0
  172. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js +65 -0
  173. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts +11 -0
  174. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -0
  175. package/src/shade/renderer/texture/format/infer_format_from_parameters.js +88 -0
  176. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts +24 -0
  177. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -0
  178. package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +71 -0
  179. package/src/shade/renderer/texture/format/texture_format_preference.d.ts +22 -0
  180. package/src/shade/renderer/texture/format/texture_format_preference.d.ts.map +1 -0
  181. package/src/shade/renderer/texture/format/texture_format_preference.js +89 -0
  182. package/src/shade/renderer/texture/format/texture_variant_select.d.ts +24 -0
  183. package/src/shade/renderer/texture/format/texture_variant_select.d.ts.map +1 -0
  184. package/src/shade/renderer/texture/format/texture_variant_select.js +38 -0
  185. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts +9 -1
  186. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts.map +1 -1
  187. package/src/shade/renderer/texture/shade_texture_might_have_alpha.js +73 -8
  188. package/src/shade/renderer/texture/source/AlphaMode.d.ts +27 -0
  189. package/src/shade/renderer/texture/source/AlphaMode.d.ts.map +1 -0
  190. package/src/shade/renderer/texture/source/AlphaMode.js +52 -0
  191. package/src/shade/renderer/texture/source/ShadeImage.d.ts +33 -0
  192. package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
  193. package/src/shade/renderer/texture/source/ShadeImage.js +74 -0
  194. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts +78 -0
  195. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts.map +1 -0
  196. package/src/shade/renderer/texture/source/ShadeTexelData.js +158 -0
  197. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts +0 -10
  198. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts.map +1 -1
  199. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.js +73 -175
  200. package/src/shade/renderer/texture/texture_write_level.d.ts +32 -0
  201. package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -0
  202. package/src/shade/renderer/texture/texture_write_level.js +77 -0
  203. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts +8 -1
  204. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
  205. package/src/shade/renderer/texture/texture_write_to_gpu.js +62 -37
  206. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts +8 -0
  207. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts.map +1 -1
  208. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +8 -0
  209. package/src/shade/util/texture_mip_extent.d.ts +49 -0
  210. package/src/shade/util/texture_mip_extent.d.ts.map +1 -0
  211. package/src/shade/util/texture_mip_extent.js +87 -0
  212. package/src/avif/native/isobmff/ByteCursor.d.ts.map +0 -1
  213. package/src/engine/asset/loaders/image/codec/Codec.d.ts.map +0 -1
  214. package/src/engine/asset/loaders/image/codec/CodecWithFallback.d.ts.map +0 -1
  215. package/src/shade/util/compute_max_mip_count.d.ts +0 -8
  216. package/src/shade/util/compute_max_mip_count.d.ts.map +0 -1
  217. package/src/shade/util/compute_max_mip_count.js +0 -27
  218. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.d.ts +0 -0
  219. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.js +0 -0
  220. /package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"parse_image_grid.d.ts","sourceRoot":"","sources":["../../../../../src/avif/native/heif/parse_image_grid.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,0CAPW,UAAU,GACR,SAAS,CAmCrB;0BA9CyB,eAAe"}
1
+ {"version":3,"file":"parse_image_grid.d.ts","sourceRoot":"","sources":["../../../../../src/avif/native/heif/parse_image_grid.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,0CAPW,UAAU,GACR,SAAS,CAmCrB;0BA9CyB,eAAe"}
@@ -1,48 +1,49 @@
1
- import { ByteCursor } from "../isobmff/ByteCursor.js";
2
- import { ImageGrid } from "./AvifFile.js";
3
-
4
- /**
5
- * Parse a `grid` derived image's payload.
6
- *
7
- * This is not a box: it is the item's own data, laid out as version, flags, the tile counts and
8
- * the assembled output size. Bit 0 of `flags` widens the output dimensions from 16 to 32 bits.
9
- *
10
- * The tile counts are stored minus one, so a grid always has at least one row and one column.
11
- *
12
- * @param {Uint8Array} payload
13
- * @returns {ImageGrid}
14
- * @see ISO/IEC 23008-12 section 6.6.2.3 "Image grid"
15
- *
16
- * @author Alex Goldring
17
- * @copyright Company Named Limited (c) 2026
18
- */
19
- export function parse_image_grid(payload) {
20
- const cursor = new ByteCursor().init(payload);
21
-
22
- const version = cursor.u8();
23
-
24
- if (version !== 0) {
25
- throw new Error(`grid version ${version} is not supported`);
26
- }
27
-
28
- const flags = cursor.u8();
29
-
30
- const grid = new ImageGrid();
31
-
32
- grid.rows = cursor.u8() + 1;
33
- grid.columns = cursor.u8() + 1;
34
-
35
- if ((flags & 1) !== 0) {
36
- grid.output_width = cursor.u32();
37
- grid.output_height = cursor.u32();
38
- } else {
39
- grid.output_width = cursor.u16();
40
- grid.output_height = cursor.u16();
41
- }
42
-
43
- if (grid.output_width === 0 || grid.output_height === 0) {
44
- throw new Error(`grid declares a ${grid.output_width}x${grid.output_height} output`);
45
- }
46
-
47
- return grid;
48
- }
1
+ import { ByteCursor } from "../../../core/binary/ByteCursor.js";
2
+ import { EndianType } from "../../../core/binary/EndianType.js";
3
+ import { ImageGrid } from "./AvifFile.js";
4
+
5
+ /**
6
+ * Parse a `grid` derived image's payload.
7
+ *
8
+ * This is not a box: it is the item's own data, laid out as version, flags, the tile counts and
9
+ * the assembled output size. Bit 0 of `flags` widens the output dimensions from 16 to 32 bits.
10
+ *
11
+ * The tile counts are stored minus one, so a grid always has at least one row and one column.
12
+ *
13
+ * @param {Uint8Array} payload
14
+ * @returns {ImageGrid}
15
+ * @see ISO/IEC 23008-12 section 6.6.2.3 "Image grid"
16
+ *
17
+ * @author Alex Goldring
18
+ * @copyright Company Named Limited (c) 2026
19
+ */
20
+ export function parse_image_grid(payload) {
21
+ const cursor = new ByteCursor().init(payload, EndianType.BigEndian);
22
+
23
+ const version = cursor.u8();
24
+
25
+ if (version !== 0) {
26
+ throw new Error(`grid version ${version} is not supported`);
27
+ }
28
+
29
+ const flags = cursor.u8();
30
+
31
+ const grid = new ImageGrid();
32
+
33
+ grid.rows = cursor.u8() + 1;
34
+ grid.columns = cursor.u8() + 1;
35
+
36
+ if ((flags & 1) !== 0) {
37
+ grid.output_width = cursor.u32();
38
+ grid.output_height = cursor.u32();
39
+ } else {
40
+ grid.output_width = cursor.u16();
41
+ grid.output_height = cursor.u16();
42
+ }
43
+
44
+ if (grid.output_width === 0 || grid.output_height === 0) {
45
+ throw new Error(`grid declares a ${grid.output_width}x${grid.output_height} output`);
46
+ }
47
+
48
+ return grid;
49
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * LSB-first bit cursor over a byte range, with the speculative peek a Huffman decoder needs.
3
+ *
4
+ * **Why this is not {@link BitReader}.** `avif/native/bitstream/BitReader.js` is the other bit
5
+ * reader in this tree and it does not fit, for two reasons that are about the format rather than
6
+ * about convenience:
7
+ *
8
+ * 1. **It is MSB-first, and Basis is LSB-first.** The specification is explicit — "Huffman codes are
9
+ * stored in each output byte in LSB to MSB order. (This is opposite of the JPEG format)". Bit
10
+ * order is not a parameter that could be added the way {@link ByteCursor} took a byte order:
11
+ * a byte order is a property of a *field*, applied once per read, while a bit order changes what
12
+ * the single-bit primitive means and so changes every accessor beneath it.
13
+ * 2. **Huffman decoding needs peek-then-consume, which a descriptor reader has no reason to offer.**
14
+ * A canonical code's length is not known until it has been looked up, so the decoder reads bits
15
+ * it may not consume. `BitReader`'s `f(n)` is sequential by construction.
16
+ *
17
+ * One class doing both would be a flag on every method. So this is a second bit reader,
18
+ * deliberately, and it stays in `basis/` rather than moving to `core/binary/` until something other
19
+ * than Basis wants it — the same rule `ByteCursor` moved under, applied in the direction that says
20
+ * "not yet".
21
+ *
22
+ * **Peeking past the end reads zeros; consuming past it throws.** The two have to differ. A Huffman
23
+ * peek is speculative and legitimately runs off the end of a section — the last code in a stream is
24
+ * rarely flush with a byte boundary — so refusing there would refuse well-formed files. Consuming is
25
+ * a different claim, and a stream that runs out mid-symbol is corrupt.
26
+ *
27
+ * @author Alex Goldring
28
+ * @copyright Company Named Limited (c) 2026
29
+ */
30
+ export class BasisBitReader {
31
+ /**
32
+ * Point the reader at a byte range.
33
+ *
34
+ * @param {Uint8Array} data
35
+ * @param {number} [byte_offset]
36
+ * @param {number} [byte_length]
37
+ * @returns {BasisBitReader} this
38
+ * @throws {Error} for a range outside `data`
39
+ */
40
+ init(data: Uint8Array, byte_offset?: number, byte_length?: number): BasisBitReader;
41
+ /**
42
+ * Look at the next `count` bits without consuming them. Bits past the end of the range read as
43
+ * zero — see the note on the class.
44
+ *
45
+ * @param {number} count `0` to 24; the Huffman decoder's longest peek is 16
46
+ * @returns {number}
47
+ */
48
+ peek(count: number): number;
49
+ /**
50
+ * Drop the next `count` bits.
51
+ *
52
+ * @param {number} count
53
+ * @throws {Error} when the bits dropped were never in the range
54
+ */
55
+ consume(count: number): void;
56
+ /**
57
+ * Read `count` bits, least significant first.
58
+ *
59
+ * @param {number} count `0` to 24
60
+ * @returns {number}
61
+ * @throws {Error} when the range does not hold them
62
+ */
63
+ bits(count: number): number;
64
+ /**
65
+ * The specification's variable-length code: `chunk_bits` of payload plus a continuation bit,
66
+ * repeated until the continuation bit is clear.
67
+ *
68
+ * @param {number} chunk_bits
69
+ * @returns {number}
70
+ * @throws {Error} for a code that would not fit in 32 bits, which is a corrupt stream rather
71
+ * than a large number
72
+ * @see the specification's `decode_vlc`, section 10.2
73
+ */
74
+ vlc(chunk_bits: number): number;
75
+ #private;
76
+ }
77
+ //# sourceMappingURL=BasisBitReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasisBitReader.d.ts","sourceRoot":"","sources":["../../../src/basis/BasisBitReader.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IAyCI;;;;;;;;OAQG;IACH,WANW,UAAU,gBACV,MAAM,gBACN,MAAM,GACJ,cAAc,CAmB1B;IA6BD;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;OAKG;IACH,eAHW,MAAM,QAwBhB;IAED;;;;;;OAMG;IACH,YAJW,MAAM,GACJ,MAAM,CASlB;IAED;;;;;;;;;OASG;IACH,gBANW,MAAM,GACJ,MAAM,CA+BlB;;CACJ"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Bits are consumed into a 32-bit accumulator; this is how many it may hold.
3
+ *
4
+ * @readonly
5
+ * @type {number}
6
+ */
7
+ const ACCUMULATOR_CAPACITY = 32;
8
+
9
+ /**
10
+ * LSB-first bit cursor over a byte range, with the speculative peek a Huffman decoder needs.
11
+ *
12
+ * **Why this is not {@link BitReader}.** `avif/native/bitstream/BitReader.js` is the other bit
13
+ * reader in this tree and it does not fit, for two reasons that are about the format rather than
14
+ * about convenience:
15
+ *
16
+ * 1. **It is MSB-first, and Basis is LSB-first.** The specification is explicit — "Huffman codes are
17
+ * stored in each output byte in LSB to MSB order. (This is opposite of the JPEG format)". Bit
18
+ * order is not a parameter that could be added the way {@link ByteCursor} took a byte order:
19
+ * a byte order is a property of a *field*, applied once per read, while a bit order changes what
20
+ * the single-bit primitive means and so changes every accessor beneath it.
21
+ * 2. **Huffman decoding needs peek-then-consume, which a descriptor reader has no reason to offer.**
22
+ * A canonical code's length is not known until it has been looked up, so the decoder reads bits
23
+ * it may not consume. `BitReader`'s `f(n)` is sequential by construction.
24
+ *
25
+ * One class doing both would be a flag on every method. So this is a second bit reader,
26
+ * deliberately, and it stays in `basis/` rather than moving to `core/binary/` until something other
27
+ * than Basis wants it — the same rule `ByteCursor` moved under, applied in the direction that says
28
+ * "not yet".
29
+ *
30
+ * **Peeking past the end reads zeros; consuming past it throws.** The two have to differ. A Huffman
31
+ * peek is speculative and legitimately runs off the end of a section — the last code in a stream is
32
+ * rarely flush with a byte boundary — so refusing there would refuse well-formed files. Consuming is
33
+ * a different claim, and a stream that runs out mid-symbol is corrupt.
34
+ *
35
+ * @author Alex Goldring
36
+ * @copyright Company Named Limited (c) 2026
37
+ */
38
+ export class BasisBitReader {
39
+ /**
40
+ * Bytes being read. Not owned.
41
+ * @type {Uint8Array}
42
+ */
43
+ #data = null;
44
+
45
+ /**
46
+ * Index into {@link #data} of the next byte to pull into {@link #accumulator}.
47
+ * @type {number}
48
+ */
49
+ #byte_position = 0;
50
+
51
+ /**
52
+ * Index into {@link #data} one past the last readable byte.
53
+ * @type {number}
54
+ */
55
+ #end = 0;
56
+
57
+ /**
58
+ * Buffered bits, least significant first. Only the low {@link #bit_count} are meaningful.
59
+ * @type {number}
60
+ */
61
+ #accumulator = 0;
62
+
63
+ /**
64
+ * How many of {@link #accumulator}'s bits are meaningful.
65
+ * @type {number}
66
+ */
67
+ #bit_count = 0;
68
+
69
+ /**
70
+ * Bits of {@link #accumulator} that were manufactured past {@link #end} rather than read.
71
+ *
72
+ * They sit at the most significant end, since that is where a refill puts them. Consuming far
73
+ * enough to reach them is the overrun that throws.
74
+ *
75
+ * @type {number}
76
+ */
77
+ #phantom_bits = 0;
78
+
79
+ /**
80
+ * Point the reader at a byte range.
81
+ *
82
+ * @param {Uint8Array} data
83
+ * @param {number} [byte_offset]
84
+ * @param {number} [byte_length]
85
+ * @returns {BasisBitReader} this
86
+ * @throws {Error} for a range outside `data`
87
+ */
88
+ init(data, byte_offset = 0, byte_length = data.length - byte_offset) {
89
+ if (byte_offset < 0 || byte_length < 0 || byte_offset + byte_length > data.length) {
90
+ throw new Error(
91
+ `Basis: a bit reader range of [${byte_offset}, ${byte_offset + byte_length}) is`
92
+ + ` outside the ${data.length} byte buffer it was given`
93
+ );
94
+ }
95
+
96
+ this.#data = data;
97
+ this.#byte_position = byte_offset;
98
+ this.#end = byte_offset + byte_length;
99
+ this.#accumulator = 0;
100
+ this.#bit_count = 0;
101
+ this.#phantom_bits = 0;
102
+
103
+ return this;
104
+ }
105
+
106
+ /**
107
+ * Fill {@link #accumulator} to at least `count` meaningful bits, manufacturing zeros past the
108
+ * end of the range.
109
+ *
110
+ * @param {number} count
111
+ */
112
+ #fill(count) {
113
+ while (this.#bit_count < count) {
114
+ const past_end = this.#byte_position >= this.#end;
115
+
116
+ const byte = past_end ? 0 : this.#data[this.#byte_position];
117
+
118
+ if (past_end) {
119
+ this.#phantom_bits += 8;
120
+ }
121
+
122
+ this.#byte_position++;
123
+
124
+ /*
125
+ `<<` is a signed 32-bit shift, so a byte landing on bits 24..31 would make the
126
+ accumulator negative; `>>> 0` puts it back in the unsigned range the masks assume.
127
+ */
128
+ this.#accumulator = (this.#accumulator | (byte << this.#bit_count)) >>> 0;
129
+ this.#bit_count += 8;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Look at the next `count` bits without consuming them. Bits past the end of the range read as
135
+ * zero — see the note on the class.
136
+ *
137
+ * @param {number} count `0` to 24; the Huffman decoder's longest peek is 16
138
+ * @returns {number}
139
+ */
140
+ peek(count) {
141
+ if (count === 0) {
142
+ return 0;
143
+ }
144
+
145
+ this.#fill(count);
146
+
147
+ return this.#accumulator & ((1 << count) - 1);
148
+ }
149
+
150
+ /**
151
+ * Drop the next `count` bits.
152
+ *
153
+ * @param {number} count
154
+ * @throws {Error} when the bits dropped were never in the range
155
+ */
156
+ consume(count) {
157
+ if (count === 0) {
158
+ return;
159
+ }
160
+
161
+ this.#fill(count);
162
+
163
+ /*
164
+ The phantom bits sit at the top of the accumulator, so the bits being consumed are real
165
+ exactly when the meaningful ones below them outnumber the request.
166
+ */
167
+ if (this.#bit_count - this.#phantom_bits < count) {
168
+ throw new Error(
169
+ `Basis: the bitstream ended mid-symbol — ${count} bits were asked for and only`
170
+ + ` ${Math.max(this.#bit_count - this.#phantom_bits, 0)} remain in the section`
171
+ );
172
+ }
173
+
174
+ this.#accumulator = count === ACCUMULATOR_CAPACITY ? 0 : this.#accumulator >>> count;
175
+
176
+ this.#bit_count -= count;
177
+ }
178
+
179
+ /**
180
+ * Read `count` bits, least significant first.
181
+ *
182
+ * @param {number} count `0` to 24
183
+ * @returns {number}
184
+ * @throws {Error} when the range does not hold them
185
+ */
186
+ bits(count) {
187
+ const value = this.peek(count);
188
+
189
+ this.consume(count);
190
+
191
+ return value;
192
+ }
193
+
194
+ /**
195
+ * The specification's variable-length code: `chunk_bits` of payload plus a continuation bit,
196
+ * repeated until the continuation bit is clear.
197
+ *
198
+ * @param {number} chunk_bits
199
+ * @returns {number}
200
+ * @throws {Error} for a code that would not fit in 32 bits, which is a corrupt stream rather
201
+ * than a large number
202
+ * @see the specification's `decode_vlc`, section 10.2
203
+ */
204
+ vlc(chunk_bits) {
205
+ const chunk_size = 1 << chunk_bits;
206
+ const chunk_mask = chunk_size - 1;
207
+
208
+ let value = 0;
209
+ let offset = 0;
210
+
211
+ for (; ;) {
212
+ const chunk = this.bits(chunk_bits + 1);
213
+
214
+ value |= (chunk & chunk_mask) << offset;
215
+ offset += chunk_bits;
216
+
217
+ if ((chunk & chunk_size) === 0) {
218
+ break;
219
+ }
220
+
221
+ if (offset >= ACCUMULATOR_CAPACITY) {
222
+ throw new Error(
223
+ `Basis: a variable-length code ran past ${ACCUMULATOR_CAPACITY} bits without`
224
+ + ` terminating, which no valid stream does`
225
+ );
226
+ }
227
+ }
228
+
229
+ return value >>> 0;
230
+ }
231
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Longest code the format permits, from the specification's `cHuffmanMaxSupportedCodeSize`.
3
+ *
4
+ * @readonly
5
+ * @type {number}
6
+ */
7
+ export const HUFFMAN_MAX_CODE_SIZE: number;
8
+ /**
9
+ * Most symbols a table may describe, from the specification's `cHuffmanMaxSyms` — `1 << 14`.
10
+ *
11
+ * @readonly
12
+ * @type {number}
13
+ */
14
+ export const HUFFMAN_MAX_SYMBOLS: number;
15
+ /**
16
+ * A canonical Huffman decoding table, built from per-symbol code lengths.
17
+ *
18
+ * **Canonical in the Deflate sense**, which the specification says outright: codes are assigned in
19
+ * order of increasing length and, within a length, increasing symbol. What differs from Deflate is
20
+ * only where the bits come from — {@link BasisBitReader} hands them over least significant first, so
21
+ * a code appears in the stream with its bits reversed, and the fast table is indexed by that
22
+ * reversal.
23
+ *
24
+ * **Incomplete tables are legal.** The specification calls out the single-symbol case explicitly —
25
+ * one symbol with a one-bit code, assigned the code zero, leaving half the code space unused. So an
26
+ * under-full table is built rather than refused, and only a code that actually lands in the unused
27
+ * space throws.
28
+ *
29
+ * @author Alex Goldring
30
+ * @copyright Company Named Limited (c) 2026
31
+ */
32
+ export class BasisHuffmanTable {
33
+ /**
34
+ * Build the table from an array of per-symbol code lengths, `0` meaning "symbol not used".
35
+ *
36
+ * @param {Uint8Array} code_lengths
37
+ * @returns {BasisHuffmanTable} this
38
+ * @throws {Error} for a length past the format's maximum, or a set of lengths that
39
+ * over-subscribes the code space
40
+ */
41
+ init(code_lengths: Uint8Array): BasisHuffmanTable;
42
+ /**
43
+ * Read one symbol.
44
+ *
45
+ * @param {BasisBitReader} reader
46
+ * @returns {number} the symbol
47
+ * @throws {Error} for a prefix that matches no code in the table
48
+ */
49
+ decode(reader: BasisBitReader): number;
50
+ #private;
51
+ }
52
+ import { BasisBitReader } from "./BasisBitReader.js";
53
+ //# sourceMappingURL=BasisHuffmanTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasisHuffmanTable.d.ts","sourceRoot":"","sources":["../../../src/basis/BasisHuffmanTable.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;GAKG;AACH,kCAFU,MAAM,CAE2B;AAsB3C;;;;;;;;;;;;;;;;GAgBG;AACH;IAqCI;;;;;;;OAOG;IACH,mBALW,UAAU,GACR,iBAAiB,CAyE7B;IAiDD;;;;;;OAMG;IACH,eAJW,cAAc,GACZ,MAAM,CAuClB;;CACJ;+BAtQ8B,qBAAqB"}