@flighthq/surface 0.1.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 (210) hide show
  1. package/dist/index.d.ts +43 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +42 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/surface.d.ts +16 -0
  6. package/dist/surface.d.ts.map +1 -0
  7. package/dist/surface.js +84 -0
  8. package/dist/surface.js.map +1 -0
  9. package/dist/surfaceAffine.d.ts +27 -0
  10. package/dist/surfaceAffine.d.ts.map +1 -0
  11. package/dist/surfaceAffine.js +159 -0
  12. package/dist/surfaceAffine.js.map +1 -0
  13. package/dist/surfaceAlpha.d.ts +27 -0
  14. package/dist/surfaceAlpha.d.ts.map +1 -0
  15. package/dist/surfaceAlpha.js +83 -0
  16. package/dist/surfaceAlpha.js.map +1 -0
  17. package/dist/surfaceBevel.d.ts +42 -0
  18. package/dist/surfaceBevel.d.ts.map +1 -0
  19. package/dist/surfaceBevel.js +102 -0
  20. package/dist/surfaceBevel.js.map +1 -0
  21. package/dist/surfaceBlur.d.ts +62 -0
  22. package/dist/surfaceBlur.d.ts.map +1 -0
  23. package/dist/surfaceBlur.js +263 -0
  24. package/dist/surfaceBlur.js.map +1 -0
  25. package/dist/surfaceChannel.d.ts +24 -0
  26. package/dist/surfaceChannel.d.ts.map +1 -0
  27. package/dist/surfaceChannel.js +126 -0
  28. package/dist/surfaceChannel.js.map +1 -0
  29. package/dist/surfaceColorMatrix.d.ts +57 -0
  30. package/dist/surfaceColorMatrix.d.ts.map +1 -0
  31. package/dist/surfaceColorMatrix.js +127 -0
  32. package/dist/surfaceColorMatrix.js.map +1 -0
  33. package/dist/surfaceCompare.d.ts +18 -0
  34. package/dist/surfaceCompare.d.ts.map +1 -0
  35. package/dist/surfaceCompare.js +64 -0
  36. package/dist/surfaceCompare.js.map +1 -0
  37. package/dist/surfaceComposite.d.ts +53 -0
  38. package/dist/surfaceComposite.d.ts.map +1 -0
  39. package/dist/surfaceComposite.js +230 -0
  40. package/dist/surfaceComposite.js.map +1 -0
  41. package/dist/surfaceConvolution.d.ts +27 -0
  42. package/dist/surfaceConvolution.d.ts.map +1 -0
  43. package/dist/surfaceConvolution.js +103 -0
  44. package/dist/surfaceConvolution.js.map +1 -0
  45. package/dist/surfaceCopy.d.ts +23 -0
  46. package/dist/surfaceCopy.d.ts.map +1 -0
  47. package/dist/surfaceCopy.js +78 -0
  48. package/dist/surfaceCopy.js.map +1 -0
  49. package/dist/surfaceCoverage.d.ts +11 -0
  50. package/dist/surfaceCoverage.d.ts.map +1 -0
  51. package/dist/surfaceCoverage.js +29 -0
  52. package/dist/surfaceCoverage.js.map +1 -0
  53. package/dist/surfaceCrop.d.ts +33 -0
  54. package/dist/surfaceCrop.d.ts.map +1 -0
  55. package/dist/surfaceCrop.js +174 -0
  56. package/dist/surfaceCrop.js.map +1 -0
  57. package/dist/surfaceDisplacement.d.ts +48 -0
  58. package/dist/surfaceDisplacement.d.ts.map +1 -0
  59. package/dist/surfaceDisplacement.js +131 -0
  60. package/dist/surfaceDisplacement.js.map +1 -0
  61. package/dist/surfaceDissolve.d.ts +21 -0
  62. package/dist/surfaceDissolve.d.ts.map +1 -0
  63. package/dist/surfaceDissolve.js +97 -0
  64. package/dist/surfaceDissolve.js.map +1 -0
  65. package/dist/surfaceDraw.d.ts +8 -0
  66. package/dist/surfaceDraw.d.ts.map +1 -0
  67. package/dist/surfaceDraw.js +14 -0
  68. package/dist/surfaceDraw.js.map +1 -0
  69. package/dist/surfaceEncode.d.ts +3 -0
  70. package/dist/surfaceEncode.d.ts.map +1 -0
  71. package/dist/surfaceEncode.js +18 -0
  72. package/dist/surfaceEncode.js.map +1 -0
  73. package/dist/surfaceFill.d.ts +12 -0
  74. package/dist/surfaceFill.d.ts.map +1 -0
  75. package/dist/surfaceFill.js +85 -0
  76. package/dist/surfaceFill.js.map +1 -0
  77. package/dist/surfaceFingerprint.d.ts +26 -0
  78. package/dist/surfaceFingerprint.d.ts.map +1 -0
  79. package/dist/surfaceFingerprint.js +99 -0
  80. package/dist/surfaceFingerprint.js.map +1 -0
  81. package/dist/surfaceFlip.d.ts +16 -0
  82. package/dist/surfaceFlip.d.ts.map +1 -0
  83. package/dist/surfaceFlip.js +98 -0
  84. package/dist/surfaceFlip.js.map +1 -0
  85. package/dist/surfaceFormat.d.ts +26 -0
  86. package/dist/surfaceFormat.d.ts.map +1 -0
  87. package/dist/surfaceFormat.js +80 -0
  88. package/dist/surfaceFormat.js.map +1 -0
  89. package/dist/surfaceFrom.d.ts +14 -0
  90. package/dist/surfaceFrom.d.ts.map +1 -0
  91. package/dist/surfaceFrom.js +87 -0
  92. package/dist/surfaceFrom.js.map +1 -0
  93. package/dist/surfaceGradient.d.ts +57 -0
  94. package/dist/surfaceGradient.d.ts.map +1 -0
  95. package/dist/surfaceGradient.js +176 -0
  96. package/dist/surfaceGradient.js.map +1 -0
  97. package/dist/surfaceGradientFill.d.ts +32 -0
  98. package/dist/surfaceGradientFill.d.ts.map +1 -0
  99. package/dist/surfaceGradientFill.js +120 -0
  100. package/dist/surfaceGradientFill.js.map +1 -0
  101. package/dist/surfaceHistogram.d.ts +20 -0
  102. package/dist/surfaceHistogram.d.ts.map +1 -0
  103. package/dist/surfaceHistogram.js +61 -0
  104. package/dist/surfaceHistogram.js.map +1 -0
  105. package/dist/surfaceImageChannel.d.ts +2 -0
  106. package/dist/surfaceImageChannel.d.ts.map +1 -0
  107. package/dist/surfaceImageChannel.js +2 -0
  108. package/dist/surfaceImageChannel.js.map +1 -0
  109. package/dist/surfaceMedian.d.ts +14 -0
  110. package/dist/surfaceMedian.d.ts.map +1 -0
  111. package/dist/surfaceMedian.js +77 -0
  112. package/dist/surfaceMedian.js.map +1 -0
  113. package/dist/surfaceMorphological.d.ts +29 -0
  114. package/dist/surfaceMorphological.d.ts.map +1 -0
  115. package/dist/surfaceMorphological.js +81 -0
  116. package/dist/surfaceMorphological.js.map +1 -0
  117. package/dist/surfaceNoise.d.ts +48 -0
  118. package/dist/surfaceNoise.d.ts.map +1 -0
  119. package/dist/surfaceNoise.js +245 -0
  120. package/dist/surfaceNoise.js.map +1 -0
  121. package/dist/surfacePaletteMap.d.ts +17 -0
  122. package/dist/surfacePaletteMap.d.ts.map +1 -0
  123. package/dist/surfacePaletteMap.js +45 -0
  124. package/dist/surfacePaletteMap.js.map +1 -0
  125. package/dist/surfacePixel.d.ts +9 -0
  126. package/dist/surfacePixel.d.ts.map +1 -0
  127. package/dist/surfacePixel.js +36 -0
  128. package/dist/surfacePixel.js.map +1 -0
  129. package/dist/surfacePixelate.d.ts +13 -0
  130. package/dist/surfacePixelate.d.ts.map +1 -0
  131. package/dist/surfacePixelate.js +61 -0
  132. package/dist/surfacePixelate.js.map +1 -0
  133. package/dist/surfaceQuery.d.ts +13 -0
  134. package/dist/surfaceQuery.d.ts.map +1 -0
  135. package/dist/surfaceQuery.js +46 -0
  136. package/dist/surfaceQuery.js.map +1 -0
  137. package/dist/surfaceRegion.d.ts +20 -0
  138. package/dist/surfaceRegion.d.ts.map +1 -0
  139. package/dist/surfaceRegion.js +28 -0
  140. package/dist/surfaceRegion.js.map +1 -0
  141. package/dist/surfaceResize.d.ts +27 -0
  142. package/dist/surfaceResize.d.ts.map +1 -0
  143. package/dist/surfaceResize.js +191 -0
  144. package/dist/surfaceResize.js.map +1 -0
  145. package/dist/surfaceRotate.d.ts +32 -0
  146. package/dist/surfaceRotate.d.ts.map +1 -0
  147. package/dist/surfaceRotate.js +143 -0
  148. package/dist/surfaceRotate.js.map +1 -0
  149. package/dist/surfaceShadow.d.ts +107 -0
  150. package/dist/surfaceShadow.d.ts.map +1 -0
  151. package/dist/surfaceShadow.js +173 -0
  152. package/dist/surfaceShadow.js.map +1 -0
  153. package/dist/surfaceSharpen.d.ts +25 -0
  154. package/dist/surfaceSharpen.d.ts.map +1 -0
  155. package/dist/surfaceSharpen.js +47 -0
  156. package/dist/surfaceSharpen.js.map +1 -0
  157. package/dist/surfaceTone.d.ts +28 -0
  158. package/dist/surfaceTone.d.ts.map +1 -0
  159. package/dist/surfaceTone.js +69 -0
  160. package/dist/surfaceTone.js.map +1 -0
  161. package/dist/surfaceTransform.d.ts +40 -0
  162. package/dist/surfaceTransform.d.ts.map +1 -0
  163. package/dist/surfaceTransform.js +163 -0
  164. package/dist/surfaceTransform.js.map +1 -0
  165. package/dist/surfaceWarp.d.ts +48 -0
  166. package/dist/surfaceWarp.d.ts.map +1 -0
  167. package/dist/surfaceWarp.js +284 -0
  168. package/dist/surfaceWarp.js.map +1 -0
  169. package/package.json +39 -0
  170. package/src/surface.test.ts +78 -0
  171. package/src/surfaceAffine.test.ts +98 -0
  172. package/src/surfaceAlpha.test.ts +113 -0
  173. package/src/surfaceBevel.test.ts +67 -0
  174. package/src/surfaceBlur.test.ts +240 -0
  175. package/src/surfaceChannel.test.ts +97 -0
  176. package/src/surfaceColorMatrix.test.ts +220 -0
  177. package/src/surfaceCompare.test.ts +92 -0
  178. package/src/surfaceComposite.test.ts +256 -0
  179. package/src/surfaceConvolution.test.ts +136 -0
  180. package/src/surfaceCopy.test.ts +54 -0
  181. package/src/surfaceCoverage.test.ts +39 -0
  182. package/src/surfaceCrop.test.ts +116 -0
  183. package/src/surfaceDisplacement.test.ts +142 -0
  184. package/src/surfaceDissolve.test.ts +99 -0
  185. package/src/surfaceDraw.test.ts +38 -0
  186. package/src/surfaceEncode.test.ts +18 -0
  187. package/src/surfaceFill.test.ts +89 -0
  188. package/src/surfaceFingerprint.test.ts +103 -0
  189. package/src/surfaceFlip.test.ts +59 -0
  190. package/src/surfaceFormat.test.ts +124 -0
  191. package/src/surfaceFrom.test.ts +62 -0
  192. package/src/surfaceGradient.test.ts +91 -0
  193. package/src/surfaceGradientFill.test.ts +107 -0
  194. package/src/surfaceHistogram.test.ts +70 -0
  195. package/src/surfaceImageChannel.test.ts +19 -0
  196. package/src/surfaceMedian.test.ts +45 -0
  197. package/src/surfaceMorphological.test.ts +75 -0
  198. package/src/surfaceNoise.test.ts +169 -0
  199. package/src/surfacePaletteMap.test.ts +55 -0
  200. package/src/surfacePixel.test.ts +99 -0
  201. package/src/surfacePixelate.test.ts +46 -0
  202. package/src/surfaceQuery.test.ts +48 -0
  203. package/src/surfaceRegion.test.ts +34 -0
  204. package/src/surfaceResize.test.ts +112 -0
  205. package/src/surfaceRotate.test.ts +119 -0
  206. package/src/surfaceShadow.test.ts +165 -0
  207. package/src/surfaceSharpen.test.ts +50 -0
  208. package/src/surfaceTone.test.ts +104 -0
  209. package/src/surfaceTransform.test.ts +134 -0
  210. package/src/surfaceWarp.test.ts +124 -0
@@ -0,0 +1,245 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ /**
3
+ * Fills the `dest` region with uniform random noise in `[low, high]`, derived
4
+ * deterministically from `seed` (the same seed always produces the same image,
5
+ * which a `Math.random()` fill could not guarantee — important for reproducible
6
+ * tests and a future C port). Region pixels outside the surface are skipped.
7
+ *
8
+ * When `grayScale` is true, R, G, and B share one value per pixel; otherwise
9
+ * each channel is independent. Alpha is set fully opaque (255).
10
+ */
11
+ export function fillSurfaceNoise(dest, seed, low = 0, high = 255, grayScale = false) {
12
+ let state = (seed | 0) >>> 0 || 1;
13
+ const lo = Math.max(0, Math.min(255, low));
14
+ const span = Math.max(0, Math.min(255, high)) - lo;
15
+ const data = dest.surface.data;
16
+ const surfaceWidth = dest.surface.width;
17
+ for (let py = 0; py < dest.height; py++) {
18
+ const y = dest.y + py;
19
+ for (let px = 0; px < dest.width; px++) {
20
+ // Advance the generator for every region pixel so the field stays
21
+ // deterministic regardless of which pixels fall outside the surface.
22
+ state = nextRandomState(state);
23
+ const r = lo + (state / 0x100000000) * span;
24
+ let g = r;
25
+ let b = r;
26
+ if (!grayScale) {
27
+ state = nextRandomState(state);
28
+ g = lo + (state / 0x100000000) * span;
29
+ state = nextRandomState(state);
30
+ b = lo + (state / 0x100000000) * span;
31
+ }
32
+ const x = dest.x + px;
33
+ if (y < 0 || y >= dest.surface.height || x < 0 || x >= surfaceWidth)
34
+ continue;
35
+ const i = (y * surfaceWidth + x) * 4;
36
+ data[i] = Math.round(r);
37
+ data[i + 1] = Math.round(g);
38
+ data[i + 2] = Math.round(b);
39
+ data[i + 3] = 255;
40
+ }
41
+ }
42
+ invalidateImageResource(dest.surface);
43
+ }
44
+ /**
45
+ * Fills `out` with fractal value noise summed over `octaves`. `baseX` and
46
+ * `baseY` are the wavelengths (in pixels) of the first octave: larger values
47
+ * produce smoother, lower-frequency noise. Each successive octave doubles the
48
+ * frequency and halves the amplitude. Output is normalized to 0..255.
49
+ *
50
+ * - `baseX`, `baseY`: wavelengths in pixels of the first octave (larger = smoother).
51
+ * - `octaves`: number of frequency doublings (1 = smooth; higher = more detail).
52
+ * - `seed`: deterministic integer seed.
53
+ * - `stitch`: when `true`, the noise field tiles seamlessly at the region borders.
54
+ * - `grayScale`: when `true`, R=G=B share one noise channel. Overrides
55
+ * `channelOptions` for the RGB channels.
56
+ * - `channelOptions`: bitmask of channels to fill (default `0x7` = RGB, matching
57
+ * OpenFL's `perlinNoise` default). Channels not selected are left unchanged in
58
+ * `dest`, except alpha: when the A bit is not selected, alpha is set opaque
59
+ * (255) rather than left as-is. Use `SURFACE_NOISE_CHANNEL_*` constants. When
60
+ * `grayScale` is true the same field drives all selected RGB channels.
61
+ *
62
+ * Output range is normalized to 0..255. Alpha defaults to 255 unless the A
63
+ * bit is explicitly included in `channelOptions`.
64
+ */
65
+ export function fillSurfacePerlinNoise(dest, baseX, baseY, octaves, seed, grayScale = false, stitch = false, channelOptions = 0x7) {
66
+ const fx0 = baseX > 0 ? 1 / baseX : 0;
67
+ const fy0 = baseY > 0 ? 1 / baseY : 0;
68
+ const passes = Math.max(1, Math.round(octaves));
69
+ const data = dest.surface.data;
70
+ const surfaceWidth = dest.surface.width;
71
+ const w = dest.width;
72
+ const h = dest.height;
73
+ for (let py = 0; py < dest.height; py++) {
74
+ const y = dest.y + py;
75
+ if (y < 0 || y >= dest.surface.height)
76
+ continue;
77
+ for (let px = 0; px < dest.width; px++) {
78
+ const x = dest.x + px;
79
+ if (x < 0 || x >= surfaceWidth)
80
+ continue;
81
+ const di = (y * surfaceWidth + x) * 4;
82
+ const nx = stitch ? stitchedCoord(px * fx0, w * fx0) : px * fx0;
83
+ const ny = stitch ? stitchedCoord(py * fy0, h * fy0) : py * fy0;
84
+ if (grayScale) {
85
+ const value = fractalValueNoise(nx, ny, passes, seed | 0);
86
+ const byte = Math.round(value * 255);
87
+ if (channelOptions & SURFACE_NOISE_CHANNEL_R)
88
+ data[di] = byte;
89
+ if (channelOptions & SURFACE_NOISE_CHANNEL_G)
90
+ data[di + 1] = byte;
91
+ if (channelOptions & SURFACE_NOISE_CHANNEL_B)
92
+ data[di + 2] = byte;
93
+ }
94
+ else {
95
+ if (channelOptions & SURFACE_NOISE_CHANNEL_R) {
96
+ data[di] = Math.round(fractalValueNoise(nx, ny, passes, seed | 0) * 255);
97
+ }
98
+ if (channelOptions & SURFACE_NOISE_CHANNEL_G) {
99
+ data[di + 1] = Math.round(fractalValueNoise(nx, ny, passes, (seed | 0) + 0x9e3779b1) * 255);
100
+ }
101
+ if (channelOptions & SURFACE_NOISE_CHANNEL_B) {
102
+ data[di + 2] = Math.round(fractalValueNoise(nx, ny, passes, (seed | 0) + 0x9e3779b2) * 255);
103
+ }
104
+ }
105
+ if (channelOptions & SURFACE_NOISE_CHANNEL_A) {
106
+ data[di + 3] = Math.round(fractalValueNoise(nx, ny, passes, (seed | 0) + 0x9e3779b3) * 255);
107
+ }
108
+ else {
109
+ data[di + 3] = 255;
110
+ }
111
+ }
112
+ }
113
+ invalidateImageResource(dest.surface);
114
+ }
115
+ /**
116
+ * Fills `dest` with fractal **turbulence** (absolute-value fBm) value noise,
117
+ * matching OpenFL's `BitmapData.perlinNoise` with `fractalNoise: false`.
118
+ * Turbulence sums `abs(octave)` values, producing a more vigorous, ridge-like
119
+ * texture than the smooth fractal sum.
120
+ *
121
+ * Parameters are identical to `fillSurfacePerlinNoise` except there is no
122
+ * `fractalNoise` flag (this function _is_ the turbulence variant).
123
+ */
124
+ export function fillSurfaceTurbulence(dest, baseX, baseY, octaves, seed, grayScale = false, stitch = false, channelOptions = 0x7) {
125
+ const fx0 = baseX > 0 ? 1 / baseX : 0;
126
+ const fy0 = baseY > 0 ? 1 / baseY : 0;
127
+ const passes = Math.max(1, Math.round(octaves));
128
+ const data = dest.surface.data;
129
+ const surfaceWidth = dest.surface.width;
130
+ const w = dest.width;
131
+ const h = dest.height;
132
+ for (let py = 0; py < dest.height; py++) {
133
+ const y = dest.y + py;
134
+ if (y < 0 || y >= dest.surface.height)
135
+ continue;
136
+ for (let px = 0; px < dest.width; px++) {
137
+ const x = dest.x + px;
138
+ if (x < 0 || x >= surfaceWidth)
139
+ continue;
140
+ const di = (y * surfaceWidth + x) * 4;
141
+ const nx = stitch ? stitchedCoord(px * fx0, w * fx0) : px * fx0;
142
+ const ny = stitch ? stitchedCoord(py * fy0, h * fy0) : py * fy0;
143
+ if (grayScale) {
144
+ const value = turbulenceNoise(nx, ny, passes, seed | 0);
145
+ const byte = Math.round(value * 255);
146
+ if (channelOptions & SURFACE_NOISE_CHANNEL_R)
147
+ data[di] = byte;
148
+ if (channelOptions & SURFACE_NOISE_CHANNEL_G)
149
+ data[di + 1] = byte;
150
+ if (channelOptions & SURFACE_NOISE_CHANNEL_B)
151
+ data[di + 2] = byte;
152
+ }
153
+ else {
154
+ if (channelOptions & SURFACE_NOISE_CHANNEL_R) {
155
+ data[di] = Math.round(turbulenceNoise(nx, ny, passes, seed | 0) * 255);
156
+ }
157
+ if (channelOptions & SURFACE_NOISE_CHANNEL_G) {
158
+ data[di + 1] = Math.round(turbulenceNoise(nx, ny, passes, (seed | 0) + 0x9e3779b1) * 255);
159
+ }
160
+ if (channelOptions & SURFACE_NOISE_CHANNEL_B) {
161
+ data[di + 2] = Math.round(turbulenceNoise(nx, ny, passes, (seed | 0) + 0x9e3779b2) * 255);
162
+ }
163
+ }
164
+ if (channelOptions & SURFACE_NOISE_CHANNEL_A) {
165
+ data[di + 3] = Math.round(turbulenceNoise(nx, ny, passes, (seed | 0) + 0x9e3779b3) * 255);
166
+ }
167
+ else {
168
+ data[di + 3] = 255;
169
+ }
170
+ }
171
+ }
172
+ invalidateImageResource(dest.surface);
173
+ }
174
+ export const SURFACE_NOISE_CHANNEL_A = 0x8;
175
+ export const SURFACE_NOISE_CHANNEL_B = 0x4;
176
+ export const SURFACE_NOISE_CHANNEL_G = 0x2;
177
+ export const SURFACE_NOISE_CHANNEL_R = 0x1;
178
+ // Fractal sum of value noise: doubling frequency, halving amplitude per octave,
179
+ // normalized back to 0..1 by the total amplitude.
180
+ function fractalValueNoise(x, y, octaves, seed) {
181
+ let sum = 0;
182
+ let amplitude = 1;
183
+ let amplitudeSum = 0;
184
+ let frequency = 1;
185
+ for (let o = 0; o < octaves; o++) {
186
+ sum += valueNoise(x * frequency, y * frequency, seed + o * 0x85ebca6b) * amplitude;
187
+ amplitudeSum += amplitude;
188
+ amplitude *= 0.5;
189
+ frequency *= 2;
190
+ }
191
+ return amplitudeSum > 0 ? sum / amplitudeSum : 0;
192
+ }
193
+ // Integer hash to a deterministic 0..1 value; the lattice corners of valueNoise.
194
+ function hashLattice(ix, iy, seed) {
195
+ let h = (Math.imul(ix, 374761393) + Math.imul(iy, 668265263) + Math.imul(seed, 0x9e3779b1)) | 0;
196
+ h = Math.imul(h ^ (h >>> 13), 1274126177);
197
+ return ((h ^ (h >>> 16)) >>> 0) / 0x100000000;
198
+ }
199
+ // Mulberry32 step: maps one 32-bit state to the next, used as an unsigned int.
200
+ function nextRandomState(state) {
201
+ let t = (state + 0x6d2b79f5) | 0;
202
+ t = Math.imul(t ^ (t >>> 15), t | 1);
203
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
204
+ return (t ^ (t >>> 14)) >>> 0 || 1;
205
+ }
206
+ // Smoothstep, so lattice cells blend without visible seams.
207
+ function smoothStep(t) {
208
+ return t * t * (3 - 2 * t);
209
+ }
210
+ // Wraps t into [0, period) so that integer lattice indices repeat, producing seamless tiling.
211
+ function stitchedCoord(t, period) {
212
+ if (period <= 0)
213
+ return t;
214
+ return ((t % period) + period) % period;
215
+ }
216
+ // Fractal turbulence: abs(2*v - 1) fBm, producing a more vigorous ridge-like texture than
217
+ // the smooth fractal sum (matches OpenFL perlinNoise with fractalNoise=false).
218
+ function turbulenceNoise(x, y, octaves, seed) {
219
+ let sum = 0;
220
+ let amplitude = 1;
221
+ let amplitudeSum = 0;
222
+ let frequency = 1;
223
+ for (let o = 0; o < octaves; o++) {
224
+ sum += Math.abs(valueNoise(x * frequency, y * frequency, seed + o * 0x85ebca6b) * 2 - 1) * amplitude;
225
+ amplitudeSum += amplitude;
226
+ amplitude *= 0.5;
227
+ frequency *= 2;
228
+ }
229
+ return amplitudeSum > 0 ? sum / amplitudeSum : 0;
230
+ }
231
+ // Bilinearly-interpolated lattice hash — one octave of value noise in 0..1.
232
+ function valueNoise(x, y, seed) {
233
+ const ix = Math.floor(x);
234
+ const iy = Math.floor(y);
235
+ const fx = smoothStep(x - ix);
236
+ const fy = smoothStep(y - iy);
237
+ const v00 = hashLattice(ix, iy, seed);
238
+ const v10 = hashLattice(ix + 1, iy, seed);
239
+ const v01 = hashLattice(ix, iy + 1, seed);
240
+ const v11 = hashLattice(ix + 1, iy + 1, seed);
241
+ const top = v00 + (v10 - v00) * fx;
242
+ const bottom = v01 + (v11 - v01) * fx;
243
+ return top + (bottom - top) * fy;
244
+ }
245
+ //# sourceMappingURL=surfaceNoise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceNoise.js","sourceRoot":"","sources":["../src/surfaceNoise.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Remaps each color channel of `source` independently through a 256-entry
4
+ * lookup table, writing into `dest`. Each table is indexed by the 0..255 input
5
+ * channel value and supplies the 0..255 output value; a `null` table leaves
6
+ * that channel unchanged. The remapped size is the overlap of the two regions.
7
+ *
8
+ * This is the building block for levels, curves, gamma, posterize, and
9
+ * per-channel inversion. Unlike Flash's 32-bit-summing `paletteMap`, the
10
+ * channels are mapped independently, which is what level/curve adjustments
11
+ * need; build a table once and reuse it across frames.
12
+ *
13
+ * Safe to pass the same surface and region in `dest` and `source` — each
14
+ * pixel's channels are read before any channel of that pixel is written.
15
+ */
16
+ export declare function applySurfacePaletteMap(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, redMap: ReadonlyArray<number> | null, greenMap: ReadonlyArray<number> | null, blueMap: ReadonlyArray<number> | null, alphaMap: ReadonlyArray<number> | null): void;
17
+ //# sourceMappingURL=surfacePaletteMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePaletteMap.d.ts","sourceRoot":"","sources":["../src/surfacePaletteMap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,EACpC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,EACtC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,EACrC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GACrC,IAAI,CA0BN"}
@@ -0,0 +1,45 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ /**
3
+ * Remaps each color channel of `source` independently through a 256-entry
4
+ * lookup table, writing into `dest`. Each table is indexed by the 0..255 input
5
+ * channel value and supplies the 0..255 output value; a `null` table leaves
6
+ * that channel unchanged. The remapped size is the overlap of the two regions.
7
+ *
8
+ * This is the building block for levels, curves, gamma, posterize, and
9
+ * per-channel inversion. Unlike Flash's 32-bit-summing `paletteMap`, the
10
+ * channels are mapped independently, which is what level/curve adjustments
11
+ * need; build a table once and reuse it across frames.
12
+ *
13
+ * Safe to pass the same surface and region in `dest` and `source` — each
14
+ * pixel's channels are read before any channel of that pixel is written.
15
+ */
16
+ export function applySurfacePaletteMap(dest, source, redMap, greenMap, blueMap, alphaMap) {
17
+ const w = Math.min(dest.width, source.width);
18
+ const h = Math.min(dest.height, source.height);
19
+ const sd = source.surface.data;
20
+ const dd = dest.surface.data;
21
+ for (let py = 0; py < h; py++) {
22
+ const sy = source.y + py;
23
+ const dy = dest.y + py;
24
+ if (sy < 0 || sy >= source.surface.height || dy < 0 || dy >= dest.surface.height)
25
+ continue;
26
+ for (let px = 0; px < w; px++) {
27
+ const sx = source.x + px;
28
+ const dx = dest.x + px;
29
+ if (sx < 0 || sx >= source.surface.width || dx < 0 || dx >= dest.surface.width)
30
+ continue;
31
+ const si = (sy * source.surface.width + sx) * 4;
32
+ const di = (dy * dest.surface.width + dx) * 4;
33
+ const r = sd[si];
34
+ const g = sd[si + 1];
35
+ const b = sd[si + 2];
36
+ const a = sd[si + 3];
37
+ dd[di] = redMap ? redMap[r] : r;
38
+ dd[di + 1] = greenMap ? greenMap[g] : g;
39
+ dd[di + 2] = blueMap ? blueMap[b] : b;
40
+ dd[di + 3] = alphaMap ? alphaMap[a] : a;
41
+ }
42
+ }
43
+ invalidateImageResource(dest.surface);
44
+ }
45
+ //# sourceMappingURL=surfacePaletteMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePaletteMap.js","sourceRoot":"","sources":["../src/surfacePaletteMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA6B,EAC7B,MAA+B,EAC/B,MAAoC,EACpC,QAAsC,EACtC,OAAqC,EACrC,QAAsC;IAEtC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC7B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,SAAS;QAC3F,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK;gBAAE,SAAS;YACzF,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAChD,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACjB,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrB,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Surface } from '@flighthq/types';
2
+ import type { ImageChannel } from './surfaceImageChannel';
3
+ export declare function getSurfacePixel(source: Readonly<Surface>, x: number, y: number): number;
4
+ export declare function getSurfacePixelChannel(source: Readonly<Surface>, x: number, y: number, channel: ImageChannel): number;
5
+ export declare function getSurfacePixelLuminance(source: Readonly<Surface>, x: number, y: number): number;
6
+ export declare function getSurfacePixelRgb(source: Readonly<Surface>, x: number, y: number): number;
7
+ export declare function setSurfacePixel(out: Surface, x: number, y: number, color: number): void;
8
+ export declare function setSurfacePixelRgb(out: Surface, x: number, y: number, color: number): void;
9
+ //# sourceMappingURL=surfacePixel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePixel.d.ts","sourceRoot":"","sources":["../src/surfacePixel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAO1D,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGvF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAErH;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1F;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOvF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAM1F"}
@@ -0,0 +1,36 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ // W3C luma coefficients for perceptual luminance (same as CSS saturate/grayscale).
3
+ const LUMA_R = 0.2126;
4
+ const LUMA_G = 0.7152;
5
+ const LUMA_B = 0.0722;
6
+ export function getSurfacePixel(source, x, y) {
7
+ const i = (y * source.width + x) * 4;
8
+ return ((source.data[i] << 24) | (source.data[i + 1] << 16) | (source.data[i + 2] << 8) | source.data[i + 3]) >>> 0;
9
+ }
10
+ export function getSurfacePixelChannel(source, x, y, channel) {
11
+ return source.data[(y * source.width + x) * 4 + channel];
12
+ }
13
+ export function getSurfacePixelLuminance(source, x, y) {
14
+ const i = (y * source.width + x) * 4;
15
+ return Math.round(source.data[i] * LUMA_R + source.data[i + 1] * LUMA_G + source.data[i + 2] * LUMA_B);
16
+ }
17
+ export function getSurfacePixelRgb(source, x, y) {
18
+ const i = (y * source.width + x) * 4;
19
+ return ((source.data[i] << 16) | (source.data[i + 1] << 8) | source.data[i + 2]) >>> 0;
20
+ }
21
+ export function setSurfacePixel(out, x, y, color) {
22
+ const i = (y * out.width + x) * 4;
23
+ out.data[i] = (color >>> 24) & 0xff;
24
+ out.data[i + 1] = (color >> 16) & 0xff;
25
+ out.data[i + 2] = (color >> 8) & 0xff;
26
+ out.data[i + 3] = color & 0xff;
27
+ invalidateImageResource(out);
28
+ }
29
+ export function setSurfacePixelRgb(out, x, y, color) {
30
+ const i = (y * out.width + x) * 4;
31
+ out.data[i] = (color >> 16) & 0xff;
32
+ out.data[i + 1] = (color >> 8) & 0xff;
33
+ out.data[i + 2] = color & 0xff;
34
+ invalidateImageResource(out);
35
+ }
36
+ //# sourceMappingURL=surfacePixel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePixel.js","sourceRoot":"","sources":["../src/surfacePixel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Pixelates (mosaics) `source` into `out`: the region is divided into
4
+ * `blockSize × blockSize` cells, each cell is averaged, and every output pixel
5
+ * in the cell takes that average color. `blockSize` is clamped to at least 1
6
+ * (a no-op copy at 1). Edge cells are clipped to the region.
7
+ *
8
+ * `out` must be at least `source.width * source.height * 4` bytes. Safe to pass
9
+ * `source.surface.data` as `out` for a full-surface region — each cell is fully
10
+ * read before it is written, and cells do not overlap.
11
+ */
12
+ export declare function pixelateSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, blockSize: number): void;
13
+ //# sourceMappingURL=surfacePixelate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePixelate.d.ts","sourceRoot":"","sources":["../src/surfacePixelate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA+ChH"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Pixelates (mosaics) `source` into `out`: the region is divided into
3
+ * `blockSize × blockSize` cells, each cell is averaged, and every output pixel
4
+ * in the cell takes that average color. `blockSize` is clamped to at least 1
5
+ * (a no-op copy at 1). Edge cells are clipped to the region.
6
+ *
7
+ * `out` must be at least `source.width * source.height * 4` bytes. Safe to pass
8
+ * `source.surface.data` as `out` for a full-surface region — each cell is fully
9
+ * read before it is written, and cells do not overlap.
10
+ */
11
+ export function pixelateSurface(out, source, blockSize) {
12
+ const block = Math.max(1, Math.round(blockSize));
13
+ const w = source.width;
14
+ const h = source.height;
15
+ const surfaceWidth = source.surface.width;
16
+ const surfaceHeight = source.surface.height;
17
+ const data = source.surface.data;
18
+ for (let by = 0; by < h; by += block) {
19
+ const yEnd = Math.min(by + block, h);
20
+ for (let bx = 0; bx < w; bx += block) {
21
+ const xEnd = Math.min(bx + block, w);
22
+ let r = 0;
23
+ let g = 0;
24
+ let b = 0;
25
+ let a = 0;
26
+ let count = 0;
27
+ for (let py = by; py < yEnd; py++) {
28
+ const sy = source.y + py;
29
+ if (sy < 0 || sy >= surfaceHeight)
30
+ continue;
31
+ for (let px = bx; px < xEnd; px++) {
32
+ const sx = source.x + px;
33
+ if (sx < 0 || sx >= surfaceWidth)
34
+ continue;
35
+ const si = (sy * surfaceWidth + sx) * 4;
36
+ r += data[si];
37
+ g += data[si + 1];
38
+ b += data[si + 2];
39
+ a += data[si + 3];
40
+ count++;
41
+ }
42
+ }
43
+ if (count === 0)
44
+ continue;
45
+ const ar = Math.round(r / count);
46
+ const ag = Math.round(g / count);
47
+ const ab = Math.round(b / count);
48
+ const aa = Math.round(a / count);
49
+ for (let py = by; py < yEnd; py++) {
50
+ for (let px = bx; px < xEnd; px++) {
51
+ const di = (py * w + px) * 4;
52
+ out[di] = ar;
53
+ out[di + 1] = ag;
54
+ out[di + 2] = ab;
55
+ out[di + 3] = aa;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=surfacePixelate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfacePixelate.js","sourceRoot":"","sources":["../src/surfacePixelate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { RectangleLike, SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Scans the `source` region for pixels matching `color` under `mask`
4
+ * (`findColor` true) or not matching it (false), and returns the tightest
5
+ * bounding rectangle of those pixels in surface-absolute coordinates, or `null`
6
+ * if none match. Region pixels outside the surface are skipped.
7
+ *
8
+ * The comparison is performed on the full packed 0xRRGGBBAA pixel value. To
9
+ * match by a subset of channels, supply a `mask` that isolates the relevant
10
+ * bytes — e.g. 0xffffff00 to ignore alpha.
11
+ */
12
+ export declare function getSurfaceColorBoundsRectangle(source: Readonly<SurfaceRegion>, mask: number, color: number, findColor?: boolean): RectangleLike | null;
13
+ //# sourceMappingURL=surfaceQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceQuery.d.ts","sourceRoot":"","sources":["../src/surfaceQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,OAAc,GACxB,aAAa,GAAG,IAAI,CA6BtB"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Scans the `source` region for pixels matching `color` under `mask`
3
+ * (`findColor` true) or not matching it (false), and returns the tightest
4
+ * bounding rectangle of those pixels in surface-absolute coordinates, or `null`
5
+ * if none match. Region pixels outside the surface are skipped.
6
+ *
7
+ * The comparison is performed on the full packed 0xRRGGBBAA pixel value. To
8
+ * match by a subset of channels, supply a `mask` that isolates the relevant
9
+ * bytes — e.g. 0xffffff00 to ignore alpha.
10
+ */
11
+ export function getSurfaceColorBoundsRectangle(source, mask, color, findColor = true) {
12
+ const data = source.surface.data;
13
+ const surfaceWidth = source.surface.width;
14
+ const maskedColor = (color >>> 0) & (mask >>> 0);
15
+ let minX = Infinity;
16
+ let minY = Infinity;
17
+ let maxX = -1;
18
+ let maxY = -1;
19
+ for (let py = 0; py < source.height; py++) {
20
+ const y = source.y + py;
21
+ if (y < 0 || y >= source.surface.height)
22
+ continue;
23
+ for (let px = 0; px < source.width; px++) {
24
+ const x = source.x + px;
25
+ if (x < 0 || x >= surfaceWidth)
26
+ continue;
27
+ const i = (y * surfaceWidth + x) * 4;
28
+ const pixel = (((data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]) >>> 0) & (mask >>> 0);
29
+ const matches = pixel === maskedColor;
30
+ if (matches === findColor) {
31
+ if (x < minX)
32
+ minX = x;
33
+ if (x > maxX)
34
+ maxX = x;
35
+ if (y < minY)
36
+ minY = y;
37
+ if (y > maxY)
38
+ maxY = y;
39
+ }
40
+ }
41
+ }
42
+ if (maxX === -1)
43
+ return null;
44
+ return { x: minX, y: minY, width: maxX - minX + 1, height: maxY - minY + 1 };
45
+ }
46
+ //# sourceMappingURL=surfaceQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceQuery.js","sourceRoot":"","sources":["../src/surfaceQuery.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAA+B,EAC/B,IAAY,EACZ,KAAa,EACb,YAAqB,IAAI;IAEzB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IACjC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1C,MAAM,WAAW,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;IACjD,IAAI,IAAI,GAAG,QAAQ,CAAC;IACpB,IAAI,IAAI,GAAG,QAAQ,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IAEd,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;YAAE,SAAS;QAClD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY;gBAAE,SAAS;YACzC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;YAChH,MAAM,OAAO,GAAG,KAAK,KAAK,WAAW,CAAC;YACtC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,GAAG,IAAI;oBAAE,IAAI,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Surface, SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Allocates a `SurfaceRegion`. With no bounds it covers the whole surface, so
4
+ * `createSurfaceRegion(surface)` is the fast path for "operate on everything".
5
+ *
6
+ * Region functions read these fields synchronously and never retain the object,
7
+ * so in a hot loop you can allocate one region up front and reuse it with
8
+ * `setSurfaceRegion` instead of building a literal per call.
9
+ */
10
+ export declare function createSurfaceRegion(surface: Surface, x?: number, y?: number, width?: number, height?: number): SurfaceRegion;
11
+ /**
12
+ * Writes region fields into an existing `out` region without allocating, and
13
+ * returns `out`. With no bounds it covers the whole surface. Use this to thread
14
+ * a single reusable region through a hot loop:
15
+ *
16
+ * const r = createSurfaceRegion(surface);
17
+ * for (…) fillSurfaceRectangle(setSurfaceRegion(r, surface, x, y, w, h), color);
18
+ */
19
+ export declare function setSurfaceRegion(out: SurfaceRegion, surface: Surface, x?: number, y?: number, width?: number, height?: number): SurfaceRegion;
20
+ //# sourceMappingURL=surfaceRegion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceRegion.d.ts","sourceRoot":"","sources":["../src/surfaceRegion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,CAAC,GAAE,MAAU,EACb,CAAC,GAAE,MAAU,EACb,KAAK,GAAE,MAAsB,EAC7B,MAAM,GAAE,MAAuB,GAC9B,aAAa,CAEf;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,OAAO,EAChB,CAAC,GAAE,MAAU,EACb,CAAC,GAAE,MAAU,EACb,KAAK,GAAE,MAAsB,EAC7B,MAAM,GAAE,MAAuB,GAC9B,aAAa,CAOf"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Allocates a `SurfaceRegion`. With no bounds it covers the whole surface, so
3
+ * `createSurfaceRegion(surface)` is the fast path for "operate on everything".
4
+ *
5
+ * Region functions read these fields synchronously and never retain the object,
6
+ * so in a hot loop you can allocate one region up front and reuse it with
7
+ * `setSurfaceRegion` instead of building a literal per call.
8
+ */
9
+ export function createSurfaceRegion(surface, x = 0, y = 0, width = surface.width, height = surface.height) {
10
+ return { surface, x, y, width, height };
11
+ }
12
+ /**
13
+ * Writes region fields into an existing `out` region without allocating, and
14
+ * returns `out`. With no bounds it covers the whole surface. Use this to thread
15
+ * a single reusable region through a hot loop:
16
+ *
17
+ * const r = createSurfaceRegion(surface);
18
+ * for (…) fillSurfaceRectangle(setSurfaceRegion(r, surface, x, y, w, h), color);
19
+ */
20
+ export function setSurfaceRegion(out, surface, x = 0, y = 0, width = surface.width, height = surface.height) {
21
+ out.surface = surface;
22
+ out.x = x;
23
+ out.y = y;
24
+ out.width = width;
25
+ out.height = height;
26
+ return out;
27
+ }
28
+ //# sourceMappingURL=surfaceRegion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceRegion.js","sourceRoot":"","sources":["../src/surfaceRegion.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,IAAY,CAAC,EACb,IAAY,CAAC,EACb,QAAgB,OAAO,CAAC,KAAK,EAC7B,SAAiB,OAAO,CAAC,MAAM;IAE/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAkB,EAClB,OAAgB,EAChB,IAAY,CAAC,EACb,IAAY,CAAC,EACb,QAAgB,OAAO,CAAC,KAAK,EAC7B,SAAiB,OAAO,CAAC,MAAM;IAE/B,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IACtB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;IAClB,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,GAAG,CAAC;AACb,CAAC"}